From e00560f81a72eb0429d1a638577c9727a30d449c Mon Sep 17 00:00:00 2001 From: Flavio Copes Date: Tue, 24 Nov 2015 15:18:10 +0100 Subject: [PATCH 01/12] Handle languages that support _PLURAL_MORE_THAN_TWO Ex. WEEK_PLURAL, WEEK_PLURAL_MORE_THAN_TWO --- system/src/Grav/Common/Twig/TwigExtension.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/system/src/Grav/Common/Twig/TwigExtension.php b/system/src/Grav/Common/Twig/TwigExtension.php index 4ea09e350..12a1cb633 100644 --- a/system/src/Grav/Common/Twig/TwigExtension.php +++ b/system/src/Grav/Common/Twig/TwigExtension.php @@ -355,6 +355,12 @@ class TwigExtension extends \Twig_Extension $periods[$j] .= '_PLURAL'; } + if ($this->grav['language']->getTranslation($this->grav['language']->getLanguage(), $periods[$j] . '_MORE_THAN_TWO')) { + if ($difference > 2) { + $periods[$j] .= '_MORE_THAN_TWO'; + } + } + $periods[$j] = $this->grav['language']->translate($periods[$j], null, true); return "$difference $periods[$j] {$tense}"; From 34f83ebde2c7529bf2ab33e3cd17e8022aa7096f Mon Sep 17 00:00:00 2001 From: Flavio Copes Date: Tue, 24 Nov 2015 21:13:46 +0100 Subject: [PATCH 02/12] Use the new security salt to calculate the nonce instead of using password_hash --- system/src/Grav/Common/Utils.php | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php index 759d3f949..90e79ffa2 100644 --- a/system/src/Grav/Common/Utils.php +++ b/system/src/Grav/Common/Utils.php @@ -423,7 +423,6 @@ abstract class Utils return in_array($value, [true, 1, '1', 'yes', 'on', 'true'], true); } - /** * Generates a nonce string to be hashed. Called by self::getNonce() * @@ -451,7 +450,7 @@ abstract class Utils $i++; } - return ( $i . '|' . $action . '|' . $username . '|' . $token ); + return ( $i . '|' . $action . '|' . $username . '|' . $token . '|' . self::getGrav()['config']->get('security.salt')); } /** @@ -468,19 +467,6 @@ abstract class Utils return (int)ceil(time() / ( $secondsInHalfADay )); } - /** - * Get hash of given string - * - * @param string $data string to hash - * - * @return string hashed value of $data, cut to 10 characters - */ - public static function hash($data) - { - $hash = password_hash($data, PASSWORD_DEFAULT); - return $hash; - } - /** * Creates a hashed nonce tied to the passed action. Tied to the current user and time. The nonce for a given * action is the same for 12 hours. @@ -496,9 +482,8 @@ abstract class Utils if (isset(static::$nonces[$action])) { return static::$nonces[$action]; } - $nonce = self::hash(self::generateNonceString($action, $plusOneTick)); - - static::$nonces[$action] = str_replace('/', 'SLASH', $nonce); + $nonce = md5(self::generateNonceString($action, $plusOneTick)); + static::$nonces[$action] = $nonce; return static::$nonces[$action]; } @@ -513,21 +498,18 @@ abstract class Utils */ public static function verifyNonce($nonce, $action) { - $nonce = str_replace('SLASH', '/', $nonce); - //Nonce generated 0-12 hours ago - if (password_verify(self::generateNonceString($action), $nonce)) { + if ($nonce == self::getNonce($action)) { return true; } //Nonce generated 12-24 hours ago $plusOneTick = true; - if (password_verify(self::generateNonceString($action, $plusOneTick), $nonce)) { + if ($nonce == self::getNonce($action, $plusOneTick)) { return true; } //Invalid nonce return false; } - } From 13207f13addca3d303fe651f567fb9aaac7936cd Mon Sep 17 00:00:00 2001 From: Djamil Legato Date: Tue, 24 Nov 2015 14:57:05 -0800 Subject: [PATCH 03/12] Fixed nested logic for lists and forms parsing (fixes #273) --- system/src/Grav/Common/Data/Blueprint.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/src/Grav/Common/Data/Blueprint.php b/system/src/Grav/Common/Data/Blueprint.php index 6f0c71e50..c261ed877 100644 --- a/system/src/Grav/Common/Data/Blueprint.php +++ b/system/src/Grav/Common/Data/Blueprint.php @@ -331,7 +331,7 @@ class Blueprint implements \ArrayAccess, ExportInterface $field['name'] = $prefix . $key; $field += $params; - if (isset($field['fields']) && (!isset($field['type']) || $field['type'] !== 'list')) { + if (isset($field['fields']) && isset($field['type'])) { // Recursively get all the nested fields. $newParams = array_intersect_key($this->filter, $field); $this->parseFormFields($field['fields'], $newParams, $prefix, $current[$key]['fields']); From 9c07d69c4587c551fe988475b7ee3fd6d78c4d3a Mon Sep 17 00:00:00 2001 From: nazwa Date: Tue, 24 Nov 2015 23:02:42 +0000 Subject: [PATCH 04/12] Proper handling of list fields Moved field handling to a separate function and added logic to correctly process nested lists. --- system/src/Grav/Common/Data/Blueprint.php | 178 ++++++++++++---------- 1 file changed, 101 insertions(+), 77 deletions(-) diff --git a/system/src/Grav/Common/Data/Blueprint.php b/system/src/Grav/Common/Data/Blueprint.php index 6f0c71e50..aefd1b75c 100644 --- a/system/src/Grav/Common/Data/Blueprint.php +++ b/system/src/Grav/Common/Data/Blueprint.php @@ -314,91 +314,115 @@ class Blueprint implements \ArrayAccess, ExportInterface } /** - * Gets all field definitions from the blueprints. - * - * @param array $fields - * @param array $params - * @param string $prefix - * @param array $current - * @internal - */ - protected function parseFormFields(array &$fields, $params, $prefix, array &$current) - { - // Go though all the fields in current level. - foreach ($fields as $key => &$field) { - $current[$key] = &$field; - // Set name from the array key. - $field['name'] = $prefix . $key; - $field += $params; + * Gets all field definitions from the blueprints. + * + * @param array $fields + * @param array $params + * @param string $prefix + * @param array $current + * @internal + */ + protected function parseFormFields(array &$fields, $params, $prefix, array &$current) + { + // Go though all the fields in current level. + foreach ($fields as $key => &$field) { + $current[$key] = &$field; + // Set name from the array key. + $field['name'] = $prefix . $key; + $field += $params; - if (isset($field['fields']) && (!isset($field['type']) || $field['type'] !== 'list')) { - // Recursively get all the nested fields. - $newParams = array_intersect_key($this->filter, $field); - $this->parseFormFields($field['fields'], $newParams, $prefix, $current[$key]['fields']); - } else if ($field['type'] !== 'ignore') { - // Add rule. + if (isset($field['fields']) && (!isset($field['type']) || $field['type'] !== 'list')) { + // Recursively get all the nested fields. + $newParams = array_intersect_key($this->filter, $field); + $this->parseFormFields($field['fields'], $newParams, $prefix, $current[$key]['fields']); + } else if( $field['type'] === 'list') { + // Lists have different structure for fields (one level deeper) + // This means we need to loop through the list to get to the actual field + // The property and rule setting need to be set on the list field + // and NOT on the children, which is why we need to duplicate some of + // the code below :( + + $this->rules[$prefix . $key] = &$field; + $this->addProperty($prefix . $key); + + foreach($field['fields'] as $subName => &$subField) { + $this->parseFormField($subField, $prefix, $key, false); + } + + if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { + $field['validate'] += $this->getRule($field['validate']['rule']); + } + } else if ($field['type'] !== 'ignore') { $this->rules[$prefix . $key] = &$field; - $this->addProperty($prefix . $key); + $this->addProperty($prefix . $key); - foreach ($field as $name => $value) { - // Support nested blueprints. - if ($this->context && $name == '@import') { - $values = (array) $value; - if (!isset($field['fields'])) { - $field['fields'] = array(); - } - foreach ($values as $bname) { - $b = $this->context->get($bname); - $field['fields'] = array_merge($field['fields'], $b->fields()); - } - } + $this->parseFormField($field, $prefix, $key, true); - // Support for callable data values. - elseif (substr($name, 0, 6) == '@data-') { - $property = substr($name, 6); - if (is_array($value)) { - $func = array_shift($value); - } else { - $func = $value; - $value = array(); - } - list($o, $f) = preg_split('/::/', $func); - if (!$f && function_exists($o)) { - $data = call_user_func_array($o, $value); - } elseif ($f && method_exists($o, $f)) { - $data = call_user_func_array(array($o, $f), $value); - } + if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { + $field['validate'] += $this->getRule($field['validate']['rule']); + } + } + } + } + /** + * Parses individual field definition + * + * @param array $field + * @internal + */ + protected function parseFormField(&$field) { + foreach ($field as $name => $value) { + // Support nested blueprints. + if ($this->context && $name == '@import') { + $values = (array) $value; + if (!isset($field['fields'])) { + $field['fields'] = array(); + } + foreach ($values as $bname) { + $b = $this->context->get($bname); + $field['fields'] = array_merge($field['fields'], $b->fields()); + } + } - // If function returns a value, - if (isset($data)) { - if (isset($field[$property]) && is_array($field[$property]) && is_array($data)) { - // Combine field and @data-field together. - $field[$property] += $data; - } else { - // Or create/replace field with @data-field. - $field[$property] = $data; - } - } - } + // Support for callable data values. + elseif (substr($name, 0, 6) == '@data-') { + $property = substr($name, 6); + if (is_array($value)) { + $func = array_shift($value); + } else { + $func = $value; + $value = array(); + } + list($o, $f) = preg_split('/::/', $func); + if (!$f && function_exists($o)) { + $data = call_user_func_array($o, $value); + } elseif ($f && method_exists($o, $f)) { + $data = call_user_func_array(array($o, $f), $value); + } - elseif (substr($name, 0, 8) == '@config-') { - $property = substr($name, 8); - $default = isset($field[$property]) ? $field[$property] : null; - $config = self::getGrav()['config']->get($value, $default); + // If function returns a value, + if (isset($data)) { + if (isset($field[$property]) && is_array($field[$property]) && is_array($data)) { + // Combine field and @data-field together. + $field[$property] += $data; + } else { + // Or create/replace field with @data-field. + $field[$property] = $data; + } + } + } - if (!is_null($config)) { - $field[$property] = $config; - } - } - } + elseif (substr($name, 0, 8) == '@config-') { + $property = substr($name, 8); + $default = isset($field[$property]) ? $field[$property] : null; + $config = self::getGrav()['config']->get($value, $default); - // Initialize predefined validation rule. - if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { - $field['validate'] += $this->getRule($field['validate']['rule']); - } - } - } - } + if (!is_null($config)) { + $field[$property] = $config; + } + } + } + } /** * Add property to the definition. From fb3e68e16e124dda0cf211d3aa78146af377d92b Mon Sep 17 00:00:00 2001 From: Maciej Ka Date: Tue, 24 Nov 2015 23:34:47 +0000 Subject: [PATCH 05/12] removed old parameters --- system/src/Grav/Common/Data/Blueprint.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/src/Grav/Common/Data/Blueprint.php b/system/src/Grav/Common/Data/Blueprint.php index aefd1b75c..04bf51040 100644 --- a/system/src/Grav/Common/Data/Blueprint.php +++ b/system/src/Grav/Common/Data/Blueprint.php @@ -346,7 +346,7 @@ class Blueprint implements \ArrayAccess, ExportInterface $this->addProperty($prefix . $key); foreach($field['fields'] as $subName => &$subField) { - $this->parseFormField($subField, $prefix, $key, false); + $this->parseFormField($subField); } if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { @@ -356,7 +356,7 @@ class Blueprint implements \ArrayAccess, ExportInterface $this->rules[$prefix . $key] = &$field; $this->addProperty($prefix . $key); - $this->parseFormField($field, $prefix, $key, true); + $this->parseFormField($field); if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { $field['validate'] += $this->getRule($field['validate']['rule']); From edfd7db88b7db461d32850d40780046ba1abf91e Mon Sep 17 00:00:00 2001 From: Maciej Ka Date: Tue, 24 Nov 2015 23:48:22 +0000 Subject: [PATCH 06/12] pretty & clean --- system/src/Grav/Common/Data/Blueprint.php | 40 +++++++++-------------- 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/system/src/Grav/Common/Data/Blueprint.php b/system/src/Grav/Common/Data/Blueprint.php index 04bf51040..8598d8436 100644 --- a/system/src/Grav/Common/Data/Blueprint.php +++ b/system/src/Grav/Common/Data/Blueprint.php @@ -335,33 +335,23 @@ class Blueprint implements \ArrayAccess, ExportInterface // Recursively get all the nested fields. $newParams = array_intersect_key($this->filter, $field); $this->parseFormFields($field['fields'], $newParams, $prefix, $current[$key]['fields']); - } else if( $field['type'] === 'list') { - // Lists have different structure for fields (one level deeper) - // This means we need to loop through the list to get to the actual field - // The property and rule setting need to be set on the list field - // and NOT on the children, which is why we need to duplicate some of - // the code below :( - - $this->rules[$prefix . $key] = &$field; - $this->addProperty($prefix . $key); - - foreach($field['fields'] as $subName => &$subField) { - $this->parseFormField($subField); - } - - if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { - $field['validate'] += $this->getRule($field['validate']['rule']); - } } else if ($field['type'] !== 'ignore') { $this->rules[$prefix . $key] = &$field; - $this->addProperty($prefix . $key); - - $this->parseFormField($field); - - if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { - $field['validate'] += $this->getRule($field['validate']['rule']); - } - } + $this->addProperty($prefix . $key); + + if ($field['type'] === 'list') { + // we loop through list to get the actual field + foreach($field['fields'] as $subName => &$subField) { + $this->parseFormField($subField); + } + } else { + $this->parseFormField($field); + } + + if (isset($field['validate']['rule']) && $field['type'] !== 'ignore') { + $field['validate'] += $this->getRule($field['validate']['rule']); + } + } } } /** From 8d8420c0d66395b47337e6ee54bb46b498660969 Mon Sep 17 00:00:00 2001 From: Flavio Copes Date: Wed, 25 Nov 2015 22:30:45 +0100 Subject: [PATCH 07/12] If the page does not exist trigger a 404 --- system/src/Grav/Common/Twig/Twig.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/system/src/Grav/Common/Twig/Twig.php b/system/src/Grav/Common/Twig/Twig.php index 0f5f4b97d..f88f835b6 100644 --- a/system/src/Grav/Common/Twig/Twig.php +++ b/system/src/Grav/Common/Twig/Twig.php @@ -297,6 +297,11 @@ class Twig $this->grav->fireEvent('onTwigSiteVariables'); $pages = $this->grav['pages']; $page = $this->grav['page']; + + if (!$page) { + throw new \RuntimeException('Page Not Found', 404); + } + $content = $page->content(); $config = $this->grav['config']; From e8972a6aa51903e31ea346e7a926e3dffc63de22 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 25 Nov 2015 15:41:53 -0700 Subject: [PATCH 08/12] vendor updates --- composer.lock | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 25c0429a7..d19e9a3f8 100644 --- a/composer.lock +++ b/composer.lock @@ -1,11 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], "hash": "b1323e540382de7390663756b3a87de7", - "content-hash": "158cd4e3e1a40d5d1db9e3f29c24d83a", "packages": [ { "name": "doctrine/cache", @@ -217,12 +216,12 @@ "source": { "type": "git", "url": "https://github.com/filp/whoops.git", - "reference": "50a288b51058fa94cf5b37cfa4277535983cc9d5" + "reference": "9a393ceb80f7497b6513feb574638e87048fed55" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/filp/whoops/zipball/50a288b51058fa94cf5b37cfa4277535983cc9d5", - "reference": "50a288b51058fa94cf5b37cfa4277535983cc9d5", + "url": "https://api.github.com/repos/filp/whoops/zipball/9a393ceb80f7497b6513feb574638e87048fed55", + "reference": "9a393ceb80f7497b6513feb574638e87048fed55", "shasum": "" }, "require": { @@ -267,7 +266,7 @@ "whoops", "zf2" ], - "time": "2015-11-14 20:08:27" + "time": "2015-09-27 09:47:06" }, { "name": "gregwar/cache", From b259927348b50400beab51465eb07a65424d2028 Mon Sep 17 00:00:00 2001 From: Andy Miller Date: Wed, 25 Nov 2015 15:42:11 -0700 Subject: [PATCH 09/12] no message --- user/localhost/config/security.yaml | 1 + 1 file changed, 1 insertion(+) create mode 100644 user/localhost/config/security.yaml diff --git a/user/localhost/config/security.yaml b/user/localhost/config/security.yaml new file mode 100644 index 000000000..715f1c778 --- /dev/null +++ b/user/localhost/config/security.yaml @@ -0,0 +1 @@ +salt: Y5UKcWPzyQ7XT0 From 77db54c50dbf379eaae5d41eff98706e127cbeba Mon Sep 17 00:00:00 2001 From: Flavio Copes Date: Wed, 25 Nov 2015 22:50:29 +0100 Subject: [PATCH 10/12] Revert "If the page does not exist trigger a 404" This reverts commit 8d8420c0d66395b47337e6ee54bb46b498660969. --- system/src/Grav/Common/Twig/Twig.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/system/src/Grav/Common/Twig/Twig.php b/system/src/Grav/Common/Twig/Twig.php index f88f835b6..0f5f4b97d 100644 --- a/system/src/Grav/Common/Twig/Twig.php +++ b/system/src/Grav/Common/Twig/Twig.php @@ -297,11 +297,6 @@ class Twig $this->grav->fireEvent('onTwigSiteVariables'); $pages = $this->grav['pages']; $page = $this->grav['page']; - - if (!$page) { - throw new \RuntimeException('Page Not Found', 404); - } - $content = $page->content(); $config = $this->grav['config']; From 793ac1a1bbabf71f7834f57316a54de19e0325c9 Mon Sep 17 00:00:00 2001 From: Flavio Copes Date: Thu, 26 Nov 2015 11:54:05 +0100 Subject: [PATCH 11/12] Revert "no message" This reverts commit b259927348b50400beab51465eb07a65424d2028. --- user/localhost/config/security.yaml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 user/localhost/config/security.yaml diff --git a/user/localhost/config/security.yaml b/user/localhost/config/security.yaml deleted file mode 100644 index 715f1c778..000000000 --- a/user/localhost/config/security.yaml +++ /dev/null @@ -1 +0,0 @@ -salt: Y5UKcWPzyQ7XT0 From 63890661fea8d15fd0917bda45c93ed063fe8dfa Mon Sep 17 00:00:00 2001 From: Flavio Copes Date: Thu, 26 Nov 2015 11:55:13 +0100 Subject: [PATCH 12/12] Add security.yaml to the ignored files --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 01b701cf8..755814004 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ user/plugins/* !user/plugins/.* user/themes/* !user/themes/.* +user/localhost/config/security.yaml # OS Generated .DS_Store*