/** * 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; }
/** * @return bool */ public static function selfupgrade() { $upgrader = new Upgrader(); if (!Installer::isGravInstance(GRAV_ROOT)) { return false; } if (is_link(GRAV_ROOT . DS . 'index.php')) { Installer::setError(Installer::IS_LINK); return false; } if (method_exists($upgrader, 'meetsRequirements') && !$upgrader->meetsRequirements()) { $error = []; $error[] = '<p>Grav has increased the minimum PHP requirement.<br />'; $error[] = 'You are currently running PHP <strong>' . PHP_VERSION . '</strong>'; $error[] = ', but PHP <strong>' . GRAV_PHP_MIN . '</strong> is required.</p>'; $error[] = '<p><a href="http://getgrav.org/blog/changing-php-requirements-to-5.5" class="button button-small secondary">Additional information</a></p>'; Installer::setError(implode("\n", $error)); return false; } $update = $upgrader->getAssets()['grav-update']; $tmp = Admin::getTempDir() . '/Grav-' . uniqid(); $file = self::_downloadSelfupgrade($update, $tmp); Installer::install($file, GRAV_ROOT, ['sophisticated' => true, 'overwrite' => true, 'ignore_symlinks' => true]); $errorCode = Installer::lastErrorCode(); Folder::delete($tmp); if ($errorCode & (Installer::ZIP_OPEN_ERROR | Installer::ZIP_EXTRACT_ERROR)) { return false; } return true; }