toteph42 / identy_switch

This plugin allows users to switch between different accounts (and check for new mails) in a single Roundcube session.
GNU General Public License v3.0
7 stars 4 forks source link

Argument #1 ($string) must be of type string, array given in identy_switch/identy_switch.php:174 #4

Closed HLFH closed 6 months ago

HLFH commented 6 months ago

When I am trying to enable the plugin (latest version).

[02-May-2024 21:50:22 Europe/Paris] PHP Fatal error:  Uncaught TypeError: substr(): Argument #1 ($string) must be of type string, array given in /srv/http/mail.example.com/plugins/identy_switch/identy_switch.php:174
Stack trace:
#0 /srv/http/mail.example.com/plugins/identy_switch/identy_switch.php(174): substr()
#1 /srv/http/mail.example.com/program/lib/Roundcube/rcube_plugin_api.php(520): identy_switch->on_render_page()
#2 /srv/http/mail.example.com/program/include/rcmail_output_html.php(828): rcube_plugin_api->exec_hook()
#3 /srv/http/mail.example.com/program/include/rcmail_output_html.php(654): rcmail_output_html->parse()
#4 /srv/http/mail.example.com/program/include/rcmail.php(296): rcmail_output_html->send()
#5 /srv/http/mail.example.com/index.php(278): rcmail->action_handler()
#6 {main}
  thrown in /srv/http/mail.example.com/plugins/identy_switch/identy_switch.php on line 174
HLFH commented 6 months ago

Here is the important part of my Roundcube conf:

// To specify different SMTP servers for different IMAP hosts provide an array
// of IMAP host (no prefix or port) and SMTP server e.g. ['imap.example.com' => 'smtp.example.net']
$config['smtp_host'] = [
    'imap.example.com' => 'ssl://smtp.example.com',
    'imap.example2.com' => 'ssl://smtp.example2.com',
    'imap.example3.com' => 'ssl://smtp.example3.com'
];
HLFH commented 6 months ago

You should fix your code with:

$hosts = $rc->config->get('smtp_host');

foreach ($hosts as $imap_host => $smtp_host) {
    $p = 0;
    if (substr($smtp_host, 3, 1) == ':') {
        self::set(-1, 'smtp_port', 465);
        self::set(-1, 'flags', self::get(-1, 'flags') | self::SMTP_IMAP);
        $smtp_host = substr($smtp_host, 6);
    } else {
        self::set(-1, 'smtp_port', 587);
    }

    if (($p = strpos($smtp_host, ':')) !== false) {
        self::set(-1, 'smtp_port', substr($smtp_host, $p + 1));
        self::set(-1, 'smtp_host', substr($smtp_host, 0, $p));
    } else {
        self::set(-1, 'smtp_host', $smtp_host);
    }

    $prefs = $rc->user->get_prefs();
}
HLFH commented 6 months ago

And fix this line 163:

          if ($_SESSION['storage_ssl'] == 'tsl')
HLFH commented 6 months ago

I believe SQL setup should be detailed. With mysql.initial, I have this error:

Erreur dans la requête (1005): Can't create table `roundcubemail`.`identy_switch` (errno: 121 "Duplicate key on write or update")
HLFH commented 6 months ago

I believe when I put ssl:// in the config, it means 465, so I don't need to precise it at the end again with :465

HLFH commented 6 months ago

Duplicate key on write or update

Fixed with:

DROP TABLE IF EXISTS ident_switch;
CREATE TABLE IF NOT EXISTS `identy_switch`(
    `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
    `user_id` INT(10) UNSIGNED NOT NULL,
    `iid` INT(10) UNSIGNED NOT NULL,
    `label` VARCHAR(32),
    `flags` INT NOT NULL DEFAULT 0,
    `imap_user` VARCHAR(64),
    `imap_pwd` VARCHAR(64),
    `imap_host` VARCHAR(64),
    `imap_port` SMALLINT DEFAULT 0,
    `imap_delim` CHAR(1),
    `newmail_check` SMALLINT DEFAULT 300,
    `notify_timeout` SMALLINT DEFAULT 10,
    `smtp_host` VARCHAR(64),
    `smtp_port` SMALLINT DEFAULT 0,
    `drafts` VARCHAR(64) DEFAULT '',
    `sent` VARCHAR(64) DEFAULT '',
    `junk` VARCHAR(64) DEFAULT '',
    `trash` VARCHAR(64) DEFAULT '',
    UNIQUE KEY `user_id_label`(`user_id`, `label`),
    CONSTRAINT `fk_user_id` FOREIGN KEY(`user_id`) REFERENCES `users`(`user_id`) ON DELETE CASCADE ON UPDATE CASCADE,
    CONSTRAINT `fk_identity_id` FOREIGN KEY(`iid`) REFERENCES `identities`(`identity_id`) ON DELETE CASCADE ON UPDATE CASCADE,
    PRIMARY KEY(`id`),
    INDEX `IX_identy_switch_user_id`(`user_id`),
    INDEX `IX_identy_switch_iid`(`iid`)
);
HLFH commented 6 months ago

@toteph42 PR is here: https://github.com/toteph42/identy_switch/pull/5

toteph42 commented 6 months ago

You should fix your code with:

$hosts = $rc->config->get('smtp_host');

foreach ($hosts as $imap_host => $smtp_host) {
    $p = 0;
    if (substr($smtp_host, 3, 1) == ':') {
        self::set(-1, 'smtp_port', 465);
        self::set(-1, 'flags', self::get(-1, 'flags') | self::SMTP_IMAP);
        $smtp_host = substr($smtp_host, 6);
    } else {
        self::set(-1, 'smtp_port', 587);
    }

    if (($p = strpos($smtp_host, ':')) !== false) {
        self::set(-1, 'smtp_port', substr($smtp_host, $p + 1));
        self::set(-1, 'smtp_host', substr($smtp_host, 0, $p));
    } else {
        self::set(-1, 'smtp_host', $smtp_host);
    }

    $prefs = $rc->user->get_prefs();
}

Thank you for your suggestion. I found another solution: A check needs to be added for which IMAP which SMTP should be used.

toteph42 commented 6 months ago

I believe when I put ssl:// in the config, it means 465, so I don't need to precise it at the end again with :465

Yes, you can use either ssl:// or specify the port

toteph42 commented 6 months ago

Dropping of ident_switch table is not part of this plugin. If you've installed ìdent_switch plugin, you should follow the rules to remove the plugin.

DROP TABLE IF EXISTS ident_switch;

I'm not responsible for the "old" plugin and will not add your suggestions. Instead I created a file migrate.sql which can be used to swap data and then delete "old" table.

toteph42 commented 6 months ago

Updates added by hand into 1.0.13 - Thank you very much for your suggestions!

And fix this line 163:

        if ($_SESSION['storage_ssl'] == 'tsl')

I added tlsand also to ident_switch_prefs.php

toteph42 commented 6 months ago

Thank you very much for your input. I'll apply some your changes to code in version 1.0.13.