Skip to content

Commit

Permalink
Merge pull request #558 from kohana/3.3/merge/3.2-master-with-mb_subs…
Browse files Browse the repository at this point in the history
…titute_character

Merge bugfixes from 3.2/master up to 3.3/develop.

Also closes #557 (an earlier version of this pull) and 
closes #554 (a bugfix that was already applied in 3.2 
and is merged up with this pull request.
  • Loading branch information
acoulton committed Sep 26, 2014
2 parents 30d16cd + d10ee63 commit bb5e93b
Show file tree
Hide file tree
Showing 14 changed files with 276 additions and 24 deletions.
14 changes: 13 additions & 1 deletion classes/Kohana/Request.php
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,12 @@ public static function process(Request $request, $routes = NULL)

foreach ($routes as $name => $route)
{
// Use external routes for reverse routing only
if ($route->is_external())
{
continue;
}

// We found something suitable
if ($params = $route->matches($request))
{
Expand Down Expand Up @@ -747,7 +753,13 @@ public function uri($uri = NULL)
*/
public function url($protocol = NULL)
{
// Create a URI with the current route and convert it to a URL
if ($this->is_external())
{
// If it's an external request return the URI
return $this->uri();
}

// Create a URI with the current route, convert to a URL and returns
return URL::site($this->uri(), $protocol);
}

Expand Down
5 changes: 4 additions & 1 deletion classes/Kohana/Request/Client/Curl.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ public function _send_message(Request $request, Response $response)
// if using a request other than POST. PUT does support this method
// and DOES NOT require writing data to disk before putting it, if
// reading the PHP docs you may have got that impression. SdF
$options[CURLOPT_POSTFIELDS] = $request->body();
// This will also add a Content-Type: application/x-www-form-urlencoded header unless you override it
if ($body = $request->body()) {
$options[CURLOPT_POSTFIELDS] = $body;
}

// Process headers
if ($headers = $request->headers())
Expand Down
8 changes: 8 additions & 0 deletions classes/Kohana/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,14 @@ public function is_external()
*/
public function uri(array $params = NULL)
{
if ($params)
{
// @issue #4079 rawurlencode parameters
$params = array_map('rawurlencode', $params);
// decode slashes back, see Apache docs about AllowEncodedSlashes and AcceptPathInfo
$params = str_replace(array('%2F', '%5C'), array('/', '\\'), $params);
}

$defaults = $this->_defaults;

/**
Expand Down
25 changes: 24 additions & 1 deletion classes/Kohana/Session/Native.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,31 @@ public function id()
*/
protected function _read($id = NULL)
{
/**
* session_set_cookie_params will override php ini settings
* If Cookie::$domain is NULL or empty and is passed, PHP
* will override ini and sent cookies with the host name
* of the server which generated the cookie
*
* see issue #3604
*
* see http://www.php.net/manual/en/function.session-set-cookie-params.php
* see http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-domain
*
* set to Cookie::$domain if available, otherwise default to ini setting
*/
$session_cookie_domain = empty(Cookie::$domain)
? ini_get('session.cookie_domain')
: Cookie::$domain;

// Sync up the session cookie with Cookie parameters
session_set_cookie_params($this->_lifetime, Cookie::$path, Cookie::$domain, Cookie::$secure, Cookie::$httponly);
session_set_cookie_params(
$this->_lifetime,
Cookie::$path,
$session_cookie_domain,
Cookie::$secure,
Cookie::$httponly
);

// Do not allow PHP to send Cache-Control headers
session_cache_limiter(FALSE);
Expand Down
24 changes: 15 additions & 9 deletions classes/Kohana/Text.php
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,15 @@ public static function censor($str, $badwords, $replacement = '#', $replace_part

$regex = '!'.$regex.'!ui';

// if $replacement is a single character: replace each of the characters of the badword with $replacement
if (UTF8::strlen($replacement) == 1)
{
return preg_replace_callback($regex, function($matches) use ($replacement) {
return str_repeat($replacement, UTF8::strlen($matches[1]));
}, $str);
}

// if $replacement is not a single character, fully replace the badword with $replacement
return preg_replace($regex, $replacement, $str);
}

Expand Down Expand Up @@ -588,20 +590,24 @@ public static function number($number)
*
* echo Text::widont($text);
*
* regex courtesy of the Typogrify project
* @link http://code.google.com/p/typogrify/
*
* @param string $str text to remove widows from
* @return string
*/
public static function widont($str)
{
$str = rtrim($str);
$space = strrpos($str, ' ');

if ($space !== FALSE)
{
$str = substr($str, 0, $space).' '.substr($str, $space + 1);
}

return $str;
// use '%' as delimiter and 'x' as modifier
$widont_regex = "%
((?:</?(?:a|em|span|strong|i|b)[^>]*>)|[^<>\s]) # must be proceeded by an approved inline opening or closing tag or a nontag/nonspace
\s+ # the space to replace
([^<>\s]+ # must be flollowed by non-tag non-space characters
\s* # optional white space!
(</(a|em|span|strong|i|b)>\s*)* # optional closing inline tags with optional white space after each
((</(p|h[1-6]|li|dt|dd)>)|$)) # end with a closing p, h1-6, li or the end of the string
%x";
return preg_replace($widont_regex, '$1&nbsp;$2', $str);
}

/**
Expand Down
10 changes: 10 additions & 0 deletions classes/Kohana/UTF8.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,17 @@ public static function clean($var, $charset = NULL)

if ( ! UTF8::is_ascii($var))
{
// Temporarily save the mb_substitute_character() value into a variable
$mb_substitute_character = mb_substitute_character();

// Disable substituting illegal characters with the default '?' character
mb_substitute_character('none');

// convert encoding, this is expensive, used when $var is not ASCII
$var = mb_convert_encoding($var, $charset, $charset);

// Reset mb_substitute_character() value back to the original setting
mb_substitute_character($mb_substitute_character);
}
}

Expand Down
9 changes: 8 additions & 1 deletion classes/Kohana/Validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ public function rule($field, $rule, array $params = NULL)
if ($field !== TRUE AND ! isset($this->_labels[$field]))
{
// Set the field label to the field name
$this->_labels[$field] = preg_replace('/[^\pL]+/u', ' ', $field);
$this->_labels[$field] = $field;
}

// Store the rule and params for this rule
Expand Down Expand Up @@ -430,6 +430,13 @@ public function check()
}
}

// Unbind all the automatic bindings to avoid memory leaks.
unset($this->_bound[':validation']);
unset($this->_bound[':data']);
unset($this->_bound[':field']);
unset($this->_bound[':value']);


// Restore the data to its original form
$this->_data = $original;

Expand Down
4 changes: 2 additions & 2 deletions guide/kohana/bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ You can add conditional statements to make the bootstrap have different values b
/**
* Set the environment status by the domain.
*/
if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE)
if (strpos($_SERVER['HTTP_HOST'], 'kohanaframework.org') !== FALSE)
{
// We are live!
Kohana::$environment = Kohana::PRODUCTION;
Expand All @@ -66,7 +66,7 @@ if (strpos($_SERVER['HTTP_HOST'], 'kohanaphp.com') !== FALSE)
... [trimmed]
*/
Kohana::init(array(
'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/' : '/kohanaphp.com/',
'base_url' => Kohana::$environment === Kohana::PRODUCTION ? '/' : '/kohanaframework.org/',
'caching' => Kohana::$environment === Kohana::PRODUCTION,
'profile' => Kohana::$environment !== Kohana::PRODUCTION,
'index_file' => FALSE,
Expand Down
2 changes: 1 addition & 1 deletion guide/kohana/flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ Every application follows the same flow:
5. Calls the [Controller::after] method.
* The above 5 steps can be repeated multiple times when using [HMVC sub-requests](requests).
3. Application flow returns to index.php
12. The main [Request] response is displayed
12. The main [Request] response is displayed
23 changes: 21 additions & 2 deletions tests/kohana/RequestTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ public function provider_url()
'http',
'http://localhost/kohana/foo'
),
array(
'http://www.google.com',
'http',
'http://www.google.com'
),
);
}

Expand All @@ -296,7 +301,14 @@ public function test_url($uri, $protocol, $expected)
'Kohana::$index_file' => FALSE,
));

$this->assertEquals(Request::factory($uri)->url($protocol), $expected);
// issue #3967: inject the route so that we don't conflict with the application's default route
$route = new Route('(<controller>(/<action>))');
$route->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));

$this->assertEquals(Request::factory($uri, array(), TRUE, array($route))->url($protocol), $expected);
}

/**
Expand Down Expand Up @@ -397,8 +409,15 @@ public function test_post_max_size_exceeded($content_length, $expected)
*/
public function provider_uri_only_trimed_on_internal()
{
// issue #3967: inject the route so that we don't conflict with the application's default route
$route = new Route('(<controller>(/<action>))');
$route->defaults(array(
'controller' => 'welcome',
'action' => 'index',
));

$old_request = Request::$initial;
Request::$initial = new Request(TRUE);
Request::$initial = new Request(TRUE, array(), TRUE, array($route));

$result = array(
array(
Expand Down
39 changes: 39 additions & 0 deletions tests/kohana/RouteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -909,4 +909,43 @@ public function test_route_filter_modify_params($route, $defaults, $filter, $uri
$this->assertSame($expected_params, $params);
}

/**
* Provides test data for test_route_uri_encode_parameters
*
* @return array
*/
public function provider_route_uri_encode_parameters()
{
return array(
array(
'article',
'blog/article/<article_name>',
array(
'controller' => 'home',
'action' => 'index'
),
'article_name',
'Article name with special chars \\ ##',
'blog/article/Article%20name%20with%20special%20chars%20\\%20%23%23'
)
);
}

/**
* http://dev.kohanaframework.org/issues/4079
*
* @test
* @covers Route::get
* @ticket 4079
* @dataProvider provider_route_uri_encode_parameters
*/
public function test_route_uri_encode_parameters($name, $uri_callback, $defaults, $uri_key, $uri_value, $expected)
{
Route::set($name, $uri_callback)->defaults($defaults);

$get_route_uri = Route::get($name)->uri(array($uri_key => $uri_value));

$this->assertSame($expected, $get_route_uri);
}

}
87 changes: 84 additions & 3 deletions tests/kohana/TextTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -386,9 +386,90 @@ function provider_widont()
{
return array
(
array('No gain, no&nbsp;pain', 'No gain, no pain'),
array("spaces?what'rethey?", "spaces?what'rethey?"),
array('', ''),
// A very simple widont test
array(
'A very simple&nbsp;test',
'A very simple test',
),
// Single word items shouldn't be changed
array(
'Test',
'Test',
),
// Single word after single space shouldn't be changed either
array(
' Test',
' Test',
),
// Single word with HTML all around
array(
'<ul><li><p>Test</p></li><ul>',
'<ul><li><p>Test</p></li><ul>',
),
// Single word after single space with HTML all around
array(
'<ul><li><p> Test</p></li><ul>',
'<ul><li><p> Test</p></li><ul>',
),
// Widont with more than one paragraph
array(
'<p>In a couple of&nbsp;paragraphs</p><p>paragraph&nbsp;two</p>',
'<p>In a couple of paragraphs</p><p>paragraph two</p>',
),
// a link inside a heading
array(
'<h1><a href="#">In a link inside a&nbsp;heading </a></h1>',
'<h1><a href="#">In a link inside a heading </a></h1>',
),
// a link followed by text
array(
'<h1><a href="#">In a link</a> followed by other&nbsp;text</h1>',
'<h1><a href="#">In a link</a> followed by other text</h1>',
),
// empty html, with no text inside
array(
'<h1><a href="#"></a></h1>',
'<h1><a href="#"></a></h1>',
),
// apparently, we don't love DIVs
array(
'<div>Divs get no love!</div>',
'<div>Divs get no love!</div>',
),
// we don't love PREs, either
array(
'<pre>Neither do PREs</pre>',
'<pre>Neither do PREs</pre>',
),
// but we love DIVs with paragraphs
array(
'<div><p>But divs with paragraphs&nbsp;do!</p></div>',
'<div><p>But divs with paragraphs do!</p></div>',
),
array(
'No gain, no&nbsp;pain',
'No gain, no pain',
),
array(
"spaces?what'rethey?",
"spaces?what'rethey?",
),
/*
* // @issue 3499, with HTML at the end
* array(
* 'with HTML at the end &nbsp;<strong>Kohana</strong>',
* 'with HTML at the end <strong>Kohana</strong>',
* ),
* // @issue 3499, with HTML with attributes at the end
* array(
* 'with HTML at the end:&nbsp;<a href="#" title="Kohana">Kohana</a>',
* 'with HTML at the end: <a href="#" title="Kohana">Kohana</a>',
* ),
*/
array(
'',
'',
),
);
}

Expand Down
Loading

0 comments on commit bb5e93b

Please sign in to comment.