diff --git a/integrations/nextcloud/snappymail/lib/Controller/FetchController.php b/integrations/nextcloud/snappymail/lib/Controller/FetchController.php index df8c8dabe..f15a76fe8 100644 --- a/integrations/nextcloud/snappymail/lib/Controller/FetchController.php +++ b/integrations/nextcloud/snappymail/lib/Controller/FetchController.php @@ -26,7 +26,7 @@ class FetchController extends Controller { $error = 'Upgrade failed'; try { SnappyMailHelper::loadApp(); - if (SnappyMail\Upgrade::core()) { + if (\SnappyMail\Upgrade::core()) { return new JSONResponse([ 'status' => 'success', 'Message' => $this->l->t('Upgraded successfully') @@ -60,10 +60,9 @@ class FetchController extends Controller { } if (!empty($_POST['import-rainloop'])) { - $result = SnappyMailHelper::importRainLoop(); return new JSONResponse([ 'status' => 'success', - 'Message' => \implode("\n", $result) + 'Message' => \implode("\n", \OCA\SnappyMail\Util\RainLoop::import()) ]); } @@ -92,22 +91,18 @@ class FetchController extends Controller { */ public function setPersonal(): JSONResponse { try { - + $sEmail = ''; if (isset($_POST['appname'], $_POST['snappymail-password'], $_POST['snappymail-email']) && 'snappymail' === $_POST['appname']) { $sUser = \OC::$server->getUserSession()->getUser()->getUID(); - $sPostEmail = $_POST['snappymail-email']; - $this->config->setUserValue($sUser, 'snappymail', 'snappymail-email', $sPostEmail); + $sEmail = $_POST['snappymail-email']; + $this->config->setUserValue($sUser, 'snappymail', 'snappymail-email', $sEmail); $sPass = $_POST['snappymail-password']; if ('******' !== $sPass) { - require_once $this->appManager->getAppPath('snappymail').'/lib/Util/SnappyMailHelper.php'; - $this->config->setUserValue($sUser, 'snappymail', 'snappymail-password', - $sPass ? SnappyMailHelper::encodePassword($sPass, \md5($sPostEmail)) : ''); + $sPass ? SnappyMailHelper::encodePassword($sPass, \md5($sEmail)) : ''); } - - $sEmail = $this->config->getUserValue($sUser, 'snappymail', 'snappymail-email', ''); } else { return new JSONResponse([ 'status' => 'error', diff --git a/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php b/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php index badf83d21..22211e659 100644 --- a/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php +++ b/integrations/nextcloud/snappymail/lib/Settings/PersonalSettings.php @@ -1,8 +1,6 @@ getUserSession()->getUser()->getUID(); $sEmail = $this->config->getUserValue($uid, 'snappymail', 'snappymail-email'); if (!$sEmail) { - $sEmail = $this->config->getUserValue($uid, 'rainloop', 'rainloop-email'); - if ($sEmail) { - $this->config->setUserValue($uid, 'rainloop', 'rainloop-email'. $sEmail); - $sPassword = $this->config->getUserValue($uid, 'rainloop', 'rainloop-password'); - if ($sPassword) { - require_once \dirname(__DIR__) . '/Util/SnappyMailHelper.php'; - $sPassword = SnappyMailHelper::decodeRainLoopPassword($sPassword, md5($sEmail)); - } - if ($sPassword) { - $this->config->setUserValue($uid, 'snappymail', 'snappymail-password', SnappyMailHelper::encodePassword($sPassword, \md5($sEmail))); + $aRainLoop = \OCA\SnappyMail\Util\RainLoop::getLoginCredentials($uid, $this->config); + if ($aRainLoop) { + $sEmail = $aRainLoop[0]; + $this->config->setUserValue($uid, 'snappymail', 'snappymail-email', $sEmail); + if ($aRainLoop[1]) { + $this->config->setUserValue($uid, 'snappymail', 'snappymail-password', + \OCA\SnappyMail\Util\SnappyMailHelper::encodePassword($aRainLoop[1], \md5($sEmail)) + ); } } } diff --git a/integrations/nextcloud/snappymail/lib/Util/RainLoop.php b/integrations/nextcloud/snappymail/lib/Util/RainLoop.php new file mode 100644 index 000000000..58750b763 --- /dev/null +++ b/integrations/nextcloud/snappymail/lib/Util/RainLoop.php @@ -0,0 +1,128 @@ +getUserValue($sUID, 'rainloop', 'rainloop-email')); + if ($sEmail) { + $sPassword = $config->getUserValue($sUID, 'rainloop', 'rainloop-password', ''); + return [ + $sEmail, + $sPassword ? static::decodePassword($sPassword, \md5($sEmail)) : '' + ]; + } + return null; + } + + /** + * Imports data from RainLoop + * skips: /data/rainloop-storage/_data_/_default_/configs/application.ini + * skips: /data/rainloop-storage/_data_/_default_/domains/disabled + * skips: /data/rainloop-storage/SALT.php + * skips: /data/rainloop-storage/index.html + * skips: /data/rainloop-storage/INSTALLED + * skips: /data/rainloop-storage/index.php + */ + public static function import() : array + { + $dir = \rtrim(\trim(\OC::$server->getSystemConfig()->getValue('datadirectory', '')), '\\/'); + $dir_snappy = $dir . '/appdata_snappymail/'; + $dir_rainloop = $dir . '/rainloop-storage'; + $result = []; + $rainloop_plugins = []; + if (\is_dir($dir_rainloop)) { + \is_dir($dir_snappy) || \mkdir($dir_snappy, 0755, true); + $iterator = new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir_rainloop, \RecursiveDirectoryIterator::SKIP_DOTS), + \RecursiveIteratorIterator::SELF_FIRST + ); + foreach ($iterator as $item) { + $target = $dir_snappy . $iterator->getSubPathname(); + if (\preg_match('@/plugins/([^/]+)@', $target, $match)) { + $rainloop_plugins[$match[1]] = $match[1]; + } else if (!\strpos($target, '/cache/')) { + if ($item->isDir()) { + \is_dir($target) || \mkdir($target, 0755, true); + } else if (\file_exists($target)) { + $result[] = "skipped: {$target}"; + } else { + \copy($item, $target); + $result[] = "copied : {$target}"; + } + } + } + } + +// $password = APP_PRIVATE_DATA . 'admin_password.txt'; +// \is_file($password) && \unlink($password); + + SnappyMailHelper::loadApp(); + + // Attempt to install same plugins as RainLoop + if ($rainloop_plugins) { + foreach (\SnappyMail\Repository::getPackagesList()['List'] as $plugin) { + if (\in_array($plugin['id'], $rainloop_plugins)) { + $result[] = "install plugin : {$plugin['id']}"; + \SnappyMail\Repository::installPackage('plugin', $plugin['id']); + unset($rainloop_plugins[$plugin['id']]); + } + } + foreach ($rainloop_plugins as $plugin) { + $result[] = "skipped plugin : {$plugin}"; + } + } + + $oConfig = \RainLoop\Api::Config(); + $oConfig->Set('webmail', 'theme', 'Nextcloud@custom'); + $oConfig->Save(); + + return $result; + } + + /** + * @param string $sPassword + * @param string $sSalt + * + * @return string + */ + public static function decodePassword($sPassword, $sSalt) + { + $sPassword = \base64_decode(\trim($sPassword)); + + $method = 'AES-256-CBC'; + if (\function_exists('openssl_encrypt') + && \function_exists('openssl_decrypt') + && \function_exists('openssl_random_pseudo_bytes') + && \function_exists('openssl_cipher_iv_length') + && \function_exists('openssl_get_cipher_methods') + && \defined('OPENSSL_RAW_DATA') + && \defined('OPENSSL_ZERO_PADDING') + && \in_array($method, \openssl_get_cipher_methods()) + ) { + $aParts = \explode('|', $sPassword, 2); + if (\is_array($aParts) && !empty($aParts[0]) && !empty($aParts[1])) { + $sData = \base64_decode($aParts[0]); + $iv = \base64_decode($aParts[1]); + return \base64_decode(\trim( + \openssl_decrypt($sData, $method, \md5($sSalt), OPENSSL_RAW_DATA, $iv) + )); + } + } + + if (\function_exists('mcrypt_encrypt') + && \function_exists('mcrypt_decrypt') + && \defined('MCRYPT_RIJNDAEL_256') + && \defined('MCRYPT_MODE_ECB') + ) { + return \base64_decode(\trim( + \mcrypt_decrypt(MCRYPT_RIJNDAEL_256, \md5($sSalt), $sPassword, MCRYPT_MODE_ECB) + )); + } + + return $sPassword; + } +} diff --git a/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php b/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php index 4fadef8e8..61e046827 100644 --- a/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php +++ b/integrations/nextcloud/snappymail/lib/Util/SnappyMailHelper.php @@ -123,16 +123,11 @@ class SnappyMailHelper if ($sPassword) { $sPassword = static::decodePassword($sPassword, \md5($sEmail)); } - } else if ($sCustomEmail = $config->getUserValue($sUID, 'rainloop', 'rainloop-email')) { - $sEmail = $sCustomEmail; - $this->config->setUserValue($sUser, 'snappymail', 'snappymail-email', $sEmail); - - $sPassword = $config->getUserValue($sUID, 'rainloop', 'rainloop-password', ''); - if ($sPassword) { - $sPassword = static::decodeRainLoopPassword($sPassword, md5($sEmail)); - } - if ($sPassword) { - $this->config->setUserValue($sUser, 'snappymail', 'snappymail-password', static::encodePassword($sPassword, \md5($sEmail))); + } else if ($aRainLoop = RainLoop::getLoginCredentials($sUID, $config)) { + $sEmail = $aRainLoop[0]; + $config->setUserValue($sUser, 'snappymail', 'snappymail-email', $sEmail); + if ($aRainLoop[1]) { + $config->setUserValue($sUser, 'snappymail', 'snappymail-password', static::encodePassword($aRainLoop[1], \md5($sEmail))); } } return [$sUID, $sEmail, $sPassword ?: '']; @@ -164,103 +159,4 @@ class SnappyMailHelper static::loadApp(); return \SnappyMail\Crypt::DecryptUrlSafe($sPassword, $sSalt); } - - // Imports data from RainLoop - public static function importRainLoop() : array - { - $result = []; - - $dir = \rtrim(\trim(\OC::$server->getSystemConfig()->getValue('datadirectory', '')), '\\/'); - $dir_snappy = $dir . '/appdata_snappymail/'; - $dir_rainloop = $dir . '/rainloop-storage'; - $rainloop_plugins = []; - if (\is_dir($dir_rainloop)) { - \is_dir($dir_snappy) || \mkdir($dir_snappy, 0755, true); - $iterator = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($dir_rainloop, \RecursiveDirectoryIterator::SKIP_DOTS), - \RecursiveIteratorIterator::SELF_FIRST - ); - foreach ($iterator as $item) { - $target = $dir_snappy . $iterator->getSubPathname(); - if (\preg_match('@/plugins/([^/])@', $target, $match)) { - $rainloop_plugins[$match[1]] = $match[1]; - } else if (!\strpos($target, '/cache/')) { - if ($item->isDir()) { - \is_dir($target) || \mkdir($target, 0755, true); - } else if (\file_exists($target)) { - $result[] = "skipped: {$target}"; - } else { - \copy($item, $target); - $result[] = "copied : {$target}"; - } - } - } - } - -// $password = APP_PRIVATE_DATA . 'admin_password.txt'; -// \is_file($password) && \unlink($password); - - static::loadApp(); - - // Attempt to install same plugins as RainLoop - if ($rainloop_plugins) { - foreach (\SnappyMail\Repository::getPackagesList()['List'] as $plugin) { - if (\in_array($plugin['id'], $rainloop_plugins)) { - $result[] = "install plugin : {$plugin['id']}"; - \SnappyMail\Repository::installPackage('plugin', $plugin['id']); - unset($rainloop_plugins[$plugin['id']]); - } - } - foreach ($rainloop_plugins as $plugin) { - $result[] = "skipped plugin : {$plugin}"; - } - } - - $oConfig = \RainLoop\Api::Config(); - $oConfig->Set('webmail', 'theme', 'Nextcloud@custom'); - $oConfig->Save(); - - return $result; - } - - /** - * @param string $sPassword - * @param string $sSalt - * - * @return string - */ - public static function decodeRainLoopPassword($sPassword, $sSalt) - { - $method = 'AES-256-CBC'; - if (\function_exists('openssl_encrypt') && - \function_exists('openssl_decrypt') && - \function_exists('openssl_random_pseudo_bytes') && - \function_exists('openssl_cipher_iv_length') && - \function_exists('openssl_get_cipher_methods') && - \defined('OPENSSL_RAW_DATA') && \defined('OPENSSL_ZERO_PADDING') && - \in_array($method, openssl_get_cipher_methods()) - ) { - $sLine = base64_decode(trim($sPassword)); - $aParts = explode('|', $sLine, 2); - if (is_array($aParts) && !empty($aParts[0]) && !empty($aParts[1])) { - $sData = @base64_decode($aParts[0]); - $iv = @base64_decode($aParts[1]); - return @base64_decode(trim( - @openssl_decrypt($sData, $method, md5($sSalt), OPENSSL_RAW_DATA, $iv) - )); - } - } - - if (\function_exists('mcrypt_encrypt') && - \function_exists('mcrypt_decrypt') && - \defined('MCRYPT_RIJNDAEL_256') && - \defined('MCRYPT_MODE_ECB') - ) { - return @base64_decode(trim( - @mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5($sSalt), base64_decode(trim($sPassword)), MCRYPT_MODE_ECB) - )); - } - - return @base64_decode(trim($sPassword)); - } }