Skip to content

Commit

Permalink
Better RC integration
Browse files Browse the repository at this point in the history
  • Loading branch information
jaudriga committed Apr 16, 2024
1 parent ea8d801 commit ab52b17
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 69 deletions.
92 changes: 42 additions & 50 deletions bridge.php
Original file line number Diff line number Diff line change
@@ -1,24 +1,18 @@
<?php
// Parts of this file are based on index.php (Roundcube version 1.4.8).
// TODO Reduce amount of duplicate code from index.php. We may be able to do that by:
// * removing authenticate hook logic using $_POST.
// * moving login logic to a function provided by base Roundcube
// Assuming we are inside RC's plugins/jmap dir
// TODO first change - we no loner use iniset.php
// TODO finish
define('RCUBE_ROOT', realpath('../../'));
#TODO remove define('INSTALL_PATH', RCUBE_ROOT . '/');
define('RCUBE_INSTALL_PATH', RCUBE_ROOT . '/');

// include environment
require_once __DIR__ . '/../../program/include/iniset.php';
// load the Roundcube framework with its autoloader
require_once RCUBE_ROOT . '/lib/Roundcube/bootstrap.php';
// TODO second change - use only rcube instead of RCMAIL
$RCMAIL = \rcmail::get_instance(\rcube::INIT_WITH_DB | \rcube::INIT_WITH_PLUGINS);

// init application, start session, init output class, etc.
$RCMAIL = rcmail::get_instance(0, $GLOBALS['env']);

/// Auth hack BEGIN
// TODO authenticate hook may actually be removed. Unclear if this is required for cPanel auth.
// Set some global POST vars that would be usually set via HTML <input> tags are:
// _task, _action, _timezone, _user, _pass, _token . We set all except for token.
// Token should only be required for an existing session. Also disregarding Timezone for now
$_POST['_user'] = $_SERVER['PHP_AUTH_USER'];
$_POST['_pass'] = $_SERVER['PHP_AUTH_PW'];
$_POST['_action'] = 'login';
$_POST['_task'] = 'login';
$user = $_SERVER['PHP_AUTH_USER'];
$pass = $_SERVER['PHP_AUTH_PW'];

/// Impersonation / admin auth BEGIN
// An array to store the admin user, as well the user-to-impersonate
Expand All @@ -28,41 +22,39 @@
// Check if we're dealing with admin auth credentials
// and if yes, then take the first part as the admin username
// to use for login
if (mb_strpos($_POST['_user'], "*")) {
$users = explode("*", $_POST['_user']);
$_POST['_user'] = $users[0];
if (mb_strpos($user, "*")) {
$users = explode("*", $user);
$user = $users[0];
}
/// Impersonation / admin auth END

/// Authenticate hook
// TODO authenticate hook may actually be removed. Unclear if this is required for cPanel auth.
$pass_charset = $RCMAIL->config->get('password_charset', 'UTF-8');

$auth = $RCMAIL->plugins->exec_hook('authenticate', array(
'host' => $RCMAIL->autoselect_host(),
'user' => trim(rcube_utils::get_input_value('_user', rcube_utils::INPUT_POST)),
'pass' => rcube_utils::get_input_value('_pass', rcube_utils::INPUT_POST, true, $pass_charset),
'user' => trim(rcube_utils::parse_input_value($_SERVER['PHP_AUTH_USER'])),
'pass' => rcube_utils::parse_input_value($_SERVER['PHP_AUTH_PW'], true, $pass_charset),
'valid' => true, // It is always valid in Karlsruhe!
'cookiecheck' => false, // No cookies for you in Karlsruhe!
));
/// Auth hack END

// Login
// TODO The following contains quite a lot of duplicate code from RC's index.php.
// It may be moved to an own function (except for returning errors via API)?
if (
$auth['valid'] && !$auth['abort']
&& $RCMAIL->login($auth['user'], $auth['pass'], $auth['host'], $auth['cookiecheck'])
) {
$logger->info("Successfully logged in as " . $auth['user']);

// log successful login
$RCMAIL->log_login();
} else {

// IMAP Login
$login_success = false;
if ($auth['valid'] && !$auth['abort']){
if($RCMAIL->login($auth['user'], $auth['pass'], $auth['host'], false, true)) {
$logger->info("Successfully logged in as " . $auth['user']);
// initialize user object to rcube framework. TODO might not work?
$RCMAIL->set_user($user);
$login_success = true;
}
}
if (!$auth['valid'] || $auth['abort'] || !$login_success){
if (!$auth['valid']) {
$error_code = rcmail::ERROR_INVALID_REQUEST;
} else {
$error_code = is_numeric($auth['error']) ? $auth['error'] : $RCMAIL->login_error();
}

$error_labels = array(
rcmail::ERROR_STORAGE => 'storageerror',
rcmail::ERROR_COOKIES_DISABLED => 'cookiesdisabled',
Expand All @@ -83,17 +75,17 @@
$loginError = null;

switch ($error_code) {
case rcmail::ERROR_RATE_LIMIT:
$loginError = 'urn:ietf:params:jmap:error:limit';
header('HTTP/1.0 429 Too Many Requests');
break;
case rcmail::ERROR_INVALID_REQUEST:
$loginError = 'urn:ietf:params:jmap:error:notRequest';
header('HTTP/1.0 400 Bad Request');
break;
default:
$loginError = '401 Unauthorized';
header('HTTP/1.0 401 Unauthorized');
case rcmail::ERROR_RATE_LIMIT:
$loginError = 'urn:ietf:params:jmap:error:limit';
header('HTTP/1.0 429 Too Many Requests');
break;
case rcmail:ERROR_INVALID_REQUEST:
$loginError = 'urn:ietf:params:jmap:error:notRequest';
header('HTTP/1.0 400 Bad Request');
break;
default:
$loginError = '401 Unauthorized';
header('HTTP/1.0 401 Unauthorized');
}

die($loginError);
Expand Down
20 changes: 1 addition & 19 deletions jmap.php
Original file line number Diff line number Diff line change
@@ -1,27 +1,9 @@
<?php

use OpenXPort\Jmap\Contact\ContactsAccountCapability;
use OpenXPort\Jmap\Core\CoreAccountCapability;
use OpenXPort\Jmap\Mail\SubmissionAccountCapability;
use OpenXPort\Util\RoundcubeSessionUtil;

// Define version
$oxpVersion = '1.4.0';

/**
* Fix for a refactoring bug (due to usage of bridge.php)
*
* The problem is that $_SERVER['SCRIPT_FILENAME'] is used for setting the include_path for Roundcube,
* but it references the currently executed script, which is jmap.php in our case.
* Since jmap.php is not positioned as a file on the same level as index.php,
* which is normally the running script, the include_path of Roundcube gets messed up.
* That's why we have to explicitly hack $_SERVER['SCRIPT_FILENAME'] so roundcube gets the correct
* include_path.
* For more info, see: https://github.com/roundcube/roundcubemail/blob/master/program/include/iniset.php
* (lines 27, 47 and 48)
*/

$_SERVER['SCRIPT_FILENAME'] = realpath(__DIR__ . '/../../index.php');
$oxpVersion = '1.4.1';

/* START OF OPENXPORT Code only */
// Use our composer autoload
Expand Down

0 comments on commit ab52b17

Please sign in to comment.