CS-Cart v2.2.3 released

In 2.2.3 the bulk edit on features pretty much stinks in every browser. We've tried it in Firefox, IE, Chrome and Safari for Windows. If you try to edit 100 items at a time and do the features at the same time it will either not work or IE will give you an error asking if you want the script to continue.

Due too some odd reason I cannot seem to get access to the Bug-Tracker. Could someone please relay the information regarding the fix for the MIME problem in 2.2.3?

[quote name='AmitP' timestamp='1317489230' post='122753']

Unfortunately we just updated our main site and found out that it broke our Paypal Express. The customer's details are not being sent back to the cart after visiting Paypal. I had to revert back again and 2.2.2 is working as intended again now!



Regards

[/quote]



Did you warn CS team about that PayPal Express issue? Any official answer?

Are you also experiencing this,i raised a ticket thinking it might just be our setup?

I am trying to figure out how the Google Base (or whatever it is called this week) is fixed. Does anyone know? In the initial post of this thread by CS-Cart they say…

[quote][+] The “Google Export” add-on was added to meet the changes made to Google Product Search feed specification and policies. [/quote]

I can't figure out what was added. Does it export the MPN? If so, where is do we put in the MPN? I know that I can put it in the Features area, but that is not what I am talking about. I'm trying to figure out how to uploaded using the Google Base export.



Right now on one of my sites I am still uploading via the “Data Feeds” area to Google and I'm not having any real issues there. But I really don't want to have to create a new data feed on a couple of the other sites if CS did in fact fix the Google Export.

Apparently CSC is completely abandoning the original Google base. It's an add-on now that is called “Google export” that you need to install then it will show up when you open up data feeds.



Edit: On top of that, everything is a feature. Sure is going to make it fun when importing features. NOT!



What is really ignorant is that “Availability” is a feature as well. This should have been automatically created base on the quantity/amount.

[quote name='clips' timestamp='1317505630' post='122778']

In 2.2.3 the bulk edit on features pretty much stinks in every browser. We've tried it in Firefox, IE, Chrome and Safari for Windows. If you try to edit 100 items at a time and do the features at the same time it will either not work or IE will give you an error asking if you want the script to continue.

[/quote]



Hello Clips,



Unfortunately, the issue you described is not clear to me. Could you describe the issue in more details? If possible, please provide step-by-step instructions on how we may reproduce the issue. Some screenshots will also be very helpful.



Speaking generally, we have made several changes that should accelerate the speed of work of the Product Features functionality. For example, we have added pagination to the feature variants page and added the “PRODUCT_FEATURE_VARIANTS_THRESHOLD” constant which defines when a usual select box should be replaced with an ajax select box.



We look forward to your reply.



Thank you.

[quote name='The Tool' timestamp='1317612835' post='122824']

Apparently CSC is completely abandoning the original Google base. It's an add-on now that is called “Google export” that you need to install then it will show up when you open up data feeds.



Edit: On top of that, everything is a feature. Sure is going to make it fun when importing features. NOT!



What is really ignorant is that “Availability” is a feature as well. This should have been automatically created base on the quantity/amount.

[/quote]



I agree with you , but it does work for google's new standards, since there are more variants to availability than in stock and out of stock with pre-order and available to order, this works for me, my data feed to google was accepted, but now I have to edit 2500 items to apply all the features, and as Clips said bulk editing will hang the browser.

Well, I may try the new add on with a couple of my sites, but I'm not going to mess with it on one of my primary sites. I didn't realize they opted for an add on. Likewise, since their bulk edit is broke I really don't want to mess with it on the other sites until CS fixes the bug.



@bimib

Sorry you didn't understand. The Tool describes the problem and then gasngrills reinforces the issue that we can't bulk edit the “features” because of the bug in 2.2.3.

[quote name='The Tool' timestamp='1317612835' post='122824']

Apparently CSC is completely abandoning the original Google base. It's an add-on now that is called “Google export” that you need to install then it will show up when you open up data feeds.



Edit: On top of that, everything is a feature. Sure is going to make it fun when importing features. NOT!



What is really ignorant is that “Availability” is a feature as well. This should have been automatically created base on the quantity/amount.

[/quote]



Instead of improving existing google base export function, someone here obviously more like to develop and play with a new toys. New google export add-on/data feed is a disaster for me. Do I need to manually update one by one a several thousands of products, adding google export features?! On the other side, requested “Availability” column missing in the old google base export, and all of my products are now disapproved in the google base listing. Any quick and simple solution for this issue?!

[quote name='Ranger-1' timestamp='1317576227' post='122809']

Due too some odd reason I cannot seem to get access to the Bug-Tracker. Could someone please relay the information regarding the fix for the MIME problem in 2.2.3?

[/quote]



Bump!



Does anyone know how to fix the MIME error? If so, could you please inform us on how to solve this problem?



Thanks!

[quote name='Ranger-1' timestamp='1317738323' post='122896']

Bump!



Does anyone know how to fix the MIME error? If so, could you please inform us on how to solve this problem?



Thanks!

[/quote]



http://forum.cs-cart.com/tracker/issue-2731-image-upload-to-products-is-broken/

Hi All,

I replace the codes manuely, but now when i add a picture i become a blank page.

The Bold once with the italic, and the underlined one i deleted.

Please tell where i am make a mistake.

Best Regards,

This is the file fs.fn.php orginaly :


/***************************************************************************
* *
* (c) 2004 Vladimir V. Kalynyak, Alexey V. Vinokurov, Ilya M. Shalnev *
* *
* This is commercial software, only users who have purchased a valid *
* license and accept to the terms of the License Agreement can install *
* and use this program. *
* *
****************************************************************************
* PLEASE READ THE FULL TEXT OF THE SOFTWARE LICENSE AGREEMENT IN THE *
* "copyright.txt" FILE PROVIDED WITH THIS DISTRIBUTION PACKAGE. *
****************************************************************************/
if ( !defined('AREA') ) { die('Access denied'); }
//
// File system functions definitions
//
/**
* Delete file function
*
* @param string $file_path file location
* @return bool true
*/
function fn_delete_file($file_path)
{
if (!empty($file_path)) {
if (is_file($file_path)) {
@chmod($file_path, 0775);
@unlink($file_path);
}
}
return true;
}
/**
* Normalize path: remove "../", "./" and duplicated slashes
*
* @param string $path
* @param string $separator
* @return string normilized path
*/
function fn_normalize_path($path, $separator = '/')
{
$result = array();
$path = preg_replace("/[\\\\\/]+/S", $separator, $path);
$path_array = explode($separator, $path);
if (!$path_array[0]) {
$result[] = '';
}
foreach ($path_array as $key => $dir) {
if ($dir == '..') {
if (end($result) == '..') {
$result[] = '..';
} elseif (!array_pop($result)) {
$result[] = '..';
}
} elseif ($dir != '' && $dir != '.') {
$result[] = $dir;
}
}
if (!end($path_array)) {
$result[] = '';
}
return fn_is_empty($result) ? '' : implode($separator, $result);
}
/**
* Create directory wrapper. Allows to create included directories
*
* @param string $dir
* @param int $perms permission for new directory
*/
function fn_mkdir($dir, $perms = DEFAULT_DIR_PERMISSIONS)
{
$result = false;
// Truncate the full path to related to avoid problems with
// some buggy hostings
if (strpos($dir, DIR_ROOT) === 0) {
$dir = './' . substr($dir, strlen(DIR_ROOT) + 1);
$old_dir = getcwd();
chdir(DIR_ROOT);
}
if (!empty($dir)) {
clearstatcache();
if (@!is_dir($dir)) {
$dir = fn_normalize_path($dir, '/');
$path = '';
$dir_arr = array();
if (strstr($dir, '/')) {
$dir_arr = explode('/', $dir);
} else {
$dir_arr[] = $dir;
}
foreach ($dir_arr as $k => $v) {
$path .= (empty($k) ? '' : '/') . $v;
clearstatcache();
if (!@file_exists($path)) {
umask(0);
$result = @mkdir($path, $perms);
if (!$result) {
$parent_dir = dirname($path);
$parent_perms = fileperms($parent_dir);
@chmod($parent_dir, 0777);
$result = @mkdir($path, $perms);
@chmod($parent_dir, $parent_perms);
if (!$result) {
break;
}
}
}
}
} else {
$result = true;
}
}
if (!empty($old_dir)) {
@chdir($old_dir);
}
return $result;
}
/**
* Compress files with Tar archiver
*
* @param string $archive_name - name of the compressed file will be created
* @param string $file_list - list of files to place into archive
* @param string $dirname - directory, where the files should be get from
* @return bool true
*/
function fn_compress_files($archive_name, $file_list, $dirname = '')
{
include_once(DIR_LIB . 'tar/tar.php');
$tar = new Archive_Tar($archive_name, 'gz');
if (!is_object($tar)) {
fn_error(debug_backtrace(), 'Archiver initialization error', false);
}
if (!empty($dirname) && is_dir($dirname)) {
chdir($dirname);
$tar->create($file_list);
chdir(DIR_ROOT);
} else {
$tar->create($file_list);
}
return true;
}
/**
* Extract files with Tar archiver
*
* @param $archive_name - name of the compressed file will be created
* @param $file_list - list of files to place into archive
* @param $dirname - directory, where the files should be extracted to
* @return bool true
*/
function fn_decompress_files($archive_name, $dirname = '')
{
include_once(DIR_LIB . 'tar/tar.php');
$tar = new Archive_Tar($archive_name, 'gz');
if (!is_object($tar)) {
fn_error(debug_backtrace(), 'Archiver initialization error', false);
}
if (!empty($dirname) && is_dir($dirname)) {
chdir($dirname);
$tar->extract('');
chdir(DIR_ROOT);
} else {
$tar->extract('');
}
return true;
}
/**
* Get mime type by the file name
*
* @param string $filename
* @return string $file_type
*/
function fn_get_file_type($filename)
{
$file_type = 'application/octet-stream';
static $types = array (
'zip' => 'application/zip',
'tgz' => 'application/tgz',
'rar' => 'application/rar',
'exe' => 'application/exe',
'com' => 'application/com',
'bat' => 'application/bat',
'png' => 'image/png',
'jpg' => 'image/jpeg',
'jpeg' => 'jpeg',
'gif' => 'image/gif',
'bmp' => 'image/bmp',
'swf' => 'application/x-shockwave-flash',
'csv' => 'text/csv',
'txt' => 'text/plain',
'doc' => 'application/msword',
'xls' => 'application/vnd.ms-excel',
'ppt' => 'application/vnd.ms-powerpoint',
'pdf' => 'application/pdf'
);
$ext = substr($filename, strrpos($filename, '.') + 1);
if (!empty($types[$ext])) {
$file_type = $types[$ext];
}
return $file_type;
}
/**
* Function try to get MIME type by different ways.
*
* @param string $filename Full path with name to file
* @return string MIME type of the given file.
*/
[u]function fn_get_mime_content_type($filename)
{
if (class_exists('finfo')) {
$finfo_handler = finfo_open(FILEINFO_MIME);
$type = @finfo_file($finfo_handler, $filename);
list($type) = explode(';', $type);
finfo_close($finfo_handler);
} elseif (function_exists('mime_content_type')) {
$type = mime_content_type($filename);
} else {
if (strpos(basename($filename), '.') !== false) {
$type = fn_get_file_type(basename($filename));
} else {
$type = 'text/plain';
}
}
return $type;
}[/u]

/**
* Get the EDP downloaded
*
* @param string $path path to the file
* @param string $filename file name to be displayed in download dialog
*
*/
function fn_get_file($filepath, $filename = '')
{
$fd = @fopen($filepath, 'rb');
if ($fd) {
$fsize = filesize($filepath);
$ftime = date('D, d M Y H:i:s T', filemtime($filepath)); // get last modified time
if (isset($_SERVER['HTTP_RANGE'])) {
header($_SERVER['SERVER_PROTOCOL'] . ' 206 Partial Content');
$range = $_SERVER['HTTP_RANGE'];
$range = str_replace('bytes=', '', $range);
list($range, $end) = explode('-', $range);
if (!empty($range)) {
fseek($fd, $range);
}
} else {
header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
$range = 0;
}
if (empty($filename)) {
// Non-ASCII filenames containing spaces and underscore characters are chunked if no locale is provided
setlocale(LC_ALL, 'en_US.UTF8');
$filename = basename($filepath);
}
// Browser bug workaround: Filenames can't be sent to IE if there is any kind of traffic compression enabled on the server side
if (USER_AGENT == 'ie') {
if (function_exists('apache_setenv')) {
apache_setenv('no-gzip', '1');
}
ini_set("zlib.output_compression", "Off");
// Browser bug workaround: During the file download with IE, non-ASCII filenames appears with a broken encoding
$filename = rawurlencode($filename);
}
header("Content-disposition: attachment; filename=\"$filename\"");
header('Content-type: ' . fn_get_file_type($filepath));
header('Last-Modified: ' . $ftime);
header('Accept-Ranges: bytes');
header('Content-Length: ' . ($fsize - $range));
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Cache-Control: private', false);
if ($range) {
header("Content-Range: bytes $range-" . ($fsize - 1) . '/' . $fsize);
}
$result = fpassthru($fd);
if ($result == false) {
fclose($fd);
return false;
} else {
fclose($fd);
exit;
}
}
return false;
}
/**
* Create temporary file for uploaded file
*
* @param $val file path
* @return array $val
*/
function fn_get_server_data($val)
{
$tmp = fn_strip_slashes($val);
if (defined('IS_WINDOWS')) {
$tmp = str_replace('\\', '/', $tmp);
}
if (strpos($tmp, DIR_ROOT) === 0) {
$tmp = substr_replace($tmp, '', 0, strlen(DIR_ROOT));
}

$val = array();
setlocale(LC_ALL, 'en_US.UTF8');
$val['name'] = basename($tmp);
$val['path'] = fn_normalize_path(DIR_ROOT . '/' . $tmp);
$tempfile = fn_create_temp_file();
fn_copy($val['path'], $tempfile);
clearstatcache();
$val['path'] = $tempfile;
$val['size'] = filesize($val['path']);

$cache = & Registry::get('temp_fs_data');

if (!isset($cache[$val['path']])) { // cache file to allow multiple usage
$cache[$val['path']] = $tempfile;
}

return $val;
}

/**
* Rebuild $_FILES array to more user-friendly view
*
* @param string $name
* @return array $rebuilt rebuilt file array
*/
function fn_rebuid_files($name)
{
$rebuilt = array();

if (!is_array(@$_FILES[$name])) {
return $rebuilt;
}

if (isset($_FILES[$name]['error'])) {
if (!is_array($_FILES[$name]['error'])) {
return $_FILES[$name];
}
} elseif (fn_is_empty($_FILES[$name]['size'])) {
return $_FILES[$name];
}

foreach ($_FILES[$name] as $k => $v) {
if ($k == 'tmp_name') {
$k = 'path';
}
$rebuilt = fn_array_multimerge($rebuilt, $v, $k);
}

return $rebuilt;
}

/**
* Recursively copy directory (or just a file)
*
* @param string $source
* @param string $dest
* @param bool $silent
*/
function fn_copy($source, $dest, $silent = true)
{
// Simple copy for a file
if (is_file($source)) {
if (@is_dir($dest)) {
$dest .= '/' . basename($source);
}
if (filesize($source) == 0) {
$fd = fopen($dest, 'w');
fclose($fd);
$res = true;
} else {
$res = @copy($source, $dest);
}
@chmod($dest, DEFAULT_FILE_PERMISSIONS);
return $res;
}

// Make destination directory
if ($silent == false) {
fn_set_progress('echo', 'Copying directory ' . ((strpos($dest, DIR_ROOT) === 0) ? str_replace(DIR_ROOT . '/', '', $dest) : $dest) . '
');
}

if (!@is_dir($dest)) {
if (fn_mkdir($dest) == false) {
return false;
}
}

// Loop through the folder
if (@is_dir($source)) {
$dir = dir($source);
while (false !== $entry = $dir->read()) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}

// Deep copy directories
if ($dest !== $source . '/' . $entry) {
if (fn_copy($source . '/' . $entry, $dest . '/' . $entry, $silent) == false) {
return false;
}
}
}

// Clean up
$dir->close();

return true;
} else {
return false;
}
}

/**
* Recursively remove directory (or just a file)
*
* @param string $source
* @param bool $delete_root
* @param string $pattern
* @return bool
*/
function fn_rm($source, $delete_root = true, $pattern = '')
{
// Simple copy for a file
if (is_file($source)) {
$res = true;
if (empty($pattern) || (!empty($pattern) && preg_match('/' . $pattern . '/', basename($source)))) {
$res = @unlink($source);
}
return $res;
}

// Loop through the folder
if (is_dir($source)) {
$dir = dir($source);
while (false !== $entry = $dir->read()) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
if (fn_rm($source . '/' . $entry, true, $pattern) == false) {
return false;
}
}
// Clean up
$dir->close();
return ($delete_root == true && empty($pattern)) ? @rmdir($source) : true;
} else {
return false;
}
}

/**
* Get file extension
*
* @param string $filename
*/
function fn_get_file_ext($filename)
{
$i = strrpos($filename, '.');
if ($i === false) {
return '';
}

return substr($filename, $i + 1);
}

/**
* Get directory contents
*
* @param string $dir directory path
* @param bool $get_dirs get sub directories
* @param bool $get_files
* @param mixed $extension allowed file extensions
* @param string $prefix file/dir path prefix
* @return array $contents directory contents
*/
function fn_get_dir_contents($dir, $get_dirs = true, $get_files = false, $extension = '', $prefix = '', $recursive = false)
{

$contents = array();
if (is_dir($dir)) {
if ($dh = opendir($dir)) {

// $extention - can be string or array. Transform to array.
$extension = is_array($extension) ? $extension : array($extension);

while (($file = readdir($dh)) !== false) {
if ($file == '.' || $file == '..' || $file{0} == '.') {
continue;
}

if ($recursive == true && is_dir($dir . '/' . $file)) {
$contents = fn_array_merge($contents, fn_get_dir_contents($dir . '/' . $file, $get_dirs, $get_files, $extension, $prefix . $file . '/', $recursive), false);
}

if ((is_dir($dir . '/' . $file) && $get_dirs == true) || (is_file($dir . '/' . $file) && $get_files == true)) {
if ($get_files == true && !fn_is_empty($extension)) {
// Check all extentions for file
foreach ($extension as $_ext) {
if (substr($file, -strlen($_ext)) == $_ext) {
$contents[] = $prefix . $file;
break;
}
}
} else {
$contents[] = $prefix . $file;
}
}
}
closedir($dh);
}
}

asort($contents, SORT_STRING);

return $contents;
}

/**
* Get file contents from local or remote filesystem
*
* @param string $location file location
* @param string $base_dir
* @return string $result
*/
function fn_get_contents($location, $base_dir = '')
{
$result = '';
$path = $base_dir . $location;

if (!empty($base_dir) && !fn_check_path($path)) {
return $result;
}

// Location is regular file
if (is_file($path)) {
$result = @file_get_contents($path);

// Location is url
} elseif (strpos($path, '://') !== false) {

// Prepare url
$path = str_replace(' ', '%20', $path);
if (fn_get_ini_param('allow_url_fopen') == true) {
$result = @file_get_contents($path);
} else {
list(, $result) = fn_http_request('GET', $path);
}
}

return $result;
}

/**
* Write a string to a file
*
* @param string $location file location
* @param string $content
* @param string $base_dir
* @return string $result
*/
function fn_put_contents($location, $content, $base_dir = '')
{
$result = '';
$path = $base_dir . $location;

if (!empty($base_dir) && !fn_check_path($path)) {
return false;
}

// Location is regular file
$result = @file_put_contents($path, $content);
if ($result !== false) {
@chmod($path, DEFAULT_FILE_PERMISSIONS);
}
return $result;
}

/**
* Get data from url
*
* @param string $val
* @return array $val
*/
function fn_get_url_data($val)
{
$tmp = fn_strip_slashes($val);
$_data = fn_get_contents($tmp);

if (!empty($_data)) {
$val = array();
$val['name'] = basename($tmp);

// Check if the file is dynamically generated
if (strpos($val['name'], '&') !== false || strpos($val['name'], '?') !== false) {
$val['name'] = 'url_uploaded_file_'.uniqid(TIME);
}
$val['path'] = fn_create_temp_file();
$val['size'] = strlen($_data);

$fd = fopen($val['path'], 'wb');
fwrite($fd, $_data, $val['size']);
fclose($fd);
@chmod($val['path'], DEFAULT_FILE_PERMISSIONS);

$cache = & Registry::get('temp_fs_data');

if (!isset($cache[$val['path']])) { // cache file to allow multiple usage
$cache[$val['path']] = $val['path'];
}
}
return $val;
}

/**
* Function get local uploaded
*
* @param unknown_type $val
* @staticvar array $cache
* @return unknown
*/
function fn_get_local_data($val)
{
$cache = & Registry::get('temp_fs_data');

if (!isset($cache[$val['path']])) { // cache file to allow multiple usage
$tempfile = fn_create_temp_file();
if (move_uploaded_file($val['path'], $tempfile) == true) {
@chmod($tempfile, DEFAULT_FILE_PERMISSIONS);
$cache[$val['path']] = $tempfile;
} else {
$cache[$val['path']] = '';
}
}

if (defined('KEEP_UPLOADED_FILES')) {
$tempfile = fn_create_temp_file();
fn_copy($cache[$val['path']], $tempfile);
clearstatcache();
$val['path'] = $tempfile;
} else {
$val['path'] = $cache[$val['path']];
}

return $val;
}

/**
* Finds the last key in the array and applies the custom function to it.
*
* @param array $arr
* @param string $fn
* @param bool $is_first
*/
function fn_get_last_key(&$arr, $fn = '', $is_first = false)
{
if (!is_array($arr)&&$is_first == true) {
$arr = call_user_func($fn, $arr);
return;
}

foreach ($arr as $k => $v) {
if (is_array($v) && count($v)) {
fn_get_last_key($arr[$k], $fn);
}
elseif (!is_array($v)&&!empty($v)) {
$arr[$k] = call_user_func($fn, $arr[$k]);
}
}
}

/**
* Filter data from file uploader
*
* @param string $name
* @return array $filtered
*/
function fn_filter_uploaded_data($name)
{
$udata_local = fn_rebuid_files('file_' . $name);
$udata_other = !empty($_REQUEST['file_' . $name]) ? $_REQUEST['file_' . $name] : array();
$utype = !empty($_REQUEST['type_' . $name]) ? $_REQUEST['type_' . $name] : array();

if (empty($utype)) {
return array();
}

$filtered = array();

foreach ($utype as $id => $type) {
if ($type == 'local' && !fn_is_empty(@$udata_local[$id])) {
$filtered[$id] = fn_get_local_data(fn_strip_slashes($udata_local[$id]));

} elseif ($type == 'server' && !fn_is_empty(@$udata_other[$id]) && AREA == 'A') {
fn_get_last_key($udata_other[$id], 'fn_get_server_data', true);
$filtered[$id] = $udata_other[$id];

} elseif ($type == 'url' && !fn_is_empty(@$udata_other[$id])) {
fn_get_last_key($udata_other[$id], 'fn_get_url_data', true);
$filtered[$id] = $udata_other[$id];
}

if (!empty($filtered[$id]['name'])) {
$filtered[$id]['name'] = str_replace(' ', '_', urldecode($filtered[$id]['name'])); // replace spaces with underscores
$ext = fn_get_file_ext($filtered[$id]['name']);
if (in_array(strtolower($ext), Registry::get('config.forbidden_file_extensions'))) {
unset($filtered[$id]);
$msg = fn_get_lang_var('text_forbidden_file_extension');
$msg = str_replace('[ext]', $ext, $msg);
fn_set_notification('E', fn_get_lang_var('error'), $msg);
}

[b]if (!empty($filtered) && (!is_array($filtered[$id]) || !empty($filtered[$id]['path']) && in_array(fn_get_mime_content_type($filtered[$id]['path']), Registry::get('config.forbidden_mime_types')))) {[/b]
[i]if (!is_array($filtered[$id]) || !empty($filtered[$id]['path']) && in_array(mime_content_type($filtered[$id]['path']), Registry::get('config.forbidden_mime_types'))) {[/i]


if (!is_array($filtered[$id])) {
$msg = fn_get_lang_var('cant_upload_file');
} else {
[b]$mime = fn_get_mime_content_type($filtered[$id]['path']);[/b]
[i]$mime = mime_content_type($filtered[$id]['path']);[/i]

$msg = fn_get_lang_var('text_forbidden_file_mime');
$msg = str_replace('[mime]', $mime, $msg);
}

fn_set_notification('E', fn_get_lang_var('error'), $msg);
unset($filtered[$id]);
}
}
}

static $shutdown_inited;

if (!$shutdown_inited) {
$shutdown_inited = true;
register_shutdown_function('fn_remove_temp_data');
}

return $filtered;
}

/**
* Remove temporary files
*/
function fn_remove_temp_data()
{
$fs_data = Registry::get('temp_fs_data');
if (!empty($fs_data)) {
foreach ($fs_data as $file) {
fn_delete_file($file);
}
}
}

/**
* Create temporary file
*
* @return temporary file
*/
function fn_create_temp_file()
{
return tempnam(DIR_COMPILED, 'ztemp');
}

/**
* Returns correct path from url "path" component
*
* @param string $path
* @return correct path
*/
function fn_get_url_path($path)
{
$dir = dirname($path);

if ($dir == '.' || $dir == '/') {
return '';
}

return (IIS == true) ? str_replace('\\', '/', $dir) : $dir;
}

/**
* Check path to file
*
* @param string $path
* @return bool
*/
function fn_check_path($path)
{
$real_path = realpath($path);
return str_replace('\\', '/', $real_path) == $path ? true : false;
}

/**
* Gets line from file pointer and parse for CSV fields
*
* @param handle $f a valid file pointer to a file successfully opened by fopen(), popen(), or fsockopen().
* @param int $length maximum line length
* @param string $d field delimiter
* @param string $q the field enclosure character
* @return array structured data
*/
function fn_fgetcsv($f, $length, $d = ',', $q = '"')
{
$list = array();
$st = fgets($f, $length);
if ($st === false || $st === null) {
return $st;
}

if (trim($st) === '') {
return array('');
}

$st = rtrim($st, "\n\r");
if (substr($st, -strlen($d)) == $d){
$st .= '""';
}

while ($st !== '' && $st !== false) {
if ($st[0] !== $q) {
// Non-quoted.
list ($field) = explode($d, $st, 2);
$st = substr($st, strlen($field) + strlen($d));
} else {
// Quoted field.
$st = substr($st, 1);
$field = '';
while (1) {
// Find until finishing quote (EXCLUDING) or eol (including)
preg_match("/^((?:[^$q]+|$q$q)*)/sx", $st, $p);
$part = $p[1];
$partlen = strlen($part);
$st = substr($st, strlen($p[0]));
$field .= str_replace($q . $q, $q, $part);
if (strlen($st) && $st[0] === $q) {
// Found finishing quote.
list ($dummy) = explode($d, $st, 2);
$st = substr($st, strlen($dummy) + strlen($d));
break;
} else {
// No finishing quote - newline.
$st = fgets($f, $length);
}
}
}

$list[] = $field;
}

return $list;
}

/**
* Wrapper for rename with chmod
*
* @param string $oldname The old name. The wrapper used in oldname must match the wrapper used in newname.
* @param string $newname The new name.
* @param resource $context Note: Context support was added with PHP 5.0.0. For a description of contexts, refer to Stream Functions.
*
* @return boolean Returns TRUE on success or FALSE on failure.
*/
function fn_rename($oldname, $newname, $context = null)
{
$result = ($context === null) ? rename($oldname, $newname) : rename($oldname, $newname, $context);
if ($result !== false) {
@chmod($newname, DEFAULT_FILE_PERMISSIONS);
}
return $result;
}

/**
* Create a new filename with postfix
*
* @param string $path
* @param string $file
* @return array ($full_path, $new_filename)
*/
function fn_generate_file_name($path, $file)
{
if (!file_exists($path . $file)) {
return array($path . $file, $file);
}

$files = fn_get_dir_contents($path, false, true);
$num = 1;
$found = false;
$file_ext = fn_get_file_ext($file);
$file_name = basename($path . $file, '.' . $file_ext);

while (!$found) {
$new_filename = $file_name . '_' . $num . '.' . $file_ext;
if (!in_array($new_filename, $files)) {
break;
}

$num++;
}


return array($path . $new_filename, $new_filename);
}

?>

[quote name=‘Flow’ timestamp=‘1317398909’ post=‘122682’]

Upgraded 2 sites in 2 minutes! Gotta love my hook setup :)

[/quote]

How did you set up your hook? advice please :D

Tom

[quote name=‘tom437’ timestamp=‘1317918024’ post=‘123046’]

How did you set up your hook? advice please :D

Tom

[/quote]



Nothing special! I’m just using hooks for all but one of my customizations so I can upgrade trouble free :)

Just upgraded my production store to 2.2.3 from 2.1.4.



I noticed that the downloads area of orders no longer has an activation area. My downloads are set for Manual and I expected too see a select box (or a checkbox) indicating that the download should be activated. But all there is is the link to the product page. So how is one supposed to activate downloads now?



I also noticed that all the email configurations in order_statuses were reset to have no notifications and to be using the default verbiage.



Has anyone else seen this?



Waiting to see what else is broken… I thought this was just a bugfix/stabilization release. Doesn't appear to be an improvement to me so far.



Very nervous now about production site being stable. May revert back tomorrow…

Weird! I don't do downloads so I can't help you there.



As for the order notifications. I just checked and mine are still OK.



Shops are also running very stable at 2.2.3

The latest docs are versioned 2.1.4. Will the docs be updated for the 2.2 series?

Seems download option is a bug (support was very quick in both responding and resolving - Thank you cs-cart) and is addressed by:


In order to fix this bug, please replace the following part of the code:

} elseif ($mode == 'details') {
$_REQUEST['order_id'] = empty($_REQUEST['order_id']) ? 0 : $_REQUEST['order_id'];

$order_info = fn_get_order_info($_REQUEST['order_id'], false, true, false, true);


with this one:

} elseif ($mode == 'details') {
$_REQUEST['order_id'] = empty($_REQUEST['order_id']) ? 0 : $_REQUEST['order_id'];

$order_info = fn_get_order_info($_REQUEST['order_id'], false, true, true, true);


in the "orders.php" file located in the "controllers/admin" directory.




Change 'false' to 'true' in the 4th parameter of the fn_get_order_info() call.



CS can't reproduce the status issue but it happened (in hindsight) on both my test and production stores. Easy enough to go through and reset the way I want, but seems they prior settings should have been saved regardless of what schema updates that might have been done. I have lots of custom statuses so maybe it relates to that.

Just noticed on one of my test stores also was reset by the upgrade. Had nothing special there, but everything is checked off.