[imp] IMAP ACLs - a first stab [PATCH]

Chris Hastie lists at oak-wood.co.uk
Wed Jan 29 11:43:23 PST 2003


The attached files and patches represent my first stab at a way of 
managing Access Control Lists on IMAP servers that support RFC 2086.

The code here can only edit the ACL - it will not display the current 
ACL. That's on it's way, but in the absence of a PHP function to easily 
retrieve ACLs from the server it is a little clumsy.

If anyone knows of an easier way of retrieving an ACL than using 
fsockopen() to connect to the IMAP server I'd love to hear about it. 
Similarly, any better way of getting the server's capabilities than the 
getCapability() function in the attached imp/lib/Acl.php would be good.
-- 
Chris Hastie
-------------- next part --------------
<?php

/**
 * Contains functions related to managing
 * Access Control Lists on an IMAP server using RFC 2086.
 *
 * $Horde: imp/lib/Acl.php,v 1.00  $
 *
 * Copyright 2003 Chris Hastie <imp at oak-wood.co.uk>
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 *
 * @author  Chris Hastie <imp at oak-wood.co.uk>
 * @version $Revision: 1.1 $
 * @since   IMP 4.0
 * @package imp
 */


/**
 * Sets the ACL on an IMAP server
 *
 * @access public
 *
 * @param string $folder  The folder on which to edit the ACL
 *                           
 * @param string $share_user  The user to grant rights to
 *
 * @param array $acl  An array, the keys of which are the 
 *                    rights to be granted (see RFC 2086)
 *
 * @return mixed  True on success, false on failure unless
 *                server doesn't support ACLs, returns 'no_acl'
 */

function setAcl($folder, $share_user, $acl) {

    global $imp, $notification;
    $acl_str = '';
    
    if (!empty($acl)) {
        foreach ($acl as $key => $val) {
            $acl_str .= $key;
        }
    }
    $result = imap_setacl($imp['stream'], $folder, $share_user, $acl_str);
    
    if (!$result) {
        $errors = @imap_errors();
        foreach ($errors as $err) {
            if ($err == "ACL not available on this IMAP server"){
                $err = _("This IMAP server does not support sharing folders.");
                $result = 'no_acl';
            }
            $notification->push($err, 'horde.error');
        }
    } else {
        $notification->push(_("User")." ".$share_user." "._("successfully given the following rights for the folder ").$folder.": ".$acl_str , 'horde.success');
    }

    return $result;

}

/**
 * Attempts to get the result of a CAPABILITY command to 
 * the current IMAP server. If protocol is imap/ssl, will
 * only attempt ssl connection with PHP >= 4.3
 *
 * @access public
 *
 * @return array  An array containing the server's capabilities
 
 */
 
function getCapability() {
    global $notification;
    $capabilities = null;
    $sub_proto = null;
    
    if (($pos = strpos($_SESSION['imp']['protocol'], '/'))) {
        $sub_proto = substr($_SESSION['imp']['protocol'], $pos+1);
    }  
    
    $server = $_SESSION['imp']['server'];
    
    if ($sub_proto == "ssl") {
        if (version_compare( phpversion(), "4.3.0") >= 0 ){
            $server = $sub_proto."://".$server;
        } else {
            $notification->push(_("Could not retrieve server's capabilities"),'horde.warn');
            return null;
        }
    }
         
    $imap = fsockopen($server, $_SESSION['imp']['port'], $errno, $errstr, 30);

    if (!$imap) {
        $notification->push(_("Could not retrieve server's capabilities"),'horde.warn');
        return null;
    } else {
        $response = fgets($imap, 4096);
        if (preg_match("/^\*\sOK/", $response)) {
            fputs($imap, "x CAPABILITY\r\n");            
            $response =  trim(fgets ($imap,1024));
            if (preg_match("/^\*\sCAPABILITY/", $response)) {
                $response_array = explode(" ", $response);
                foreach ($response_array as $var){
                    if (preg_match("/=/", $var)) {
                        $var2 = explode("=", $var, 2);
                        $capabilities[strtolower($var2[0])][strtolower($var2[1])]=1;
                    } else {
                        $capabilities[strtolower($var)] = 1;
                    }
                }
               
            } else {
                $notification->push(_("Could not retrieve server's capabilities"),'horde.warn');
            }
        } else {
            $notification->push(_("Could not retrieve server's capabilities"),'horde.warn');
        }
        fclose ($imap);
    }   
    return $capabilities;
}
-------------- next part --------------
<?php
/**
 * $Horde: imp/acl.php,v 1.1 $
 *
 * Copyright 2000-2003 Chris Hastie <imp at oak-wood.co.uk>
 *
 * See the enclosed file COPYING for license information (GPL).  If you
 * did not receive this file, see http://www.fsf.org/copyleft/gpl.html.
 */
define('IMP_BASE', dirname(__FILE__));
$authentication = OP_HALFOPEN;
require_once IMP_BASE . '/lib/base.php';
require_once IMP_BASE . '/lib/Acl.php';
require_once IMP_BASE . '/lib/Folder.php';

/* Redirect back to the options screen if acl is not
   allowed. */
if ($prefs->isLocked('acl')) {
    $notification->push(_("Folder sharing is disabled"), 'horde.error');
    header('Location: ' . Horde::applicationUrl('prefs.php', true));
    exit;
}

/* Check the capability of the server. Redirect to options screen with error
   message if it doesn't support ACLs */
$cap = getCapability();
if (!empty($cap) && !array_key_exists('acl', $cap)){
    $notification->push(_("This IMAP server does not support sharing folders."), 'horde.error');
    header('Location: ' . Horde::applicationUrl('prefs.php', true));
    exit;
}

$is_imap = false;

/* Don't bother if it's not an IMAP server */
if ($_SESSION['imp']['base_protocol'] == 'imap') {
    $is_imap = true;
    
    /* Run through the action handlers */
    $actionID = Horde::getFormData('actionID');
    switch ($actionID) {

    case IMP_ACL_SET:
        $ok_form = true;
        $acl = Horde::getFormData('acl');
        if(!($share_user = Horde::getFormData('share_user'))) {
            $notification->push(_("No user specified"), 'horde.error');   
            $ok_form = false;
        }
        if(!($folder = Horde::getFormData('folder'))) {
            $notification->push(_("No folder selected"), 'horde.error');   
            $ok_form = false;
        }
        if($share_user == $_SESSION['imp']['user']) {
            $notification->push(_("Changing your own permissions is not allowed"), 'horde.error');   
            $ok_form = false;
        }       
        if ($ok_form){
            $result = setAcl($folder, $share_user, $acl);
            if ($result == "no_acl") {
                header('Location: ' . Horde::applicationUrl('prefs.php', true));
                exit;            
            }
        }
        break;
    

    }
    $imp_folder = &IMP_Folder::singleton();
    
    if (count($imp_folder->flist_IMP())) {
        $options = IMP::flistSelect(_("select folder"), true);
    }

} else {
    $notification->push( _("Folder sharing is only available with IMAP servers"), 'horde.error');
}

$title = _("Share Folders");
$js_onLoad = null;
require IMP_TEMPLATES . '/common-header.inc';
require IMP_BASE . '/menu.php';
require IMP_BASE . '/status.php';


if ($is_imap) {
    require IMP_TEMPLATES . '/acl/manage.inc';
}
require IMP_TEMPLATES . '/common-footer.inc';
-------------- next part --------------
<form method="post" name="acl" action="<?php echo Horde::applicationUrl('acl.php') ?>">
<input type="hidden" name="actionID" value="<?php echo IMP_ACL_SET ?>" />

<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
    <td colspan="2"  class="header" ><?php echo _("Share mail folders") ?></td>
</tr>

<tr>
<td colspan="2" class="header" ><?php echo _("Folder to share") ?></td>
</tr>

<tr>
<td colspan="2"><select name="folder" ><?php echo $options ?></select></td>
</tr>


<tr>
    <td colspan="2" class="header" ><?php echo _("User to grant access to") ?></td>
</tr>

<tr>
    <td colspan="2"><input class="fixed" type="text" name="share_user" /></td>
</tr>

<tr>
    <td colspan="2" class="header" ><?php echo _("Permissions") ?></td>
</tr>

<tr>
<td><input type="checkbox" name="acl[l]" /></td>
<td><?php echo _("Visible - user can see the folder") ?> (l)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[r]" /></td>
<td><?php echo _("Read messages") ?> (r)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[s]" /></td>
<td><?php echo _("Mark with seen / unseen flags") ?> (s)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[w]" /></td>
<td><?php echo _("Mark with other flags (eg Important / Answered)") ?> (w)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[i]" /></td>
<td><?php echo _("Insert messages") ?> (i)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[p]" /></td>
<td><?php echo _("Post to this address (not enforced by IMAP)") ?> (p)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[c]" /></td>
<td><?php echo _("Create sub folders") ?> (c)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[d]" /></td>
<td><?php echo _("Delete and purge messages") ?> (d)</td>
</tr>

<tr>
<td><input type="checkbox" name="acl[a]" /></td>
<td><?php echo _("Administer - set permissions for other users") ?> (a)</td>
</tr>


<tr>
    
    <td class="header" colspan = "2" valign="middle">
        <input type="button" class="button" name="fbutton" onclick="document.acl.submit();" value="<?php echo _("Create") ?>" />
        <input type="button" class="button" onclick="document.acl.reset()" value="<?php echo _("Reset") ?>" />
        <input type="button" class="button" name="back" onclick="document.location.href='<?php echo Horde::applicationUrl('prefs.php', true) ?>'" value="<?php echo _("Return to Options") ?>" />
    </td>
    
</tr>

<table>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: shared.gif
Type: image/gif
Size: 183 bytes
Desc: imp/graphics/shared.gif
Url : http://lists.horde.org/archives/imp/attachments/20030129/7b267906/shared-0001.gif
-------------- next part --------------
--- imp/lib/constants.php,v 1.24
+++ imp/lib/constants.php	Wed Jan 29 11:13:26 2003
@@ -83,6 +83,7 @@
 /** @const SMIME_ENCRYPT Send Message - S/MIME Encrypt */ define('SMIME_ENCRYPT', 174);
 /** @const SMIME_SIGN Send Message - S/MIME Sign       */ define('SMIME_SIGN', 175);
 /** @const SMIME_SIGNENC Send Message - S/MIME Sign/Enc*/ define('SMIME_SIGNENC', 176);
+/** @const IMP_ACL_SET Set IMAP access control list    */ define('IMP_ACL_SET', 177);
 
 // IMAP Flags
 /** @const IMP_ALL Match all IMAP flags.      */ define('IMP_ALL', 0);
-------------- next part --------------
--- imp/config/prefs.php.dist,v 1.140
+++ imp/config/prefs.php	Tue Jan 28 10:18:46 2003
@@ -87,6 +87,14 @@
     'desc' => _("Customize accounts for fetching mail from other POP3/IMAP accounts."),
     'members' => array('fetchmail_link', 'fetchmail_popup', 'fetchmail_menu'));
 
+if (!empty($_SESSION['imp']['base_protocol']) && $_SESSION['imp']['base_protocol'] == 'imap') {
+    $prefGroups['acl'] = array(
+        'column' => _("Mail Management"),
+        'label' => _("Share Folders"),
+        'desc' => _("Share you mail folders with other users."),
+        'members' => array('acl_link'));
+}
+
 $prefGroups['display'] = array(
     'column' => _("Other Options"),
     'label' => _("Display Options"),
@@ -392,7 +400,23 @@
     'type' => 'implicit');
 
 // End Filter preferences
+// Folder sharing preferences
+
+$_prefs['acl_link'] = array(
+    'type' => 'link',
+    'url' => 'acl.php',
+    'img' => 'shared.gif',
+    'desc' => _("Edit folder sharing"));
+    
+// folder sharing options
+// set 'locked' => true to disable folder sharing
+$_prefs['acl'] = array(
+    'value' => '',
+    'locked' => false,
+    'shared' => false,
+    'type' => 'implicit');    
 
+// End folder sharing preferences
 
 // Message Viewing preferences
 


More information about the imp mailing list