diff --git a/modules/nux/assets/data/server_accounts_sample.csv b/modules/nux/assets/data/server_accounts_sample.csv index b2739367a5..2678167e56 100644 --- a/modules/nux/assets/data/server_accounts_sample.csv +++ b/modules/nux/assets/data/server_accounts_sample.csv @@ -1,2 +1,2 @@ -server_name;support_jmap;jmap_server;username;password;imap_port;imap_tls;imap_server;support_smtp;smtp_server;smtp_port;smtp_tls;sieve_host;sieve_port -Exemple;FALSE;;email@exemple.org;secret;993;TRUE;imap.exemple.org;TRUE;smtp.exemple.org;465;TRUE;tls://imap.exemple.org;4190 \ No newline at end of file +server_name;support_jmap;jmap_server;username;password;imap_port;imap_tls;imap_server;smtp_server;smtp_port;smtp_tls;sieve_host;sieve_port +Exemple;FALSE;;email@exemple.org;secret;993;TRUE;imap.exemple.org;smtp.exemple.org;465;TRUE;tls://imap.exemple.org;4190 \ No newline at end of file diff --git a/modules/nux/assets/data/server_accounts_sample.yaml b/modules/nux/assets/data/server_accounts_sample.yaml index 5ce2c406f1..0c81738064 100644 --- a/modules/nux/assets/data/server_accounts_sample.yaml +++ b/modules/nux/assets/data/server_accounts_sample.yaml @@ -9,7 +9,6 @@ Test1: tls: true imap_server: imap.example.org smtp: - support_smtp: true smtp_server: smtp.example.org smtp_port: 465 smtp_tls: true @@ -27,7 +26,6 @@ Test2: tls: true imap_server: mail.example.org smtp: - support_smtp: true smtp_server: mail.example.org smtp_port: 465 smtp_tls: true diff --git a/modules/nux/functions.php b/modules/nux/functions.php new file mode 100644 index 0000000000..ed9d747e8c --- /dev/null +++ b/modules/nux/functions.php @@ -0,0 +1,120 @@ +setFlags(SplFileObject::DROP_NEW_LINE); + + // Initialize an array to hold the rows + $rows = []; + $is_first_line = true; + $header = []; + // Loop through each line in the CSV file + while (!$file->eof()) { + // Get the line as a string + $line = $file->fgets(); + + // Skip empty lines (e.g., due to trailing newlines) + if ($line === [null] || $line === false) { + continue; + } + + // Split the line into an array using the specified delimiter + $fields = explode($delimiter, $line); + // Process the header line + if ($is_first_line) { + $header = $fields; + $is_first_line = false; + } else { + // Ensure that the number of fields matches the header count + if (count($fields) === count($header)) { + // Combine the header and fields into an associative array + $rows[] = array_combine($header, $fields); + } + } + } + return $rows; +}} + +/** + * @subpackage nux/functions + */ +if (!hm_exists('oauth2_form')) { + function oauth2_form($details, $mod) + { + $oauth2 = new Hm_Oauth2($details['client_id'], $details['client_secret'], $details['redirect_uri']); + $url = $oauth2->request_authorization_url($details['auth_uri'], $details['scope'], 'nux_authorization', $details['email']); + $res = ''; + $res .= '
' . $mod->html_safe($details['name']) . '
'; + $res .= $mod->trans('This provider supports Oauth2 access to your account.'); + $res .= $mod->trans(' This is the most secure way to access your E-mail. Click "Enable" to be redirected to the provider site to allow access.'); + $res .= '
' . $mod->trans('Enable') . ''; + $res .= 'Reset
'; + return $res; + } +} + +/** + * @subpackage nux/functions + */ +if (!hm_exists('credentials_form')) { + function credentials_form($details, $mod) + { + $res = ''; + $res .= ''; + $res .= '
' . $mod->html_safe($details['name']) . '
'; + $res .= $mod->trans('Enter your password for this E-mail provider to complete the connection process'); + + $res .= '
'; + // E-mail Address Field + $res .= '
'; + $res .= ''; + $res .= '
'; + + // E-mail Password Field + $res .= '
'; + $res .= ''; + $res .= '
'; + + // Connect Button + $res .= ''; + + // Reset Link + $res .= 'Reset'; + + $res .= '
'; + + return $res; + } +} + +/** + * @subpackage nux/functions + */ +if (!hm_exists('data_source_available')) { + function data_source_available($mods, $types) + { + if (!is_array($types)) { + $types = array($types); + } + return count(array_intersect($types, $mods)) == count($types); + } +} diff --git a/modules/nux/modules.php b/modules/nux/modules.php index 5a13e86749..c9f7f92004 100644 --- a/modules/nux/modules.php +++ b/modules/nux/modules.php @@ -1,6 +1,4 @@ commit->message); $res[] = array( 'hash' => $c->sha, @@ -63,10 +60,8 @@ public function process() { /** * @subpackage nux/handler */ -class Hm_Handler_nux_homepage_data extends Hm_Handler_Module -{ - public function process() - { +class Hm_Handler_nux_homepage_data extends Hm_Handler_Module { + public function process() { $imap_servers = NULL; $smtp_servers = NULL; @@ -101,10 +96,8 @@ public function process() /** * @subpackage nux/handler */ -class Hm_Handler_process_oauth2_authorization extends Hm_Handler_Module -{ - public function process() - { +class Hm_Handler_process_oauth2_authorization extends Hm_Handler_Module { + public function process() { if (array_key_exists('state', $this->request->get) && $this->request->get['state'] == 'nux_authorization') { if (array_key_exists('code', $this->request->get)) { $details = $this->session->get('nux_add_service_details'); @@ -142,15 +135,19 @@ public function process() $this->session->record_unsaved('IMAP server added'); $this->session->secure_cookie($this->request, 'hm_reload_folders', '1'); $this->session->close_early(); - } else { + } + else { Hm_Msgs::add('ERRAn Error Occurred'); } - } elseif (array_key_exists('error', $this->request->get)) { + } + elseif (array_key_exists('error', $this->request->get)) { Hm_Msgs::add('ERR' . ucwords(str_replace('_', ' ', $this->request->get['error']))); - } else { + } + else { Hm_Msgs::add('ERRAn Error Occurred'); } $this->save_hm_msgs(); + Hm_Dispatch::page_redirect('?page=servers'); } } } @@ -158,18 +155,16 @@ public function process() /** * @subpackage nux/handler */ -class Hm_Handler_process_nux_add_service extends Hm_Handler_Module -{ - public function process() - { +class Hm_Handler_process_nux_add_service extends Hm_Handler_Module { + public function process() { list($success, $form) = $this->process_form(array('nux_pass', 'nux_service', 'nux_email', 'nux_name')); if ($success) { if (Nux_Quick_Services::exists($form['nux_service'])) { $details = Nux_Quick_Services::details($form['nux_service']); $details['name'] = $form['nux_name']; if ($form['nux_service'] == 'all-inkl') { - $details['server'] = $this->request->post['nux_all_inkl_login'] . $details['server']; - $details['smtp']['server'] = $this->request->post['nux_all_inkl_login'] . $details['smtp']['server']; + $details['server'] = $this->request->post['nux_all_inkl_login'].$details['server']; + $details['smtp']['server'] = $this->request->post['nux_all_inkl_login'].$details['smtp']['server'] ; } $imap_list = array( 'name' => $details['name'], @@ -180,7 +175,7 @@ public function process() 'pass' => $form['nux_pass'], ); if ($details['sieve'] && $this->module_is_supported('sievefilters') && $this->user_config->get('enable_sieve_filter_setting', true)) { - $imap_list['sieve_config_host'] = $details['sieve']['host'] . ':' . $details['sieve']['port']; + $imap_list['sieve_config_host'] = $details['sieve']['host'].':'.$details['sieve']['port']; } $new_id = Hm_IMAP_List::add($imap_list); if (! can_save_last_added_server('Hm_IMAP_List', $form['nux_email'])) { @@ -209,8 +204,10 @@ public function process() $this->save_hm_msgs(); $this->session->close_early(); $this->out('nux_account_added', true); - $this->out('nux_server_id', $new_id); - $this->out('nux_service_name', $form['nux_service']); + if ($this->module_is_supported('imap_folders')) { + $this->out('nux_server_id', $new_id); + $this->out('nux_service_name', $form['nux_service']); + } } else { Hm_IMAP_List::del($new_id); Hm_Msgs::add('ERRAuthentication failed'); @@ -223,10 +220,8 @@ public function process() /** * @subpackage nux/handler */ -class Hm_Handler_setup_nux extends Hm_Handler_Module -{ - public function process() - { +class Hm_Handler_setup_nux extends Hm_Handler_Module { + public function process() { Nux_Quick_Services::oauth2_setup($this->config); } } @@ -234,10 +229,8 @@ public function process() /** * @subpackage nux/handler */ -class Hm_Handler_process_nux_service extends Hm_Handler_Module -{ - public function process() - { +class Hm_Handler_process_nux_service extends Hm_Handler_Module { + public function process() { list($success, $form) = $this->process_form(array('nux_service', 'nux_email')); if ($success) { if (Nux_Quick_Services::exists($form['nux_service'])) { @@ -281,166 +274,176 @@ public function process() list($success, $form) = $this->process_form(array('accounts_source')); if ($success) { - $file = $this->request->files['accounts_sample']; - if (!is_null($file) && $file['type'] == 'application/x-yaml') { + if (!is_array($this->request->files) || !array_key_exists('accounts_sample', $this->request->files)) { + return; + } + if (!is_array($this->request->files['accounts_sample']) || !array_key_exists('tmp_name', $this->request->files['accounts_sample'])) { + return; + } + + if ($this->request->files['accounts_sample']['type'] == 'application/x-yaml') { try { - $servers = Yaml::parseFile($file['tmp_name']); + $servers = Yaml::parseFile($this->request->files['accounts_sample']['tmp_name']); + foreach ($servers as $key => $value) { + if (empty($value['user']['username']) or empty($value['user']['password'])) { + Hm_Msgs::add('ERRUsername and password are required for: ' . $key . ' server'); + return; + } + if ($value['jmap'] && !empty($value['jmap']['jmap_server'])) { + if (!$this->module_is_supported('jmap')) { + Hm_Msgs::add("ERRJMAP module is not enabled"); + return; + } + $jmap_server_id = connect_to_imap_server( + $value['jmap']['jmap_server'], + $key, + null, + $value['user']['username'], + $value['user']['password'], + false, + null, + false, + 'jmap', + $this, + false + ); + Hm_Msgs::add("JMAP Server " . $key . " saved"); + } + if ($value['smtp'] && !empty($value['smtp']['smtp_server'])) { + // Check if module is supported + if (!$this->module_is_supported('smtp')) { + Hm_Msgs::add("ERRSMTP module is not enabled"); + } else { + //TO DO: check first if the smtp_server server is already configured before connecting. can use the in_server_list function or create a new one specifically for my case + $smtp_server_id = connect_to_smtp_server( + $value['smtp']['smtp_server'], + $key, + $value['smtp']['smtp_port'], + $value['user']['username'], + $value['user']['password'], + $value['smtp']['smtp_tls'], + false + ); + Hm_Msgs::add("SMTP Server " . $key . " saved"); + } + } + + if ($value['imap'] && !empty($value['imap']['imap_server'])) { + // Check if module is supported + if (!$this->module_is_supported('imap')) { + Hm_Msgs::add("ERRIMAP module is not enabled"); + return; + } + //TO DO: check first if the imap_server server is already configured before connecting can use the in_server_list function or create a new one specifically for my case + $imap_server_id = connect_to_imap_server( + $value['imap']['imap_server'], + $key, + $value['imap']['port'], + $value['user']['username'], + $value['user']['password'], + $value['imap']['tls'], + $value['sieve']['sieve_host'].':'.$value['sieve']['sieve_port'], + !empty($value['sieve']['sieve_port']) && !empty($value['sieve']['sieve_host']) ? true : false, + 'imap', + $this + ); + Hm_Msgs::add("Server " . $key . " saved"); + } + + // Verify connection requirements + if (($jmap_server_id === null && $imap_server_id === null) || $smtp_server_id === null) { + if ($jmap_server_id !== null) { + Hm_IMAP_List::del($jmap_server_id); + } + if ($imap_server_id !== null) { + Hm_IMAP_List::del($imap_server_id); + } + if ($smtp_server_id !== null) { + Hm_SMTP_List::del($smtp_server_id); + } + } + } } catch (\Throwable $th) { Hm_Msgs::add('ERR' . $th->getMessage()); - $this->save_hm_msgs(); - Hm_Dispatch::page_redirect('?page=servers'); } - foreach ($servers as $key => $value) { - if (empty($value['user']['username']) or empty($value['user']['password'])) { - Hm_Msgs::add('ERRUsername and password are required for: ' . $key . ' server'); - return; - } - if ($value['jmap'] && !empty($value['jmap']['jmap_server'])) { + }elseif($this->request->files['accounts_sample']['type'] == 'text/csv'){ + try { + $server_data = parse_csv_with_headers($this->request->files['accounts_sample']['tmp_name']); + if ($server_data['jmap_server'] && !empty($server_data['jmap_server'])) { if (!$this->module_is_supported('jmap')) { Hm_Msgs::add("ERRJMAP module is not enabled"); - return; + }else { + $jmap_server_id = connect_to_imap_server( + $server_data['jmap_server'], + $server_data['server_name'], + null, + $server_data['username'], + $server_data['password'], + false, + null, + false, + 'jmap', + $this, + false + ); + if ($jmap_server_id !== null) { + Hm_Msgs::add("JMAP Server " . $server_data['server_name'] . " saved"); + } + } + }elseif($server_data['imap_server'] && !empty($server_data['imap_server'])) { + if (!$this->module_is_supported('imap')) { + Hm_Msgs::add("ERRIMAP module is not enabled"); + }else { + $imap_server_id = connect_to_imap_server( + $server_data['imap_server'], + $server_data['server_name'], + $server_data['imap_port'], + $server_data['username'], + $server_data['password'], + $server_data['imap_tls'] === "TRUE", + $server_data['sieve_host'].':'.$server_data['sieve_port'], + !empty($server_data['sieve_port']) && !empty($server_data['sieve_host']) ? true : false, + 'imap', + $this + ); + if ($imap_server_id !== null) { + Hm_Msgs::add("Server " . $server_data['server_name'] . " saved"); + } } - connect_to_imap_server( - $value['jmap']['jmap_server'], - $key, - null, - $value['user']['username'], - $value['user']['password'], - false, - null, - false, - 'jmap', - $this, - false - ); - Hm_Msgs::add("JMAP Server " . $key . " saved"); } - if ($value['smtp'] && !empty($value['smtp']['smtp_server'])) { - // Check if module is supported + if ($server_data['smtp_server'] && !empty($server_data['smtp_server'])) { if (!$this->module_is_supported('smtp')) { Hm_Msgs::add("ERRSMTP module is not enabled"); } else { - //TO DO: check first if the smtp_server server is already configured before connecting. can use the in_server_list function or create a new one specifically for my case $smtp_server_id = connect_to_smtp_server( - $value['smtp']['smtp_server'], - $key, - $value['smtp']['smtp_port'], - $value['user']['username'], - $value['user']['password'], - $value['smtp']['smtp_tls'], + $server_data['smtp_server'], + $server_data['server_name'], + $server_data['smtp_port'], + $server_data['username'], + $server_data['password'], + $server_data['smtp_tls'] === "TRUE", false ); - Hm_Msgs::add("SMTP Server " . $key . " saved"); + if ($smtp_server_id !== null) { + Hm_Msgs::add("SMTP Server " . $server_data['server_name'] . " saved"); + } } } - if ($value['imap'] && !empty($value['imap']['imap_server'])) { - // Check if module is supported - if (!$this->module_is_supported('imap')) { - Hm_Msgs::add("ERRIMAP module is not enabled"); - return; + // Verify connection requirements + if (($jmap_server_id === null && $imap_server_id === null) || $smtp_server_id === null) { + if ($jmap_server_id !== null) { + Hm_IMAP_List::del($jmap_server_id); } - //TO DO: check first if the imap_server server is already configured before connecting can use the in_server_list function or create a new one specifically for my case - $imap_server_id = connect_to_imap_server( - $value['imap']['imap_server'], - $key, - $value['imap']['port'], - $value['user']['username'], - $value['user']['password'], - $value['imap']['tls'], - $value['sieve']['sieve_host'], - $value['sieve']['sieve_port'], - 'imap', - $this - ); - Hm_Msgs::add("Server " . $key . " saved"); - } - } - - $this->save_hm_msgs(); - }elseif(!is_null($file) && $file['type'] == 'text/csv'){ - try { - $file = new SplFileObject($file['tmp_name']); - // Set the file to read as CSV - $file->setFlags(SplFileObject::READ_CSV); - $is_first_line = true; - // Loop through each line in the CSV file - while (!$file->eof()) { - $line = $file->fgetcsv(); - // Skip processing if it's the first line - if ($is_first_line) { - $is_first_line = false; - continue; + if ($imap_server_id !== null) { + Hm_IMAP_List::del($imap_server_id); } - // Check if line is not empty to avoid processing false empty line - if ($line && !empty(array_filter($line))) { - // Process the CSV line here - $server_data = explode(';', $line[0]); - //check jmap support and jmap host address data - if ($server_data[1] && !empty($server_data[2])) { - if (!$this->module_is_supported('jmap')) { - Hm_Msgs::add("ERRJMAP module is not enabled"); - }else { - connect_to_imap_server( - $server_data[2], - $server_data[0], - null, - $server_data[3], - $server_data[4], - false, - null, - false, - 'jmap', - $this, - false - ); - Hm_Msgs::add("JMAP Server " . $server_data[0] . " saved"); - } - } - //check stmp support and stmp host address data - if ($server_data[8] && !empty($server_data[9])) { - if (!$this->module_is_supported('smtp')) { - Hm_Msgs::add("ERRSMTP module is not enabled"); - } else { - $smtp_server_id = connect_to_smtp_server( - $server_data[9], - $server_data[0], - $server_data[10], - $server_data[3], - $server_data[4], - $server_data[11], - false - ); - Hm_Msgs::add("SMTP Server " . $server_data[0] . " saved"); - } - } - //check imap support and stmp host address data - if ($server_data[6] && !empty($server_data[7])) { - if (!$this->module_is_supported('imap')) { - Hm_Msgs::add("ERRIMAP module is not enabled"); - }else { - $imap_server_id = connect_to_imap_server( - $server_data[7], - $server_data[0], - $server_data[5], - $server_data[3], - $server_data[4], - $server_data[6], - $server_data[12], - $server_data[13], - 'imap', - $this - ); - Hm_Msgs::add("Server " . $server_data[0] . " saved"); - } - } + if ($smtp_server_id !== null) { + Hm_SMTP_List::del($smtp_server_id); } - } - $this->save_hm_msgs(); - + } } catch (\Exception $ex) { Hm_Msgs::add('ERR' . $ex->getMessage()); - $this->save_hm_msgs(); } } } @@ -451,31 +454,29 @@ public function process() /** * @subpackage nux/output */ -class Hm_Output_quick_add_dialog extends Hm_Output_Module -{ - protected function output() - { +class Hm_Output_quick_add_dialog extends Hm_Output_Module { + protected function output() { if ($this->get('single_server_mode')) { return ''; } - return '
' . - '
' . - '

' . $this->trans('Quickly add an account from popular E-mail providers. To manually configure an account, use the IMAP/SMTP sections below.') . '

' . - '
' . - ' ' . - '
' . - - '
' . - '' . - '
' . - - '
' . - '' . - '
' . - - '' . + return '
'. + '
'. + '

'.$this->trans('Quickly add an account from popular E-mail providers. To manually configure an account, use the IMAP/SMTP sections below.').'

'. + '
'. + ' '. + '
'. + + '
'. + ''. + '
'. + + '
'. + ''. + '
'. + + ''. '
'; } } @@ -483,10 +484,8 @@ protected function output() /** * @subpackage nux/output */ -class Hm_Output_quick_add_multiple_dialog extends Hm_Output_Module -{ - protected function output() - { +class Hm_Output_quick_add_multiple_dialog extends Hm_Output_Module { + protected function output() { if ($this->get('single_server_mode')) { return ''; } @@ -528,7 +527,8 @@ protected function output() if (!empty($details)) { if (array_key_exists('auth', $details) && $details['auth'] == 'oauth2') { $this->out('nux_service_step_two', oauth2_form($details, $this)); - } else { + } + else { $this->out('nux_service_step_two', credentials_form($details, $this)); } } @@ -538,10 +538,8 @@ protected function output() /** * @subpackage nux/output */ -class Hm_Output_service_details extends Hm_Output_Module -{ - protected function output() - { +class Hm_Output_service_details extends Hm_Output_Module { + protected function output() { $details = $this->get('nux_add_service_details', array()); $this->out('service_details', json_encode($details)); } @@ -557,9 +555,8 @@ protected function output() { } $res = '

'.$this->trans('Development Updates').'

'; foreach ($this->get('nux_dev_news', array()) as $vals) { - $res .= sprintf( - '', + $res .= sprintf('', $this->html_safe($vals['hash']), $this->html_safe($vals['shash']), $this->html_safe($vals['name']), @@ -575,23 +572,19 @@ protected function output() { /** * @subpackage nux/output */ -class Hm_Output_nux_help extends Hm_Output_Module -{ - protected function output() - { - return '

' . $this->trans('Help') . '

' . - $this->trans('Cypht is a webmail program. You can use it to access your E-mail accounts from any service that offers IMAP, or SMTP access - which most do.') . ' ' . - '
'; +class Hm_Output_nux_help extends Hm_Output_Module { + protected function output() { + return '

'.$this->trans('Help').'

'. + $this->trans('Cypht is a webmail program. You can use it to access your E-mail accounts from any service that offers IMAP, or SMTP access - which most do.').' '. + '
'; } } /** * @subpackage nux/output */ -class Hm_Output_welcome_dialog extends Hm_Output_Module -{ - protected function output() - { +class Hm_Output_welcome_dialog extends Hm_Output_Module { + protected function output() { if ($this->get('single_server_mode')) { return ''; } @@ -599,9 +592,9 @@ protected function output() $tz = $this->get('tzone'); $protos = array('imap', 'smtp', 'feeds', 'profiles'); - $res = '

' . $this->trans('Welcome to Cypht') . '

'; - $res .= '

' . $this->trans('Add a popular E-mail source quickly and easily') . '

'; - $res .= '' . $this->trans('Add an E-mail Account') . ''; + $res = '

'.$this->trans('Welcome to Cypht').'

'; + $res .= '

'.$this->trans('Add a popular E-mail source quickly and easily').'

'; + $res .= ''.$this->trans('Add an E-mail Account').''; $res .= '
    '; foreach ($protos as $proto) { @@ -609,7 +602,7 @@ protected function output() if ($proto == 'feeds') { $proto_dsp = 'RSS/ATOM'; } - $res .= '
  • '; + $res .= '
  • '; // Check if user have profiles configured if ($proto == 'profiles') { @@ -631,7 +624,8 @@ protected function output() elseif ($server_data[$proto] === 0) { $res .= sprintf($this->trans('You don\'t have any %s sources'), mb_strtoupper($proto_dsp)); $res .= sprintf(' %s', $proto, $this->trans('Add')); - } else { + } + else { if ($server_data[$proto] > 1) { $res .= sprintf($this->trans('You have %d %s sources'), $server_data[$proto], mb_strtoupper($proto_dsp)); } @@ -646,10 +640,11 @@ protected function output() $res .= '
    '; if (!$tz) { $res .= $this->trans('Your timezone is NOT set'); - } else { + } + else { $res .= sprintf($this->trans('Your timezone is set to %s'), $this->html_safe($tz)); } - $res .= ' ' . $this->trans('Update') . '
'; + $res .= ' '.$this->trans('Update').'
'; return $res; } } @@ -657,13 +652,11 @@ protected function output() /** * @subpackage nux/output */ -class Hm_Output_nux_message_list_notice extends Hm_Output_Module -{ - protected function output() - { +class Hm_Output_nux_message_list_notice extends Hm_Output_Module { + protected function output() { $msg = '
'; $msg .= $this->trans('You don\'t have any data sources assigned to this page.'); - $msg .= '
' . $this->trans('Add some') . ''; + $msg .= '
'.$this->trans('Add some').''; $msg .= '
'; return $msg; } @@ -672,128 +665,42 @@ protected function output() /** * @subpackage nux/output */ -class Hm_Output_quick_add_section extends Hm_Output_Module -{ - protected function output() - { +class Hm_Output_quick_add_section extends Hm_Output_Module { + protected function output() { if ($this->get('single_server_mode')) { return ''; } - return '
%s' . - '%s%s%s
%s'. + '%s%s%s