Example #1
0
 /**
  * Check if the current route is under the admin path
  *
  * @return bool
  */
 public function isAdminPath()
 {
     if ($this->uri->route() == $this->base || substr($this->uri->route(), 0, strlen($this->base) + 1) == $this->base . '/') {
         return true;
     }
     return false;
 }
Example #2
0
 /**
  * Initialize the admin.
  *
  * @throws \RuntimeException
  */
 protected function initializeAdmin()
 {
     $this->enable(['onPagesInitialized' => ['onPagesInitialized', 1000], 'onTwigTemplatePaths' => ['onTwigTemplatePaths', 1000], 'onTwigSiteVariables' => ['onTwigSiteVariables', 1000], 'onTask.GPM' => ['onTaskGPM', 0]]);
     // Check for required plugins
     if (!$this->grav['config']->get('plugins.login.enabled') || !$this->grav['config']->get('plugins.form.enabled') || !$this->grav['config']->get('plugins.email.enabled')) {
         throw new \RuntimeException('One of the required plugins is missing or not enabled');
     }
     // Double check we have system.yaml and site.yaml
     $config_files[] = $this->grav['locator']->findResource('user://config') . '/system.yaml';
     $config_files[] = $this->grav['locator']->findResource('user://config') . '/site.yaml';
     foreach ($config_files as $config_file) {
         if (!file_exists($config_file)) {
             touch($config_file);
         }
     }
     // Decide admin template and route.
     $path = trim(substr($this->uri->route(), strlen($this->base)), '/');
     $this->template = 'dashboard';
     if ($path) {
         $array = explode('/', $path, 2);
         $this->template = array_shift($array);
         $this->route = array_shift($array);
     }
     // Initialize admin class.
     require_once __DIR__ . '/classes/admin.php';
     $this->admin = new Admin($this->grav, $this->base, $this->template, $this->route);
     // And store the class into DI container.
     $this->grav['admin'] = $this->admin;
     // Get theme for admin
     $this->theme = $this->config->get('plugins.admin.theme', 'grav');
 }
Example #3
0
 public function testInvalidLinksSubDirAbsoluteUrl()
 {
     $this->config->set('system.absolute_urls', true);
     $this->uri->initializeWithUrlAndRootPath('http://testing.dev/subdir/item2/item2-2', '/subdir')->init();
     $this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/no-page">Non Existent Page</a></p>', $this->parsedown->text('[Non Existent Page](no-page)'));
     $this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/existing-file.zip">Existent File</a></p>', $this->parsedown->text('[Existent File](existing-file.zip)'));
     $this->assertSame('<p><a href="http://testing.dev/subdir/item2/item2-2/missing-file.zip">Non Existent File</a></p>', $this->parsedown->text('[Non Existent File](missing-file.zip)'));
 }
Example #4
0
 public function testAddNonce()
 {
     $url = 'http://localhost/foo';
     $this->assertStringStartsWith($url, Uri::addNonce($url, 'test-action'));
     $this->assertStringStartsWith($url . '/nonce:', Uri::addNonce($url, 'test-action'));
     $this->uri->initializeWithURL(Uri::addNonce($url, 'test-action'))->init();
     $this->assertTrue(is_string($this->uri->param('nonce')));
     $this->assertSame(Utils::getNonce('test-action'), $this->uri->param('nonce'));
 }
Example #5
0
 protected function _before()
 {
     $grav = Fixtures::get('grav');
     $this->grav = $grav();
     $this->pages = $this->grav['pages'];
     $this->config = $this->grav['config'];
     $this->uri = $this->grav['uri'];
     $this->language = $this->grav['language'];
     $this->old_home = $this->config->get('system.home.alias');
     $this->config->set('system.home.alias', '/item1');
     $this->config->set('system.absolute_urls', false);
     $this->config->set('system.languages.supported', []);
     unset($this->grav['language']);
     $this->grav['language'] = new Language($this->grav);
     /** @var UniformResourceLocator $locator */
     $locator = $this->grav['locator'];
     $locator->addPath('page', '', 'tests/fake/nested-site/user/pages', false);
     $this->pages->init();
     $defaults = ['extra' => false, 'auto_line_breaks' => false, 'auto_url_links' => false, 'escape_markup' => false, 'special_chars' => ['>' => 'gt', '<' => 'lt']];
     $this->page = $this->pages->dispatch('/item2/item2-2');
     $this->uri->initializeWithURL('http://testing.dev/item2/item2-2')->init();
 }
Example #6
0
 /**
  * Initialize the admin.
  *
  * @throws \RuntimeException
  */
 protected function initializeAdmin()
 {
     $this->enable(['onTwigExtensions' => ['onTwigExtensions', 1000], 'onPagesInitialized' => ['onPagesInitialized', 1000], 'onTwigTemplatePaths' => ['onTwigTemplatePaths', 1000], 'onTwigSiteVariables' => ['onTwigSiteVariables', 1000], 'onTask.GPM' => ['onTaskGPM', 0]]);
     // Check for required plugins
     if (!$this->grav['config']->get('plugins.login.enabled') || !$this->grav['config']->get('plugins.form.enabled') || !$this->grav['config']->get('plugins.email.enabled')) {
         throw new \RuntimeException('One of the required plugins is missing or not enabled');
     }
     // Double check we have system.yaml and site.yaml
     $config_files[] = $this->grav['locator']->findResource('user://config') . '/system.yaml';
     $config_files[] = $this->grav['locator']->findResource('user://config') . '/site.yaml';
     foreach ($config_files as $config_file) {
         if (!file_exists($config_file)) {
             touch($config_file);
         }
     }
     // Initialize Admin Language if needed
     /** @var Language $language */
     $language = $this->grav['language'];
     if ($language->enabled() && empty($this->grav['session']->admin_lang)) {
         $this->grav['session']->admin_lang = $language->getLanguage();
     }
     // Decide admin template and route.
     $path = trim(substr($this->uri->route(), strlen($this->base)), '/');
     $this->template = 'dashboard';
     if ($path) {
         $array = explode('/', $path, 2);
         $this->template = array_shift($array);
         $this->route = array_shift($array);
     }
     // Initialize admin class.
     require_once __DIR__ . '/classes/admin.php';
     $this->admin = new Admin($this->grav, $this->base, $this->template, $this->route);
     // And store the class into DI container.
     $this->grav['admin'] = $this->admin;
     // Get theme for admin
     $this->theme = $this->config->get('plugins.admin.theme', 'grav');
     $assets = $this->grav['assets'];
     $translations = 'if (!window.translations) window.translations = {}; ' . PHP_EOL . 'window.translations.PLUGIN_ADMIN = {};' . PHP_EOL;
     // Enable language translations
     $translations_actual_state = $this->config->get('system.languages.translations');
     $this->config->set('system.languages.translations', true);
     $strings = ['EVERYTHING_UP_TO_DATE', 'UPDATES_ARE_AVAILABLE', 'IS_AVAILABLE_FOR_UPDATE', 'AND', 'IS_NOW_AVAILABLE', 'CURRENT', 'UPDATE_GRAV_NOW', 'TASK_COMPLETED', 'UPDATE', 'UPDATING_PLEASE_WAIT', 'GRAV_SYMBOLICALLY_LINKED', 'OF_YOUR', 'OF_THIS', 'HAVE_AN_UPDATE_AVAILABLE', 'UPDATE_AVAILABLE', 'UPDATES_AVAILABLE', 'FULLY_UPDATED', 'DAYS', 'PAGE_MODES', 'PAGE_TYPES', 'ACCESS_LEVELS'];
     foreach ($strings as $string) {
         $translations .= 'translations.PLUGIN_ADMIN.' . $string . ' = "' . $this->admin->translate('PLUGIN_ADMIN.' . $string) . '"; ' . PHP_EOL;
     }
     // set the actual translations state back
     $this->config->set('system.languages.translations', $translations_actual_state);
     $assets->addInlineJs($translations);
 }
Example #7
0
 public function onOutputGenerated()
 {
     // Clear flash objects for previously uploaded files
     // whenever the user switches page / reloads
     // ignoring any JSON / extension call
     if (is_null($this->uri->extension()) && $this->admin->task !== 'save') {
         // Discard any previously uploaded files session.
         // and if there were any uploaded file, remove them from the filesystem
         if ($flash = $this->session->getFlashObject('files-upload')) {
             $flash = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($flash));
             foreach ($flash as $key => $value) {
                 if ($key !== 'tmp_name') {
                     continue;
                 }
                 @unlink($value);
             }
         }
     }
 }
Example #8
0
 /**
  * Authenticate user.
  *
  * @param  array $form Form fields.
  * @return bool
  */
 public function authenticate($form)
 {
     if (!$this->user->authenticated && isset($form['username']) && isset($form['password'])) {
         $user = User::load($form['username']);
         if ($user->exists()) {
             $user->authenticated = true;
             // Authenticate user.
             $result = $user->authenticate($form['password']);
             if ($result) {
                 $this->user = $this->session->user = $user;
                 /** @var Grav $grav */
                 $grav = $this->grav;
                 $l = $this->grav['language'];
                 $this->setMessage($l->translate('LOGIN_LOGGED_IN'), 'info');
                 //                    $redirect_route =$this->getLoginRedirect() ?: $this->uri->route();
                 $redirect_route = $this->uri->route();
                 $grav->redirect($redirect_route);
             }
         }
     }
     return $this->authorise();
 }
Example #9
0
 /**
  * Authenticate user.
  *
  * @param  array $form Form fields.
  *
  * @return bool
  */
 public function authenticate($form)
 {
     if (!$this->user->authenticated && isset($form['username']) && isset($form['password'])) {
         $user = User::load($form['username']);
         //default to english if language not set
         if (empty($user->language)) {
             $user->set('language', 'en');
         }
         if ($user->exists()) {
             $user->authenticated = true;
             // Authenticate user.
             $result = $user->authenticate($form['password']);
             if ($result) {
                 $this->user = $this->session->user = $user;
                 /** @var Grav $grav */
                 $grav = $this->grav;
                 $this->setMessage($this->translate('PLUGIN_ADMIN.LOGIN_LOGGED_IN', [$this->user->language]), 'info');
                 $redirect_route = $this->uri->route();
                 $grav->redirect($redirect_route);
             }
         }
     }
     return $this->authorize();
 }
Example #10
0
 /**
  * Process an image excerpt
  *
  * @param $excerpt
  * @param $page
  * @return mixed
  */
 public static function processImageExcerpt($excerpt, $page)
 {
     $url = $excerpt['element']['attributes']['src'];
     $url_parts = parse_url(htmlspecialchars_decode(urldecode($url)));
     if (isset($url_parts['scheme']) && !Utils::startsWith($url_parts['scheme'], 'http')) {
         $stream_path = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];
         $url_parts['path'] = $stream_path;
         unset($url_parts['host']);
         unset($url_parts['scheme']);
     }
     $this_host = isset($url_parts['host']) && $url_parts['host'] == Grav::instance()['uri']->host();
     // if there is no host set but there is a path, the file is local
     if ((!isset($url_parts['host']) || $this_host) && isset($url_parts['path'])) {
         $path_parts = pathinfo($url_parts['path']);
         $media = null;
         // get the local path to page media if possible
         if ($path_parts['dirname'] == $page->url(false, false, false)) {
             // get the media objects for this page
             $media = $page->media();
         } else {
             // see if this is an external page to this one
             $base_url = rtrim(Grav::instance()['base_url_relative'] . Grav::instance()['pages']->base(), '/');
             $page_route = '/' . ltrim(str_replace($base_url, '', $path_parts['dirname']), '/');
             $ext_page = Grav::instance()['pages']->dispatch($page_route, true);
             if ($ext_page) {
                 $media = $ext_page->media();
             } else {
                 Grav::instance()->fireEvent('onMediaLocate', new Event(['route' => $page_route, 'media' => &$media]));
             }
         }
         // if there is a media file that matches the path referenced..
         if ($media && isset($media->all()[$path_parts['basename']])) {
             // get the medium object
             /** @var Medium $medium */
             $medium = $media->all()[$path_parts['basename']];
             // Process operations
             $medium = static::processMediaActions($medium, $url_parts);
             $alt = isset($excerpt['element']['attributes']['alt']) ? $excerpt['element']['attributes']['alt'] : '';
             $title = isset($excerpt['element']['attributes']['title']) ? $excerpt['element']['attributes']['title'] : '';
             $class = isset($excerpt['element']['attributes']['class']) ? $excerpt['element']['attributes']['class'] : '';
             $id = isset($excerpt['element']['attributes']['id']) ? $excerpt['element']['attributes']['id'] : '';
             $excerpt['element'] = $medium->parseDownElement($title, $alt, $class, $id, true);
         } else {
             // not a current page media file, see if it needs converting to relative
             $excerpt['element']['attributes']['src'] = Uri::buildUrl($url_parts);
         }
     }
     return $excerpt;
 }
Example #11
0
 /**
  * Handle form processing instructions.
  *
  * @param Event $event
  */
 public function onFormProcessed(Event $event)
 {
     $form = $event['form'];
     $action = $event['action'];
     $params = $event['params'];
     $this->process($form);
     switch ($action) {
         case 'captcha':
             if (isset($params['recaptcha_secret'])) {
                 $recaptchaSecret = $params['recaptcha_secret'];
             } else {
                 if (isset($params['recatpcha_secret'])) {
                     // Included for backwards compatibility with typo (issue #51)
                     $recaptchaSecret = $params['recatpcha_secret'];
                 } else {
                     $recaptchaSecret = $this->config->get('plugins.form.recaptcha.secret_key');
                 }
             }
             // Validate the captcha
             $query = http_build_query(['secret' => $recaptchaSecret, 'response' => $form->value('g-recaptcha-response', true)]);
             $url = 'https://www.google.com/recaptcha/api/siteverify?' . $query;
             $response = json_decode(file_get_contents($url), true);
             if (!isset($response['success']) || $response['success'] !== true) {
                 $this->grav->fireEvent('onFormValidationError', new Event(['form' => $form, 'message' => $this->grav['language']->translate('PLUGIN_FORM.ERROR_VALIDATING_CAPTCHA')]));
                 $event->stopPropagation();
                 return;
             }
             break;
         case 'ip':
             $label = isset($params['label']) ? $params['label'] : 'User IP';
             $blueprint = $form->value()->blueprints();
             $blueprint->set('form/fields/ip', ['name' => 'ip', 'label' => $label]);
             $form->setFields($blueprint->fields());
             $form->setData('ip', Uri::ip());
             break;
         case 'message':
             $translated_string = $this->grav['language']->translate($params);
             $vars = array('form' => $form);
             /** @var Twig $twig */
             $twig = $this->grav['twig'];
             $processed_string = $twig->processString($translated_string, $vars);
             $form->message = $processed_string;
             break;
         case 'redirect':
             $this->grav['session']->setFlashObject('form', $form);
             $this->grav->redirect((string) $params);
             break;
         case 'reset':
             if (Utils::isPositive($params)) {
                 $form->reset();
             }
             break;
         case 'display':
             $route = (string) $params;
             if (!$route || $route[0] != '/') {
                 /** @var Uri $uri */
                 $uri = $this->grav['uri'];
                 $route = rtrim($uri->route(), '/') . '/' . ($route ?: '');
             }
             /** @var Twig $twig */
             $twig = $this->grav['twig'];
             $twig->twig_vars['form'] = $form;
             /** @var Pages $pages */
             $pages = $this->grav['pages'];
             $page = $pages->dispatch($route, true);
             if (!$page) {
                 throw new \RuntimeException('Display page not found. Please check the page exists.', 400);
             }
             unset($this->grav['page']);
             $this->grav['page'] = $page;
             break;
         case 'save':
             $prefix = !empty($params['fileprefix']) ? $params['fileprefix'] : '';
             $format = !empty($params['dateformat']) ? $params['dateformat'] : 'Ymd-His-u';
             $ext = !empty($params['extension']) ? '.' . trim($params['extension'], '.') : '.txt';
             $filename = !empty($params['filename']) ? $params['filename'] : '';
             $operation = !empty($params['operation']) ? $params['operation'] : 'create';
             if (!$filename) {
                 $filename = $prefix . $this->udate($format) . $ext;
             }
             /** @var Twig $twig */
             $twig = $this->grav['twig'];
             $vars = ['form' => $form];
             // Process with Twig
             $filename = $twig->processString($filename, $vars);
             $locator = $this->grav['locator'];
             $path = $locator->findResource('user://data', true);
             $dir = $path . DS . $form->name();
             $fullFileName = $dir . DS . $filename;
             $file = File::instance($fullFileName);
             if ($operation == 'create') {
                 $body = $twig->processString(!empty($params['body']) ? $params['body'] : '{% include "forms/data.txt.twig" %}', $vars);
                 $file->save($body);
             } elseif ($operation == 'add') {
                 if (!empty($params['body'])) {
                     // use body similar to 'create' action and append to file as a log
                     $body = $twig->processString($params['body'], $vars);
                     // create folder if it doesn't exist
                     if (!file_exists($dir)) {
                         mkdir($dir);
                     }
                     // append data to existing file
                     file_put_contents($fullFileName, $body, FILE_APPEND | LOCK_EX);
                 } else {
                     // serialize YAML out to file for easier parsing as data sets
                     $vars = $vars['form']->value()->toArray();
                     foreach ($form->fields as $field) {
                         if (isset($field['process']) && isset($field['process']['ignore']) && $field['process']['ignore']) {
                             unset($vars[$field['name']]);
                         }
                     }
                     if (file_exists($fullFileName)) {
                         $data = Yaml::parse($file->content());
                         if (count($data) > 0) {
                             array_unshift($data, $vars);
                         } else {
                             $data[] = $vars;
                         }
                     } else {
                         $data[] = $vars;
                     }
                     $file->save(Yaml::dump($data));
                 }
             }
             break;
     }
 }
 protected function getMessageFromUrl(Uri $uri)
 {
     $message_success = $this->overwriteConfigVariable('plugins.recaptchacontact.messages.success', 'RECAPTCHACONTACT.MESSAGES.SUCCESS');
     $message_error = $this->overwriteConfigVariable('plugins.recaptchacontact.messages.error', 'RECAPTCHACONTACT.MESSAGES.ERROR');
     $message_fail = $this->overwriteConfigVariable('plugins.recaptchacontact.messages.fail', 'RECAPTCHACONTACT.MESSAGES.FAIL');
     switch ($uri->param('send')) {
         case 'success':
             $this->setSubmissionMessage('success', $message_success);
             break;
         case 'error':
             $this->setSubmissionMessage('error', $message_error);
             break;
         case 'fail':
             $this->setSubmissionMessage('fail', $message_fail);
             break;
     }
 }
 /**
  * Execute shortcode.
  *
  * @param  Event        $event An event object.
  * @return string|null         Return modified contents.
  */
 public function execute(Event $event)
 {
     /* @var \Grav\Common\Grav $grav */
     $grav = $event['grav'];
     /* @var \Grav\Plugin\Shortcodes\Shortcodes $shortcodes */
     $shortcodes = $event['shortcodes'];
     /* @var \Grav\Common\Data\Data $options */
     $options = $event['options'];
     $options->setDefaults($this->defaults);
     $type = strtolower($options->get('type'));
     $body = trim(strip_tags($event['body'], '<link><script>'));
     if ($options->get('inline')) {
         $shortcodes->addExtra('assets', 'addInline' . ucfirst($type), $body);
     } else {
         /* @var \Grav\Common\Page\Page $page */
         $page = $event['page'];
         /* @var UniformResourceLocator $locator */
         $locator = $grav['locator'];
         /* @var Uri $uri */
         $uri = $grav['uri'];
         $priority = $options->get('priority', 10);
         $pipeline = $options->get('pipeline', false);
         $loading = $options->get('load', '');
         $entries = explode("\n", $body);
         $name = $type === 'css' ? 'addCss' : 'addJs';
         foreach ($entries as $entry) {
             $url = $before = trim($entry, " \t");
             // Don't process protocol agnostic or external URLs
             if (!$grav['uri']->isExternal($url) && substr($url, 0, 2) !== '//') {
                 if (false !== strpos($url, '://')) {
                     // Get relative path to the resource (or false if not found).
                     if ($resource = $locator->findResource($url, false)) {
                         $url = rtrim($uri->rootUrl(false), '/') . '/' . $resource;
                     }
                 } else {
                     // Resolve URL (relative or absolute with respect to current page)
                     $url = Uri::convertUrl($page, $url);
                 }
                 if (false === strpos($url, '://')) {
                     $url = preg_replace('~^' . preg_quote($uri->rootUrl(false)) . '~i', '', $url);
                     $url = rtrim($uri->rootUrl(true), '/') . $url;
                 }
             }
             $shortcodes->addExtra('assets', $name, [$url, $priority, $pipeline, $loading]);
         }
     }
 }
 protected function inlineLink($excerpt)
 {
     if (isset($excerpt['type'])) {
         $type = $excerpt['type'];
     } else {
         $type = 'link';
     }
     // do some trickery to get around Parsedown requirement for valid URL if its Twig in there
     if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) {
         $excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']);
         $excerpt = parent::inlineLink($excerpt);
         $excerpt['element']['attributes']['href'] = $matches[1];
         $excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1;
         return $excerpt;
     } else {
         $excerpt = parent::inlineLink($excerpt);
     }
     // if this is a link
     if (isset($excerpt['element']['attributes']['href'])) {
         $url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href']));
         // if there is a query, then parse it and build action calls
         if (isset($url['query'])) {
             $actions = array_reduce(explode('&', $url['query']), function ($carry, $item) {
                 $parts = explode('=', $item, 2);
                 $value = isset($parts[1]) ? $parts[1] : true;
                 $carry[$parts[0]] = $value;
                 return $carry;
             }, []);
             // valid attributes supported
             $valid_attributes = ['rel', 'target', 'id', 'class', 'classes'];
             // Unless told to not process, go through actions
             if (array_key_exists('noprocess', $actions)) {
                 unset($actions['noprocess']);
             } else {
                 // loop through actions for the image and call them
                 foreach ($actions as $attrib => $value) {
                     $key = $attrib;
                     if (in_array($attrib, $valid_attributes)) {
                         // support both class and classes
                         if ($attrib == 'classes') {
                             $attrib = 'class';
                         }
                         $excerpt['element']['attributes'][$attrib] = str_replace(',', ' ', $value);
                         unset($actions[$key]);
                     }
                 }
             }
             $url['query'] = http_build_query($actions, null, '&', PHP_QUERY_RFC3986);
         }
         // if no query elements left, unset query
         if (empty($url['query'])) {
             unset($url['query']);
         }
         // if there is no scheme, the file is local and we'll need to convert that URL
         if (!isset($url['scheme']) && count($url) > 0) {
             $excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type, true);
         } else {
             $excerpt['element']['attributes']['href'] = Uri::buildUrl($url);
         }
     }
     return $excerpt;
 }
Example #15
0
 /**
  * Converts links from absolute '/' or relative (../..) to a grav friendly format
  *
  * @param         $page         the current page to use as reference
  * @param  string $markdown_url the URL as it was written in the markdown
  *
  * @return string the more friendly formatted url
  */
 public static function convertUrl(Page $page, $markdown_url)
 {
     $grav = Grav::instance();
     $pages_dir = $grav['locator']->findResource('page://');
     $base_url = rtrim($grav['base_url'] . $grav['pages']->base(), '/');
     // if absolute and starts with a base_url move on
     if (pathinfo($markdown_url, PATHINFO_DIRNAME) == '.' && $page->url() == '/') {
         return '/' . $markdown_url;
         // no path to convert
     } elseif ($base_url != '' && Utils::startsWith($markdown_url, $base_url)) {
         return $markdown_url;
         // if contains only a fragment
     } elseif (Utils::startsWith($markdown_url, '#')) {
         return $markdown_url;
     } else {
         $target = null;
         // see if page is relative to this or absolute
         if (Utils::startsWith($markdown_url, '/')) {
             $normalized_url = Utils::normalizePath($base_url . $markdown_url);
             $normalized_path = Utils::normalizePath($pages_dir . $markdown_url);
         } else {
             $normalized_url = $base_url . Utils::normalizePath($page->route() . '/' . $markdown_url);
             $normalized_path = Utils::normalizePath($page->path() . '/' . $markdown_url);
         }
         // special check to see if path checking is required.
         $just_path = str_replace($normalized_url, '', $normalized_path);
         if ($just_path == $page->path()) {
             return $normalized_url;
         }
         $url_bits = parse_url($normalized_path);
         $full_path = $url_bits['path'];
         if (file_exists($full_path)) {
             // do nothing
         } elseif (file_exists(urldecode($full_path))) {
             $full_path = urldecode($full_path);
         } else {
             return $normalized_url;
         }
         $path_info = pathinfo($full_path);
         $page_path = $path_info['dirname'];
         $filename = '';
         if ($markdown_url == '..') {
             $page_path = $full_path;
         } else {
             // save the filename if a file is part of the path
             if (is_file($full_path)) {
                 if ($path_info['extension'] != 'md') {
                     $filename = '/' . $path_info['basename'];
                 }
             } else {
                 $page_path = $full_path;
             }
         }
         // get page instances and try to find one that fits
         $instances = $grav['pages']->instances();
         if (isset($instances[$page_path])) {
             $target = $instances[$page_path];
             $url_bits['path'] = $base_url . $target->route() . $filename;
             return Uri::buildUrl($url_bits);
         }
         return $normalized_url;
     }
 }
 /**
  * Handle the Form Process
  *
  * @param \Grav\Common\Uri $uri
  */
 protected function processFormAction(Uri $uri)
 {
     $message_success = $this->overwriteConfigVariable('plugins.recaptchacontact.messages.success', 'RECAPTCHACONTACT.MESSAGES.SUCCESS');
     $message_error = $this->overwriteConfigVariable('plugins.recaptchacontact.messages.error', 'RECAPTCHACONTACT.MESSAGES.ERROR');
     $message_fail = $this->overwriteConfigVariable('plugins.recaptchacontact.messages.fail', 'RECAPTCHACONTACT.MESSAGES.FAIL');
     if ($_SERVER['REQUEST_METHOD'] == "POST" && isset($_POST['g-recaptcha-response'])) {
         $this->clearSession();
         if (false === $this->validateFormData()) {
             $this->setSubmissionMessage('error', $message_error);
             $this->setSessionFields();
         } else {
             if (false === $this->sendEmail()) {
                 $this->setSubmissionMessage('fail', $message_fail);
                 $this->setSessionFields();
             } else {
                 $this->setSubmissionMessage('success', $message_success);
             }
         }
         $this->grav->redirectLangSafe($uri->url());
     }
 }
 protected function inlineLink($excerpt)
 {
     if (isset($excerpt['type'])) {
         $type = $excerpt['type'];
     } else {
         $type = 'link';
     }
     // do some trickery to get around Parsedown requirement for valid URL if its Twig in there
     if (preg_match($this->twig_link_regex, $excerpt['text'], $matches)) {
         $excerpt['text'] = str_replace($matches[1], '/', $excerpt['text']);
         $excerpt = parent::inlineLink($excerpt);
         $excerpt['element']['attributes']['href'] = $matches[1];
         $excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1;
         return $excerpt;
     } else {
         $excerpt = parent::inlineLink($excerpt);
     }
     // if this is a link
     if (isset($excerpt['element']['attributes']['href'])) {
         $url = parse_url(htmlspecialchars_decode($excerpt['element']['attributes']['href']));
         // if there is no scheme, the file is local
         if (!isset($url['scheme']) && count($url) > 0) {
             // convert the URl is required
             $excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type);
         }
     }
     return $excerpt;
 }
 protected function identifyLink($Excerpt)
 {
     /** @var Config $config */
     $config = self::$grav['config'];
     // Run the parent method to get the actual results
     $Excerpt = parent::identifyLink($Excerpt);
     $actions = array();
     $this->base_url = self::$grav['base_url'];
     // if this is a link
     if (isset($Excerpt['element']['attributes']['href'])) {
         $url = parse_url(htmlspecialchars_decode($Excerpt['element']['attributes']['href']));
         // if there is no host set but there is a path, the file is local
         if (!isset($url['host']) && isset($url['path'])) {
             // convert the URl is required
             $Excerpt['element']['attributes']['href'] = $this->convertUrl(Uri::build_url($url));
         }
     }
     // if this is an image
     if (isset($Excerpt['element']['attributes']['src'])) {
         $alt = isset($Excerpt['element']['attributes']['alt']) ? $Excerpt['element']['attributes']['alt'] : '';
         $title = isset($Excerpt['element']['attributes']['title']) ? $Excerpt['element']['attributes']['title'] : '';
         //get the url and parse it
         $url = parse_url(htmlspecialchars_decode($Excerpt['element']['attributes']['src']));
         // if there is no host set but there is a path, the file is local
         if (!isset($url['host']) && isset($url['path'])) {
             // get the media objects for this page
             $media = $this->page->media();
             // if there is a media file that matches the path referenced..
             if (isset($media->images()[$url['path']])) {
                 // get the medium object
                 $medium = $media->images()[$url['path']];
                 // if there is a query, then parse it and build action calls
                 if (isset($url['query'])) {
                     parse_str($url['query'], $actions);
                 }
                 // loop through actions for the image and call them
                 foreach ($actions as $action => $params) {
                     // as long as it's a valid action
                     if (in_array($action, Medium::$valid_actions)) {
                         call_user_func_array(array(&$medium, $action), explode(',', $params));
                     }
                 }
                 // Get the URL for regular images, or an array of bits needed to put together
                 // the lightbox HTML
                 if (!isset($actions['lightbox'])) {
                     $src = $medium->url();
                 } else {
                     $src = $medium->lightboxRaw();
                 }
                 // set the src element with the new generated url
                 if (!isset($actions['lightbox']) && !is_array($src)) {
                     $Excerpt['element']['attributes']['src'] = $src;
                 } else {
                     // Create the custom lightbox element
                     $Element = array('name' => 'a', 'attributes' => array('rel' => $src['a_rel'], 'href' => $src['a_url']), 'handler' => 'element', 'text' => array('name' => 'img', 'attributes' => array('src' => $src['img_url'], 'alt' => $alt, 'title' => $title)));
                     // Set the lightbox element on the Excerpt
                     $Excerpt['element'] = $Element;
                 }
             } else {
                 // not a current page media file, see if it needs converting to relative
                 $Excerpt['element']['attributes']['src'] = $this->convertUrl(Uri::build_url($url));
             }
         }
     }
     return $Excerpt;
 }