Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion system/core/Input.php
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path
'httponly' => $httponly,
'samesite' => $samesite,
);
setcookie($prefix.$name, (string) $value, $setcookie_options);
setcookie($prefix.$name, $value === NULL ? '' : $value, $setcookie_options);
}

// --------------------------------------------------------------------
Expand Down
22 changes: 16 additions & 6 deletions system/core/Output.php
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,7 @@ public function _display($output = NULL)
public function _write_cache($output)
{
$CI =& get_instance();
$path = $CI->config->item('cache_path');
$cache_path = ($path === '') ? APPPATH.'cache'.DIRECTORY_SEPARATOR : rtrim($path, '/\\').DIRECTORY_SEPARATOR;
$cache_path = $this->_get_cache_path($CI->config->item('cache_path'));

if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
{
Expand Down Expand Up @@ -660,8 +659,7 @@ public function _write_cache($output)
*/
public function _display_cache(&$CFG, &$URI)
{
$path = $CFG->item('cache_path');
$cache_path = ($path === '') ? APPPATH.'cache'.DIRECTORY_SEPARATOR : rtrim($path, '/\\').DIRECTORY_SEPARATOR;
$cache_path = $this->_get_cache_path($CFG->item('cache_path'));

// Build the file path. The file name is an MD5 hash of the full URI
$uri = $CFG->item('base_url').$CFG->slash_item('index_page').$URI->uri_string;
Expand Down Expand Up @@ -738,8 +736,7 @@ public function _display_cache(&$CFG, &$URI)
public function delete_cache($uri = '')
{
$CI =& get_instance();
$path = $CI->config->item('cache_path');
$cache_path = ($path === '') ? APPPATH.'cache'.DIRECTORY_SEPARATOR : rtrim($path, '/\\').DIRECTORY_SEPARATOR;
$cache_path = $this->_get_cache_path($CI->config->item('cache_path'));

if ( ! is_dir($cache_path))
{
Expand Down Expand Up @@ -777,6 +774,19 @@ public function delete_cache($uri = '')

// --------------------------------------------------------------------

/**
* Get cache path
*
* @param string $path The configured cache_path value
* @return string Cache directory path with a trailing directory separator
*/
protected function _get_cache_path($path)
{
return empty($path) ? APPPATH.'cache'.DIRECTORY_SEPARATOR : rtrim($path, '/\\').DIRECTORY_SEPARATOR;
}

// --------------------------------------------------------------------

/**
* Set Cache Header
*
Expand Down
20 changes: 4 additions & 16 deletions system/helpers/captcha_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,7 @@ function create_captcha($data)
@closedir($current_dir);

// This variable will later be used later to determine whether we write to disk or output a data:image URI
// %F is locale-independent, unlike float-to-string conversion on PHP < 8.0
$img_filename = sprintf('%.6F', $now).'.png';
$img_filename = $now.'.png';
}
else
{
Expand Down Expand Up @@ -346,20 +345,9 @@ function create_captcha($data)
}
else
{
// I don't see an easier way to get the image contents without writing to file
$buffer = fopen('php://memory', 'wb+');
imagepng($im, $buffer);
rewind($buffer);
$img_src = '';

// fread() will return an empty string (not FALSE) after the entire contents are read
while (strlen($read = fread($buffer, 4096)))
{
$img_src .= $read;
}

fclose($buffer);
$img_src = 'data:image/png;base64,'.base64_encode($img_src);
ob_start();
imagepng($im);
$img_src = 'data:image/png;base64,'.base64_encode(ob_get_clean());
}

$img_class = trim($img_class);
Expand Down
2 changes: 1 addition & 1 deletion system/libraries/Cache/drivers/Cache_file.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public function __construct()
$CI =& get_instance();
$CI->load->helper('file');
$path = $CI->config->item('cache_path');
$this->_cache_path = ($path === '') ? APPPATH.'cache/' : $path;
$this->_cache_path = empty($path) ? APPPATH.'cache'.DIRECTORY_SEPARATOR : rtrim($path, '/\\').DIRECTORY_SEPARATOR;
}

// ------------------------------------------------------------------------
Expand Down
42 changes: 27 additions & 15 deletions system/libraries/Cache/drivers/Cache_redis.php
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,17 @@ public function get($key)
{
$data = $this->_redis->hMGet($key, array('__ci_type', '__ci_value'));

if ($data === FALSE || $this->_redis->sIsMember('_ci_redis_serialized', $key))
if ($this->_redis->sIsMember('_ci_redis_serialized', $key))
{
return FALSE;
}

// Also serves scalars that 3.1.x cached as plain strings
if ($data === FALSE)
{
return $this->_redis->get($key);
}

switch ($data['__ci_type'])
{
case 'array':
Expand Down Expand Up @@ -261,15 +267,7 @@ public function delete($key)
*/
public function increment($id, $offset = 1)
{
$value = $this->_redis->hIncrBy($id, '__ci_value', $offset);

if ($value !== FALSE)
{
$this->_redis->hSet($id, '__ci_type', 'integer');
return $value;
}

return FALSE;
return $this->_increment($id, $offset);
}

// ------------------------------------------------------------------------
Expand All @@ -283,15 +281,29 @@ public function increment($id, $offset = 1)
*/
public function decrement($id, $offset = 1)
{
$value = $this->_redis->hIncrBy($id, '__ci_value', -$offset);
return $this->_increment($id, -$offset);
}

if ($value !== FALSE)
// ------------------------------------------------------------------------

/**
* Add to a counter
*
* @param string $id Cache ID
* @param int $offset Amount to add (negative to subtract)
* @return mixed New value on success or FALSE on failure
*/
protected function _increment($id, $offset)
{
$value = $this->_redis->incrBy($id, $offset);

if ($value === FALSE)
{
$this->_redis->hSet($id, '__ci_type', 'integer');
return $value;
$value = $this->_redis->hIncrBy($id, '__ci_value', $offset);
$value === FALSE OR $this->_redis->hSet($id, '__ci_type', 'integer');
}

return FALSE;
return $value;
}

// ------------------------------------------------------------------------
Expand Down
2 changes: 0 additions & 2 deletions system/libraries/Form_validation.php
Original file line number Diff line number Diff line change
Expand Up @@ -587,8 +587,6 @@ protected function _reduce_array($array, $keys, $i = 0)
/**
* Re-populate the _POST array with our finalized and processed data
*
* Arrays require bracket notation or an explicit is_array rule.
*
* @return void
*/
protected function _reset_data_array(&$data)
Expand Down
6 changes: 2 additions & 4 deletions system/libraries/Image_lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1251,8 +1251,7 @@ public function overlay_watermark()
imagecopymerge($src_img, $wm_img, $x_axis, $y_axis, 0, 0, $wm_width, $wm_height, $this->wm_opacity);
}

// We can preserve transparency for PNG images
if ($this->image_type === 3)
if ($this->image_type === 3 OR $this->image_type === 18)
{
imagealphablending($src_img, FALSE);
imagesavealpha($src_img, TRUE);
Expand Down Expand Up @@ -1425,8 +1424,7 @@ public function text_watermark()
imagestring($src_img, $this->wm_font_size, $x_axis, $y_axis, $this->wm_text, $txt_color);
}

// We can preserve transparency for PNG images
if ($this->image_type === 3)
if ($this->image_type === 3 OR $this->image_type === 18)
{
imagealphablending($src_img, FALSE);
imagesavealpha($src_img, TRUE);
Expand Down
8 changes: 5 additions & 3 deletions system/libraries/Session/drivers/Session_redis_driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,17 @@ public function __construct(&$params)
{
log_message('error', 'Session: No Redis save path configured.');
}
elseif (preg_match('#^unix://([^\?]+)(?<options>\?.+)?$#', $this->_config['save_path'], $matches))
elseif (preg_match('#^unix://([^\?]+)(?<options>\?.+)?$#i', $this->_config['save_path'], $matches))
{
$save_path = array('path' => $matches[1]);
}
elseif (preg_match('#^(?:(tcp|tls|ssl)://)?([^:?]+)(?:\:(\d+))?(?<options>\?.+)?#', $this->_config['save_path'], $matches))
elseif (preg_match('#^(?:(tcp|tls|ssl)://)?([^:?]+)(?:\:(\d+))?(?<options>\?.+)?#i', $this->_config['save_path'], $matches))
{
$scheme = strtolower($matches[1]);

// phpredis needs the tls:// or ssl:// scheme in the host to enable encryption; tcp:// is the default
$save_path = array(
'host' => (in_array($matches[1], array('tls', 'ssl'), TRUE) ? $matches[1].'://' : '').$matches[2],
'host' => (in_array($scheme, array('tls', 'ssl'), TRUE) ? $scheme.'://' : '').$matches[2],
'port' => empty($matches[3]) ? NULL : $matches[3],
'timeout' => 0.0 // We always pass this to Redis::connect(), so it needs to exist
);
Expand Down
31 changes: 31 additions & 0 deletions tests/codeigniter/core/Output_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,35 @@ public function test_get_header()
);
}

// --------------------------------------------------------------------

public function test_delete_cache_without_trailing_slash()
{
$this->ci_set_config('cache_path', APPPATH.'pagecache');
$this->ci_set_config('base_url', 'http://example.com/');
$this->ci_set_config('index_page', 'index.php');

$cache_file = md5('http://example.com/index.php/foo');
$dir = $this->ci_vfs_mkdir('pagecache', $this->ci_app_root);
vfsStream::newFile($cache_file)->at($dir)->setContent('cached');

$this->assertTrue($this->output->delete_cache('foo'));
$this->assertFalse($dir->hasChild($cache_file));
}

// --------------------------------------------------------------------

public function test_delete_cache_without_cache_path()
{
$this->ci_set_config('base_url', 'http://example.com/');
$this->ci_set_config('index_page', 'index.php');

$cache_file = md5('http://example.com/index.php/foo');
$dir = $this->ci_vfs_mkdir('cache', $this->ci_app_root);
vfsStream::newFile($cache_file)->at($dir)->setContent('cached');

$this->assertTrue($this->output->delete_cache('foo'));
$this->assertFalse($dir->hasChild($cache_file));
}

}
56 changes: 56 additions & 0 deletions tests/codeigniter/database/Postgre_forge_test.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

class Postgre_forge_test extends CI_TestCase {

/**
* @dataProvider forge_provider
*/
public function test_modify_column_comments_renamed_column($forge_class)
{
$db = new Postgre_forge_db_stub();
$forge = new $forge_class($db);

$this->assertTrue($forge->modify_column('users', array(
'old_name' => array('name' => 'new_name', 'comment' => 'Renamed column')
)));

$this->assertSame(array(
'ALTER TABLE "users" RENAME COLUMN "old_name" TO "new_name"',
'COMMENT ON COLUMN "users"."new_name" IS \'Renamed column\''
), $db->queries);
}

public function forge_provider()
{
return array(array('CI_DB_postgre_forge'), array('CI_DB_pdo_pgsql_forge'));
}

}

class Postgre_forge_db_stub {

public $dbprefix = '';
public $db_debug = FALSE;
public $queries = array();

public function version()
{
return '15.0';
}

public function escape_identifiers($item)
{
return '"'.$item.'"';
}

public function escape($str)
{
return "'".str_replace("'", "''", $str)."'";
}

public function query($sql)
{
$this->queries[] = $sql;
return TRUE;
}
}
24 changes: 9 additions & 15 deletions tests/codeigniter/helpers/captcha_helper_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,13 @@ public function tear_down()

// --------------------------------------------------------------------

public function test_create_captcha_writes_image_with_fractional_timestamp_filename()
public function test_create_captcha_names_image_after_time()
{
$captcha = $this->_create_captcha();

$this->assertTrue(is_array($captcha));
$this->assertEquals(1, preg_match('#^\d{10}\.\d{6}\.png$#', $captcha['filename']));
$this->assertSame($captcha['time'].'.png', $captcha['filename']);
$this->assertTrue(is_file($this->_img_path.$captcha['filename']));
$this->assertSame(sprintf('%.6F', $captcha['time']).'.png', $captcha['filename']);
}

// --------------------------------------------------------------------
Expand Down Expand Up @@ -148,21 +147,16 @@ public function test_create_captcha_respects_custom_expiration()

// --------------------------------------------------------------------

public function test_create_captcha_filename_is_locale_independent()
public function test_create_captcha_returns_data_uri_without_paths()
{
$original = setlocale(LC_NUMERIC, 0);
$locale = setlocale(LC_NUMERIC, 'de_DE.UTF-8', 'de_DE.utf8', 'de_DE', 'de-DE', 'German_Germany.1252', 'German');
$captcha = create_captcha(array('word' => 'test'));

if ($locale === FALSE)
{
$this->markTestSkipped('No locale with a comma decimal separator is available.');
}

$captcha = $this->_create_captcha();
setlocale(LC_NUMERIC, $original);
$this->assertTrue(is_array($captcha));
$this->assertNull($captcha['filename']);
$this->assertEquals(1, preg_match('#src="data:image/png;base64,([A-Za-z0-9+/=]+)"#', $captcha['image'], $match));
$this->assertSame("\x89PNG", substr(base64_decode($match[1]), 0, 4));

$this->assertEquals(1, preg_match('#^\d{10}\.\d{6}\.png$#', $captcha['filename']));
$this->assertTrue(is_file($this->_img_path.$captcha['filename']));
$this->assertFalse(create_captcha(array('word' => 'test', 'img_url' => 'http://example.com/captcha/')));
}

// --------------------------------------------------------------------
Expand Down
Loading