1: <?php
2:
3: param_to_global('id', 'int', 'old_id', 'principal_id' );
4:
5: $privilege_names = array( 'read', 'write-properties', 'write-content', 'unlock', 'read-acl', 'read-current-user-privilege-set',
6: 'bind', 'unbind', 'write-acl', 'read-free-busy', 'schedule-deliver-invite', 'schedule-deliver-reply',
7: 'schedule-query-freebusy', 'schedule-send-invite', 'schedule-send-reply', 'schedule-send-freebusy' );
8: $privilege_xlate = array(
9: 'all' => translate('All privileges'),
10: 'read' => translate('Read'),
11: 'write-properties' => translate('Write Metadata'),
12: 'write-content' => translate('Write Data'),
13: 'unlock' => translate('Override a Lock'),
14: 'read-acl' => translate('Read Access Controls'),
15: 'read-current-user-privilege-set' => translate('Read Current User\'s Access'),
16: 'bind' => translate('Create Events/Collections'),
17: 'unbind' => translate('Delete Events/Collections'),
18: 'write-acl' => translate('Write Access Controls'),
19: 'read-free-busy' => translate('Read Free/Busy Information'),
20: 'schedule-deliver-invite' => translate('Scheduling: Deliver an Invitation'),
21: 'schedule-deliver-reply' => translate('Scheduling: Deliver a Reply'),
22: 'schedule-query-freebusy' => translate('Scheduling: Query free/busy'),
23: 'schedule-send-invite' => translate('Scheduling: Send an Invitation'),
24: 'schedule-send-reply' => translate('Scheduling: Send a Reply'),
25: 'schedule-send-freebusy' => translate('Scheduling: Send free/busy'),
26: 'write' => translate('Write'),
27: 'schedule-deliver' => translate('Scheduling: Delivery'),
28: 'schedule-send' => translate('Scheduling: Sending')
29: );
30:
31: $can_write_principal = ($session->AllowedTo('Admin') || ($session->principal_id == $id));
32: if ( !$can_write_principal && $id > 0 ) {
33: $target_principal = new Principal('principal_id', $id);
34: $can_write_principal = $session->HavePrivilegeTo('DAV::write', $target_principal->dav_name());
35: }
36:
37:
38: $delete_collection_confirmation_required = null;
39: $delete_principal_confirmation_required = null;
40: $delete_ticket_confirmation_required = null;
41: $delete_bind_in_confirmation_required = null;
42: $delete_binding_confirmation_required = null;
43:
44: function handle_subaction( $subaction ) {
45: global $session, $c, $id, $editor;
46: global $delete_collection_confirmation_required;
47: global $delete_principal_confirmation_required;
48: global $delete_ticket_confirmation_required;
49: global $delete_bind_in_confirmation_required;
50: global $delete_binding_confirmation_required;
51: global $can_write_principal;
52:
53: dbg_error_log('admin-principal-edit',':handle_action: Action %s', $subaction );
54:
55: switch( $subaction ) {
56: case 'delete_collection':
57: dbg_error_log('admin-principal-edit',':handle_action: Deleting collection %s for principal %d', $_GET['dav_name'], $id );
58: if ($can_write_principal) {
59: if ( $session->CheckConfirmationHash('GET', 'confirm') ) {
60: dbg_error_log('admin-principal-edit',':handle_action: Allowed to delete collection %s for principal %d', $_GET['dav_name'], $id );
61: $qry = new AwlQuery('DELETE FROM collection WHERE dav_name=?;', $_GET['dav_name'] );
62: if ( $qry->Exec() ) {
63: $c->messages[] = i18n('Collection deleted.');
64: return true;
65: }
66: else {
67: $c->messages[] = i18n('There was an error writing to the database.');
68: return false;
69: }
70: }
71: else {
72: $c->messages[] = i18n('Please confirm deletion of collection - see below');
73: $delete_collection_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
74: return false;
75: }
76: }
77: else {
78: $c->messages[] = i18n('You are not allowed to delete collections for this principal.');
79: }
80: break;
81:
82: case 'delete_principal':
83: dbg_error_log('admin-principal-edit',':handle_action: Deleting principal %d', $id );
84: if ( $session->AllowedTo('Admin') ) {
85: if ( isset($id) && $id > 1 && $session->CheckConfirmationHash('GET', 'confirm') ) {
86: dbg_error_log('admin-principal-edit',':handle_action: Allowed to delete principal %d -%s', $id );
87: $qry = new AwlQuery('DELETE FROM dav_principal WHERE principal_id=?', $id );
88: if ( $qry->Exec() ) {
89: $c->messages[] = i18n('Principal deleted.');
90: return true;
91: }
92: else {
93: $c->messages[] = i18n('There was an error writing to the database.');
94: return false;
95: }
96: }
97: else {
98: $c->messages[] = i18n('Please confirm deletion of the principal');
99: $delete_principal_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
100: return false;
101: }
102: }
103: else {
104: $c->messages[] = i18n('You are not allowed to delete principals.');
105: }
106: break;
107:
108: case 'delete_ticket':
109: dbg_error_log('admin-principal-edit',':handle_action: Deleting ticket "%s" for principal %d', $_GET['ticket_id'], $id );
110: if ($can_write_principal) {
111: if ( $session->CheckConfirmationHash('GET', 'confirm') ) {
112: dbg_error_log('admin-principal-edit',':handle_action: Allowed to delete ticket "%s" for principal %d', $_GET['ticket_id'], $id );
113: $qry = new AwlQuery('DELETE FROM access_ticket WHERE ticket_id=?;', $_GET['ticket_id'] );
114: if ( $qry->Exec() ) {
115: $c->messages[] = i18n('Access ticket deleted.');
116: return true;
117: }
118: else {
119: $c->messages[] = i18n('There was an error writing to the database.');
120: return false;
121: }
122: }
123: else {
124: $c->messages[] = i18n('Please confirm deletion of access ticket - see below');
125: $delete_ticket_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
126: return false;
127: }
128: }
129: else {
130: $c->messages[] = i18n('You are not allowed to delete tickets for this principal.');
131: }
132: break;
133:
134: case 'delete_bind_in':
135: case 'delete_binding':
136: dbg_error_log('admin-principal-edit',':handle_action: Deleting binding "%s" for principal %d', $_GET['bind_id'], $id );
137: if ($can_write_principal) {
138: if ( $session->CheckConfirmationHash('GET', 'confirm') ) {
139: dbg_error_log('admin-principal-edit',':handle_action: Allowed to delete binding "%s" for principal %d', $_GET['bind_id'], $id );
140: $qry = new AwlQuery('DELETE FROM dav_binding WHERE bind_id=?;', $_GET['bind_id'] );
141: if ( $qry->Exec() ) {
142: $c->messages[] = i18n('Binding deleted.');
143: return true;
144: }
145: else {
146: $c->messages[] = i18n('There was an error writing to the database.');
147: return false;
148: }
149: }
150: else {
151: $c->messages[] = i18n('Please confirm deletion of binding - see below');
152: if ( $subaction == 'delete_bind_in' ) {
153: $delete_bind_in_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
154: }
155: else {
156: $delete_binding_confirmation_required = $session->BuildConfirmationHash('GET', 'confirm');
157: }
158: return false;
159: }
160: }
161: else {
162: $c->messages[] = i18n('You are not allowed to delete bindings for this principal.');
163: }
164: break;
165:
166: default:
167: return false;
168: }
169: return false;
170: }
171:
172: function principal_editor() {
173: global $c, $id, $can_write_principal, $session;
174: $editor = new Editor(translate('Principal'), 'dav_principal');
175:
176: $editor->SetLookup( 'date_format_type', "SELECT 'E', 'European' UNION SELECT 'U', 'US Format' UNION SELECT 'I', 'ISO Format'" );
177: $editor->SetLookup( 'type_id', 'SELECT principal_type_id, principal_type_desc FROM principal_type ORDER BY principal_type_id' );
178: $editor->SetLookup( 'locale', 'SELECT \'\', \''.translate("*** Default Locale ***").'\' UNION SELECT locale, locale_name_locale FROM supported_locales ORDER BY 1 ASC' );
179: $editor->AddAttribute( 'locale', 'title', translate("The preferred language for this person.") );
180: $editor->AddAttribute( 'fullname', 'title', translate("The full name for this person, group or other type of principal.") );
181: $editor->AddAttribute( 'email', 'title', translate("The email address identifies principals when processing invitations and freebusy lookups. It should be set to a unique value.") );
182: $editor->SetWhere( 'principal_id='.$id );
183:
184: $editor->AddField('is_admin', 'EXISTS( SELECT 1 FROM role_member WHERE role_no = 1 AND role_member.user_no = dav_principal.user_no )' );
185: $editor->AddAttribute('is_admin', 'title', translate('An "Administrator" user has full rights to the whole DAViCal System'));
186:
187: $post_values = false;
188:
189: if ( isset($_POST['xxxxusername']) ) {
190: $_POST['xxxxusername'] = trim(str_replace('/', '', $_POST['xxxxusername']));
191: if ( $_POST['xxxxusername'] == '' ) {
192: $c->messages[] = i18n("The username must not be blank, and may not contain a slash");
193: $can_write_principal = false;
194: }
195: };
196: if ( isset($_POST['fullname']) && trim($_POST['fullname']) == '' ) {
197: $c->messages[] = i18n("The full name must not be blank.");
198: $can_write_principal = false;
199: };
200: if ( isset($_POST['email']) && trim($_POST['email']) == '' ) {
201: $c->messages[] = i18n("The email address really should not be blank.");
202: }
203:
204: $pwstars = '@@@@@@@@@@';
205: if ( $can_write_principal && $editor->IsSubmit() ) {
206: $editor->WhereNewRecord( "principal_id=(SELECT CURRVAL('dav_id_seq'))" );
207: if ( ! $session->AllowedTo('Admin') ) {
208: unset($_POST['admin_role']);
209: unset($_POST['user_active']);
210: }
211: unset($_POST['password']);
212: if ( $_POST['newpass1'] != '' && $_POST['newpass1'] != $pwstars ) {
213: if ( $_POST['newpass1'] == $_POST['newpass2'] ) {
214: $_POST['password'] = $_POST['newpass1'];
215: }
216: else {
217: $c->messages[] = "Password not updated. The supplied passwords do not match.";
218: }
219: }
220: if ( isset($_POST['fullname']) && !isset($_POST['displayname']) ) {
221: $_POST['displayname'] = $_POST['fullname'];
222: }
223: if ( isset($_POST['locale']) ) {
224: awl_set_locale($_POST['locale']);
225: }
226: if ( isset($_POST['default_privileges']) ) {
227: $privilege_bitpos = array_flip($privilege_names);
228: $priv_names = array_keys($_POST['default_privileges']);
229: $privs = privilege_to_bits($priv_names);
230: $_POST['default_privileges'] = sprintf('%024s',decbin($privs));
231: $editor->Assign('default_privileges', $privs_dec);
232: }
233: if ( $editor->IsCreate() ) {
234: $c->messages[] = i18n("Creating new Principal record.");
235: }
236: else {
237: $c->messages[] = i18n("Updating Principal record.");
238: }
239: $editor->Write();
240: if ( $_POST['type_id'] != 3 && $editor->IsCreate() ) {
241:
242: require_once('auth-functions.php');
243: CreateHomeCollections($editor->Value('username'), $c->default_timezone);
244: CreateDefaultRelationships($editor->Value('username'));
245: }
246: if ( $session->AllowedTo('Admin') ) {
247: if ( $_POST['is_admin'] == 'on' ) {
248: $sql = 'INSERT INTO role_member (role_no, user_no) SELECT 1, dav_principal.user_no FROM dav_principal WHERE user_no = :user_no AND NOT EXISTS(SELECT 1 FROM role_member rm WHERE rm.role_no = 1 AND rm.user_no = dav_principal.user_no )';
249: $editor->Assign('is_admin', 't');
250: }
251: else {
252: $sql = 'DELETE FROM role_member WHERE role_no = 1 AND user_no = :user_no';
253: $editor->Assign('is_admin', 'f');
254: }
255: $params[':user_no'] = $editor->Value('user_no');
256: $qry = new AwlQuery( $sql, $params );
257: $qry->Exec('admin-principal-edit');
258: }
259: }
260: else if ( isset($id) && $id > 0 ) {
261: $editor->GetRecord();
262: if ( $editor->IsSubmit() ) {
263: $c->messages[] = i18n('You do not have permission to modify this record.');
264: }
265: }
266: if ( $editor->Available() ) {
267: $c->page_title = $editor->Title(translate('Principal').': '.$editor->Value('fullname'));
268: }
269: else {
270: $c->page_title = $editor->Title(translate('Create New Principal'));
271: $privs = decbin(privilege_to_bits($c->default_privileges));
272: $editor->Assign('default_privileges', $privs);
273: $editor->Assign('user_active', 't');
274: foreach( $c->template_usr AS $k => $v ) {
275: $editor->Assign($k, $v);
276: }
277: }
278: if ( $post_values ) {
279: $editor->PostToValues();
280: if ( isset($_POST['default_privileges']) ) {
281: $privilege_bitpos = array_flip($privilege_names);
282: $priv_names = array_keys($_POST['default_privileges']);
283: $privs = privilege_to_bits($priv_names);
284: $_POST['default_privileges'] = sprintf('%024s',decbin($privs));
285: $editor->Assign('default_privileges', $_POST['default_privileges']);
286: }
287: }
288:
289:
290: $prompt_principal_id = translate('Principal ID');
291: $value_id = ( $editor->Available() ? '##principal_id.hidden####principal_id.value##' : translate('New Principal'));
292: $prompt_username = translate('Username');
293: $prompt_password_1 = translate('Change Password');
294: $prompt_password_2 = translate('Confirm Password');
295: $prompt_fullname = translate('Fullname');
296: $prompt_displayname = translate('Display Name');
297: $prompt_email = translate('Email Address');
298: $prompt_date_format = translate('Date Format Style');
299: $prompt_admin = translate('Administrator');
300: $prompt_active = translate('Active');
301: $prompt_locale = translate('Locale');
302: $prompt_type = translate('Principal Type');
303: $prompt_privileges = translate('Privileges granted to All Users');
304:
305: if ($can_write_principal) {
306: $privs_html = build_privileges_html( $editor, 'default_privileges');
307: $submit_row = '<tr> <th class="right"></th> <td class="left" colspan="2">##submit##</td> </tr>';
308: } else {
309: $privs_html = principal_privilege_format_function( $editor->Value('default_privileges') );
310: $submit_row = '';
311: }
312:
313: $admin_row_entry = '';
314: $delete_principal_button = '';
315: if ( $session->AllowedTo('Admin') ) {
316: $admin_row_entry = ' <tr> <th class="right">'.$prompt_admin.':</th><td class="left">##is_admin.checkbox##</td> </tr>';
317: $admin_row_entry .= ' <tr> <th class="right">'.$prompt_active.':</th><td class="left">##user_active.checkbox##</td> </tr>';
318: if ( isset($id) )
319: $delete_principal_button = '<a href="'.$c->base_url . '/admin.php?action=edit&t=principal&subaction=delete_principal&id='.$id.'" class="submit">' . translate("Delete Principal") . '</a>';
320: }
321:
322: $email_unique = '';
323: $qry = new AwlQuery('SELECT user_no FROM usr WHERE lower(usr.email) = lower(:email)',
324: array( ':email' => $editor->Value('email') ));
325: $qry->Exec('principal-edit', __LINE__, __FILE__);
326: if ($qry->rows() > 1 ) {
327: $email_unique = ' <b style="color:red;">' . translate('Attention: email address not unique, scheduling may not work!') . '</b>';
328: }
329:
330: $id = $editor->Value('principal_id');
331: $template = <<<EOTEMPLATE
332: ##form##
333: <script language="javascript">
334: function toggle_privileges() {
335: var argv = toggle_privileges.arguments;
336: var argc = argv.length;
337:
338: if ( argc < 2 ) {
339: return;
340: }
341: var match_me = argv[0];
342:
343: var set_to = -1;
344: if ( argv[1] == 'all' ) {
345: var form = document.getElementById(argv[2]);
346: var fieldcount = form.elements.length;
347: var matching = '/^' + match_me + '/';
348: for (var i = 0; i < fieldcount; i++) {
349: var fieldname = form.elements[i].name;
350: if ( fieldname.match( match_me ) ) {
351: if ( set_to == -1 ) {
352: set_to = ( form.elements[i].checked ? 0 : 1 );
353: }
354: form.elements[i].checked = set_to;
355: }
356: }
357: }
358: else {
359: for (var i = 1; i < argc; i++) {
360: var f = document.getElementById( match_me + '_' + argv[i]);
361: if ( set_to == -1 ) {
362: set_to = ( f.checked ? 0 : 1 );
363: }
364: f.checked = set_to;
365: }
366: }
367: }
368: </script>
369: <style>
370: th.right, label.privilege {
371: white-space:nowrap;
372: }
373: label.privilege {
374: margin:0.2em 1em 0.2em 0.1em;
375: padding:0 0.2em;
376: line-height:1.6em;
377: font-size:87%;
378: }
379: </style>
380: <table>
381: <tr> <th class="right">$prompt_principal_id:</th><td class="left">
382: <table width="100%" class="form_inner"><tr>
383: <td>$value_id</td>
384: <td align="right">$delete_principal_button</td>
385: </tr></table>
386: </td></tr>
387: <tr> <th class="right">$prompt_username:</th> <td class="left">##xxxxusername.input.50##</td> </tr>
388: <tr> <th class="right">$prompt_password_1:</th> <td class="left">##newpass1.password.$pwstars##</td> </tr>
389: <tr> <th class="right">$prompt_password_2:</th> <td class="left">##newpass2.password.$pwstars##</td> </tr>
390: <tr> <th class="right">$prompt_fullname:</th> <td class="left">##fullname.input.50##</td> </tr>
391: <tr> <th class="right">$prompt_email:</th> <td class="left">##email.input.50##$email_unique</td> </tr>
392: <tr> <th class="right">$prompt_locale:</th> <td class="left">##locale.select##</td> </tr>
393: <tr> <th class="right">$prompt_date_format:</th> <td class="left">##date_format_type.select##</td> </tr>
394: <tr> <th class="right">$prompt_type:</th> <td class="left">##type_id.select##</td> </tr>
395: $admin_row_entry
396: <tr> <th class="right" style="white-space:normal;">$prompt_privileges:</th><td class="left">$privs_html</td> </tr>
397: $submit_row
398: </table>
399: </form>
400: EOTEMPLATE;
401:
402: $editor->SetTemplate( $template );
403: return $editor;
404: }
405:
406:
407: function build_privileges_html( $ed, $fname ) {
408: global $privilege_xlate, $privilege_names;
409:
410: $btn_all = htmlspecialchars(translate('All')); $btn_all_title = htmlspecialchars(translate('Toggle all privileges'));
411: $btn_rw = htmlspecialchars(translate('Read/Write')); $btn_rw_title = htmlspecialchars(translate('Set read+write privileges'));
412: $btn_read = htmlspecialchars(translate('Read')); $btn_read_title = htmlspecialchars(translate('Set read privileges'));
413: $btn_fb = htmlspecialchars(translate('Free/Busy')); $btn_fb_title = htmlspecialchars(translate('Set free/busy privileges'));
414: $btn_sd = htmlspecialchars(translate('Schedule Deliver')); $btn_sd_title = htmlspecialchars(translate('Privileges to allow delivery of scheduling messages'));
415: $btn_ss = htmlspecialchars(translate('Schedule Send')); $btn_ss_title = htmlspecialchars(translate('Privileges to delegate scheduling decisions'));
416:
417: $privs_dec = bindec($ed->Value($fname));
418: $privileges_set = sprintf('<div id="privileges"><input type="hidden" name="%s[fake_privilege_for_input]" value="0">%s', $fname, "\n");
419: for( $i=0; $i < count($privilege_names); $i++ ) {
420: $privilege_set = ( (1 << $i) & $privs_dec ? ' CHECKED' : '');
421: $privileges_set .= sprintf( ' <label class="privilege"><input name="%s[%s]" id="%s_%s" type="checkbox"%s>%s</label>'."\n",
422: $fname, $privilege_names[$i], $fname, $privilege_names[$i], $privilege_set,
423: $privilege_xlate[$privilege_names[$i]]);
424: }
425: $privileges_set .= '</div>'."\n";
426:
427: $form_id = $ed->Id();
428: $html = <<<EOTEMPLATE
429: <input type="button" value="$btn_all" class="submit" title="$btn_all_title"
430: onclick="toggle_privileges('$fname', 'all', 'form_$form_id');">
431: <input type="button" value="$btn_rw" class="submit" title="$btn_rw_title"
432: onclick="toggle_privileges('$fname', 'read', 'write-properties', 'write-content', 'bind', 'unbind', 'read-free-busy', 'read-current-user-privilege-set', 'schedule-deliver-invite', 'schedule-deliver-reply', 'schedule-query-freebusy', 'schedule-send-invite', 'schedule-send-reply', 'schedule-send-freebusy' );">
433: <input type="button" value="$btn_read" class="submit" title="$btn_read_title"
434: onclick="toggle_privileges('$fname', 'read', 'read-free-busy', 'schedule-query-freebusy', 'read-current-user-privilege-set' );">
435: <input type="button" value="$btn_fb" class="submit" title="$btn_fb_title"
436: onclick="toggle_privileges('$fname', 'read-free-busy', 'schedule-query-freebusy' );">
437: <input type="button" value="$btn_sd" class="submit" title="$btn_sd_title"
438: onclick="toggle_privileges('$fname', 'schedule-deliver-invite', 'schedule-deliver-reply', 'schedule-query-freebusy' );">
439: <input type="button" value="$btn_ss" class="submit" title="$btn_ss_title"
440: onclick="toggle_privileges('$fname', 'schedule-send-invite', 'schedule-send-reply', 'schedule-send-freebusy' );">
441: <br>$privileges_set
442: EOTEMPLATE;
443:
444: return $html;
445: }
446:
447:
448: 449: 450: 451: 452: 453: 454: 455: 456:
457: function principal_privilege_format_function( $value, $column, $row ) {
458: global $privilege_xlate;
459:
460: $privs = bits_to_privilege($value,'*');
461: $formatted = '';
462: foreach( $privs AS $k => $v ) {
463: $formatted .= ($formatted == '' ? '' : ', ');
464: $v = preg_replace( '{^.*:}', '', $v );
465: $formatted .= (isset($privilege_xlate[$v]) ? $privilege_xlate[$v] : $v );
466: }
467: return $formatted;
468: }
469:
470:
471: function confirm_delete_principal($confirmation_hash, $displayname ) {
472: $html = '<p class="error">';
473: $html .= sprintf('<b>%s</b> \'%s\' <a class="error" href="%s&%s">%s</a> %s',
474: translate('Deleting Principal:'), $displayname, $_SERVER['REQUEST_URI'],
475: $confirmation_hash, translate('Confirm Deletion of the Principal'),
476: translate('All of the principal\'s calendars and events will be unrecoverably deleted.') );
477: $html .= "</p>\n";
478: return $html;
479: }
480:
481:
482:
483: function group_memberships_browser() {
484: global $c, $id, $editor;
485: $browser = new Browser(translate('Group Memberships'));
486:
487: $browser->AddColumn( 'group_id', translate('ID'), 'right', '##principal_link##' );
488: $rowurl = $c->base_url . '/admin.php?action=edit&t=principal&id=';
489: $browser->AddHidden( 'principal_link', "'<a href=\"$rowurl' || principal_id || '\">' || principal_id || '</a>'" );
490: $browser->AddColumn( 'displayname', translate('Display Name') );
491: $browser->AddColumn( 'member_of', translate('Is Member of'), '', '', 'is_member_of_list(principal_id)' );
492: $browser->AddColumn( 'members', translate('Has Members'), '', '', 'has_members_list(principal_id)' );
493:
494: $browser->SetOrdering( 'displayname', 'A' );
495:
496: $browser->SetJoins( "group_member LEFT JOIN dav_principal ON (group_id = principal_id) " );
497: $browser->SetWhere( 'user_active AND member_id = '.$id );
498:
499: if ( $c->enable_row_linking ) {
500: $browser->RowFormat( '<tr onMouseover="LinkHref(this,1);" title="'.translate('Click to edit principal details').'" class="r%d">', '</tr>', '#even' );
501: }
502: else {
503: $browser->RowFormat( '<tr class="r%d">', '</tr>', '#even' );
504: }
505: $browser->DoQuery();
506: return $browser;
507: }
508:
509:
510: function group_row_editor() {
511: global $c, $id, $editor, $can_write_principal;
512: $grouprow = new Editor("Group Members", "group_member");
513: $sql = 'SELECT principal_id, coalesce(displayname,fullname,username) FROM dav_principal ';
514: $sql .= 'WHERE principal_id NOT IN (SELECT member_id FROM group_member WHERE group_id = '.$id.') ';
515: $sql .= 'AND principal_id != '.$id;
516: $sql .= 'ORDER BY 2';
517: $grouprow->SetLookup( 'member_id', $sql);
518: $grouprow->SetSubmitName( 'savegrouprow' );
519:
520: if ( $can_write_principal ) {
521: if ( $grouprow->IsSubmit() ) {
522: if ( $grouprow->IsUpdate() )
523: $c->messages[] = translate('Updating Member of this Group Principal');
524: else
525: $c->messages[] = translate('Adding new member to this Group Principal');
526:
527: $_POST['group_id'] = $id;
528: $member_id = intval($_POST['member_id']);
529: $grouprow->SetWhere( 'group_id='.$id.' AND member_id='.$member_id);
530: $grouprow->Write( );
531: unset($_GET['member_id']);
532: }
533: elseif ( isset($_GET['delete_member']) ) {
534: $qry = new AwlQuery('DELETE FROM group_member WHERE group_id=:group_id AND member_id = :member_id',
535: array( ':group_id' => $id, ':member_id' => intval($_GET['delete_member']) ));
536: $qry->Exec('principal-edit');
537: $c->messages[] = translate('Member deleted from this Group Principal');
538: }
539: }
540: return $grouprow;
541: }
542:
543:
544: function edit_group_row( $row_data ) {
545: global $id, $grouprow;
546:
547: $form_url = preg_replace( '#&(edit|delete)_group=\d+#', '', $_SERVER['REQUEST_URI'] );
548:
549: $template = <<<EOTEMPLATE
550: <form method="POST" enctype="multipart/form-data" id="add_group" action="$form_url">
551: <td class="left"><input type="hidden" name="id" value="$id"></td>
552: <td class="left" colspan="3">##member_id.select## ##Add.submit##</td>
553: <td class="center"></td>
554: </form>
555:
556: EOTEMPLATE;
557:
558: $grouprow->SetTemplate( $template );
559: $grouprow->Title("");
560: if ( $row_data->group_id > -1 ) $grouprow->SetRecord( $row_data );
561:
562: return $grouprow->Render();
563: }
564:
565: function group_members_browser() {
566: global $c, $id, $editor, $can_write_principal;
567: $browser = new Browser(translate('Group Members'));
568:
569: $browser->AddColumn( 'group_id', translate('ID'), 'right', '##principal_link##' );
570: $rowurl = $c->base_url . '/admin.php?action=edit&t=principal&id=';
571: $browser->AddHidden( 'principal_id' );
572: $browser->AddHidden( 'principal_link', "'<a href=\"$rowurl' || principal_id || '\">' || principal_id || '</a>'" );
573: $browser->AddColumn( 'displayname', translate('Display Name') );
574: $browser->AddColumn( 'member_of', translate('Is Member of'), '', '', 'is_member_of_list(principal_id)' );
575: $browser->AddColumn( 'members', translate('Has Members'), '', '', 'has_members_list(principal_id)' );
576:
577: if ( $can_write_principal ) {
578: $del_link = '<a href="'.$c->base_url.'/admin.php?action=edit&t=principal&id='.$id.'&delete_member=##principal_id##" class="submit" title="">'.translate('Remove').'</a>';
579: $browser->AddColumn( 'action', translate('Action'), 'center', '', "'$edit_link $del_link'" );
580: }
581:
582: $browser->SetOrdering( 'displayname', 'A' );
583:
584: $browser->SetJoins( "group_member LEFT JOIN dav_principal ON (member_id = principal_id) " );
585: $browser->SetWhere( 'user_active AND group_id = '.$id );
586:
587: if ( $c->enable_row_linking ) {
588: $browser->RowFormat( '<tr onMouseover="LinkHref(this,1);" title="'.translate('Click to edit principal details').'" class="r%d">', '</tr>', '#even' );
589: }
590: else {
591: $browser->RowFormat( '<tr class="r%d">', '</tr>', '#even' );
592: }
593: $browser->DoQuery();
594:
595: if ( $can_write_principal ) {
596: $browser->ExtraRowFormat( '<tr class="r%d">', '</tr>', '#even' );
597: $extra_row = array( 'group_id' => -1 );
598: $browser->MatchedRow('group_id', -1, 'edit_group_row');
599: $extra_row = (object) $extra_row;
600: $browser->AddRow($extra_row);
601: }
602: return $browser;
603: }
604:
605:
606: function grant_row_editor() {
607: global $c, $id, $editor, $can_write_principal, $privilege_names;
608:
609: $grantrow = new Editor("Grants", "grants");
610: $grantrow->SetSubmitName( 'savegrantrow' );
611: $edit_grant_clause = '';
612: if ( isset($_GET['edit_grant']) ) {
613: $edit_grant_clause = ' AND to_principal != '.intval($_GET['edit_grant']);
614: }
615: $grantrow->SetLookup( 'to_principal', 'SELECT principal_id, displayname FROM dav_principal WHERE user_active AND principal_id NOT IN (SELECT to_principal FROM grants WHERE by_principal = '.$id.$edit_grant_clause.') ORDER BY fullname' );
616: if ( $can_write_principal ) {
617: if ( $grantrow->IsSubmit() ) {
618: if ( $grantrow->IsUpdate() )
619: $c->messages[] = translate('Updating grants by this Principal');
620: else
621: $c->messages[] = translate('Granting new privileges from this Principal');
622: $_POST['by_principal'] = $id;
623: $to_principal = intval($_POST['to_principal']);
624: $orig_to_id = intval($_POST['orig_to_id']);
625: $grantrow->SetWhere( 'by_principal='.$id.' AND to_principal='.$orig_to_id);
626: if ( isset($_POST['grant_privileges']) ) {
627: $privilege_bitpos = array_flip($privilege_names);
628: $priv_names = array_keys($_POST['grant_privileges']);
629: $privs_dec = privilege_to_bits($priv_names);
630: $_POST['privileges'] = sprintf('%024s',decbin($privs_dec));
631: $grantrow->Assign('privileges', $privs_dec);
632: }
633: $grantrow->Write( );
634: unset($_GET['to_principal']);
635: }
636: elseif ( isset($_GET['delete_grant']) ) {
637: $qry = new AwlQuery("DELETE FROM grants WHERE by_principal=:grantor_id AND to_principal = :to_principal",
638: array( ':grantor_id' => $id, ':to_principal' => intval($_GET['delete_grant']) ));
639: $qry->Exec('principal-edit');
640: $c->messages[] = translate('Deleted a grant from this Principal');
641: }
642: }
643: return $grantrow;
644: }
645:
646:
647: function edit_grant_row_principal( $row_data ) {
648: global $id, $grantrow;
649:
650: $orig_to_id = intval($row_data->to_principal);
651: if ( $orig_to_id > -1 ) {
652: $grantrow->SetRecord( $row_data );
653: }
654: else {
655: $grantrow->Initialise( $row_data );
656: }
657:
658: $privs_html = build_privileges_html( $grantrow, 'grant_privileges' );
659:
660: $form_id = $grantrow->Id();
661: $form_url = preg_replace( '#&(edit|delete)_grant=\d+#', '', $_SERVER['REQUEST_URI'] );
662:
663: $template = <<<EOTEMPLATE
664: <form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
665: <td class="left" colspan="2"><input type="hidden" name="id" value="$id"><input type="hidden" name="orig_to_id" value="$orig_to_id">##to_principal.select##</td>
666: <td class="left" colspan="2">$privs_html</td>
667: <td class="center">##submit##</td>
668: </form>
669:
670: EOTEMPLATE;
671:
672: $grantrow->SetTemplate( $template );
673: $grantrow->Title("");
674:
675: return $grantrow->Render();
676: }
677:
678:
679: function principal_grants_browser() {
680: global $c, $id, $editor, $can_write_principal;
681: $browser = new Browser(translate('Principal Grants'));
682:
683: $browser->AddColumn( 'to_principal', translate('To ID'), 'right', '##principal_link##' );
684: $rowurl = $c->base_url . '/admin.php?action=edit&t=principal&id=';
685: $browser->AddHidden( 'principal_link', "'<a href=\"$rowurl' || to_principal || '\">' || to_principal || '</a>'" );
686: $browser->AddHidden( 'grant_privileges', 'privileges' );
687: $browser->AddColumn( 'displayname', translate('Display Name') );
688: $browser->AddColumn( 'privs', translate('Privileges'), '', '', 'privileges', '', '', 'principal_privilege_format_function' );
689: $browser->AddColumn( 'members', translate('Has Members'), '', '', 'has_members_list(principal_id)' );
690:
691: if ( $can_write_principal ) {
692: $del_link = '<a href="'.$c->base_url.'/admin.php?action=edit&t=principal&id='.$id.'&delete_grant=##to_principal##" class="submit" title="">'.translate('Revoke').'</a>';
693: $edit_link = '<a href="'.$c->base_url.'/admin.php?action=edit&t=principal&id='.$id.'&edit_grant=##to_principal##" class="submit" title="">'.translate('Edit').'</a>';
694: $browser->AddColumn( 'action', translate('Action'), 'center', '', "'$edit_link $del_link'" );
695: }
696:
697: $browser->SetOrdering( 'displayname', 'A' );
698:
699: $browser->SetJoins( "grants LEFT JOIN dav_principal ON (to_principal = principal_id) " );
700: $browser->SetWhere( 'by_principal = '.$id );
701:
702: if ( $c->enable_row_linking ) {
703: $browser->RowFormat( '<tr onMouseover="LinkHref(this,1);" title="'.translate('Click to edit principal details').'" class="r%d">', '</tr>', '#even' );
704: }
705: else {
706: $browser->RowFormat( '<tr class="r%d">', '</tr>', '#even' );
707: }
708: $browser->DoQuery();
709:
710:
711: if ( $can_write_principal ) {
712: if ( isset($_GET['edit_grant']) ) {
713: $browser->MatchedRow('to_principal', $_GET['edit_grant'], 'edit_grant_row_principal');
714: }
715: else if ( isset($id ) ) {
716: $browser->ExtraRowFormat( '<tr class="r%d">', '</tr>', '#even' );
717: $extra_row = array( 'to_principal' => -1 );
718: $browser->MatchedRow('to_principal', -1, 'edit_grant_row_principal');
719: $extra_row = (object) $extra_row;
720: $browser->AddRow($extra_row);
721: }
722: }
723: return $browser;
724: }
725:
726:
727: function ticket_row_editor() {
728: global $c, $id, $editor, $can_write_principal, $privilege_names;
729:
730: $ticketrow = new Editor("Tickets", "access_ticket");
731: $ticketrow->SetSubmitName( 'ticketrow' );
732: if ( $can_write_principal && $ticketrow->IsSubmit() ) {
733:
734: $username = $editor->Value('username');
735: $ugly_path = $_POST['target'];
736: if ( $ugly_path == '/'.$username || $ugly_path == '/'.$username.'/' ) {
737: $target_collection = $id;
738: }
739: else {
740: $username_len = strlen($username) + 2;
741: $sql = "SELECT collection_id FROM collection WHERE dav_name = :exact_name";
742: $sql .= " AND substring(dav_name FROM 1 FOR $username_len) = '/$username/'";
743: $params = array( ':exact_name' => $ugly_path );
744: if ( !preg_match( '#/$#', $ugly_path ) ) {
745: $sql .= " OR dav_name = :truncated_name OR dav_name = :trailing_slash_name";
746: $params[':truncated_name'] = preg_replace( '#[^/]*$#', '', $ugly_path);
747: $params[':trailing_slash_name'] = $ugly_path."/";
748: }
749: $sql .= " ORDER BY LENGTH(dav_name) DESC LIMIT 1";
750: $qry = new AwlQuery( $sql, $params );
751: if ( $qry->Exec() && $qry->rows() > 0 ) {
752: $row = $qry->Fetch();
753: $target_collection = $row->collection_id;
754: }
755: else {
756: $c->messages[] = translate('Can only add tickets for existing collection paths which you own');
757: return $ticketrow;
758: }
759: }
760:
761: $_POST['dav_owner_id'] = $id;
762: $_POST['target_collection_id'] = $target_collection;
763: $ticket_id = check_by_regex($_POST['ticket_id'], '/[A-Za-z0-9]+/');
764: $ticketrow->SetWhere( 'dav_owner_id='.$id.' AND ticket_id='.AwlQuery::quote($ticket_id));
765: if ( isset($_POST['ticket_privileges']) ) {
766: $privilege_bitpos = array_flip($privilege_names);
767: $priv_names = array_keys($_POST['ticket_privileges']);
768: $privs_dec = privilege_to_bits($priv_names);
769: $_POST['privileges'] = sprintf('%024s',decbin($privs_dec));
770: $ticketrow->Assign('privileges', $privs_dec);
771: }
772: $c->messages[] = translate('Creating new ticket granting privileges to this Principal');
773: $ticketrow->Write( );
774: }
775: return $ticketrow;
776: }
777:
778:
779: function edit_ticket_row( $row_data ) {
780: global $id, $ticketrow;
781:
782: if ( isset($row_data->ticket_id) ) {
783: $ticketrow->Initialise( $row_data );
784: }
785:
786: $privs_html = build_privileges_html( $ticketrow, 'ticket_privileges' );
787:
788: $form_id = $ticketrow->Id();
789: $ticket_id = $row_data->ticket_id;
790: $form_url = preg_replace( '#&(edit|delete)_[a-z]+=\d+#', '', $_SERVER['REQUEST_URI'] );
791:
792: $template = <<<EOTEMPLATE
793: <form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
794: <td class="left">$ticket_id<input type="hidden" name="id" value="$id"><input type="hidden" name="ticket_id" value="$ticket_id"></td>
795: <td class="left"><input type="text" name="target" value="$row_data->target"></td>
796: <td class="left"><input type="text" name="expires" value="$row_data->expires" size="10"></td>
797: <td class="left">$privs_html</td>
798: <td class="center">##submit##</td>
799: </form>
800:
801: EOTEMPLATE;
802:
803: $ticketrow->SetTemplate( $template );
804: $ticketrow->Title("");
805:
806: return $ticketrow->Render();
807: }
808:
809:
810: function access_ticket_browser() {
811: global $c, $id, $editor, $can_write_principal;
812:
813: $browser = new Browser(translate('Access Tickets'));
814:
815: if ( $can_write_principal ) {
816: $browser->AddColumn( 'ticket_id', translate('Ticket ID'), '', '' );
817: }
818: $browser->AddColumn( 'target', translate('Target'), '', '<td style="white-space:nowrap;">%s</td>', "COALESCE(d.dav_name,c.dav_name)" );
819: $browser->AddColumn( 'expires', translate('Expires'), '', '', 'TO_CHAR(expires,\'YYYY-MM-DD HH:MI:SS\')');
820: $browser->AddColumn( 'privs', translate('Privileges'), '', '', 'privileges', '', '', 'principal_privilege_format_function' );
821: if ($can_write_principal) {
822: $delurl = $c->base_url . '/admin.php?action=edit&t=principal&id='.$id.'&ticket_id=##URL:ticket_id##&subaction=delete_ticket';
823: $browser->AddColumn( 'delete', translate('Action'), 'center', '', "'<a class=\"submit\" href=\"$delurl\">".translate('Delete')."</a>'" );
824: }
825:
826: $browser->SetOrdering( 'target', 'A' );
827:
828: $browser->SetJoins( 'access_ticket t LEFT JOIN collection c ON (target_collection_id=collection_id) LEFT JOIN caldav_data d ON (target_resource_id=dav_id)' );
829: $browser->SetWhere( 'dav_owner_id = '.intval($editor->Value('principal_id')) );
830:
831: $browser->RowFormat( '<tr class="r%d">', '</tr>', '#even' );
832:
833: $browser->DoQuery();
834:
835: if ( $can_write_principal ) {
836: $ticket_id = substr( str_replace('/', '', str_replace('+', '',base64_encode(sha1(date('r') .rand(0,2100000000) . microtime(true),true)))), 7, 8);
837: $extra_row = array( 'ticket_id' => $ticket_id,
838: 'expires' => date( 'Y-m-d', time() + (86400 * 31) ),
839: 'target' => '/'.$editor->Value('username').'/'.$c->home_calendar_name.'/'
840: );
841: $browser->MatchedRow('ticket_id', $ticket_id, 'edit_ticket_row');
842: $browser->AddRow($extra_row);
843: }
844: return $browser;
845: }
846:
847:
848: function confirm_delete_ticket($confirmation_hash) {
849: $html = '<table><tr><td class="error">';
850: $html .= sprintf('<b>%s</b> "%s" <a class="error" href="%s&%s">%s</a> %s',
851: translate('Deleting Ticket:'), $_GET['ticket_id'], $_SERVER['REQUEST_URI'],
852: $confirmation_hash,
853: translate('Confirm Deletion of the Ticket'),
854: translate('The access ticket will be deleted.') );
855: $html .= "</td></tr></table>\n";
856: return $html;
857: }
858:
859:
860: function principal_collection_browser() {
861: global $c, $page_elements, $id, $editor, $can_write_principal;
862:
863: $browser = new Browser(translate('Principal Collections'));
864:
865: $browser->AddColumn( 'collection_id', translate('ID'), 'right', '##collection_link##' );
866: $rowurl = $c->base_url . '/admin.php?action=edit&t=collection&id=';
867: $browser->AddHidden( 'collection_link', "'<a href=\"$rowurl' || collection_id || '\">' || collection_id || '</a>'" );
868: $browser->AddColumn( 'dav_name', translate('Path') );
869: $browser->AddColumn( 'dav_displayname', translate('Display Name') );
870: $browser->AddColumn( 'publicly_readable', translate('Public'), 'centre', '', 'CASE WHEN publicly_readable THEN \''.translate('Yes').'\' ELSE \''.translate('No').'\' END' );
871: $browser->AddColumn( 'privs', translate('Privileges'), '', '',
872: "COALESCE( privileges_list(default_privileges), '[".translate('from principal')."]')" );
873: if ($can_write_principal) {
874: $delurl = $c->base_url . '/admin.php?action=edit&t=principal&id='.$id.'&dav_name=##URL:dav_name##&subaction=delete_collection';
875: $browser->AddColumn( 'delete', translate('Action'), 'center', '', "'<a class=\"submit\" href=\"$delurl\" title=\"\">".translate('Delete')."</a>'" );
876: }
877:
878: $browser->SetOrdering( 'dav_name', 'A' );
879:
880: $browser->SetJoins( "collection " );
881: $browser->SetWhere( 'user_no = '.intval($editor->Value('user_no')) );
882:
883: if ($can_write_principal) {
884: $browser->ExtraRowFormat( '<tr class="r%d">', '</tr>', '#even' );
885: $browser->AddRow( array( 'dav_name' => '<a href="'.$rowurl.'&user_no='.intval($editor->Value('user_no')).'" class="submit">'.translate('Create Collection').'</a>' ));
886: }
887:
888: if ( $c->enable_row_linking ) {
889: $browser->RowFormat( '<tr onMouseover="LinkHref(this,1);" title="'.translate('Click to edit collection details').'" class="r%d">', '</tr>', '#even' );
890: }
891: else {
892: $browser->RowFormat( '<tr class="r%d">', '</tr>', '#even' );
893: }
894: $browser->DoQuery();
895: return $browser;
896: }
897:
898: function confirm_delete_collection($confirmation_hash) {
899: $html = '<table><tr><td class="error">';
900: $html .= sprintf('<b>%s</b> "%s" <a class="error" href="%s&%s">%s</a> %s',
901: translate('Deleting Collection:'), $_GET['dav_name'], $_SERVER['REQUEST_URI'],
902: $confirmation_hash,
903: translate('Confirm Deletion of the Collection'),
904: translate('All collection data will be unrecoverably deleted.') );
905: $html .= "</td></tr></table>\n";
906: return $html;
907: }
908:
909:
910: function binding_row_editor() {
911: global $c, $id, $editor, $can_write_principal;
912:
913: $bindingrow = new Editor("Bindings", "dav_binding");
914: $bindingrow->SetSubmitName( 'bindingrow' );
915: if ( $can_write_principal && $bindingrow->IsSubmit() ) {
916: if ( substr($_POST['dav_name'], -1) != '/' ) {
917: $_POST['dav_name'] .= '/';
918: }
919:
920: $dav_name = $_POST['dav_name'];
921: $parent = '/'.$editor->Value('username').'/';
922: if ( strpos($dav_name, $parent) !== 0 ) {
923: $c->messages[] = translate("Can only bind collections into the current principal's namespace");
924: return $bindingrow;
925: }
926: if ( substr_count($dav_name, '/') != 3 || substr_count($dav_name, '\\') > 0 ) {
927: $c->messages[] = translate("Bound As is invalid");
928: return $bindingrow;
929: }
930: $qry = new AwlQuery('SELECT dav_name FROM collection where dav_name = :dav_name UNION SELECT dav_name FROM dav_binding WHERE dav_name = :dav_name', array( ':dav_name' => $dav_name) );
931: if ( $qry->Exec('dav_name') && $qry->rows() > 0 ) {
932: $c->messages[] = translate('A resource already exists at the destination.');
933: return $bindingrow;
934: }
935:
936: if ( empty($_POST['access_ticket_id']) )
937: $_POST['access_ticket_id'] = null;
938: $_POST['dav_owner_id'] = $id;
939: $_POST['parent_container'] = $parent;
940:
941:
942: $href = $_POST['source'];
943: if ( preg_match ( '{^(?:https?://|file:///)([^/]+)(:[0-9]\+)?/.+$}', $href, $matches )
944: && strcasecmp( $matches[0], 'localhost' ) !== 0 && strcasecmp( $matches[0], '127.0.0.1' ) !== 0
945: && strcasecmp( $matches[0], $_SERVER['SERVER_NAME'] ) !== 0 && strcasecmp( $matches[0], $_SERVER['SERVER_ADDR'] ) !== 0
946: ) {
947: $path = '/.external/' . md5($href);
948: $qry->QDo('SELECT collection_id FROM collection WHERE dav_name = :dav_name ', array( ':dav_name' => $path ));
949: if ( $qry->rows() == 1 && ($row = $qry->Fetch()) ) {
950: $dav_id = $row->collection_id;
951: }
952: else {
953: $qry->QDo( 'INSERT INTO collection ( user_no, parent_container, dav_name, dav_etag, dav_displayname,
954: is_calendar, is_addressbook, resourcetypes, created )
955: VALUES( :user_no, :parent_container, :dav_name, :dav_etag, :dav_displayname,
956: :is_calendar, :is_addressbook, :resourcetypes, current_timestamp )',
957: array(
958: ':user_no' => $editor->Value('user_no'),
959: ':parent_container' => '/.external/',
960: ':dav_name' => $path,
961: ':dav_etag' => md5( $editor->Value('user_no') . $path ),
962: ':dav_displayname' => $_POST['dav_displayname'],
963: ':is_calendar' => 't',
964: ':is_addressbook' => 'f',
965: ':resourcetypes' => '<DAV::collection/><urn:ietf:params:xml:ns:caldav:calendar/>'
966: )
967: );
968:
969: $qry->QDo('SELECT collection_id FROM collection WHERE dav_name = :dav_name ', array( ':dav_name' => $path ));
970: if ( $qry->rows() != 1 || !($row = $qry->Fetch()) ) {
971: $c->messages[] = translate('Database Error');
972: return $bindingrow;
973: }
974: $dav_id = $row->collection_id;
975: }
976:
977: $_POST['bound_source_id'] = $dav_id;
978: $_POST['external_url'] = $href;
979: $_POST['external_type'] = 'calendar';
980: }
981: else {
982:
983: require_once('DAVResource.php');
984: $source = new DAVResource( $href );
985: if ( !$source->Exists() || $source->IsPrincipal() || !$source->IsCollection() || $source->dav_name() == '/' ) {
986: $c->messages[] = translate('The BIND Request MUST identify an existing resource.');
987: return $bindingrow;
988: }
989: if ( $source->IsBinding() )
990: $source = new DAVResource( $source->bound_from() );
991: $_POST['bound_source_id'] = $source->collection_id();
992: }
993:
994: $c->messages[] = 'Creating new binding for this principal';
995: $bindingrow->SetWhere( "dav_name = '$dav_name'" );
996: $bindingrow->Write();
997: }
998: return $bindingrow;
999: }
1000:
1001:
1002: function edit_binding_row( $row_data ) {
1003: global $id, $bindingrow;
1004:
1005: if ( isset($row_data->dav_name) ) {
1006: $bindingrow->Initialise( $row_data );
1007: }
1008:
1009: $form_id = $bindingrow->Id();
1010: $form_url = preg_replace( '#&(edit|delete)_[a-z]+=\d+#', '', $_SERVER['REQUEST_URI'] );
1011: $source_title = translate('Path to collection you wish to bind, like /user1/calendar/ or https://cal.example.com/user2/cal/');
1012: $access_title = translate('optional');
1013:
1014: $template = <<<EOTEMPLATE
1015: <form method="POST" enctype="multipart/form-data" id="form_$form_id" action="$form_url">
1016: <td class="left"> <input type="hidden" name="id" value="$id"></td>
1017: <td class="left"><input type="text" name="dav_name" value="$row_data->dav_name" size="25"></td>
1018: <td class="left"><input type="text" name="dav_displayname" size="20"></td>
1019: <td class="left"><input type="text" name="source" size="40" title="$source_title"></td>
1020: <td class="left"><input type="text" name="access_ticket_id" size="10" title="$access_title"></td>
1021: <td class="left"> </td>
1022: <td class="center">##submit##</td>
1023: </form>
1024: EOTEMPLATE;
1025:
1026: $bindingrow->SetTemplate( $template );
1027: $bindingrow->Title("");
1028:
1029: return $bindingrow->Render();
1030: }
1031:
1032:
1033: function bindings_to_other_browser() {
1034: global $c, $editor, $can_write_principal;
1035: $browser = new Browser(translate('Bindings to other collections'));
1036: $browser->AddColumn( 'bind_id', translate('ID'), '', '' );
1037: $browser->AddHidden( 'b.dav_owner_id' );
1038: $browser->AddHidden( 'p.principal_id' );
1039: $browser->AddColumn( 'bound_as', translate('Bound As'), '', '<td style="white-space:nowrap;">%s</td>', 'b.dav_name' );
1040: $browser->AddColumn( 'dav_displayname', translate('Display Name'), '', '', 'b.dav_displayname' );
1041: $browser->AddColumn( 'dav_name', translate('To Collection'), '', '<td style="white-space:nowrap;">%s</td>', 'c.dav_name' );
1042: $browser->AddColumn( 'access_ticket_id', translate('Ticket ID'), '', '' );
1043: $browser->AddColumn( 'privs', translate('Privileges'), '', '', "privileges_list(privileges)" );
1044: if ($can_write_principal) {
1045: $delurl = $c->base_url . sprintf('/admin.php?action=edit&t=principal&id=%s&bind_id=##bind_id##&subaction=delete_bind_in', $editor->Value('principal_id'));
1046: $browser->AddColumn( 'delete', translate('Action'), 'center', '', "'<a class=\"submit\" href=\"$delurl\">".translate('Delete')."</a>'" );
1047: }
1048:
1049: $browser->SetOrdering( 'bound_as', 'A' );
1050:
1051: $browser->SetJoins( 'dav_binding b LEFT JOIN collection c ON (bound_source_id=collection_id) LEFT JOIN access_ticket t ON (ticket_id=access_ticket_id) LEFT JOIN principal p USING(user_no)' );
1052: $browser->SetWhere( 'b.dav_name ~ '.sprintf("'^/%s/'", $editor->Value('username')) );
1053:
1054: $browser->RowFormat( '<tr class="r%d">', '</tr>', '#even' );
1055:
1056: $browser->DoQuery();
1057:
1058: if ( $can_write_principal ) {
1059: $extra_row = (object) array( 'bind_id' => -1,
1060: 'dav_name' => '/'.$editor->Value('username').'/boundcalendar/'
1061: );
1062: $browser->MatchedRow('bind_id', -1, 'edit_binding_row');
1063: $browser->AddRow($extra_row);
1064: }
1065: return $browser;
1066: }
1067:
1068: function confirm_delete_bind_in($confirmation_hash) {
1069: $html = '<table><tr><td class="error">';
1070: $html .= sprintf('<b>%s</b> "%s" <a class="error" href="%s&%s">%s</a> %s',
1071: translate('Deleting Binding:'), $_GET['bind_id'], $_SERVER['REQUEST_URI'],
1072: $confirmation_hash,
1073: translate('Confirm Deletion of the Binding'),
1074: translate('The binding will be deleted.') );
1075: $html .= "</td></tr></table>\n";
1076: return $html;
1077: }
1078:
1079:
1080: function bindings_to_us_browser() {
1081: global $c, $editor, $session;
1082: $browser = new Browser(translate('Bindings to this Principal\'s Collections'));
1083: $browser->AddColumn( 'bind_id', translate('ID'), '', '' );
1084: $browser->AddHidden( 'b.dav_owner_id' );
1085: $browser->AddHidden( 'p.principal_id' );
1086: $browser->AddColumn( 'dav_name', translate('Collection'), '', '<td style="white-space:nowrap;">%s</td>', 'c.dav_name' );
1087: $browser->AddColumn( 'bound_as', translate('Bound As'), '', '<td style="white-space:nowrap;">%s</td>', 'b.dav_name' );
1088: $browser->AddColumn( 'access_ticket_id', translate('Ticket ID'), '', '' );
1089: $browser->AddColumn( 'privs', translate('Privileges'), '', '', "privileges_list(privileges)" );
1090: if ( $session->AllowedTo('Admin') ) {
1091: $delurl = $c->base_url . '/admin.php?action=edit&t=principal&id=##principal_id##&bind_id=##bind_id##&subaction=delete_binding';
1092: $browser->AddColumn( 'delete', translate('Action'), 'center', '', "'<a class=\"submit\" href=\"$delurl\">".translate('Delete')."</a>'" );
1093: }
1094:
1095: $browser->SetOrdering( 'dav_name', 'A' );
1096:
1097: $browser->SetJoins( 'dav_binding b LEFT JOIN collection c ON (bound_source_id=collection_id) LEFT JOIN access_ticket t ON (ticket_id=access_ticket_id) LEFT JOIN principal p USING(user_no)' );
1098: $browser->SetWhere( 'p.principal_id = '.intval($editor->Value('principal_id')) );
1099:
1100: $browser->RowFormat( '<tr class="r%d">', '</tr>', '#even' );
1101:
1102: $browser->DoQuery();
1103: return $browser;
1104: }
1105:
1106: function confirm_delete_binding( $confirmation_hash ) {
1107: $html = '<table><tr><td class="error">';
1108: $html .= sprintf('<b>%s</b> "%s" <a class="error" href="%s&%s">%s</a> %s',
1109: translate('Deleting Binding:'), $_GET['bind_id'], $_SERVER['REQUEST_URI'],
1110: $confirmation_hash,
1111: translate('Confirm Deletion of the Binding'),
1112: translate('The binding will be deleted.') );
1113: $html .= "</td></tr></table>\n";
1114: return $html;
1115: }
1116:
1117:
1118: if ( isset($_GET['subaction']) ) {
1119: if ( handle_subaction($_GET['subaction']) && 'delete_principal' == $_GET['subaction'] ) {
1120: return true;
1121: }
1122: }
1123:
1124: $editor = principal_editor();
1125: $page_elements[] = $editor;
1126:
1127: if ( isset($id) && $id > 0 ) {
1128: $c->stylesheets[] = 'css/browse.css';
1129: $c->scripts[] = 'js/browse.js';
1130:
1131: if ( isset($delete_principal_confirmation_required) )
1132: $page_elements[] = confirm_delete_principal($delete_principal_confirmation_required, $editor->Value('displayname'));
1133:
1134:
1135: $page_elements[] = group_memberships_browser();
1136: if ( $editor->Value('type_id') == 3 ) {
1137: $grouprow = group_row_editor();
1138: $page_elements[] = group_members_browser();
1139: }
1140: $grantrow = grant_row_editor();
1141: $page_elements[] = principal_grants_browser();
1142: if ( isset($delete_grant_confirmation_required) ) $page_elements[] = confirm_delete_grant($delete_grant_confirmation_required);
1143:
1144: $ticketrow = ticket_row_editor();
1145: $page_elements[] = access_ticket_browser();
1146: if ( isset($delete_ticket_confirmation_required) ) $page_elements[] = confirm_delete_ticket($delete_ticket_confirmation_required);
1147:
1148: $page_elements[] = principal_collection_browser();
1149: if ( isset($delete_collection_confirmation_required) ) $page_elements[] = confirm_delete_collection($delete_collection_confirmation_required);
1150:
1151: $bindingrow = binding_row_editor();
1152: $page_elements[] = bindings_to_other_browser();
1153: if ( isset($delete_bind_in_confirmation_required) ) $page_elements[] = confirm_delete_bind_in($delete_bind_in_confirmation_required);
1154:
1155: $page_elements[] = bindings_to_us_browser();
1156: if ( isset($delete_binding_confirmation_required) ) $page_elements[] = confirm_delete_binding($delete_binding_confirmation_required);
1157: }
1158: