public function execute(Request $request, WorkingFolder $workingFolder, EventDispatcher $dispatcher, CacheManager $cache, ResizedImageRepository $resizedImageRepository, ThumbnailRepository $thumbnailRepository, Acl $acl) { $fileName = (string) $request->query->get('fileName'); $editedImage = new EditedImage($fileName, $this->app); $saveAsNew = false; if (!$editedImage->exists()) { $saveAsNew = true; $editedImage->saveAsNew(true); } else { // If file exists check for FILE_DELETE permission $resourceTypeName = $workingFolder->getResourceType()->getName(); $path = $workingFolder->getClientCurrentFolder(); if (!$acl->isAllowed($resourceTypeName, $path, Permission::FILE_DELETE)) { throw new UnauthorizedException(sprintf('Unauthorized: no FILE_DELETE permission in %s:%s', $resourceTypeName, $path)); } } if (!Image::isSupportedExtension($editedImage->getExtension())) { throw new InvalidExtensionException('Unsupported image type or not image file'); } $imageFormat = Image::mimeTypeFromExtension($editedImage->getExtension()); $uploadedData = (string) $request->request->get('content'); if (null === $uploadedData || strpos($uploadedData, 'data:image/png;base64,') !== 0) { throw new InvalidUploadException('Invalid upload. Expected base64 encoded PNG image.'); } $data = explode(',', $uploadedData); $data = isset($data[1]) ? base64_decode($data[1]) : false; if (!$data) { throw new InvalidUploadException(); } try { $uploadedImage = Image::create($data); } catch (\Exception $e) { // No need to check if secureImageUploads is enabled - image must be valid here throw new InvalidUploadException('Invalid upload: corrupted image', Error::UPLOADED_CORRUPT, array(), $e); } $editedImage->setNewContents($uploadedImage->getData($imageFormat)); $editedImage->setNewDimensions($uploadedImage->getWidth(), $uploadedImage->getHeight()); if (!$editedImage->isValid()) { throw new InvalidUploadException('Invalid file provided'); } $editFileEvent = new EditFileEvent($this->app, $editedImage); $imageInfo = $uploadedImage->getInfo(); $cache->set(Path::combine($workingFolder->getResourceType()->getName(), $workingFolder->getClientCurrentFolder(), $fileName), $uploadedImage->getInfo()); $dispatcher->dispatch(CKFinderEvent::SAVE_IMAGE, $editFileEvent); $saved = false; if (!$editFileEvent->isPropagationStopped()) { $saved = $editedImage->save($editFileEvent->getNewContents()); if (!$saved) { throw new AccessDeniedException("Couldn't save image file"); } //Remove thumbnails and resized images in case if file is overwritten if (!$saveAsNew && $saved) { $resourceType = $workingFolder->getResourceType(); $thumbnailRepository->deleteThumbnails($resourceType, $workingFolder->getClientCurrentFolder(), $fileName); $resizedImageRepository->deleteResizedImages($resourceType, $workingFolder->getClientCurrentFolder(), $fileName); } } return array('saved' => (int) $saved, 'date' => Utils::formatDate(time()), 'size' => Utils::formatSize($imageInfo['size'])); }
/** * Returns a resized image for provided source file * * If an appropriate resized version already exists it's reused. * * @param ResourceType $sourceFileResourceType * @param string $sourceFilePath * @param string $sourceFileName * @param int $requestedWidth * @param int $requestedHeight * * @return ResizedImage * * @throws \Exception */ public function getResizedImage(ResourceType $sourceFileResourceType, $sourceFilePath, $sourceFileName, $requestedWidth, $requestedHeight) { $resizedImage = new ResizedImage($this, $sourceFileResourceType, $sourceFilePath, $sourceFileName, $requestedWidth, $requestedHeight); if (!$this->acl->isAllowed($sourceFileResourceType->getName(), $sourceFilePath, Permission::IMAGE_RESIZE_CUSTOM) && !$this->isSizeAllowedInConfig($requestedWidth, $requestedHeight)) { throw new UnauthorizedException('Provided size is not allowed in images.sizes configuration'); } if (!$resizedImage->exists() && $resizedImage->requestedSizeIsValid()) { $resizedImage->create(); $resizeImageEvent = new ResizeImageEvent($this->app, $resizedImage); $this->dispatcher->dispatch(CKFinderEvent::CREATE_RESIZED_IMAGE, $resizeImageEvent); if (!$resizeImageEvent->isPropagationStopped()) { $resizedImage = $resizeImageEvent->getResizedImage(); $resizedImage->save(); } } return $resizedImage; }
public function execute(Request $request, ResourceTypeFactory $resourceTypeFactory, Acl $acl, EventDispatcher $dispatcher) { $copiedFiles = (array) $request->request->get('files'); $copied = 0; $errors = array(); // Initial validation foreach ($copiedFiles as $arr) { if (!isset($arr['name'], $arr['type'], $arr['folder'])) { throw new InvalidRequestException(); } if (!$acl->isAllowed($arr['type'], $arr['folder'], Permission::FILE_VIEW)) { throw new UnauthorizedException(); } } foreach ($copiedFiles as $arr) { if (empty($arr['name'])) { continue; } $name = $arr['name']; $type = $arr['type']; $folder = $arr['folder']; $resourceType = $resourceTypeFactory->getResourceType($type); $copiedFile = new CopiedFile($name, $folder, $resourceType, $this->app); $options = isset($arr['options']) ? $arr['options'] : ''; $copiedFile->setCopyOptions($options); if ($copiedFile->isValid()) { $copyFileEvent = new CopyFileEvent($this->app, $copiedFile); $dispatcher->dispatch(CKFinderEvent::COPY_FILE, $copyFileEvent); if (!$copyFileEvent->isPropagationStopped()) { if ($copiedFile->doCopy()) { $copied++; } } } $errors = array_merge($errors, $copiedFile->getErrors()); } $data = array('copied' => $copied); if (!empty($errors)) { $data['error'] = array('number' => Error::COPY_FAILED, 'errors' => $errors); } return $data; }
public function execute(Request $request, ResourceTypeFactory $resourceTypeFactory, Acl $acl, EventDispatcher $dispatcher) { $deletedFiles = (array) $request->get('files'); $deleted = 0; $errors = array(); foreach ($deletedFiles as $arr) { if (!isset($arr['name'], $arr['type'], $arr['folder'])) { throw new InvalidRequestException(); } if (empty($arr['name'])) { continue; } $name = $arr['name']; $type = $arr['type']; $folder = $arr['folder']; $resourceType = $resourceTypeFactory->getResourceType($type); $deletedFile = new DeletedFile($name, $folder, $resourceType, $this->app); if (!$acl->isAllowed($type, $folder, Permission::FILE_DELETE)) { throw new UnauthorizedException(); } if ($deletedFile->isValid()) { $deleteFileEvent = new DeleteFileEvent($this->app, $deletedFile); $dispatcher->dispatch(CKFinderEvent::DELETE_FILE, $deleteFileEvent); if (!$deleteFileEvent->isPropagationStopped()) { if ($deletedFile->doDelete()) { $deleted++; } } } $errors = array_merge($errors, $deletedFile->getErrors()); } $data = array('deleted' => $deleted); if (!empty($errors)) { $data['error'] = array('number' => Error::DELETE_FAILED, 'errors' => $errors); } return $data; }
public function execute(Request $request, Acl $acl, Config $config, ResourceTypeFactory $resourceTypeFactory) { $data = new \stdClass(); /** * Connector is always enabled here * * @see CKFinder::checkAuth() */ $data->enabled = true; $ln = ''; $lc = str_replace('-', '', ($config->get('licenseKey') ?: $config->get('LicenseKey')) . ' '); $pos = strpos(CKFinder::CHARS, $lc[2]) % 5; if ($pos == 1 || $pos == 2) { $ln = $config->get('licenseName') ?: $config->get('LicenseName'); } $data->s = $ln; $data->c = trim($lc[1] . $lc[8] . $lc[17] . $lc[22] . $lc[3] . $lc[13] . $lc[11] . $lc[20] . $lc[5] . $lc[24] . $lc[27]); // Thumbnails $thumbnailsConfig = $config->get('thumbnails'); $thumbnailsEnabled = (bool) $thumbnailsConfig['enabled']; if ($thumbnailsEnabled) { $sizes = array(); foreach ($thumbnailsConfig['sizes'] as $sizeInfo) { $sizes[] = sprintf("%dx%d", $sizeInfo['width'], $sizeInfo['height']); } $data->thumbs = $sizes; } // Images $imagesConfig = $config->get('images'); $images = array('max' => $imagesConfig['maxWidth'] . 'x' . $imagesConfig['maxHeight']); if (isset($imagesConfig['sizes'])) { $resize = array(); foreach ($imagesConfig['sizes'] as $name => $sizeInfo) { $resize[$name] = $sizeInfo['width'] . 'x' . $sizeInfo['height']; } $images['sizes'] = $resize; } $data->images = $images; $resourceTypesNames = $config->getDefaultResourceTypes() ?: $config->getResourceTypes(); $data->resourceTypes = array(); if (!empty($resourceTypesNames)) { $phpMaxSize = 0; $maxUpload = Utils::returnBytes(ini_get('upload_max_filesize')); if ($maxUpload) { $phpMaxSize = $maxUpload; } $maxPost = Utils::returnBytes(ini_get('post_max_size')); if ($maxPost) { $phpMaxSize = $phpMaxSize ? min($phpMaxSize, $maxPost) : $maxPost; } //ini_get('memory_limit') only works if compiled with "--enable-memory-limit" $memoryLimit = Utils::returnBytes(@ini_get('memory_limit')); if ($memoryLimit && $memoryLimit != -1) { $phpMaxSize = $phpMaxSize ? min($phpMaxSize, $memoryLimit) : $memoryLimit; } $data->uploadMaxSize = $phpMaxSize; $data->uploadCheckImages = !$config->get('checkSizeAfterScaling'); $requestedType = (string) $request->query->get('type'); foreach ($resourceTypesNames as $resourceTypeName) { if ($requestedType && $requestedType !== $resourceTypeName) { continue; } $aclMask = $acl->getComputedMask($resourceTypeName, '/'); if (!(Permission::FOLDER_VIEW & $aclMask)) { continue; } $resourceType = $resourceTypeFactory->getResourceType($resourceTypeName); $resourceTypeObject = array('name' => $resourceTypeName, 'allowedExtensions' => implode(",", $resourceType->getAllowedExtensions()), 'deniedExtensions' => implode(",", $resourceType->getDeniedExtensions()), 'hash' => $resourceType->getHash(), 'acl' => $aclMask, 'maxSize' => $resourceType->getMaxSize() ? min($resourceType->getMaxSize(), $phpMaxSize) : $phpMaxSize); $resourceTypeBackend = $resourceType->getBackend(); if ($resourceType->isLazyLoaded()) { $resourceTypeObject['hasChildren'] = false; $resourceTypeObject['lazyLoad'] = true; } else { $resourceTypeObject['hasChildren'] = $resourceTypeBackend->containsDirectories($resourceType, $resourceType->getDirectory()); } if ($label = $resourceType->getLabel()) { $resourceTypeObject['label'] = $label; } $useProxyCommand = $resourceTypeBackend->usesProxyCommand(); if ($useProxyCommand) { $resourceTypeObject['useProxyCommand'] = true; } else { $baseUrl = $resourceTypeBackend->getBaseUrl(); if ($baseUrl) { $resourceTypeObject['url'] = rtrim(Path::combine($baseUrl, $resourceType->getDirectory()), '/') . '/'; } } $trackedOperations = $resourceTypeBackend->getTrackedOperations(); if (!empty($trackedOperations)) { $resourceTypeObject['trackedOperations'] = $trackedOperations; } $data->resourceTypes[] = $resourceTypeObject; } } $enabledPlugins = $config->get('plugins'); if (!empty($enabledPlugins)) { $data->plugins = $enabledPlugins; } $proxyCacheLifetime = (int) $config->get('cache.proxyCommand'); if ($proxyCacheLifetime) { $data->proxyCache = $proxyCacheLifetime; } return $data; }
/** * Constructor * * @param array|string $config an array containing configuration options or a path * to configuration file * * @see config.php */ public function __construct($config) { parent::__construct(); $app = $this; $this['config'] = function () use($config) { return new Config($config); }; $this['exception_handler'] = function () use($app) { return new ExceptionHandler($app['translator'], $app['debug'], $app['logger']); }; $this['dispatcher'] = function () use($app) { $eventDispatcher = new EventDispatcher(); $eventDispatcher->addListener(KernelEvents::VIEW, array($this, 'createResponse'), -512); $eventDispatcher->addListener(KernelEvents::RESPONSE, array($this, 'afterCommand'), -512); $eventDispatcher->addSubscriber($app['exception_handler']); return $eventDispatcher; }; $this['resolver'] = function () use($app) { $commandResolver = new CommandResolver($app); $commandResolver->setCommandsNamespace(CKFinder::COMMANDS_NAMESPACE); $commandResolver->setPluginsNamespace(CKFinder::PLUGINS_NAMESPACE); return $commandResolver; }; $this['request_stack'] = function () { return new RequestStack(); }; $this['working_folder'] = function () use($app) { $workingFolder = new WorkingFolder($app); $this['dispatcher']->addSubscriber($workingFolder); return $workingFolder; }; $this['kernel'] = function () use($app) { return new HttpKernel($app['dispatcher'], $app['resolver'], $app['request_stack']); }; $this['acl'] = function () use($app) { $config = $app['config']; $roleContext = new SessionRoleContext($config->get('roleSessionVar')); $acl = new Acl($roleContext); $acl->setRules($config->get('accessControl')); return $acl; }; $this['backend_factory'] = function () use($app) { return new BackendFactory($app['acl'], $app['config']); }; $this['resource_type_factory'] = function () use($app) { return new ResourceTypeFactory($app); }; $this['thumbnail_repository'] = function () use($app) { return new ThumbnailRepository($app); }; $this['resized_image_repository'] = function () use($app) { return new ResizedImageRepository($app); }; $this['cache'] = function () use($app) { $cacheBackend = $app['backend_factory']->getPrivateDirBackend('cache'); $cacheDir = $app['config']->getPrivateDirPath('cache') . '/data'; return new CacheManager(new BackendAdapter($cacheBackend, $cacheDir)); }; $this['translator'] = function () { return new Translator(); }; $this['debug'] = $app['config']->get('debug'); $this['logger'] = function () use($app) { $logger = new Logger('CKFinder'); if ($app['config']->isDebugLoggerEnabled('firephp')) { $logger->pushHandler(new FirePHPHandler()); } if ($app['config']->isDebugLoggerEnabled('error_log')) { $logger->pushHandler(new ErrorLogHandler()); } return $logger; }; }
/** * @param Request $request * @param WorkingFolder $workingFolder * @param EventDispatcher $dispatcher * @param Acl $acl * * @return array * * @throws \Exception */ public function execute(Request $request, WorkingFolder $workingFolder, EventDispatcher $dispatcher, Acl $acl, ResizedImageRepository $resizedImageRepository, ThumbnailRepository $thumbnailRepository) { $fileName = (string) $request->get('fileName'); $newFileName = (string) $request->get('newFileName'); $editedImage = new EditedImage($fileName, $this->app, $newFileName); $resourceType = $workingFolder->getResourceType(); if (null === $newFileName) { $resourceTypeName = $resourceType->getName(); $path = $workingFolder->getClientCurrentFolder(); if (!$acl->isAllowed($resourceTypeName, $path, Permission::FILE_DELETE)) { throw new UnauthorizedException(sprintf('Unauthorized: no FILE_DELETE permission in %s:%s', $resourceTypeName, $path)); } } if (!Image::isSupportedExtension($editedImage->getExtension())) { throw new InvalidExtensionException('Unsupported image type or not image file'); } $image = Image::create($editedImage->getContents()); $actions = (array) $request->get('actions'); if (empty($actions)) { throw new InvalidRequestException(); } foreach ($actions as $actionInfo) { if (!isset($actionInfo['action'])) { throw new InvalidRequestException('ImageEdit: action name missing'); } switch ($actionInfo['action']) { case self::OPERATION_CROP: if (!Utils::arrayContainsKeys($actionInfo, array('x', 'y', 'width', 'height'))) { throw new InvalidRequestException(); } $x = $actionInfo['x']; $y = $actionInfo['y']; $width = $actionInfo['width']; $height = $actionInfo['height']; $image->crop($x, $y, $width, $height); break; case self::OPERATION_ROTATE: if (!isset($actionInfo['angle'])) { throw new InvalidRequestException(); } $degrees = $actionInfo['angle']; $bgcolor = isset($actionInfo['bgcolor']) ? $actionInfo['bgcolor'] : 0; $image->rotate($degrees, $bgcolor); break; case self::OPERATION_RESIZE: if (!Utils::arrayContainsKeys($actionInfo, array('width', 'height'))) { throw new InvalidRequestException(); } $width = $actionInfo['width']; $height = $actionInfo['height']; $image->resize($width, $height); break; } } $editFileEvent = new EditFileEvent($this->app, $editedImage); $editedImage->setNewContents($image->getData()); $editedImage->setNewDimensions($image->getWidth(), $image->getHeight()); if (!$editedImage->isValid()) { throw new InvalidUploadException('Invalid file provided'); } $dispatcher->dispatch(CKFinderEvent::EDIT_IMAGE, $editFileEvent); $saved = false; if (!$editFileEvent->isPropagationStopped()) { $saved = $editedImage->save($editFileEvent->getNewContents()); //Remove thumbnails and resized images in case if file is overwritten if ($newFileName === null && $saved) { $thumbnailRepository->deleteThumbnails($resourceType, $workingFolder->getClientCurrentFolder(), $fileName); $resizedImageRepository->deleteResizedImages($resourceType, $workingFolder->getClientCurrentFolder(), $fileName); } } return array('saved' => (int) $saved, 'date' => Utils::formatDate(time())); }
/** * Checks if directory contains subdirectories * * @param Backend $backend * @param ResourceType $resourceType * @param string $clientPath * @param Acl $acl * * @return bool */ public function containsDirectories(Backend $backend, ResourceType $resourceType, $clientPath, Acl $acl) { $location = rtrim($this->applyPathPrefix(Path::combine($resourceType->getDirectory(), $clientPath)), '/\\') . '/'; if (!is_dir($location) || false === ($fh = @opendir($location))) { return false; } $hasChildren = false; $resourceTypeName = $resourceType->getName(); $clientPath = rtrim($clientPath, '/\\') . '/'; while (false !== ($filename = readdir($fh))) { if ($filename == '.' || $filename == '..') { continue; } if (is_dir($location . $filename)) { if (!$acl->isAllowed($resourceTypeName, $clientPath . $filename, Permission::FOLDER_VIEW)) { continue; } if ($backend->isHiddenFolder($filename)) { continue; } $hasChildren = true; break; } } closedir($fh); return $hasChildren; }