private function cleanFilesData($key, $file)
 {
     $config = $this->grav['config'];
     $blueprint = isset($this->items['fields'][$key]['files']) ? $this->items['fields'][$key]['files'] : [];
     /** @var Page $page */
     $page = null;
     $cleanFiles[$key] = [];
     if (!isset($blueprint)) {
         return false;
     }
     $type = trim("{$this->view}/{$this->admin->route}", '/');
     $data = $this->admin->data($type, $this->post);
     $fields = $data->blueprints()->fields();
     $blueprint = isset($fields[$key]) ? $fields[$key] : [];
     $cleanFiles = [$key => []];
     foreach ((array) $file['error'] as $index => $error) {
         if ($error == UPLOAD_ERR_OK) {
             $tmp_name = $file['tmp_name'][$index];
             $name = $file['name'][$index];
             $type = $file['type'][$index];
             $destination = Folder::getRelativePath(rtrim($blueprint['destination'], '/'));
             if (!$this->match_in_array($type, $blueprint['accept'])) {
                 throw new \RuntimeException('File "' . $name . '" is not an accepted MIME type.');
             }
             if (Utils::startsWith($destination, '@page:')) {
                 $parts = explode(':', $destination);
                 $route = $parts[1];
                 $page = $this->grav['page']->find($route);
                 if (!$page) {
                     throw new \RuntimeException('Unable to upload file to destination. Page route not found.');
                 }
                 $destination = $page->relativePagePath();
             } else {
                 if ($destination == '@self') {
                     $page = $this->admin->page(true);
                     $destination = $page->relativePagePath();
                 } else {
                     Folder::mkdir($destination);
                 }
             }
             if (move_uploaded_file($tmp_name, "{$destination}/{$name}")) {
                 $path = $page ? $this->grav['uri']->convertUrl($page, $page->route() . '/' . $name) : $destination . '/' . $name;
                 $cleanFiles[$key][] = $path;
             } else {
                 throw new \RuntimeException("Unable to upload file(s) to {$destination}/{$name}");
             }
         }
     }
     return $cleanFiles[$key];
 }
 /**
  * Detects all plugins with a configuration file and returns last modification time.
  *
  * @param  string $lookup Location to look up from.
  * @param  bool $blueprints
  * @return array
  * @internal
  */
 protected function detectConfig($lookup = SYSTEM_DIR, $blueprints = false)
 {
     $location = $blueprints ? 'blueprintFiles' : 'configFiles';
     $path = trim(Folder::getRelativePath($lookup), '/');
     if (isset($this->{$location}[$path])) {
         return [$path => $this->{$location}[$path]];
     }
     if (is_dir($lookup)) {
         // Find all system and user configuration files.
         $options = ['compare' => 'Filename', 'pattern' => '|\\.yaml$|', 'filters' => ['key' => '|\\.yaml$|', 'value' => function (\RecursiveDirectoryIterator $file) use($path) {
             return ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()];
         }], 'key' => 'SubPathname'];
         $list = Folder::all($lookup, $options);
     } else {
         $list = [];
     }
     $this->{$location}[$path] = $list;
     return [$path => $list];
 }
Beispiel #3
0
 private function cleanFilesData($key, $file)
 {
     /** @var Page $page */
     $page = null;
     $blueprint = $this->items['fields'][$key]['files'];
     $cleanFiles[$key] = [];
     if (!isset($blueprint)) {
         return false;
     }
     $cleanFiles = [$key => []];
     foreach ((array) $file['error'] as $index => $error) {
         if ($error == UPLOAD_ERR_OK) {
             $tmp_name = $file['tmp_name'][$index];
             $name = $file['name'][$index];
             $type = $file['type'][$index];
             $destination = Folder::getRelativePath(rtrim($blueprint['destination'], '/'));
             if (!$this->match_in_array($type, $blueprint['accept'])) {
                 throw new \RuntimeException('File "' . $name . '" is not an accepted MIME type.');
             }
             if (Utils::startsWith($destination, '@page:')) {
                 $parts = explode(':', $destination);
                 $route = $parts[1];
                 $page = self::getGrav()['page']->find($route);
                 if (!$page) {
                     throw new \RuntimeException('Unable to upload file to destination. Page route not found.');
                 }
                 $destination = $page->relativePagePath();
             } else {
                 if ($destination == '@self') {
                     $page = self::getGrav()['page'];
                     $destination = $page->relativePagePath();
                 } else {
                     Folder::mkdir($destination);
                 }
             }
             if (move_uploaded_file($tmp_name, "{$destination}/{$name}")) {
                 $path = $page ? self::getGrav()['uri']->convertUrl($page, $page->route() . '/' . $name) : $destination . '/' . $name;
                 $cleanFiles[$key][$path] = ['name' => $file['name'][$index], 'type' => $file['type'][$index], 'size' => $file['size'][$index], 'file' => $destination . '/' . $name, 'route' => $page ? $path : null];
             } else {
                 throw new \RuntimeException('Unable to upload file(s). Error Code: ' . $error);
             }
         }
     }
     return $cleanFiles[$key];
 }
Beispiel #4
0
 /**
  * Detects all plugins with a configuration file and returns them with last modification time.
  *
  * @param  string $folder   Location to look up from.
  * @param  string $pattern  Pattern to match the file. Pattern will also be removed from the key.
  * @param  int    $levels   Maximum number of recursive directories.
  * @return array
  * @internal
  */
 protected function detectAll($folder, $pattern, $levels)
 {
     $path = trim(Folder::getRelativePath($folder), '/');
     if (is_dir($folder)) {
         // Find all system and user configuration files.
         $options = ['levels' => $levels, 'compare' => 'Filename', 'pattern' => $pattern, 'filters' => ['pre-key' => $this->base, 'key' => $pattern, 'value' => function (\RecursiveDirectoryIterator $file) use($path) {
             return ["{$path}/{$file->getSubPathname()}" => $file->getMTime()];
         }], 'key' => 'SubPathname'];
         $list = Folder::all($folder, $options);
         ksort($list);
     } else {
         $list = [];
     }
     return $list;
 }
Beispiel #5
0
 /**
  * Detects all plugins with a configuration file and returns them with last modification time.
  *
  * @param  string $folder Location to look up from.
  * @return array
  * @internal
  */
 protected function detectRecursive($folder)
 {
     $path = trim(Folder::getRelativePath($folder), '/');
     if (is_dir($folder)) {
         // Find all system and user configuration files.
         $options = ['compare' => 'Filename', 'pattern' => '|\\.yaml$|', 'filters' => ['key' => '|\\.yaml$|', 'value' => function (\RecursiveDirectoryIterator $file) use($path) {
             return ['file' => "{$path}/{$file->getSubPathname()}", 'modified' => $file->getMTime()];
         }], 'key' => 'SubPathname'];
         $list = Folder::all($folder, $options);
     } else {
         $list = [];
     }
     return [$path => $list];
 }
Beispiel #6
0
<?php

/**
 * Multisite setup for sub-directories or path based
 * URLs for subsites.
 *
 * DO NOT EDIT UNLESS YOU KNOW WHAT YOU ARE DOING!
 */
use Grav\Common\Filesystem\Folder;
// Get relative path from Grav root.
$path = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : Folder::getRelativePath($_SERVER['REQUEST_URI'], ROOT_DIR);
// Extract name of subsite from path
$name = Folder::shift($path);
$folder = "sites/{$name}";
$prefix = "/{$name}";
if (!$name || !is_dir(ROOT_DIR . "user/{$folder}")) {
    return [];
}
// Prefix all pages with the name of the subsite
$container['pages']->base($prefix);
return ['environment' => $name, 'streams' => ['schemes' => ['user' => ['type' => 'ReadOnlyStream', 'prefixes' => ['' => ["user/{$folder}"]]]]]];
Beispiel #7
0
 /**
  * Handles ajax upload for files.
  * Stores in a flash object the temporary file and deals with potential file errors.
  *
  * @return mixed True if the action was performed.
  */
 public function uploadFiles()
 {
     $post = $_POST;
     $grav = Grav::instance();
     $uri = $grav['uri']->url;
     $config = $grav['config'];
     $session = $grav['session'];
     $settings = $this->data->blueprints()->schema()->getProperty($post['name']);
     $settings = (object) array_merge(['destination' => $config->get('plugins.form.files.destination', 'self@'), 'avoid_overwriting' => $config->get('plugins.form.files.avoid_overwriting', false), 'random_name' => $config->get('plugins.form.files.random_name', false), 'accept' => $config->get('plugins.form.files.accept', ['image/*']), 'limit' => $config->get('plugins.form.files.limit', 10), 'filesize' => $config->get('plugins.form.files.filesize', 5242880)], (array) $settings, ['name' => $post['name']]);
     $upload = $this->normalizeFiles($_FILES['data'], $settings->name);
     // Handle errors and breaks without proceeding further
     if ($upload->file->error != UPLOAD_ERR_OK) {
         // json_response
         return ['status' => 'error', 'message' => sprintf($grav['language']->translate('PLUGIN_FORM.FILEUPLOAD_UNABLE_TO_UPLOAD', null, true), $upload->file->name, $this->upload_errors[$upload->file->error])];
     } else {
         // Remove the error object to avoid storing it
         unset($upload->file->error);
         // we need to move the file at this stage or else
         // it won't be available upon save later on
         // since php removes it from the upload location
         $tmp_dir = Grav::instance()['locator']->findResource('tmp://', true, true);
         $tmp_file = $upload->file->tmp_name;
         $tmp = $tmp_dir . '/uploaded-files/' . basename($tmp_file);
         Folder::create(dirname($tmp));
         if (!move_uploaded_file($tmp_file, $tmp)) {
             // json_response
             return ['status' => 'error', 'message' => sprintf($grav['language']->translate('PLUGIN_FORM.FILEUPLOAD_UNABLE_TO_MOVE', null, true), '', $tmp)];
         }
         $upload->file->tmp_name = $tmp;
     }
     // Handle file size limits
     $settings->filesize *= 1048576;
     // 2^20 [MB in Bytes]
     if ($settings->filesize > 0 && $upload->file->size > $settings->filesize) {
         // json_response
         return ['status' => 'error', 'message' => $grav['language']->translate('PLUGIN_FORM.EXCEEDED_GRAV_FILESIZE_LIMIT')];
     }
     // Handle Accepted file types
     // Accept can only be mime types (image/png | image/*) or file extensions (.pdf|.jpg)
     $accepted = false;
     $errors = [];
     foreach ((array) $settings->accept as $type) {
         // Force acceptance of any file when star notation
         if ($type == '*') {
             $accepted = true;
             break;
         }
         $isMime = strstr($type, '/');
         $find = str_replace('*', '.*', $type);
         $match = preg_match('#' . $find . '$#', $isMime ? $upload->file->type : $upload->file->name);
         if (!$match) {
             $message = $isMime ? 'The MIME type "' . $upload->file->type . '"' : 'The File Extension';
             $errors[] = $message . ' for the file "' . $upload->file->name . '" is not an accepted.';
             $accepted |= false;
         } else {
             $accepted |= true;
         }
     }
     if (!$accepted) {
         // json_response
         return ['status' => 'error', 'message' => implode('<br />', $errors)];
     }
     // Retrieve the current session of the uploaded files for the field
     // and initialize it if it doesn't exist
     $sessionField = base64_encode($uri);
     $flash = $session->getFlashObject('files-upload');
     if (!$flash) {
         $flash = [];
     }
     if (!isset($flash[$sessionField])) {
         $flash[$sessionField] = [];
     }
     if (!isset($flash[$sessionField][$upload->field])) {
         $flash[$sessionField][$upload->field] = [];
     }
     // Set destination
     $destination = Folder::getRelativePath(rtrim($settings->destination, '/'));
     $destination = $this->getPagePathFromToken($destination);
     // Create destination if needed
     if (!is_dir($destination)) {
         Folder::mkdir($destination);
     }
     // Generate random name if required
     if ($settings->random_name) {
         $extension = pathinfo($upload->file->name)['extension'];
         $upload->file->name = Utils::generateRandomString(15) . '.' . $extension;
     }
     // Handle conflicting name if needed
     if ($settings->avoid_overwriting) {
         if (file_exists($destination . '/' . $upload->file->name)) {
             $upload->file->name = date('YmdHis') . '-' . $upload->file->name;
         }
     }
     // Prepare object for later save
     $path = $destination . '/' . $upload->file->name;
     $upload->file->path = $path;
     // $upload->file->route = $page ? $path : null;
     // Prepare data to be saved later
     $flash[$sessionField][$upload->field][$path] = (array) $upload->file;
     // Finally store the new uploaded file in the field session
     $session->setFlashObject('files-upload', $flash);
     // json_response
     return ['status' => 'success', 'session' => \json_encode(['sessionField' => base64_encode($uri), 'path' => $upload->file->path, 'field' => $settings->name])];
 }
Beispiel #8
0
 /**
  * Handles ajax upload for files.
  * Stores in a flash object the temporary file and deals with potential file errors.
  *
  * @return bool True if the action was performed.
  */
 public function taskFilesUpload()
 {
     if (!$this->authorizeTask('save', $this->dataPermissions()) || !isset($_FILES)) {
         return false;
     }
     /** @var Config $config */
     $config = $this->grav['config'];
     $data = $this->view == 'pages' ? $this->admin->page(true) : $this->prepareData([]);
     $settings = $data->blueprints()->schema()->getProperty($this->post['name']);
     $settings = (object) array_merge(['avoid_overwriting' => false, 'random_name' => false, 'accept' => ['image/*'], 'limit' => 10, 'filesize' => $config->get('system.media.upload_limit', 5242880)], (array) $settings, ['name' => $this->post['name']]);
     $upload = $this->normalizeFiles($_FILES['data'], $settings->name);
     if (!isset($settings->destination)) {
         $this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.DESTINATION_NOT_SPECIFIED', null, true)];
         return false;
     }
     // Do not use self@ outside of pages
     if ($this->view != 'pages' && in_array($settings->destination, ['@self', 'self@'])) {
         $this->admin->json_response = ['status' => 'error', 'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_PREVENT_SELF', null, true), $settings->destination)];
         return false;
     }
     // Handle errors and breaks without proceeding further
     if ($upload->file->error != UPLOAD_ERR_OK) {
         $this->admin->json_response = ['status' => 'error', 'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_UPLOAD', null, true), $upload->file->name, $this->upload_errors[$upload->file->error])];
         return false;
     } else {
         // Remove the error object to avoid storing it
         unset($upload->file->error);
         // we need to move the file at this stage or else
         // it won't be available upon save later on
         // since php removes it from the upload location
         $tmp_dir = Admin::getTempDir();
         $tmp_file = $upload->file->tmp_name;
         $tmp = $tmp_dir . '/uploaded-files/' . basename($tmp_file);
         Folder::create(dirname($tmp));
         if (!move_uploaded_file($tmp_file, $tmp)) {
             $this->admin->json_response = ['status' => 'error', 'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_UNABLE_TO_MOVE', null, true), '', $tmp)];
             return false;
         }
         $upload->file->tmp_name = $tmp;
     }
     // Handle file size limits
     $settings->filesize *= 1048576;
     // 2^20 [MB in Bytes]
     if ($settings->filesize > 0 && $upload->file->size > $settings->filesize) {
         $this->admin->json_response = ['status' => 'error', 'message' => $this->admin->translate('PLUGIN_ADMIN.EXCEEDED_GRAV_FILESIZE_LIMIT')];
         return false;
     }
     // Handle Accepted file types
     // Accept can only be mime types (image/png | image/*) or file extensions (.pdf|.jpg)
     $accepted = false;
     $errors = [];
     foreach ((array) $settings->accept as $type) {
         // Force acceptance of any file when star notation
         if ($type == '*') {
             $accepted = true;
             break;
         }
         $isMime = strstr($type, '/');
         $find = str_replace('*', '.*', $type);
         $match = preg_match('#' . $find . '$#', $isMime ? $upload->file->type : $upload->file->name);
         if (!$match) {
             $message = $isMime ? 'The MIME type "' . $upload->file->type . '"' : 'The File Extension';
             $errors[] = $message . ' for the file "' . $upload->file->name . '" is not an accepted.';
             $accepted |= false;
         } else {
             $accepted |= true;
         }
     }
     if (!$accepted) {
         $this->admin->json_response = ['status' => 'error', 'message' => implode('<br />', $errors)];
         return false;
     }
     // Retrieve the current session of the uploaded files for the field
     // and initialize it if it doesn't exist
     $sessionField = base64_encode($this->uri);
     $flash = $this->admin->session()->getFlashObject('files-upload');
     if (!$flash) {
         $flash = [];
     }
     if (!isset($flash[$sessionField])) {
         $flash[$sessionField] = [];
     }
     if (!isset($flash[$sessionField][$upload->field])) {
         $flash[$sessionField][$upload->field] = [];
     }
     // Set destination
     $destination = Folder::getRelativePath(rtrim($settings->destination, '/'));
     $destination = $this->admin->getPagePathFromToken($destination);
     // Create destination if needed
     if (!is_dir($destination)) {
         Folder::mkdir($destination);
     }
     // Generate random name if required
     if ($settings->random_name) {
         // TODO: document
         $extension = pathinfo($upload->file->name)['extension'];
         $upload->file->name = Utils::generateRandomString(15) . '.' . $extension;
     }
     // Handle conflicting name if needed
     if ($settings->avoid_overwriting) {
         // TODO: document
         if (file_exists($destination . '/' . $upload->file->name)) {
             $upload->file->name = date('YmdHis') . '-' . $upload->file->name;
         }
     }
     // Prepare object for later save
     $path = $destination . '/' . $upload->file->name;
     $upload->file->path = $path;
     // $upload->file->route = $page ? $path : null;
     // Prepare data to be saved later
     $flash[$sessionField][$upload->field][$path] = (array) $upload->file;
     // Finally store the new uploaded file in the field session
     $this->admin->session()->setFlashObject('files-upload', $flash);
     $this->admin->json_response = ['status' => 'success', 'session' => \json_encode(['sessionField' => base64_encode($this->uri), 'path' => $upload->file->path, 'field' => $settings->name])];
     return true;
 }
 /**
  * Used by the filepicker field to get a list of files in a folder.
  */
 protected function taskGetFilesInFolder()
 {
     if (!$this->authorizeTask('save', $this->dataPermissions())) {
         return false;
     }
     $data = $this->view == 'pages' ? $this->admin->page(true) : $this->prepareData([]);
     $settings = $data->blueprints()->schema()->getProperty($this->post['name']);
     if (isset($settings['folder'])) {
         $folder = $settings['folder'];
     } else {
         $folder = '@self';
     }
     // Do not use self@ outside of pages
     if ($this->view != 'pages' && in_array($folder, ['@self', 'self@'])) {
         $this->admin->json_response = ['status' => 'error', 'message' => sprintf($this->admin->translate('PLUGIN_ADMIN.FILEUPLOAD_PREVENT_SELF', null), $folder)];
         return false;
     }
     // Set destination
     $folder = Folder::getRelativePath(rtrim($folder, '/'));
     $folder = $this->admin->getPagePathFromToken($folder);
     $media = new Media($folder);
     $available_files = [];
     foreach ($media->all() as $name => $medium) {
         $available_files[] = $name;
     }
     // Peak in the flashObject for optimistic filepicker updates
     $pending_files = [];
     $sessionField = base64_encode($this->grav['uri']->url());
     $flash = $this->admin->session()->getFlashObject('files-upload');
     if ($flash && isset($flash[$sessionField])) {
         foreach ($flash[$sessionField] as $field => $data) {
             foreach ($data as $file) {
                 if (dirname($file['path']) === $folder) {
                     $pending_files[] = $file['name'];
                 }
             }
         }
     }
     $this->admin->session()->setFlashObject('files-upload', $flash);
     // Handle Accepted file types
     // Accept can only be file extensions (.pdf|.jpg)
     if (isset($settings['accept'])) {
         $available_files = array_filter($available_files, function ($file) use($settings) {
             return $this->filterAcceptedFiles($file, $settings);
         });
         $pending_files = array_filter($pending_files, function ($file) use($settings) {
             return $this->filterAcceptedFiles($file, $settings);
         });
     }
     $this->admin->json_response = ['status' => 'success', 'files' => array_values($available_files), 'pending' => array_values($pending_files), 'folder' => $folder];
     return true;
 }