Извлечение символов строки по индексу

netman2002

Новичок
Добрый день!

Вот скрипт:

<?
$s1 = 'a:2:{s:7:"program";a:20:{s:14:"wpcf-post-type";s:7:"program";s:6:"labels";a:12:{s:4:"name";s:18:"Программы";s:13:"singular_name";s:18:"программа";s:7:"add_new";s:35:"Добавить программу";s:12:"add_new_item";s:35:"Добавить программу";s:9:"edit_item";s:45:"Редактировать программу";s:8:"new_item";s:29:"Новая программа";s:9:"view_item";s:35:"Просмотр программы";s:12:"search_items";s:29:"Поиск программы";s:9:"not_found";s:11:"No %s found";s:18:"not_found_in_trash";s:20:"No %s found in Trash";s:17:"parent_item_colon";s:9:"Parent %s";s:9:"all_items";s:2:"%s";}s:4:"slug";s:7:"program";s:11:"description";s:0:"";s:6:"public";s:6:"public";s:13:"menu_position";s:0:"";s:9:"menu_icon";s:0:"";s:10:"taxonomies";a:2:{s:8:"activity";i:1;s:6:"season";i:1;}s:8:"supports";a:5:{s:5:"title";s:1:"1";s:6:"editor";s:1:"1";s:9:"revisions";s:1:"1";s:7:"excerpt";s:1:"1";s:9:"thumbnail";s:1:"1";}s:7:"rewrite";a:6:{s:7:"enabled";s:1:"1";s:6:"custom";s:6:"custom";s:4:"slug";s:8:"programs";s:10:"with_front";s:1:"1";s:5:"feeds";s:1:"1";s:5:"pages";s:1:"1";}s:11:"has_archive";s:1:"1";s:12:"show_in_menu";s:1:"1";s:17:"show_in_menu_page";s:0:"";s:7:"show_ui";s:1:"1";s:18:"publicly_queryable";s:1:"1";s:10:"can_export";s:1:"1";s:17:"show_in_nav_menus";s:1:"1";s:17:"query_var_enabled";s:1:"1";s:9:"query_var";s:0:"";s:16:"permalink_epmask";s:12:"EP_PERMALINK";}s:6:"pressa";a:20:{s:14:"wpcf-post-type";s:6:"pressa";s:6:"labels";a:12:{s:4:"name";s:20:"Публикации";s:13:"singular_name";s:20:"Публикация";s:7:"add_new";s:16:"Добавить";s:12:"add_new_item";s:48:"Добавить новую публикацию";s:9:"edit_item";s:47:"Редактировать публикацию";s:8:"new_item";s:31:"Новая публикации";s:9:"view_item";s:37:"Просмотр публикации";s:12:"search_items";s:9:"Search %s";s:9:"not_found";s:11:"No %s found";s:18:"not_found_in_trash";s:20:"No %s found in Trash";s:17:"parent_item_colon";s:9:"Parent %s";s:9:"all_items";s:2:"%s";}s:4:"slug";s:6:"pressa";s:11:"description";s:0:"";s:6:"public";s:6:"public";s:13:"menu_position";s:0:"";s:9:"menu_icon";s:0:"";s:10:"taxonomies";a:3:{s:8:"category";s:1:"1";s:8:"post_tag";s:1:"1";s:7:"regions";s:1:"1";}s:8:"supports";a:4:{s:5:"title";s:1:"1";s:6:"editor";s:1:"1";s:7:"excerpt";s:1:"1";s:9:"thumbnail";s:1:"1";}s:7:"rewrite";a:6:{s:7:"enabled";s:1:"1";s:6:"custom";s:6:"normal";s:4:"slug";s:0:"";s:10:"with_front";s:1:"1";s:5:"feeds";s:1:"1";s:5:"pages";s:1:"1";}s:11:"has_archive";s:1:"1";s:12:"show_in_menu";s:1:"1";s:17:"show_in_menu_page";s:0:"";s:7:"show_ui";s:1:"1";s:18:"publicly_queryable";s:1:"1";s:10:"can_export";s:1:"1";s:17:"show_in_nav_menus";s:1:"1";s:17:"query_var_enabled";s:1:"1";s:9:"query_var";s:0:"";s:16:"permalink_epmask";s:12:"EP_PERMALINK";}}';
$s2 = '';
for ( $i=0; $i < strlen($s1); $i++ ) {
$c1 = $s1[$i];
$c2 = substr($s1, $i, 1);
if ( $c1 != $c2 ) {
echo $i . ': ' . $c1 . '/' . $c2 . '<br>';
}
}
?>

Дело в том, что на разных хостах, этот скрипт отрабатывает по разному и проблема в извлечении символа строки по индексу ($s1[$i]): на одном хосте $c1 всегда равен $c2, а на другом, как только пошла кириллица - символы не совпадают.
Версии php:
корректно работает - 5.3.5
не корректно - 5.3.13

Т.е. я подозреваю, что где-то кроется какая-то настройка... Какая - я не пойму

Как я догадываюсь, при извлечении символа по индексу, извлекается строго нужный байт (один байт), тогда как символ кириллицы кодируется двумя байтами - отсюда и проблемы. Но почему на хосте, где версия php младше все работает корректно?

PS: все корни растут из Wordpress... Я перенес копию сайта на другой хост и там все раскорячило из-за вышеуказанной проблемы, но сайт-то в оригинале работает... Значит и на другом хосте можно заставить его работать... Заменять извлечение по индексу на substr нельзя, т.к. это ядро Wordpress.

Как это урегулировать?
 
Последнее редактирование:

netman2002

Новичок
Скажем так: менять в коде ничего нельзя - это движок wordpress (старая версия)
Нужно найти настройку (php, apache, mysql)
 

netman2002

Новичок
Я и так знаю, что это за функция...
Дело в том, что на на разных хостингах функция $c1 = $s1[$i]; (извлечение символа строки по целочисленному индексу) работает по разному с символами кириллицы.

Может ли быть это связано с тем, что данная функция коряво работает на "Денвере", который установлен на Wimdows 7 ? На хостингах где Linux/Unix - вроде нормально работает...
 

WMix

герр M:)ller
Партнер клуба
продемонстрируй по шагам, создал, сериализировал, десериализировал, выбрал. и результаты на 2х разных машинах
 

AnrDaemon

Продвинутый новичок
Я и так знаю, что это за функция...
Дело в том, что на на разных хостингах функция $c1 = $s1[$i]; (извлечение символа строки по целочисленному индексу) работает по разному с символами кириллицы.
Зачем ты вообще с сериализованной строкой напрямую работаешь?…
 

netman2002

Новичок
Зачем ты вообще с сериализованной строкой напрямую работаешь?…
То, что в шапке - это всего лишь пример, который я придумал для анализа...
На самом деле все обстоит так:

Есть сайт, который работает на старом Wordpress (работает и ошибок не выдает). Было решено перенести копию сайта (с базой) на другой хостинг (в частности я решил перенести его к себе на локальный комп, на денвер). Перенес, запустил - полезли ошибки. Начал отслеживать трассировщиком... И что выяснил: один из плагинов достает из базы (средствами Wordpress) сериализованный массив и пытается с ним работать, но, в ядре вордпресса, после изъятия из базы строки, идет проверка строки функцией is_serialized(), которая начинает работать с данной строкой и извлекает из него символы по индексу (и тут весь косяк!). Это не я работаю с сериализованной строкой, а ядро вордпресс. И чтобы проверить данный косяк, я написал простенький скрипт, который и привел сверху...

Т.е. если где-то это работает, то почему у меня не работает?
 

AnrDaemon

Продвинутый новичок
Потому что ты кодировку БД не выставил нормально.
А идиот, который писал плагин, в строковое поле заносил бинарные данные.
Если этим полем никто больше не пользуется, найди, в какой кодировке данные сохранены, в какой должны получаться, если они отличаются, конвертируй сначала из сохранения в отдачу, а потом преврати эту колонку в BINARY.
 

netman2002

Новичок
продемонстрируй по шагам, создал, сериализировал, десериализировал, выбрал. и результаты на 2х разных машинах
<!DOCTYPE html>
<html>
<head>
<title>Example 1</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet" href="style.css" media="all">
</head>
<body>
<div class="box">
<?
$s1 = 'Test Тест Test Тест';
for ( $i=0; $i < strlen($s1); $i++ ) {
$c1 = $s1[$i];
$c2 = substr($s1, $i, 1);
echo $c1 . '/' . $c2 . '<br>';
}
?>
</div>
</body>
</html>

Этот php файл сохранен в кодировке utf-8

Вот результат (на моем локальном денвере):


Это на другом хосте:

 
Последнее редактирование:

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
@WMix, менять в коде ничего нельзя!!!!11111
 

netman2002

Новичок
Один и тот же код на разных хостах по разному отрабатывает... Настройки? Или это дело в Windows 7 на котором денвер?

Мне хотя бы понять, как выровнять выполнение на хостах.
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
Ему вообще не надо, у него unserialize срывается из-за неверной кодировки ответа, судя по описанию проблемы.
 

netman2002

Новичок
Срывается вот эта функция (функция из ядра вордпресс):

/**
* Check value to find if it was serialized.
*
* If $data is not an string, then returned value will always be false.
* Serialized data is always a string.
*
* @since 2.0.5
*
* @param mixed $data Value to check to see if was serialized.
* @return bool False if not serialized and true if it was.
*/
function is_serialized( $data ) {
// if it isn't a string, it isn't serialized
if ( ! is_string( $data ) )
return false;
$data = trim( $data );
if ( 'N;' == $data )
return true;
$length = strlen( $data );
if ( $length < 4 )
return false;
if ( ':' !== $data[1] )
return false;
$lastc = $data[$length-1];
if ( ';' !== $lastc && '}' !== $lastc )
return false;
$token = $data[0];
switch ( $token ) {
case 's' :
if ( '"' !== $data[$length-2] )
return false;
case 'a' :
case 'O' :
return (bool) preg_match( "/^{$token}:[0-9]+:/s", $data );
case 'b' :
case 'i' :
case 'd' :
return (bool) preg_match( "/^{$token}:[0-9.E-]+;\$/", $data );
}
return false;
}

$lastc = $data[$length-1]; - вот эта строка, вместо требуемой последней фигурной скобки } возвращает другой символ...
 
Сверху