RoundCube 0.7.1 login failed

Note to readers: RoundCube 0.7.1 uses the Iloha IMAP Library. RoundCube 0.7.2 does not, so this particular problem may already be fixed.

In the past I’ve had to enable PLAIN IMAP authentication because older versions of M$ Outlook didn’t support CRAM-MD5 authentication. This means that my IMAP server advertises CRAM-MD5 as well as PLAIN as possible authentication methods.

All my clients who wanted to login using PLAIN cannot login using CRAM-MD5 because their passwords have to be stored in a different format.

A problem occurs when you set RoundCube’s “imap_auth_type” to “check”, because it picks CRAM-MD5 over PLAIN every time. I don’t want this to happen because some of my clients cannot login using CRAM-MD5. Ideally RoundCube should be following RFC3501:

If an AUTHENTICATE command fails with a NO response, the client MAY try another authentication mechanism by issuing another AUTHENTICATE command. It MAY also attempt to authenticate by using the LOGIN command

…but RoundCube doesn’t. To temporarily fix the problem you should be able to set “imap_auth_type” to “plain” so that RoundCube always uses PLAIN to authenticate against the IMAP server. However, I found that this does not work in 0.7.1 because of the following problem:

RoundCube passes options to the iil_Connect function of the Iloha IMAP Library. The options object includes a property “auth_method”, meant to control the authentication method, but this is never used, because the iil_Connect method expects this property to be named “imap”.

Line 382 of /program/include/rcmail.php is where the options object is defined – I simply changed ‘auth_method’ to ‘imap’.

The difference between using single quotes and double quotes as string delimiters in JavaScript/PHP

I like to keep all my string delimiters in languages such as PHP and JavaScript consistent. I consistently use single quotes for a couple of good reasons, so when I encounter someone else’s script that uses double quotes the OCD in me makes me change them all to single quotes…but that is a different problem.

If you’re coming from a language such as C# or Java then note that in PHP and JavaScript there is no such thing as a character datatype – as such, you can use either single or double quotes to delimit strings.

If I could only give you one reason why I consistently use single quotes then I would have to go with this:

If you ever (God forbid) need to write HTML in a string, you don’t need to escape the double quotes around attribute values. Instead of:

    "<div id=\"foo\" class=\"bar\">foobar</div>"

You write:

    '<div id="foo" class="bar">foobar</div>'

…which is lots less characters to type and I’d say more readable. Also, I more frequently use double quotes in my JavaScript/PHP strings than single quotes so it really does make sense.

The other reason is that if you use double quotes, PHP will actually parse the contents of the string to find variables and escape characters (\n, \r, \t etc.) which it’ll replace with the variable value or correct escape character respectively. So for example:

<?php

    $baz = 'bar';
    echo "foo\n$baz";

?>

Will print:

foo
bar

Whereas:

<?php

    $baz = 'bar';
    echo 'foo\n$baz';

?>

Will print:

foo\n$baz

So if you don’t need any of this functionality in your string, you’re making PHP do some extra work for no reason.

How to use CakePHP Session data in your Model validate rules

CakePHP models don’t allow you to access the session object. It is argued that this isn’t the MVC way. I tend to agree. Your controller should really pass any needed session data to the model…somehow.

My use case is that my model needs to validate that when a new user is created, it is given a “group” with equal or lesser privileges than the creator’s group.

Whilst they wouldn’t be able to use the create user form to do this (as the form only lists groups they can assign), we still need to guard against it on the server as it would be trivial to submit a specially crafted POST request with a group ID of a group with higher privileges.

My model needed to access the logged in user’s group ID from the Auth component (which stores its data in the session). So that when my model data was validated, I could check for a valid group ID, based on the group ID of the current user.

I knew I needed to make use of custom validation methods, but how could I get hold of the current user’s group ID? The Auth component isn’t available in the Model, so, what could I do?

Luckily, CakePHP’s AppModel defines a function called “validates”. Which allows you to check whether a model’s data is valid, but crucially it allows you to pass custom options to be made available in the “beforeValidate” callback.

So instead of simply saving my model data to the database, I call this function, passing my current user’s group ID and THEN call save (passing it a parameter to tell it not to bother validating the data again).

In my model, I overrode the “beforeValidate” callback function, which defines (on the fly) a new validation rule: a custom validation method, that takes the current user’s group ID as a parameter. My custom validation method can then check the model data against the current user’s group ID to see if it is valid. WIN.

Below I’ve included some example code to illustrate how this works. In this example I pass the whole Session object to the custom validation function. Which is slightly overkill. I think you should really just pass the data you need. Create a model that looks something like:

class MyModel extends AppModel {

    var $validate = array(
        // Your usual validation rules for all fields
    );

    function beforeValidate($options) {
        
        if(!empty($options) && isset($options['Session'])) {
            
            $this->validate['fieldName'] = array(
                'ruleName' = array(
                    'rule' => array('validationFunction', $options['Session'])
                )
                // + your default validation rule(s) for this field
            );
            
        } else {
            
            // Either...
            unset($this->validate['fieldName']);
            // If you have no normal rules for this field
            // Or...
            //$this->validate['fieldName'] = array(
                // Your default validation rule(s) for this field
            //);
        }
    }

    function validationFunction($check, $session) {
        
        // Do your checks with session data
        return true; // or false
    }
}

You use this in your controller like so:

class MyController extends AppController {

    var $uses = array('MyModel');
    var $components = array('Session');

    function action() {
		
        if(!empty($this->data)) {

            $this->MyModel->create($this->data['MyModel']);

            // Validate, passing custom options to be made available in the beforeValidate callback
            if($this->MyModel->validates(array('Session' => $this->Session)) === true) {

                // Save, without validation
                $this->MyModel->save(null, false);
            }
        }
    }
}

Implementation of HTTP Digest Authentication in PHP

So I could only find one other PHP based HTTP digest auth example on the internet…and it looked as though it might not even work. I wrote an abstract class as a base that allows you to easily build your own implementation.

You’d use it like so:

class MyAuth extends HTTPDigestAuth {
    // Implementation of abstract methods
}

$authenticator = new MyAuth();
$user = $authenticator->authenticate();

if(!$user) {
    die();
}

Continue reading