public function update($tmpDir = '') { Helper::mkdir($tmpDir, true); $this->collect(); try { foreach ($this->appsToUpdate as $appId) { if (!@file_exists($this->newBase . '/' . $appId)){ continue; } $path = \OC_App::getAppPath($appId); if ($path) { Helper::move($path, $tmpDir . '/' . $appId); // ! reverted intentionally $this->done [] = array( 'dst' => $path, 'src' => $tmpDir . '/' . $appId ); Helper::move($this->newBase . '/' . $appId, $path); } else { // The app is new and doesn't exist in the current instance $pathData = first(\OC::$APPSROOTS); Helper::move($this->newBase . '/' . $appId, $pathData['path'] . '/' . $appId); } } $this->finalize(); } catch (\Exception $e) { $this->rollback(true); throw $e; } }
/** * @param OutputInterface $output */ public function loadCommands(OutputInterface $output) { // $application is required to be defined in the register_command scripts $application = $this->application; require_once \OC::$SERVERROOT . '/core/register_command.php'; if ($this->config->getSystemValue('installed', false)) { if (!\OCP\Util::needUpgrade()) { OC_App::loadApps(); foreach (\OC::$server->getAppManager()->getInstalledApps() as $app) { $appPath = \OC_App::getAppPath($app); \OC::$loader->addValidRoot($appPath); $file = $appPath . '/appinfo/register_command.php'; if (file_exists($file)) { require $file; } } } else { $output->writeln("ownCloud or one of the apps require upgrade - only a limited number of commands are available"); } } else { $output->writeln("ownCloud is not installed - only a limited number of commands are available"); } $input = new ArgvInput(); if ($input->getFirstArgument() !== 'check') { $errors = \OC_Util::checkServer(\OC::$server->getConfig()); if (!empty($errors)) { foreach ($errors as $error) { $output->writeln((string) $error['error']); $output->writeln((string) $error['hint']); $output->writeln(''); } throw new \Exception("Environment not properly prepared."); } } }
/** * @param string $script */ public function doFind($script) { $theme_dir = 'themes/' . $this->theme . '/'; if (strpos($script, '3rdparty') === 0 && $this->appendIfExist($this->thirdpartyroot, $script . '.js')) { return; } if (strpos($script, '/l10n/') !== false) { // For language files we try to load them all, so themes can overwrite // single l10n strings without having to translate all of them. $found = 0; $found += $this->appendIfExist($this->serverroot, 'core/' . $script . '.js'); $found += $this->appendIfExist($this->serverroot, $theme_dir . 'core/' . $script . '.js'); $found += $this->appendIfExist($this->serverroot, $script . '.js'); $found += $this->appendIfExist($this->serverroot, $theme_dir . $script . '.js'); $found += $this->appendIfExist($this->serverroot, $theme_dir . 'apps/' . $script . '.js'); if ($found) { return; } } else { if ($this->appendIfExist($this->serverroot, $theme_dir . 'apps/' . $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . $script . '.js') || $this->appendIfExist($this->serverroot, $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . 'core/' . $script . '.js') || $this->appendIfExist($this->serverroot, 'core/' . $script . '.js')) { return; } } $app = substr($script, 0, strpos($script, '/')); $script = substr($script, strpos($script, '/') + 1); $app_path = \OC_App::getAppPath($app); $app_url = \OC_App::getAppWebPath($app); // missing translations files fill be ignored if (strpos($script, 'l10n/') === 0) { $this->appendIfExist($app_path, $script . '.js', $app_url); return; } $this->append($app_path, $script . '.js', $app_url); }
/** * Provides \OC_App::getAppPath($appId) * * @param string $appId * @return string * @throws \Exception If the app cannot be found */ public function getAppPath($appId) { $path = \OC_App::getAppPath($appId); if ($path === false) { throw new \Exception('App not found'); } return $path; }
/** * @param string $appId * @return array */ public function analyse($appId) { $appPath = \OC_App::getAppPath($appId); if ($appPath === false) { throw new \RuntimeException("No app with given id <{$appId}> known."); } return $this->analyseFolder($appPath); }
public static function showShare($args) { \OC_Util::checkAppEnabled('files_sharing'); $token = $args['token']; \OC_App::loadApp('files_sharing'); \OC_User::setIncognitoMode(true); require_once \OC_App::getAppPath('files_sharing') . '/public.php'; }
public function __construct() { $this->filePath = \OC_App::getAppPath('owncollab_talks') . '/config/config.php'; if (is_file($this->filePath)) { $this->read(); } else { $this->error = 'File "owncollab_talks/config/config.php" not exist'; } }
/** * @param string $appId * @return array */ public function analyse($appId) { $appPath = \OC_App::getAppPath($appId); if ($appPath === false) { throw new \RuntimeException("No app with given id <{$appId}> known."); } $errors = []; $info = $this->infoParser->parse($appPath . '/appinfo/info.xml'); foreach ($info as $key => $value) { if (is_array($value)) { $value = json_encode($value); } if (in_array($key, $this->mandatoryFields)) { $this->emit('InfoChecker', 'mandatoryFieldFound', [$key, $value]); continue; } if (in_array($key, $this->optionalFields)) { $this->emit('InfoChecker', 'optionalFieldFound', [$key, $value]); continue; } if (in_array($key, $this->deprecatedFields)) { // skip empty arrays - empty arrays for remote and public are always added if ($value === '[]' && in_array($key, ['public', 'remote', 'info'])) { continue; } $this->emit('InfoChecker', 'deprecatedFieldFound', [$key, $value]); continue; } $this->emit('InfoChecker', 'unusedFieldFound', [$key, $value]); } foreach ($this->mandatoryFields as $key) { if (!isset($info[$key])) { $this->emit('InfoChecker', 'mandatoryFieldMissing', [$key]); $errors[] = ['type' => 'mandatoryFieldMissing', 'field' => $key]; } } $versionFile = $appPath . '/appinfo/version'; if (is_file($versionFile)) { $version = trim(file_get_contents($versionFile)); if (isset($info['version'])) { if ($info['version'] !== $version) { $this->emit('InfoChecker', 'differentVersions', [$version, $info['version']]); $errors[] = ['type' => 'differentVersions', 'message' => 'appinfo/version: ' . $version . ' - appinfo/info.xml: ' . $info['version']]; } else { $this->emit('InfoChecker', 'sameVersions', [$versionFile]); } } else { $this->emit('InfoChecker', 'migrateVersion', [$version]); } } else { if (!isset($info['version'])) { $this->emit('InfoChecker', 'mandatoryFieldMissing', ['version']); $errors[] = ['type' => 'mandatoryFieldMissing', 'field' => 'version']; } } return $errors; }
/** * @PublicPage * @NoCSRFRequired * * @return TemplateResponse */ public function generateFileURL($file) { $url = sha1($file . mt_rand()); $app_path = \OC_App::getAppPath("libreonline"); $tmp_path = $app_path . '/tmp'; //FIXME: We should use owncloud api here. copy("/var/www/owncloud/data/" . $this->userId . "/files{$file}", "{$tmp_path}/{$url}"); $uri = \OC_App::getAppWebPath('libreonline') . "/tmp/{$url}"; return $uri; }
/** * @param string $style */ public function doFind($style) { if (strpos($style, '3rdparty') === 0 && $this->appendIfExist($this->thirdpartyroot, $style . '.css') || $this->appendIfExist($this->serverroot, $style . '.css') || $this->appendIfExist($this->serverroot, 'core/' . $style . '.css')) { return; } $app = substr($style, 0, strpos($style, '/')); $style = substr($style, strpos($style, '/') + 1); $app_path = \OC_App::getAppPath($app); $app_url = \OC_App::getAppWebPath($app); $this->append($app_path, $style . '.css', $app_url); }
/** * Executes the current command. * * @param InputInterface $input An InputInterface instance * @param OutputInterface $output An OutputInterface instance * @return null|int null or 0 if everything went fine, or an error code */ protected function execute(InputInterface $input, OutputInterface $output) { $appName = $input->getArgument('app'); $path = \OC_App::getAppPath($appName); if ($path !== false) { $output->writeln($path); return 0; } // App not found, exit with non-zero return 1; }
/** * @PublicPage * @NoCSRFRequired * * @return TemplateResponse */ public function generateFileURL($file) { $url = sha1($file . mt_rand()); $app_path = \OC_App::getAppPath("libreonline"); $tmp_path = $app_path . '/tmp'; $config = \OC::$server->getConfig(); $datadirectory = $config->getSystemValue('datadirectory', false); copy("{$datadirectory}/" . $this->userId . "/files{$file}", "{$tmp_path}/{$url}"); $uri = \OC_App::getAppWebPath('libreonline') . "/tmp/{$url}"; return $uri; }
public function getRoutingFiles() { if (!isset($this->routing_files)) { $this->routing_files = array(); foreach (OC_APP::getEnabledApps() as $app) { $file = OC_App::getAppPath($app) . '/appinfo/routes.php'; if (file_exists($file)) { $this->routing_files[$app] = $file; } } } return $this->routing_files; }
/** * find the template with the given name * @param string $name of the template file (without suffix) * * Will select the template file for the selected theme. * Checking all the possible locations. * @param string $theme * @param string $app * @return array */ protected function findTemplate($theme, $app, $name) { // Check if it is a app template or not. if ($app !== '') { $dirs = $this->getAppTemplateDirs($theme, $app, OC::$SERVERROOT, OC_App::getAppPath($app)); } else { $dirs = $this->getCoreTemplateDirs($theme, OC::$SERVERROOT); } $locator = new \OC\Template\TemplateFileLocator($dirs); $template = $locator->find($name); $path = $locator->getPath(); return array($path, $template); }
public function doFind($style) { if (strpos($style, '3rdparty') === 0 && $this->appendIfExist($this->thirdpartyroot, $style . '.css') || $this->appendIfExist($this->serverroot, $style . $this->form_factor . '.css') || $this->appendIfExist($this->serverroot, $style . '.css') || $this->appendIfExist($this->serverroot, 'core/' . $style . $this->form_factor . '.css') || $this->appendIfExist($this->serverroot, 'core/' . $style . '.css')) { return; } $app = substr($style, 0, strpos($style, '/')); $style = substr($style, strpos($style, '/') + 1); $app_path = \OC_App::getAppPath($app); $app_url = $this->webroot . '/index.php/apps/' . $app; if ($this->appendIfExist($app_path, $style . $this->form_factor . '.css', $app_url) || $this->appendIfExist($app_path, $style . '.css', $app_url)) { return; } throw new \Exception('css file not found: style:' . $style); }
protected function execute(InputInterface $input, OutputInterface $output) { $appId = $input->getArgument('app-id'); if (\OC_App::isEnabled($appId)) { $output->writeln($appId . ' is already enabled'); } else { if (!\OC_App::getAppPath($appId)) { $output->writeln($appId . ' not found'); } else { \OC_App::enable($appId); $output->writeln($appId . ' enabled'); } } }
/** * @param string $appName * @param string $scriptName * @return string */ protected function renderScript($appName, $scriptName) { $content = ''; $appPath = \OC_App::getAppPath($appName); $scriptPath = $appPath . '/' . $scriptName; if (file_exists($scriptPath)) { // TODO: sanitize path / script name ? ob_start(); include $scriptPath; $content = ob_get_contents(); @ob_end_clean(); } return $content; }
public function doFind($script) { $theme_dir = 'themes/' . $this->theme . '/'; if (strpos($script, '3rdparty') === 0 && $this->appendIfExist($this->thirdpartyroot, $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . 'apps/' . $script . $this->form_factor . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . 'apps/' . $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . $script . $this->form_factor . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . $script . '.js') || $this->appendIfExist($this->serverroot, $script . $this->form_factor . '.js') || $this->appendIfExist($this->serverroot, $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . 'core/' . $script . $this->form_factor . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . 'core/' . $script . '.js') || $this->appendIfExist($this->serverroot, 'core/' . $script . $this->form_factor . '.js') || $this->appendIfExist($this->serverroot, 'core/' . $script . '.js')) { return; } $app = substr($script, 0, strpos($script, '/')); $script = substr($script, strpos($script, '/') + 1); $app_path = \OC_App::getAppPath($app); $app_url = \OC_App::getAppWebPath($app); if ($this->appendIfExist($app_path, $script . $this->form_factor . '.js', $app_url) || $this->appendIfExist($app_path, $script . '.js', $app_url)) { return; } throw new \Exception('js file not found: script:' . $script); }
public function testStartMigrationSuccessful() { // we need to be able to autoload the class we're mocking \OC_App::registerAutoloading('encryption', \OC_App::getAppPath('encryption')); $migration = $this->getMockBuilder('\\OCA\\Encryption\\Migration')->disableOriginalConstructor()->getMock(); $this->encryptionController->expects($this->once())->method('getMigration')->with($this->config, $this->view, $this->connection, $this->logger)->will($this->returnValue($migration)); $migration->expects($this->once())->method('reorganizeSystemFolderStructure'); $migration->expects($this->once())->method('updateDB'); $backend = $this->getMockBuilder('\\OCP\\UserInterface')->getMock(); $this->userManager->expects($this->once())->method('getBackends')->will($this->returnValue([$backend])); $backend->expects($this->once())->method('getUsers')->will($this->returnValue(['User 1', 'User 2'])); $migration->expects($this->exactly(2))->method('reorganizeFolderStructureForUser')->withConsecutive(['User 1'], ['User 2']); $migration->expects($this->once())->method('finalCleanUp'); $expected = ['data' => ['message' => 'Migration Completed'], 'status' => 'success']; $this->assertSame($expected, $this->encryptionController->startMigration()); }
protected function execute(InputInterface $input, OutputInterface $output) { $appId = $input->getArgument('app-id'); if (!\OC_App::getAppPath($appId)) { $output->writeln($appId . ' not found'); return 1; } $groups = $input->getOption('groups'); if (empty($groups)) { \OC_App::enable($appId); $output->writeln($appId . ' enabled'); } else { \OC_App::enable($appId, $groups); $output->writeln($appId . ' enabled for groups: ' . implode(', ', $groups)); } return 0; }
protected function execute(InputInterface $input, OutputInterface $output) { $app = $input->getArgument('app'); $lang = $input->getArgument('lang'); $path = \OC_App::getAppPath($app); if ($path === false) { $output->writeln("The app <{$app}> is unknown."); return; } $languages = $lang; if (empty($lang)) { $languages = $this->getAllLanguages($path); } foreach ($languages as $lang) { $this->writeFiles($app, $path, $lang, $output); } }
/** * @param string $script */ public function doFind($script) { $theme_dir = 'themes/' . $this->theme . '/'; if (strpos($script, '3rdparty') === 0 && $this->appendIfExist($this->thirdpartyroot, $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . 'apps/' . $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . $script . '.js') || $this->appendIfExist($this->serverroot, $script . '.js') || $this->appendIfExist($this->serverroot, $theme_dir . 'core/' . $script . '.js') || $this->appendIfExist($this->serverroot, 'core/' . $script . '.js')) { return; } $app = substr($script, 0, strpos($script, '/')); $script = substr($script, strpos($script, '/') + 1); $app_path = \OC_App::getAppPath($app); $app_url = \OC_App::getAppWebPath($app); // missing translations files fill be ignored if (strpos($script, 'l10n/') === 0) { $this->appendIfExist($app_path, $script . '.js', $app_url); return; } $this->append($app_path, $script . '.js', $app_url); }
/** * get the possible paths for a class * * @param string $class * @return array|bool an array of possible paths or false if the class is not part of ownCloud */ public function findClass($class) { $class = trim($class, '\\'); $paths = array(); if (array_key_exists($class, $this->classPaths)) { $paths[] = $this->classPaths[$class]; } else { if ($this->useGlobalClassPath and array_key_exists($class, \OC::$CLASSPATH)) { $paths[] = \OC::$CLASSPATH[$class]; /** * @TODO: Remove this when necessary * Remove "apps/" from inclusion path for smooth migration to mutli app dir */ if (strpos(\OC::$CLASSPATH[$class], 'apps/') === 0) { \OC_Log::write('core', 'include path for class "' . $class . '" starts with "apps/"', \OC_Log::DEBUG); $paths[] = str_replace('apps/', '', \OC::$CLASSPATH[$class]); } } elseif (strpos($class, 'OC_') === 0) { // first check for legacy classes if underscores are used $paths[] = 'private/legacy/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); $paths[] = 'private/' . strtolower(str_replace('_', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OC\\') === 0) { $paths[] = 'private/' . strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); $paths[] = strtolower(str_replace('\\', '/', substr($class, 3)) . '.php'); } elseif (strpos($class, 'OCP\\') === 0) { $paths[] = 'public/' . strtolower(str_replace('\\', '/', substr($class, 4)) . '.php'); } elseif (strpos($class, 'OCA\\') === 0) { list(, $app, $rest) = explode('\\', $class, 3); $app = strtolower($app); $appPath = \OC_App::getAppPath($app); if ($appPath && stream_resolve_include_path($appPath)) { $paths[] = $appPath . '/' . strtolower(str_replace('\\', '/', $rest) . '.php'); // If not found in the root of the app directory, insert '/lib' after app id and try again. $paths[] = $appPath . '/lib/' . strtolower(str_replace('\\', '/', $rest) . '.php'); } } elseif (strpos($class, 'Test_') === 0) { $paths[] = 'tests/lib/' . strtolower(str_replace('_', '/', substr($class, 5)) . '.php'); } elseif (strpos($class, 'Test\\') === 0) { $paths[] = 'tests/lib/' . strtolower(str_replace('\\', '/', substr($class, 5)) . '.php'); } } return $paths; }
public function update($tmpDir = '') { Helper::mkdir($tmpDir, true); $this->collect(true); try { foreach ($this->appsToUpdate as $appId) { $path = \OC_App::getAppPath($appId); if ($path) { Helper::move($path, $tmpDir . '/' . $appId); // ! reverted intentionally $this->done[] = array('dst' => $path, 'src' => $tmpDir . '/' . $appId); Helper::move($this->newBase . '/' . $appId, $path); } } $this->finalize(); } catch (\Exception $e) { $this->rollback(true); throw $e; } }
<?php set_include_path(get_include_path() . PATH_SEPARATOR . \OC_App::getAppPath('files_external') . '/3rdparty/google-api-php-client/src'); require_once 'Google_Client.php'; OCP\JSON::checkAppEnabled('files_external'); OCP\JSON::checkLoggedIn(); OCP\JSON::callCheck(); $l = \OC::$server->getL10N('files_external'); if (isset($_POST['client_id']) && isset($_POST['client_secret']) && isset($_POST['redirect'])) { $client = new Google_Client(); $client->setClientId($_POST['client_id']); $client->setClientSecret($_POST['client_secret']); $client->setRedirectUri($_POST['redirect']); $client->setScopes(array('https://www.googleapis.com/auth/drive')); if (isset($_POST['step'])) { $step = $_POST['step']; if ($step == 1) { try { $authUrl = $client->createAuthUrl(); OCP\JSON::success(array('data' => array('url' => $authUrl))); } catch (Exception $exception) { OCP\JSON::error(array('data' => array('message' => $l->t('Step 1 failed. Exception: %s', array($exception->getMessage()))))); } } else { if ($step == 2 && isset($_POST['code'])) { try { $token = $client->authenticate($_POST['code']); OCP\JSON::success(array('data' => array('token' => $token))); } catch (Exception $exception) { OCP\JSON::error(array('data' => array('message' => $l->t('Step 2 failed. Exception: %s', array($exception->getMessage()))))); }
/** * find the l10n directory * @param string $app App that needs to be translated * @return string directory */ protected static function findI18nDir($app) { // find the i18n dir $i18nDir = OC::$SERVERROOT . '/core/l10n/'; if ($app != '') { // Check if the app is in the app folder if (file_exists(OC_App::getAppPath($app) . '/l10n/')) { $i18nDir = OC_App::getAppPath($app) . '/l10n/'; } else { $i18nDir = OC::$SERVERROOT . '/' . $app . '/l10n/'; } } return $i18nDir; }
/** * Loads the routes * * @param null|string $app */ public function loadRoutes($app = null) { if (is_string($app)) { $app = \OC_App::cleanAppId($app); } $requestedApp = $app; if ($this->loaded) { return; } if (is_null($app)) { $this->loaded = true; $routingFiles = $this->getRoutingFiles(); } else { if (isset($this->loadedApps[$app])) { return; } $file = \OC_App::getAppPath($app) . '/appinfo/routes.php'; if ($file !== false && file_exists($file)) { $routingFiles = [$app => $file]; } else { $routingFiles = []; } } \OC::$server->getEventLogger()->start('loadroutes' . $requestedApp, 'Loading Routes'); foreach ($routingFiles as $app => $file) { if (!isset($this->loadedApps[$app])) { if (!\OC_App::isAppLoaded($app)) { // app MUST be loaded before app routes // try again next time loadRoutes() is called $this->loaded = false; continue; } $this->loadedApps[$app] = true; $this->useCollection($app); $this->requireRouteFile($file, $app); $collection = $this->getCollection($app); $collection->addPrefix('/apps/' . $app); $this->root->addCollection($collection); } } if (!isset($this->loadedApps['core'])) { $this->loadedApps['core'] = true; $this->useCollection('root'); require_once __DIR__ . '/../../../settings/routes.php'; require_once __DIR__ . '/../../../core/routes.php'; } if ($this->loaded) { // include ocs routes, must be loaded last for /ocs prefix require_once __DIR__ . '/../../../ocs/routes.php'; $collection = $this->getCollection('ocs'); $collection->addPrefix('/ocs'); $this->root->addCollection($collection); } \OC::$server->getEventLogger()->end('loadroutes' . $requestedApp); }
/** * install an app already placed in the app folder * @param string $app id of the app to install * @return integer */ public static function installShippedApp($app) { //install the database if (is_file(OC_App::getAppPath($app) . "/appinfo/database.xml")) { OC_DB::createDbFromStructure(OC_App::getAppPath($app) . "/appinfo/database.xml"); } //run appinfo/install.php if (is_file(OC_App::getAppPath($app) . "/appinfo/install.php")) { include OC_App::getAppPath($app) . "/appinfo/install.php"; } $info = OC_App::getAppInfo($app); if (is_null($info)) { return false; } OC_Appconfig::setValue($app, 'installed_version', OC_App::getAppVersion($app)); if (array_key_exists('ocsid', $info)) { OC_Appconfig::setValue($app, 'ocsid', $info['ocsid']); } //set remote/public handelers foreach ($info['remote'] as $name => $path) { OCP\CONFIG::setAppValue('core', 'remote_' . $name, $app . '/' . $path); } foreach ($info['public'] as $name => $path) { OCP\CONFIG::setAppValue('core', 'public_' . $name, $app . '/' . $path); } OC_App::setAppTypes($info['id']); return $info['id']; }
/** * Includes the pre-update file. Done here to prevent namespace mixups. * @param string $appId */ private function includePreUpdate($appId) { include \OC_App::getAppPath($appId) . '/appinfo/preupdate.php'; }
<?php /** * ownCloud - RainLoop mail plugin * * @author RainLoop Team * @copyright 2015 RainLoop Team * * https://github.com/RainLoop/owncloud */ OC::$CLASSPATH['OC_RainLoop_Helper'] = OC_App::getAppPath('rainloop') . '/lib/RainLoopHelper.php'; OCP\App::registerAdmin('rainloop', 'admin'); OCP\App::registerPersonal('rainloop', 'personal'); if (OCP\Config::getAppValue('rainloop', 'rainloop-autologin', false)) { OCP\Util::connectHook('OC_User', 'post_login', 'OC_RainLoop_Helper', 'login'); OCP\Util::connectHook('OC_User', 'post_setPassword', 'OC_RainLoop_Helper', 'changePassword'); } OCP\Util::connectHook('OC_User', 'logout', 'OC_RainLoop_Helper', 'logout'); OCP\Util::addScript('rainloop', 'rainloop'); OCP\App::addNavigationEntry(array('id' => 'rainloop_index', 'order' => 10, 'href' => OCP\Util::linkToRoute('rainloop_index'), 'icon' => OCP\Util::imagePath('rainloop', 'mail.png'), 'name' => 'Email'));