The Elearning Community • [Bug? Forma 2.4.x] Services_JSON, accenti - Page 2
Page 2 of 2

Re: [Bug? Forma 2.4.x] Services_JSON, accenti

Posted: Thu Jun 11, 2020 7:31 am
by max
ciao, io ho appena fatto un test analogo su una 2.4.1: caratteri accentati e speciali vengono tutti visualizzati correttamente nella lista corsi

Su questa piattaforma c'è PHP 7.0.33
Io non riscontro dunque nessun problema. Il massimo che posso fare è segnalare la cosa a qualche collega, visto che non riesco a replicarlo non mi sento di aprire un ticket

Re: [Bug? Forma 2.4.x] Services_JSON, accenti

Posted: Thu Jun 11, 2020 9:16 am
by CisterNino
Ciao Studioeco.
Premesso, che ho fatto un test e neanche io ho riscontrato il tuo problema, la soluzione che proponi potrebbe andar bene.

Ad ogni modo, se puoi, ti direi di fare questo test.
Apriti il file \lib\lib.json.php e prenditi la funzione "encode" (riga 238). Commenta le le righe di codice da 359 a 422 e richiamala passandogli in input stringhe accentate. Installala sul tuo server e verifica.

Nel frattempo, facciamo una verifica approfondita se, effettivamente la chiamata this->json->encode($result) in quel si può sostituire senza ulteriori impatti.

Re: [Bug? Forma 2.4.x] Services_JSON, accenti

Posted: Thu Jun 11, 2020 9:38 pm
by studioeco
Allora, innanzitutto grazie ad entrambi per il supporto.
Ho creato un file chiamandolo test.php e ci ho copiato dentro il seguente contenuto (in sostanza quello che ha detto CisterNino con l'aggiunta della funzione utf82utf16 in modo che funzionansse tutto localmente.

Ho quindi eseguito il file e il risultato è il seguente: Image
Vi incollo qui l'intero file che ho testato

Code: Select all

<?php
function encode($var)
{
	switch (gettype($var)) {
		case 'boolean':
			return $var ? 'true' : 'false';

		case 'NULL':
			return 'null';

		case 'integer':
			return (int) $var;

		case 'double':
		case 'float':
			return (float) $var;

		case 'string':
			// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
			$ascii = '';
			$strlen_var = strlen($var);

		   /*
			* Iterate over every character in the string,
			* escaping with a slash or encoding to UTF-8 where necessary
			*/
			for ($c = 0; $c < $strlen_var; ++$c) {

				$ord_var_c = ord($var{$c});

				switch (true) {
					case $ord_var_c == 0x08:
						$ascii .= '\b';
						break;
					case $ord_var_c == 0x09:
						$ascii .= '\t';
						break;
					case $ord_var_c == 0x0A:
						$ascii .= '\n';
						break;
					case $ord_var_c == 0x0C:
						$ascii .= '\f';
						break;
					case $ord_var_c == 0x0D:
						$ascii .= '\r';
						break;

					case $ord_var_c == 0x22:
					case $ord_var_c == 0x2F:
					case $ord_var_c == 0x5C:
						// double quote, slash, slosh
						$ascii .= '\\'.$var{$c};
						break;

					case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
						// characters U-00000000 - U-0000007F (same as ASCII)
						$ascii .= $var{$c};
						break;

					case (($ord_var_c & 0xE0) == 0xC0):
						// characters U-00000080 - U-000007FF, mask 110XXXXX
						// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
						$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
						$c += 1;
						$utf16 = utf82utf16($char);
						$ascii .= sprintf('\u%04s', bin2hex($utf16));
						break;

					case (($ord_var_c & 0xF0) == 0xE0):
						// characters U-00000800 - U-0000FFFF, mask 1110XXXX
						// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
						$char = pack('C*', $ord_var_c,
									 ord($var{$c + 1}),
									 ord($var{$c + 2}));
						$c += 2;
						$utf16 = utf82utf16($char);
						$ascii .= sprintf('\u%04s', bin2hex($utf16));
						break;

					case (($ord_var_c & 0xF8) == 0xF0):
						// characters U-00010000 - U-001FFFFF, mask 11110XXX
						// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
						$char = pack('C*', $ord_var_c,
									 ord($var{$c + 1}),
									 ord($var{$c + 2}),
									 ord($var{$c + 3}));
						$c += 3;
						$utf16 = utf82utf16($char);
						$ascii .= sprintf('\u%04s', bin2hex($utf16));
						break;

					case (($ord_var_c & 0xFC) == 0xF8):
						// characters U-00200000 - U-03FFFFFF, mask 111110XX
						// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
						$char = pack('C*', $ord_var_c,
									 ord($var{$c + 1}),
									 ord($var{$c + 2}),
									 ord($var{$c + 3}),
									 ord($var{$c + 4}));
						$c += 4;
						$utf16 = utf82utf16($char);
						$ascii .= sprintf('\u%04s', bin2hex($utf16));
						break;

					case (($ord_var_c & 0xFE) == 0xFC):
						// characters U-04000000 - U-7FFFFFFF, mask 1111110X
						// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
						$char = pack('C*', $ord_var_c,
									 ord($var{$c + 1}),
									 ord($var{$c + 2}),
									 ord($var{$c + 3}),
									 ord($var{$c + 4}),
									 ord($var{$c + 5}));
						$c += 5;
						$utf16 = utf82utf16($char);
						$ascii .= sprintf('\u%04s', bin2hex($utf16));
						break;
				}
			}

			return '"'.$ascii.'"';

		
	}
}

function utf82utf16($utf8)
{
	// oh please oh please oh please oh please oh please
	if(function_exists('mb_convert_encoding')) {
		return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
	}

	switch(strlen($utf8)) {
		case 1:
			// this case should never be reached, because we are in ASCII range
			// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
			return $utf8;

		case 2:
			// return a UTF-16 character from a 2-byte UTF-8 char
			// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
			return chr(0x07 & (ord($utf8{0}) >> 2))
				 . chr((0xC0 & (ord($utf8{0}) << 6))
					 | (0x3F & ord($utf8{1})));

		case 3:
			// return a UTF-16 character from a 3-byte UTF-8 char
			// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
			return chr((0xF0 & (ord($utf8{0}) << 4))
					 | (0x0F & (ord($utf8{1}) >> 2)))
				 . chr((0xC0 & (ord($utf8{1}) << 6))
					 | (0x7F & ord($utf8{2})));
	}

	// ignoring UTF-32 for now, sorry
	return '';
}

$test = 'àèìòùèé';
echo("The text before was: '$test'\n\n");
$converted = encode($test);
echo("The converted test is: '$converted'\n\n");
Per chiarezza la versione del server è un Centos 8 (appena scaricato usando vagrant) sul quale ho installato l'ultimo nginx e i pacchetti php70 remi sono i seguenti

Code: Select all

php70-php-pdo-7.0.33-21.el8.remi.x86_64
php70-php-xml-7.0.33-21.el8.remi.x86_64
php70-php-mcrypt-7.0.33-21.el8.remi.x86_64
php70-php-cli-7.0.33-21.el8.remi.x86_64
php70-php-fpm-7.0.33-21.el8.remi.x86_64
php70-php-mysqlnd-7.0.33-21.el8.remi.x86_64
php70-php-mbstring-7.0.33-21.el8.remi.x86_64
php70-php-pecl-zip-1.18.2-1.el8.remi.x86_64
php70-runtime-2.0-1.el8.remi.x86_64
php70-php-common-7.0.33-21.el8.remi.x86_64
php70-2.0-1.el8.remi.x86_64
php70-php-pecl-mysql-1.0.0-0.20.20180226.647c933.el8.remi.x86_64
php70-php-json-7.0.33-21.el8.remi.x86_64
Grazie ancora.

Re: [Bug? Forma 2.4.x] Services_JSON, accenti

Posted: Fri Jun 12, 2020 8:25 am
by CisterNino
Ok. Il test è quello. Però la pagina test.php, dovresti caricarla sullo stesso server sul quale hai il problema e richiamarla dal web. Il risultato atteso, stando quello che hai scritto nei tuoi post, dovrebbe essere le lettere accentate non scritte correttamente.

Re: [Bug? Forma 2.4.x] Services_JSON, accenti

Posted: Fri Jun 12, 2020 11:02 am
by studioeco
CisterNino wrote: Fri Jun 12, 2020 8:25 am Ok. Il test è quello. Però la pagina test.php, dovresti caricarla sullo stesso server sul quale hai il problema e richiamarla dal web. Il risultato atteso, stando quello che hai scritto nei tuoi post, dovrebbe essere le lettere accentate non scritte correttamente.
Ok ho scoperto l'arcano :-)

Per farla breve l'installazione di php-mbstring mancava o era fallata (che casualità) su entrambe le macchine su cui non funzionava la funzione.

Di fatto però il problema (che ripeto si rolve installando php-mbstring) sposta l'attenzione sulla funzione utf82utf16 del file lib.json.php.
In sostanza nelle prime 3 righe di quella funzione si controlla che esista mb_convert_encoding (che è una funzione che si trova nel mod mbstring appunto) per poi usarla. Il problema è quando questa funzione non esiste, perchè a quel punto si oltrepassano le prime 3 righe di codice e le seguenti generano dei caratteri non validi.

Direi che forse conviene lanciare un'eccezione a quel punto così da evitare ogni problema al riguardo.

Grazie di nuovo a tutti per il supporto.