diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c89cfc8c..41586628a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# v0.9.31 +## 07/09/2015 + +1. [](#new) + * Added xml, json, css and js to valid media file types +2. [](#improved) + * Better handling of unsupported media type downloads + * Improved `bin/grav backup` command to mimic admin plugin location/name +3. [](#bugfix) + * Critical fix for broken language translations + * Fix for Twig markdown filter error + * Safety check for download extension + # v0.9.30 ## 07/08/2015 diff --git a/bin/composer.phar b/bin/composer.phar index a08ea4eba..4b099f5b8 100755 Binary files a/bin/composer.phar and b/bin/composer.phar differ diff --git a/system/config/media.yaml b/system/config/media.yaml index 62dfa75eb..443ec8aeb 100644 --- a/system/config/media.yaml +++ b/system/config/media.yaml @@ -75,6 +75,10 @@ txt: type: file thumb: media/thumb-txt.png mime: text/plain +xml: + type: file + thumb: media/thumb-xml.png + mime: application/xml doc: type: file thumb: media/thumb-doc.png @@ -95,3 +99,16 @@ gz: type: file thumb: media/thumb-gz.png mime: application/gzip +css: + type: file + thumb: media/thumb-css.png + mime: text/css +js: + type: file + thumb: media/thumb-js.png + mime: application/javascript +json: + type: file + thumb: media/thumb-json.png + mime: application/json + diff --git a/system/config/system.yaml b/system/config/system.yaml index fa8b6019c..0e68a3e6f 100644 --- a/system/config/system.yaml +++ b/system/config/system.yaml @@ -30,7 +30,7 @@ pages: special_chars: # List of special characters to automatically convert to entities '>': 'gt' '<': 'lt' - types: 'txt|xml|html|json|rss|atom' # Pipe separated list of valid page types + types: [txt,xml,html,json,rss,atom] # list of valid page types expires: 604800 # Page expires time in seconds (604800 seconds = 7 days) last_modified: false # Set the last modified date header based on file modifcation timestamp etag: false # Set the etag header tag @@ -82,11 +82,12 @@ images: media: enable_media_timestamp: false # Enable media timetsamps upload_limit: 0 # Set maximum upload size in bytes (0 is unlimited) + unsupported_inline_types: [] # Array of unsupported media file types to try to display inline session: - enabled: true # Enable Session support - timeout: 1800 # Timeout in seconds - name: grav-site # Name prefix of the session cookie + enabled: true # Enable Session support + timeout: 1800 # Timeout in seconds + name: grav-site # Name prefix of the session cookie security: default_hash: $2y$10$kwsyMVwM8/7j0K/6LHT.g.Fs49xOCTp2b8hh/S5.dPJuJcJB6T.UK diff --git a/system/defines.php b/system/defines.php index ecbf279c5..1f80d03a8 100644 --- a/system/defines.php +++ b/system/defines.php @@ -2,7 +2,7 @@ // Some standard defines define('GRAV', true); -define('GRAV_VERSION', '0.9.30'); +define('GRAV_VERSION', '0.9.31'); define('DS', '/'); // Directories and Paths diff --git a/system/src/Grav/Common/Config/Config.php b/system/src/Grav/Common/Config/Config.php index f1d2d611b..9e749c652 100644 --- a/system/src/Grav/Common/Config/Config.php +++ b/system/src/Grav/Common/Config/Config.php @@ -179,7 +179,7 @@ class Config extends Data $this->loadCompiledConfig($this->configLookup, $this->pluginLookup, 'master'); // process languages if supported - if ($this->get('languages', false)) { + if ($this->get('system.languages', false)) { $this->languagesLookup = $locator->findResources('languages://'); $this->loadCompiledLanguages($this->languagesLookup, $this->pluginLookup, 'master'); } diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php index 71810e23e..c9c4aa221 100644 --- a/system/src/Grav/Common/Grav.php +++ b/system/src/Grav/Common/Grav.php @@ -437,11 +437,11 @@ class Grav extends Container Utils::download($medium->path(), false); } - // has an extension, try to download it... - if (isset($path_parts['extension'])) { + // unsupported media type, try to download it... + $extension = $uri->extension() ?: isset($path_parts['extension']) ? $path_parts['extension'] : null; + if ($extension) { $download = true; - // little work-around to ensure .css and .js files are always sent inline not downloaded - if (in_array($path_parts['extension'], ['.css', '.js'])) { + if (in_array(ltrim($extension, '.'), $this['config']->get('system.media.unsupported_inline_types'))) { $download = false; } Utils::download($page->path() . DIRECTORY_SEPARATOR . $uri->basename(), $download); diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php index 8f64059f2..a479c52c5 100644 --- a/system/src/Grav/Common/Page/Page.php +++ b/system/src/Grav/Common/Page/Page.php @@ -138,7 +138,6 @@ class Page } } $this->published(); - $this->extension(); } /** diff --git a/system/src/Grav/Common/TwigExtension.php b/system/src/Grav/Common/TwigExtension.php index 77d06bcfe..448c98af4 100644 --- a/system/src/Grav/Common/TwigExtension.php +++ b/system/src/Grav/Common/TwigExtension.php @@ -339,7 +339,7 @@ class TwigExtension extends \Twig_Extension public function markdownFilter($string) { $page = $this->grav['page']; - $defaults = $this->$config->get('system.pages.markdown'); + $defaults = $this->config->get('system.pages.markdown'); // Initialize the preferred variant of Parsedown if ($defaults['extra']) { diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php index c070dfcf2..cf24146dd 100644 --- a/system/src/Grav/Common/Uri.php +++ b/system/src/Grav/Common/Uri.php @@ -120,7 +120,9 @@ class Uri // set the original basename $this->basename = $parts['basename']; - if (preg_match("/\.(".$config->get('system.pages.types').")$/", $parts['basename'])) { + $valid_page_types = implode('|', $config->get('system.pages.types')); + + if (preg_match("/\.(".$valid_page_types.")$/", $parts['basename'])) { $uri = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, $parts['dirname']), DS). '/' .$parts['filename']; $this->extension = $parts['extension']; } diff --git a/system/src/Grav/Console/Cli/BackupCommand.php b/system/src/Grav/Console/Cli/BackupCommand.php index 46590bf39..a597efc7d 100644 --- a/system/src/Grav/Console/Cli/BackupCommand.php +++ b/system/src/Grav/Console/Cli/BackupCommand.php @@ -1,13 +1,15 @@ addArgument( 'destination', InputArgument::OPTIONAL, - 'Where to store the backup' + 'Where to store the backup (/backup is default)' ) ->setDescription("Creates a backup of the Grav instance") ->setHelp('The backup creates a zipped backup. Optionally can be saved in a different destination.'); - $this->source = getcwd(); } @@ -57,19 +49,22 @@ class BackupCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->output = $output; - - $output->getFormatter()->setStyle('red', new OutputFormatterStyle('red')); - $output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan')); - $output->getFormatter()->setStyle('green', new OutputFormatterStyle('green')); - $output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta')); + $this->setupConsole($input, $output); $this->progress = new ProgressBar($output); $this->progress->setFormat('Archiving %current% files [%bar%] %elapsed:6s% %memory:6s%'); - $destination = ($input->getArgument('destination')) ? $input->getArgument('destination') : ROOT_DIR; + self::getGrav()['config']->init(); - ZipBackup::backup($destination, [$this, 'output']); + $destination = ($input->getArgument('destination')) ? $input->getArgument('destination') : null; + $log = JsonFile::instance(self::getGrav()['locator']->findResource("log://backup.log", true, true)); + $backup = ZipBackup::backup($destination, [$this, 'output']); + + $log->content([ + 'time' => time(), + 'location' => $backup + ]); + $log->save(); $output->writeln(''); $output->writeln(''); @@ -97,5 +92,6 @@ class BackupCommand extends Command break; } } + } diff --git a/system/src/Grav/Console/Cli/CleanCommand.php b/system/src/Grav/Console/Cli/CleanCommand.php index 5ceaed611..350c9ab54 100644 --- a/system/src/Grav/Console/Cli/CleanCommand.php +++ b/system/src/Grav/Console/Cli/CleanCommand.php @@ -2,6 +2,7 @@ namespace Grav\Console\Cli; use Grav\Common\Filesystem\Folder; +use Grav\Console\ConsoleTrait; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\InputInterface; @@ -13,6 +14,7 @@ use Symfony\Component\Console\Output\OutputInterface; */ class CleanCommand extends Command { + use ConsoleTrait; /** * @var array @@ -177,27 +179,14 @@ class CleanCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { - - - // Create a red output option - $output->getFormatter()->setStyle('red', new OutputFormatterStyle('red')); - $output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan')); - $output->getFormatter()->setStyle('green', new OutputFormatterStyle('green')); - $output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta')); - - $this->cleanPaths($output); - - + $this->setupConsole($input, $output); + $this->cleanPaths(); } - // loops over the array of paths and deletes the files/folders - /** - * @param OutputInterface $output - */ - private function cleanPaths(OutputInterface $output) + private function cleanPaths() { - $output->writeln(''); - $output->writeln('DELETING'); + $this->output->writeln(''); + $this->output->writeln('DELETING'); $anything = false; @@ -206,16 +195,16 @@ class CleanCommand extends Command if (is_dir($path) && @Folder::delete($path)) { $anything = true; - $output->writeln('dir: ' . $path); + $this->output->writeln('dir: ' . $path); } elseif (is_file($path) && @unlink($path)) { $anything = true; - $output->writeln('file: ' . $path); + $this->output->writeln('file: ' . $path); } } if (!$anything) { - $output->writeln(''); - $output->writeln('Nothing to clean...'); + $this->output->writeln(''); + $this->output->writeln('Nothing to clean...'); } } diff --git a/system/src/Grav/Console/Cli/ClearCacheCommand.php b/system/src/Grav/Console/Cli/ClearCacheCommand.php index e565671e9..944064839 100644 --- a/system/src/Grav/Console/Cli/ClearCacheCommand.php +++ b/system/src/Grav/Console/Cli/ClearCacheCommand.php @@ -2,6 +2,7 @@ namespace Grav\Console\Cli; use Grav\Common\Cache; +use Grav\Console\ConsoleTrait; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\InputInterface; @@ -14,6 +15,7 @@ use Symfony\Component\Console\Output\OutputInterface; */ class ClearCacheCommand extends Command { + use ConsoleTrait; /** * @@ -38,40 +40,33 @@ class ClearCacheCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { - // Create a red output option - $output->getFormatter()->setStyle('red', new OutputFormatterStyle('red')); - $output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan')); - $output->getFormatter()->setStyle('green', new OutputFormatterStyle('green')); - $output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta')); - - $this->cleanPaths($input, $output); + $this->setupConsole($input, $output); + $this->cleanPaths(); } - // loops over the array of paths and deletes the files/folders /** - * @param InputInterface $input - * @param OutputInterface $output + * loops over the array of paths and deletes the files/folders */ - private function cleanPaths(InputInterface $input, OutputInterface $output) + private function cleanPaths() { - $output->writeln(''); - $output->writeln('Clearing cache'); - $output->writeln(''); + $this->output->writeln(''); + $this->output->writeln('Clearing cache'); + $this->output->writeln(''); - if ($input->getOption('all')) { + if ($this->input->getOption('all')) { $remove = 'all'; - } elseif ($input->getOption('assets-only')) { + } elseif ($this->input->getOption('assets-only')) { $remove = 'assets-only'; - } elseif ($input->getOption('images-only')) { + } elseif ($this->input->getOption('images-only')) { $remove = 'images-only'; - } elseif ($input->getOption('cache-only')) { + } elseif ($this->input->getOption('cache-only')) { $remove = 'cache-only'; } else { $remove = 'standard'; } foreach (Cache::clearCache($remove) as $result) { - $output->writeln($result); + $this->output->writeln($result); } } } diff --git a/system/src/Grav/Console/Cli/ComposerCommand.php b/system/src/Grav/Console/Cli/ComposerCommand.php index 3a28718ac..2688b78c1 100644 --- a/system/src/Grav/Console/Cli/ComposerCommand.php +++ b/system/src/Grav/Console/Cli/ComposerCommand.php @@ -66,6 +66,8 @@ class ComposerCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->setupConsole($input, $output); + $action = 'update'; if ($input->getOption('install')) { diff --git a/system/src/Grav/Console/Cli/InstallCommand.php b/system/src/Grav/Console/Cli/InstallCommand.php index 8aead008f..ef2c2fa71 100644 --- a/system/src/Grav/Console/Cli/InstallCommand.php +++ b/system/src/Grav/Console/Cli/InstallCommand.php @@ -65,6 +65,7 @@ class InstallCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->setupConsole($input, $output); $dependencies_file = '.dependencies'; $local_config_file = exec('eval echo ~/.grav/config'); @@ -74,12 +75,6 @@ class InstallCommand extends Command $this->destination = rtrim($this->destination, DS) . DS; $this->user_path = $this->destination . USER_PATH; - // Create a red output option - $output->getFormatter()->setStyle('red', new OutputFormatterStyle('red')); - $output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan')); - $output->getFormatter()->setStyle('green', new OutputFormatterStyle('green')); - $output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta')); - if (file_exists($local_config_file)) { $this->local_config = Yaml::parse($local_config_file); $output->writeln('Read local config from ' . $local_config_file . ''); @@ -101,9 +96,9 @@ class InstallCommand extends Command $output->writeln("\nInstalling vendor dependencies"); $output->writeln($this->composerUpdate(GRAV_ROOT, 'install')); - $this->gitclone($output); + $this->gitclone(); } else { - $this->symlink($output); + $this->symlink(); } } else { $output->writeln('ERROR invalid YAML in ' . $dependencies_file); @@ -112,45 +107,43 @@ class InstallCommand extends Command } - // loops over the array of paths and deletes the files/folders /** - * @param OutputInterface $output + * Clones from Git */ - private function gitclone(OutputInterface $output) + private function gitclone() { - $output->writeln(''); - $output->writeln('Cloning Bits'); - $output->writeln('============'); - $output->writeln(''); + $this->output->writeln(''); + $this->output->writeln('Cloning Bits'); + $this->output->writeln('============'); + $this->output->writeln(''); foreach ($this->config['git'] as $repo => $data) { $path = $this->destination . DS . $data['path']; if (!file_exists($path)) { exec('cd "' . $this->destination . '" && git clone -b ' . $data['branch'] . ' ' . $data['url'] . ' ' . $data['path']); - $output->writeln('SUCCESS cloned ' . $data['url'] . ' -> ' . $path . ''); - $output->writeln(''); + $this->output->writeln('SUCCESS cloned ' . $data['url'] . ' -> ' . $path . ''); + $this->output->writeln(''); } else { - $output->writeln('' . $path . ' already exists, skipping...'); - $output->writeln(''); + $this->output->writeln('' . $path . ' already exists, skipping...'); + $this->output->writeln(''); } } } - // loops over the array of paths and deletes the files/folders /** - * @param OutputInterface $output + * Symlinks */ - private function symlink(OutputInterface $output) + private function symlink() { - $output->writeln(''); - $output->writeln('Symlinking Bits'); - $output->writeln('==============='); - $output->writeln(''); + $this->output->writeln(''); + $this->output->writeln('Symlinking Bits'); + $this->output->writeln('==============='); + $this->output->writeln(''); if (!$this->local_config) { - $output->writeln('No local configuration available, aborting...'); - $output->writeln(''); + $this->output->writeln('No local configuration available, aborting...'); + $this->output->writeln(''); return; } @@ -162,15 +155,15 @@ class InstallCommand extends Command if (file_exists($from)) { if (!file_exists($to)) { symlink($from, $to); - $output->writeln('SUCCESS symlinked ' . $data['src'] . ' -> ' . $data['path'] . ''); - $output->writeln(''); + $this->output->writeln('SUCCESS symlinked ' . $data['src'] . ' -> ' . $data['path'] . ''); + $this->output->writeln(''); } else { - $output->writeln('destination: ' . $to . ' already exists, skipping...'); - $output->writeln(''); + $this->output->writeln('destination: ' . $to . ' already exists, skipping...'); + $this->output->writeln(''); } } else { - $output->writeln('source: ' . $from . ' does not exists, skipping...'); - $output->writeln(''); + $this->output->writeln('source: ' . $from . ' does not exists, skipping...'); + $this->output->writeln(''); } } diff --git a/system/src/Grav/Console/Cli/NewProjectCommand.php b/system/src/Grav/Console/Cli/NewProjectCommand.php index 708b01901..6e193fe25 100644 --- a/system/src/Grav/Console/Cli/NewProjectCommand.php +++ b/system/src/Grav/Console/Cli/NewProjectCommand.php @@ -1,6 +1,7 @@ setupConsole($input, $output); $sandboxCommand = $this->getApplication()->find('sandbox'); $installCommand = $this->getApplication()->find('install'); diff --git a/system/src/Grav/Console/Cli/SandboxCommand.php b/system/src/Grav/Console/Cli/SandboxCommand.php index a5a6ce126..d490655a6 100644 --- a/system/src/Grav/Console/Cli/SandboxCommand.php +++ b/system/src/Grav/Console/Cli/SandboxCommand.php @@ -2,6 +2,7 @@ namespace Grav\Console\Cli; use Grav\Common\Filesystem\Folder; +use Grav\Console\ConsoleTrait; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Input\InputArgument; @@ -15,6 +16,8 @@ use Symfony\Component\Console\Output\OutputInterface; */ class SandboxCommand extends Command { + use ConsoleTrait; + /** * @var array */ @@ -66,22 +69,8 @@ class SandboxCommand extends Command protected $default_file = "---\ntitle: HomePage\n---\n# HomePage\n\nLorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque porttitor eu felis sed ornare. Sed a mauris venenatis, pulvinar velit vel, dictum enim. Phasellus ac rutrum velit. Nunc lorem purus, hendrerit sit amet augue aliquet, iaculis ultricies nisl. Suspendisse tincidunt euismod risus, quis feugiat arcu tincidunt eget. Nulla eros mi, commodo vel ipsum vel, aliquet congue odio. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Pellentesque velit orci, laoreet at adipiscing eu, interdum quis nibh. Nunc a accumsan purus."; - /** - * @var - */ protected $source; - /** - * @var - */ protected $destination; - /** - * @var InputInterface $input - */ - protected $input; - /** - * @var OutputInterface $output - */ - protected $output; /** * @@ -114,14 +103,8 @@ class SandboxCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { + $this->setupConsole($input, $output); $this->destination = $input->getArgument('destination'); - $this->input = $input; - $this->output = $output; - - // Create a red output option - $this->output->getFormatter()->setStyle('red', new OutputFormatterStyle('red')); - $this->output->getFormatter()->setStyle('cyan', new OutputFormatterStyle('cyan')); - $this->output->getFormatter()->setStyle('magenta', new OutputFormatterStyle('magenta')); // Symlink the Core Stuff if ($input->getOption('symlink')) {