vendor/pimcore/pimcore/bundles/AdminBundle/Controller/Admin/MiscController.php line 255

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace Pimcore\Bundle\AdminBundle\Controller\Admin;
  15. use Pimcore\Bundle\AdminBundle\Controller\AdminController;
  16. use Pimcore\Config;
  17. use Pimcore\Controller\Config\ControllerDataProvider;
  18. use Pimcore\Controller\Configuration\TemplatePhp;
  19. use Pimcore\Db;
  20. use Pimcore\File;
  21. use Pimcore\Tool;
  22. use Pimcore\Translation\Translator;
  23. use Symfony\Component\HttpFoundation\BinaryFileResponse;
  24. use Symfony\Component\HttpFoundation\JsonResponse;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\HttpKernel\Bundle\BundleInterface;
  28. use Symfony\Component\HttpKernel\Profiler\Profiler;
  29. use Symfony\Component\Routing\Annotation\Route;
  30. /**
  31.  * @Route("/misc")
  32.  */
  33. class MiscController extends AdminController
  34. {
  35.     /**
  36.      * @Route("/get-available-modules", methods={"GET"})
  37.      *
  38.      * @param ControllerDataProvider $provider
  39.      *
  40.      * @return JsonResponse
  41.      */
  42.     public function getAvailableModulesAction(ControllerDataProvider $provider)
  43.     {
  44.         // convert to normal array
  45.         $bundles array_values($provider->getBundles());
  46.         $result array_map(function (BundleInterface $bundle) {
  47.             return [
  48.                 'name' => $bundle->getName()
  49.             ];
  50.         }, $bundles);
  51.         sort($result);
  52.         return $this->adminJson([
  53.             'data' => $result
  54.         ]);
  55.     }
  56.     /**
  57.      * @Route("/get-available-controllers", methods={"GET"})
  58.      *
  59.      * @param Request $request
  60.      * @param ControllerDataProvider $provider
  61.      *
  62.      * @return JsonResponse
  63.      */
  64.     public function getAvailableControllersAction(Request $requestControllerDataProvider $provider)
  65.     {
  66.         $routingDefaults $this->getParameter('pimcore.routing.defaults');
  67.         $bundle $request->get('moduleName');
  68.         $controllers $provider->getControllers($bundle$routingDefaults['bundle']);
  69.         $result array_map(function ($controller) {
  70.             return [
  71.                 'name' => $controller
  72.             ];
  73.         }, $controllers);
  74.         sort($result);
  75.         return $this->adminJson([
  76.             'data' => $result
  77.         ]);
  78.     }
  79.     /**
  80.      * @Route("/get-available-actions", methods={"GET"})
  81.      *
  82.      * @param Request $request
  83.      * @param ControllerDataProvider $provider
  84.      *
  85.      * @return JsonResponse
  86.      */
  87.     public function getAvailableActionsAction(Request $requestControllerDataProvider $provider)
  88.     {
  89.         $routingDefaults $this->getParameter('pimcore.routing.defaults');
  90.         $bundle $request->get('moduleName');
  91.         if (empty($bundle)) {
  92.             $bundle $routingDefaults['bundle'];
  93.         }
  94.         $controller $request->get('controllerName');
  95.         if (empty($controller)) {
  96.             $controller $routingDefaults['controller'];
  97.         }
  98.         $actions $provider->getActions($controller$bundle);
  99.         $result array_map(function ($action) {
  100.             return [
  101.                 'name' => $action
  102.             ];
  103.         }, $actions);
  104.         sort($result);
  105.         return $this->adminJson([
  106.             'data' => $result
  107.         ]);
  108.     }
  109.     /**
  110.      * @Route("/get-available-templates", methods={"GET"})
  111.      *
  112.      * @param ControllerDataProvider $provider
  113.      *
  114.      * @return JsonResponse
  115.      */
  116.     public function getAvailableTemplatesAction(ControllerDataProvider $provider)
  117.     {
  118.         $templates $provider->getTemplates();
  119.         $result array_map(function ($template) {
  120.             return [
  121.                 'path' => $template
  122.             ];
  123.         }, $templates);
  124.         sort($result);
  125.         return $this->adminJson([
  126.             'data' => $result
  127.         ]);
  128.     }
  129.     /**
  130.      * @Route("/json-translations-system", methods={"GET"})
  131.      *
  132.      * @param Request $request
  133.      *
  134.      * @return Response
  135.      */
  136.     public function jsonTranslationsSystemAction(Request $request)
  137.     {
  138.         $language $request->get('language');
  139.         $translator $this->get('translator');
  140.         $translator->lazyInitialize('admin'$language);
  141.         $translations $translator->getCatalogue($language)->all('admin');
  142.         if ($language != 'en') {
  143.             // add en as a fallback
  144.             $translator->lazyInitialize('admin''en');
  145.             foreach ($translator->getCatalogue('en')->all('admin') as $key => $value) {
  146.                 if (!isset($translations[$key]) || empty($translations[$key])) {
  147.                     $translations[$key] = $value;
  148.                 }
  149.             }
  150.         }
  151.         $caseInsensitive $translator instanceof Translator && $translator->getCaseInsensitive();
  152.         $response = new Response('pimcore.system_i18n = ' $this->encodeJson($translations) . ';pimcore.system_i18n_case_insensitive='json_encode($caseInsensitive));
  153.         $response->headers->set('Content-Type''text/javascript');
  154.         return $response;
  155.     }
  156.     /**
  157.      * @Route("/script-proxy", methods={"GET"})
  158.      *
  159.      * @param Request $request
  160.      *
  161.      * @return Response
  162.      */
  163.     public function scriptProxyAction(Request $request)
  164.     {
  165.         $allowedFileTypes = ['js''css'];
  166.         $scripts explode(','$request->get('scripts'));
  167.         if ($request->get('scriptPath')) {
  168.             $scriptPath PIMCORE_WEB_ROOT $request->get('scriptPath');
  169.         } else {
  170.             $scriptPath PIMCORE_SYSTEM_TEMP_DIRECTORY '/';
  171.         }
  172.         $scriptsContent '';
  173.         foreach ($scripts as $script) {
  174.             $filePath $scriptPath $script;
  175.             if (is_file($filePath) && is_readable($filePath) && in_array(\Pimcore\File::getFileExtension($script), $allowedFileTypes)) {
  176.                 $scriptsContent .= file_get_contents($filePath);
  177.             }
  178.         }
  179.         if (!empty($scriptsContent)) {
  180.             $fileExtension = \Pimcore\File::getFileExtension($scripts[0]);
  181.             $contentType 'text/javascript';
  182.             if ($fileExtension == 'css') {
  183.                 $contentType 'text/css';
  184.             }
  185.             $lifetime 86400;
  186.             $response = new Response($scriptsContent);
  187.             $response->headers->set('Cache-Control''max-age=' $lifetime);
  188.             $response->headers->set('Pragma''');
  189.             $response->headers->set('Content-Type'$contentType);
  190.             $response->headers->set('Expires'gmdate('D, d M Y H:i:s'time() + $lifetime) . ' GMT');
  191.             return $response;
  192.         } else {
  193.             throw $this->createNotFoundException('Scripts not found');
  194.         }
  195.     }
  196.     /**
  197.      * @Route("/admin-css", methods={"GET"})
  198.      *
  199.      * @param Request $request
  200.      * @param Config $config
  201.      *
  202.      * @return Response
  203.      */
  204.     public function adminCssAction(Request $requestConfig $config)
  205.     {
  206.         // customviews config
  207.         $cvData Tool::getCustomViewConfig();
  208.         $response $this->render('PimcoreAdminBundle:Admin/Misc:admin-css.html.php', ['customviews' => $cvData'config' => $config]);
  209.         $response->headers->set('Content-Type''text/css; charset=UTF-8');
  210.         return $response;
  211.     }
  212.     /**
  213.      * @Route("/ping", methods={"GET"})
  214.      *
  215.      * @param Request $request
  216.      *
  217.      * @return JsonResponse
  218.      */
  219.     public function pingAction(Request $request)
  220.     {
  221.         $response = [
  222.             'success' => true
  223.         ];
  224.         return $this->adminJson($response);
  225.     }
  226.     /**
  227.      * @Route("/available-languages", methods={"GET"})
  228.      *
  229.      * @param Request $request
  230.      *
  231.      * @return Response
  232.      */
  233.     public function availableLanguagesAction(Request $request)
  234.     {
  235.         $locales Tool::getSupportedLocales();
  236.         $response = new Response('pimcore.available_languages = ' $this->encodeJson($locales) . ';');
  237.         $response->headers->set('Content-Type''text/javascript');
  238.         return $response;
  239.     }
  240.     /**
  241.      * @Route("/get-valid-filename", methods={"GET"})
  242.      *
  243.      * @param Request $request
  244.      *
  245.      * @return JsonResponse
  246.      */
  247.     public function getValidFilenameAction(Request $request)
  248.     {
  249.         return $this->adminJson([
  250.             'filename' => \Pimcore\Model\Element\Service::getValidKey($request->get('value'), $request->get('type'))
  251.         ]);
  252.     }
  253.     /* FILEEXPLORER */
  254.     /**
  255.      * @Route("/fileexplorer-tree", methods={"GET"})
  256.      *
  257.      * @param Request $request
  258.      *
  259.      * @return JsonResponse
  260.      */
  261.     public function fileexplorerTreeAction(Request $request)
  262.     {
  263.         $this->checkPermission('fileexplorer');
  264.         $referencePath $this->getFileexplorerPath($request'node');
  265.         $items scandir($referencePath);
  266.         $contents = [];
  267.         foreach ($items as $item) {
  268.             if ($item == '.' || $item == '..') {
  269.                 continue;
  270.             }
  271.             $file $referencePath '/' $item;
  272.             $file str_replace('//''/'$file);
  273.             if (is_dir($file) || is_file($file)) {
  274.                 $itemConfig = [
  275.                     'id' => '/fileexplorer' str_replace(PIMCORE_PROJECT_ROOT''$file),
  276.                     'text' => $item,
  277.                     'leaf' => true,
  278.                     'writeable' => is_writable($file)
  279.                 ];
  280.                 if (is_dir($file)) {
  281.                     $itemConfig['leaf'] = false;
  282.                     $itemConfig['type'] = 'folder';
  283.                     if (is_dir_empty($file)) {
  284.                         $itemConfig['loaded'] = true;
  285.                     }
  286.                     $itemConfig['expandable'] = true;
  287.                 } elseif (is_file($file)) {
  288.                     $itemConfig['type'] = 'file';
  289.                 }
  290.                 $contents[] = $itemConfig;
  291.             }
  292.         }
  293.         return $this->adminJson($contents);
  294.     }
  295.     /**
  296.      * @Route("/fileexplorer-content", methods={"GET"})
  297.      *
  298.      * @param Request $request
  299.      *
  300.      * @return JsonResponse
  301.      */
  302.     public function fileexplorerContentAction(Request $request)
  303.     {
  304.         $this->checkPermission('fileexplorer');
  305.         $success false;
  306.         $writeable false;
  307.         $file $this->getFileexplorerPath($request'path');
  308.         $content null;
  309.         if (is_file($file)) {
  310.             if (is_readable($file)) {
  311.                 $content file_get_contents($file);
  312.                 $success true;
  313.                 $writeable is_writeable($file);
  314.             }
  315.         }
  316.         return $this->adminJson([
  317.             'success' => $success,
  318.             'content' => $content,
  319.             'writeable' => $writeable,
  320.             'filename' => basename($file),
  321.             'path' => preg_replace('@^' preg_quote(PIMCORE_PROJECT_ROOT'@') . '@'''$file)
  322.         ]);
  323.     }
  324.     /**
  325.      * @Route("/fileexplorer-content-save", methods={"PUT"})
  326.      *
  327.      * @param Request $request
  328.      *
  329.      * @return JsonResponse
  330.      */
  331.     public function fileexplorerContentSaveAction(Request $request)
  332.     {
  333.         $this->checkPermission('fileexplorer');
  334.         $success false;
  335.         if ($request->get('content') && $request->get('path')) {
  336.             $file $this->getFileexplorerPath($request'path');
  337.             if (is_file($file) && is_writeable($file)) {
  338.                 File::put($file$request->get('content'));
  339.                 $success true;
  340.             }
  341.         }
  342.         return $this->adminJson([
  343.             'success' => $success
  344.         ]);
  345.     }
  346.     /**
  347.      * @Route("/fileexplorer-add", methods={"POST"})
  348.      *
  349.      * @param Request $request
  350.      *
  351.      * @return JsonResponse
  352.      *
  353.      * @throws \Exception
  354.      */
  355.     public function fileexplorerAddAction(Request $request)
  356.     {
  357.         $this->checkPermission('fileexplorer');
  358.         $success false;
  359.         if ($request->get('filename') && $request->get('path')) {
  360.             $path $this->getFileexplorerPath($request'path');
  361.             $file $path '/' $request->get('filename');
  362.             $file resolvePath($file);
  363.             if (strpos($filePIMCORE_PROJECT_ROOT) !== 0) {
  364.                 throw new \Exception('not allowed');
  365.             }
  366.             if (is_writeable(dirname($file))) {
  367.                 File::put($file'');
  368.                 $success true;
  369.             }
  370.         }
  371.         return $this->adminJson([
  372.             'success' => $success
  373.         ]);
  374.     }
  375.     /**
  376.      * @Route("/fileexplorer-add-folder", methods={"POST"})
  377.      *
  378.      * @param Request $request
  379.      *
  380.      * @return JsonResponse
  381.      *
  382.      * @throws \Exception
  383.      */
  384.     public function fileexplorerAddFolderAction(Request $request)
  385.     {
  386.         $this->checkPermission('fileexplorer');
  387.         $success false;
  388.         if ($request->get('filename') && $request->get('path')) {
  389.             $path $this->getFileexplorerPath($request'path');
  390.             $file $path '/' $request->get('filename');
  391.             $file resolvePath($file);
  392.             if (strpos($filePIMCORE_PROJECT_ROOT) !== 0) {
  393.                 throw new \Exception('not allowed');
  394.             }
  395.             if (is_writeable(dirname($file))) {
  396.                 File::mkdir($file);
  397.                 $success true;
  398.             }
  399.         }
  400.         return $this->adminJson([
  401.             'success' => $success
  402.         ]);
  403.     }
  404.     /**
  405.      * @Route("/fileexplorer-delete", methods={"DELETE"})
  406.      *
  407.      * @param Request $request
  408.      *
  409.      * @return JsonResponse
  410.      */
  411.     public function fileexplorerDeleteAction(Request $request)
  412.     {
  413.         $this->checkPermission('fileexplorer');
  414.         $success false;
  415.         if ($request->get('path')) {
  416.             $file $this->getFileexplorerPath($request'path');
  417.             if (is_writeable($file)) {
  418.                 unlink($file);
  419.                 $success true;
  420.             }
  421.         }
  422.         return $this->adminJson([
  423.             'success' => $success
  424.         ]);
  425.     }
  426.     /**
  427.      * @Route("/fileexplorer-rename", methods={"PUT"})
  428.      *
  429.      * @param Request $request
  430.      *
  431.      * @return JsonResponse
  432.      */
  433.     public function fileexplorerRenameAction(Request $request)
  434.     {
  435.         $this->checkPermission('fileexplorer');
  436.         $success false;
  437.         if ($request->get('path') && $request->get('newPath')) {
  438.             $file $this->getFileexplorerPath($request'path');
  439.             $newFile $this->getFileexplorerPath($request'newPath');
  440.             $success rename($file$newFile);
  441.         }
  442.         return $this->adminJson([
  443.             'success' => $success
  444.         ]);
  445.     }
  446.     /**
  447.      * @param Request $request
  448.      * @param string $paramName
  449.      *
  450.      * @return mixed|string
  451.      *
  452.      * @throws \Exception
  453.      */
  454.     private function getFileexplorerPath(Request $request$paramName 'node')
  455.     {
  456.         $path preg_replace("/^\/fileexplorer/"''$request->get($paramName));
  457.         $path resolvePath(PIMCORE_PROJECT_ROOT $path);
  458.         if (strpos($pathPIMCORE_PROJECT_ROOT) !== 0) {
  459.             throw new \Exception('operation permitted, permission denied');
  460.         }
  461.         return $path;
  462.     }
  463.     /**
  464.      * @Route("/maintenance", methods={"POST"})
  465.      *
  466.      * @param Request $request
  467.      *
  468.      * @return JsonResponse
  469.      */
  470.     public function maintenanceAction(Request $request)
  471.     {
  472.         $this->checkPermission('maintenance_mode');
  473.         if ($request->get('activate')) {
  474.             Tool\Admin::activateMaintenanceMode(Tool\Session::getSessionId());
  475.         }
  476.         if ($request->get('deactivate')) {
  477.             Tool\Admin::deactivateMaintenanceMode();
  478.         }
  479.         return $this->adminJson([
  480.             'success' => true
  481.         ]);
  482.     }
  483.     /**
  484.      * @Route("/http-error-log", methods={"POST"})
  485.      *
  486.      * @param Request $request
  487.      *
  488.      * @return JsonResponse
  489.      */
  490.     public function httpErrorLogAction(Request $request)
  491.     {
  492.         $this->checkPermission('http_errors');
  493.         $db Db::get();
  494.         $limit intval($request->get('limit'));
  495.         $offset intval($request->get('start'));
  496.         $sort $request->get('sort');
  497.         $dir $request->get('dir');
  498.         $filter $request->get('filter');
  499.         if (!$limit) {
  500.             $limit 20;
  501.         }
  502.         if (!$offset) {
  503.             $offset 0;
  504.         }
  505.         if (!$sort || !in_array($sort, ['code''uri''date''count'])) {
  506.             $sort 'count';
  507.         }
  508.         if (!$dir || !in_array($dir, ['DESC''ASC'])) {
  509.             $dir 'DESC';
  510.         }
  511.         $condition '';
  512.         if ($filter) {
  513.             $filter $db->quote('%' $filter '%');
  514.             $conditionParts = [];
  515.             foreach (['uri''code''parametersGet''parametersPost''serverVars''cookies'] as $field) {
  516.                 $conditionParts[] = $field ' LIKE ' $filter;
  517.             }
  518.             $condition ' WHERE ' implode(' OR '$conditionParts);
  519.         }
  520.         $logs $db->fetchAll('SELECT code,uri,`count`,date FROM http_error_log ' $condition ' ORDER BY ' $sort ' ' $dir ' LIMIT ' $offset ',' $limit);
  521.         $total $db->fetchOne('SELECT count(*) FROM http_error_log ' $condition);
  522.         return $this->adminJson([
  523.             'items' => $logs,
  524.             'total' => $total,
  525.             'success' => true
  526.         ]);
  527.     }
  528.     /**
  529.      * @Route("/http-error-log-flush", methods={"DELETE"})
  530.      *
  531.      * @param Request $request
  532.      *
  533.      * @return JsonResponse
  534.      */
  535.     public function httpErrorLogFlushAction(Request $request)
  536.     {
  537.         $this->checkPermission('http_errors');
  538.         $db Db::get();
  539.         $db->query('TRUNCATE TABLE http_error_log');
  540.         return $this->adminJson([
  541.             'success' => true
  542.         ]);
  543.     }
  544.     /**
  545.      * @Route("/http-error-log-detail", methods={"GET"})
  546.      *
  547.      * @param Request $request
  548.      *
  549.      * @return Response
  550.      */
  551.     public function httpErrorLogDetailAction(Request $request)
  552.     {
  553.         $this->checkPermission('http_errors');
  554.         $db Db::get();
  555.         $data $db->fetchRow('SELECT * FROM http_error_log WHERE uri = ?', [$request->get('uri')]);
  556.         foreach ($data as $key => &$value) {
  557.             if (in_array($key, ['parametersGet''parametersPost''serverVars''cookies'])) {
  558.                 $value unserialize($value);
  559.             }
  560.         }
  561.         $response $this->render('PimcoreAdminBundle:Admin/Misc:http-error-log-detail.html.php', ['data' => $data]);
  562.         return $response;
  563.     }
  564.     /**
  565.      * @Route("/country-list", methods={"GET"})
  566.      *
  567.      * @param Request $request
  568.      *
  569.      * @return JsonResponse
  570.      */
  571.     public function countryListAction(Request $request)
  572.     {
  573.         $countries = \Pimcore::getContainer()->get('pimcore.locale')->getDisplayRegions();
  574.         asort($countries);
  575.         $options = [];
  576.         foreach ($countries as $short => $translation) {
  577.             if (strlen($short) == 2) {
  578.                 $options[] = [
  579.                     'name' => $translation,
  580.                     'code' => $short
  581.                 ];
  582.             }
  583.         }
  584.         return $this->adminJson(['data' => $options]);
  585.     }
  586.     /**
  587.      * @Route("/language-list", methods={"GET"})
  588.      *
  589.      * @param Request $request
  590.      *
  591.      * @return JsonResponse
  592.      */
  593.     public function languageListAction(Request $request)
  594.     {
  595.         $locales Tool::getSupportedLocales();
  596.         $options = [];
  597.         foreach ($locales as $short => $translation) {
  598.             $options[] = [
  599.                 'name' => $translation,
  600.                 'code' => $short
  601.             ];
  602.         }
  603.         return $this->adminJson(['data' => $options]);
  604.     }
  605.     /**
  606.      * @Route("/phpinfo", methods={"GET"})
  607.      *
  608.      * @param Request $request
  609.      * @param Profiler $profiler
  610.      *
  611.      * @throws \Exception
  612.      *
  613.      * @return Response
  614.      */
  615.     public function phpinfoAction(Request $request, ?Profiler $profiler)
  616.     {
  617.         if ($profiler) {
  618.             $profiler->disable();
  619.         }
  620.         if (!$this->getAdminUser()->isAdmin()) {
  621.             throw new \Exception('Permission denied');
  622.         }
  623.         ob_start();
  624.         phpinfo();
  625.         $content ob_get_clean();
  626.         return new Response($content);
  627.     }
  628.     /**
  629.      * @Route("/get-language-flag", methods={"GET"})
  630.      *
  631.      * @param Request $request
  632.      *
  633.      * @return BinaryFileResponse
  634.      */
  635.     public function getLanguageFlagAction(Request $request)
  636.     {
  637.         $iconPath Tool::getLanguageFlagFile($request->get('language'));
  638.         $response = new BinaryFileResponse($iconPath);
  639.         $response->headers->set('Content-Type''image/svg+xml');
  640.         return $response;
  641.     }
  642.     /**
  643.      * @Route("/icon-list", methods={"GET"})
  644.      * @TemplatePhp()
  645.      *
  646.      * @param Request $request
  647.      * @param Profiler $profiler
  648.      */
  649.     public function iconListAction(Request $request, ?Profiler $profiler)
  650.     {
  651.         if ($profiler) {
  652.             $profiler->disable();
  653.         }
  654.     }
  655.     /**
  656.      * @Route("/test")
  657.      *
  658.      * @param Request $request
  659.      *
  660.      * @return Response
  661.      */
  662.     public function testAction(Request $request)
  663.     {
  664.         return new Response('done');
  665.     }
  666. }