PHP Unknown error: Collator::__construct(): collator_create: unable to open ICU collator in Unknown on line 0

Full error message that occurred on mac (mavericks) homebrew version of php (php54, php55, php56) with php-intl (php54-intl, php55-intl, php56-intl) with intl.use_exceptions=1 and intl.error_level=E_ALL :

Unknown error: Collator::__construct(): collator_create: unable to open ICU collator in Unknown on line 0
PHP Fatal error: Uncaught exception 'IntlException' with message 'collator_create: unable to open ICU collator' in -:2
Stack trace:
#0 -(2): Collator->__construct('en_US')
#1 {main}
thrown in - on line 2

or without the default ini settings

PHP Fatal error: Call to a member function getLocale() on a non-object in - on line 3

Fatal error: Call to a member function getLocale() on a non-object in – on line 3

or in symfomny2

PHP Fatal error: Call to a member function asort() on null in APP_DIR/vendor/symfony/icu/Symfony/Component/Icu/IcuRegionBundle.php on line 79

After couple of hours I found the error to be inside icu4c library installed via homebrew.

The fix for this error is to reinstall the icu4c library, php and php-intl

brew reinstall icu4c php55 php55-intl

Weird characters transmitted to and from server through jQuery AJAX call

A simplified example of my app:
I have a HTML form as the output of a PHP script that gets a text from a database and fills an input of that form with it. There I can edit the text that on form submit is sent to a PHP script via a jQuery AJAX call. Through PHP the text is saved in the database and then the saved value is retrieved in PHP and sent in the JSON result of the AJAX call.
The character encoding of the HTML page is ISO-8859-1:

Let’s say the he HTML form looks like this:

<form id="my_form">
<input type="text" id="txtId" name="txt" value="" />
<input type="submit" name="btn" value="save">
</form>

On form submit this AJAX call is made:

$.ajax({
	type: "POST",
	url: "my_script.php",
	data: $("#my_form").serialize(),
	success: function (jsonObj) {
		if(!jsonObj) {
			return;
		}
		if("txt" in jsonObj) {
			$("#txtId").val(jsonObj[txt]);
		}
		return false;
	},
	error: showError,
	dataType: "json"
});

In PHP, after saving the text in the database and retrieving the saved text, I add it to an associative array which I convert into a JSON object displayed as the response of the AJAX call:

$item['txt'] = $value; //$value is the text saved in the database
header("Content-type: application/json");
echo json_encode($item);

At first I submited the form with exactly the text that came from PHP at page load. It looked fine, bun when reloading the page, a weird text filled my form input. I had the text a×b and now I got a×b.
I submitted the form again with text a×b and I studied the AJAX call response with Firebug. In both Console and Net tabs of Firebug, under Post tab of the call everything looked fine, but under Response tab I got “txt”:”a\u00d7b” instead of “txt”:”a×b”.
It looked like the text somwhere on the way back to the form got encoded in a weird manner. The × character is a Windows-1252 encoded character, not an UTF-8 encoded character and I should discover where the encoding of the text changed.
I submitted the correct text again and outputted the text saved in the database without json_encode-ing it:

echo $item['txt'];

In Firebug, in the Response tab of the AJAX call, even though under the Console tab of Firebug the text looked fine, under the Net tab it appeared like this: a×b.

Again I submitted the correct text and outputted the value that came via AJAX:

echo $_POST['txt'];

And again I obtained the correct text under the Console tab and the incorrect one under the Net tab in Firebug, which meant that the encoding broke before the text got to the server.

Then, under Headers tab of the call, I noticed among the Request Headers: Content-Type application/x-www-form-urlencoded; charset=UTF-8 and I thought maybe setting the character encoding of the jQuery.ajax call to ISO-8859-1 instead of UTF-8 would solve my problem:

$.ajax({
	type: "POST",
	url: "my_script.php",
	data: $("#my_form").serialize(),
	contentType: "application/x-www-form-urlencoded;charset=ISO-8859-1",
	success: function (jsonObj) {
		if(!jsonObj) {
			return;
		}
		if("txt" in jsonObj) {
			$("#txtId").val(jsonObj[txt]);
		}
		return false;
	},
	error: showError,
	dataType: "json"
});

But the result remained the same and even more, the Content-Type header did not change either. After lots of thinking and testing, I came to these conclusions:
1. If the data parameter of the jQuery.ajax call is not empty and the type parameter is set to “POST”, the character encoding of the request remains UTF-8 no matter what, so (if I want my encoding to take effect) what I would normaly put in the data parameter I should add to the query string of the url of the AJAX call and not specify or leave the data parameter empty (setting the value of empty string to the data parameter).
2. Explicitly setting the character encoding of the AJAX request to ISO-8859-1 didn’t help at all with my problem.
3. jQuery serialize function `messes up` special characters that are not UTF-8 encoded, because it uses JavaScript function encodeURIComponent which UTF-8-encodes special characters, so make sure to UTF-8-decode the texts in the server script when using jQuery serialize or JavaScript encodeURIComponent function in an AJAX call.

So I left the JavaScript code as it initially was (without specifying the contentType parameter to the jQuery.ajax call) and, in the PHP code, decoded the string before saving it in the database:

$txt = utf8_decode($_POST['txt']);

By now I have the correct text saved in the database, but another problem arises: the text in the response of the AJAX call is null. But why?
PHP function json_encode only works with UTF-8 encoded characters, that’s why. So I should have may own JSON-maker function:

function make_json($item) {
	foreach($item as $key => $value) {
		if(is_array($value)) {
			$arr[] = '"'.$key.'":'.make_json($item[$key]);
		} else {
			$arr[] = '"'.$key.'":"'.str_replace(array("\\", "\""), array("\\\\", "\\\""), $value).'"';
		}
	}
	return '{'.implode(",",$arr)."}";
}

And the code in the PHP script becomes:

header("Content-type: application/json");
echo make_json($item);

But now I get this weird result: a�b (diamond shaped character with question mark inside instead of special characters). This time in the Net tab of Firebug everything looks fine, while the diamond shaped characters appear in the Console tab and in the HTML page.

I solved it by explicitly setting (in PHP) the character encoding of the response of the AJAX call to ISO-8859-1 (thanks to this post):

header("Content-type: application/json; charset=ISO-8859-1");
echo make_json($item);

Null value of a string variable in the JSON response object of an AJAX call

I have a jQuery AJAX call for a PHP script that retrieves a text value from a database and outputs a JSON object containing it:

$.ajax({
	type: "GET",
	url: "my_script.php",
	success: function (jsonObj) {
		if("txt" in jsonObj) {
			console.log(jsonObj.txt);
		}
	},
	error: function(jXHR, textStatus, errorThrown) {		
		console.log("The info cannot be loaded.", jXHR, textStatus, errorThrown);
	},
	dataType: "json"
});

In PHP, after retrieving the text from the database, I add it to an associative array which I convert into a JSON object displayed as the response of the AJAX call:

$item['txt'] = $value; //$value is the text got from the database
header("Content-type: application/json");
echo json_encode($item);

Even though $value is not null, in the response of the AJAX call txt variable has the null value. Which means that json_encode function fails in the case of my text. As I later discovered, that is because the text I got from the database contained non-UTF-8 encoded characters and in the first parameter of the json_encode function, as PHP manual says, `All string data must be UTF-8 encoded.`
So if you want to handle non-UTF-8 encoded characters through jQuery AJAX calls with JSON data type response, you should make your own JSON encoding function. A basic example would be:

function make_json($item) {
	foreach($item as $key => $value) {
		if(is_array($value)) {
			$arr[] = '"'.$key.'":'.make_json($item[$key]);
		} else {
			$arr[] = '"'.$key.'":"'.str_replace(array("\\", "\""), array("\\\\", "\\\""), $value).'"';
		}
	}
	return '{'.implode(",",$arr)."}";
}

And the code in the PHP script goes like:

header("Content-type: application/json; charset=ISO-8859-1");
echo make_json($item);

NOQUEUE: reject: RCPT from unknown[xxx.xxx.xxx.xxx]: 553 5.7.1 : Sender address rejected: not owned by user

This error was written in my maillog when I was trying to send an email with Thunderbird.

It seams that the reason for this error was the fact that I used on the outgoing server’s options a port number that was used for imap instead of the needed smtp server.

This error is really weird:

Mar 27 10:33:32 somehost postfix/smtpd[34322]: NOQUEUE: reject: RCPT from unknown[127.0.0.1]: 553 5.7.1 : Sender address rejected: not owned by user login_and_sender@example.com; from= to= proto=ESMTP helo=

To fix this check out the outgoing server settings to have set the correct smtp port number.

Slow ssh and slow vsftpd login – Centos 6

The reason that the ssh commands were slow and sluggish (had to wait for seconds after enter was pressed to execute the command). There was nothing in the logs (that I could find) to help me identify this issue. I used google and many ideas from different forums without any luck.

I discovered that the changes I did to iptables some time before were wrong. Being a newbie I removed a rule that seamed suspicious (to me this rule looked too permissive):

ACCEPT all -- anywhere anywhere

To fix the issue I added the following rule back to my iptables. “This rule will allow all incoming packets destined for the localhost interface to be accepted.”

iptables -A INPUT -i lo -j ACCEPT

How to move Winamp playlist entries fast to the begining or the end of the list when having a long playlist

Selecting the Winamp entries:
1. Click on one entry in the list that you want to move.
2. If you want to move several entries, you can select them in one of the following ways:
– to select a block of entries starting with the entry chosen at step 1 (onwards/backwards from that entry):
SHIFT + left mouse button click on the last entry to be moved
or
SHIFT + up/down arrow
– to select non consecutive entries including the entry chosen at step 1: CTRL + left mouse button click on every other entry to be moved.

Moving the selected entries to the begining/end of the Winamp playlist:
1. Left mouse button click and hold on one of the selected entries and press HOME/END key on the keyboard so that you end up on the first/last page of the playlist. Don’t release the mouse button!
2. Drag the selection with the mouse to the very begining/end of the playlist.

Enjoy your audition!

PHP isset() function returns FALSE even though the variable is defined

Let’s say we have a table item in a MySQL database, with the primary key iditem and a field code that can be NULL:

CREATE TABLE `item` (
`iditem` int(10) unsigned NOT NULL,
`code` VARCHAR(10) DEFAULT NULL,
PRIMARY KEY (`iditem`),
);

--
-- Dumping data for table `item`
--

INSERT INTO `item` (`iditem`, `code`) VALUES
(1, 'as1435v'),
(2, NULL),
(3, 1, 'YHryt4t90');

In PHP we define a variable $item_code that we initialize with 0 and then we run a query for setting the value of $item_code to the code of the item which has the id 2 in our database:

$item_code = 0;
$query = "SELECT code FROM item WHERE iditem = 2";
$result = mysql_query($conn); //$conn is our database connection
if($result) {
	if($row = mysql_fetch_row($result)) {
		$item_code = $row[0];
	}
}

if(isset($item_code)) {
	echo "item code: ".$item_code;
} else {
	echo "item code is not set";
}

The output will be:
item code is not set

That is because the code is NULL in the database and it is transferred into PHP not as the empty string, but as NULL.
And the name of the isset() function is misleading as it returns FALSE not only when a variable is not defined, but also when a variable has been set to NULL.

Delayed javascript function/handler gets the right variable/parameter values

So we have a function that adds a handler function that is called after an ajax load or at a later time and we need to execute the handler function code for each item inside an array allowing the function to access the array values. Usually with the simplest try you would get some code that get’s executed with invalid variable values. Examples are below.

The wrong code:

//the function that will do the stuff for each array
var dostuff = function (arr) {
var n = arr.length,
    i;
    for(i = 0; i < n; i++) {
        var o = arr[i];
        //event bind or delayed function call
        setTimeout(function () {
                //we want to access here the correct arr[i]
                //when the code gets here the value of o is arr[arr.length-1]
                console.log(o);
        }, 1000);
    }
}
dostuff([1,2,3,4]);

You can load the code into your javascript console to see it in action.
The output appears after 1 second and it is like this:

4
4
4
4

I don't need that. I need something that works so we need to wrap the handler call into a function call that will pass the current values as parameters.

var dostuff = function (arr) {
var n = arr.length,
    i;
    for(i = 0; i < n; i++) {
        var o = arr[i];
        (function (y) {
            setTimeout(function () {
                console.log(y);
            }, 1000);
        }) (o);
    }
}
dostuff([1,2,3,4]);

The output appears after 1 second and it is like this:

1
2
3
4

The final best solution would be to have the function inside for already defined so you don't define it on every loop:

var dostuff_item = function (y) {
            setTimeout(function () {
                console.log(y);
         }, 1000);
 }
var dostuff = function (arr) {
var n = arr.length,
    i;
    for(i = 0; i < n; i++) {
        var o = arr[i];
        dostuff_item (o);
    }
}
dostuff([1,2,3,4]);

Tada!

Updating multiple fields in multiple rows with different values in a single query in MySQL using the CASE operator does not supply a correct result

Suppose we have a table with rows representing nodes of a tree structure, each node being represented by an id, a parent id and a position between the children of its parent node:

CREATE TABLE  `tree`.`node` (
`idnode` TINYINT NOT NULL AUTO_INCREMENT ,
`idnode_parent` TINYINT NULL ,
`position` TINYINT NULL ,
PRIMARY KEY ( `idnode` )
);

The nodes with idnode_parent set to 0 or NULL are on the first level of the tree structure.

Now we populate the table:

#add some first level nodes
INSERT INTO `tree`.`node` VALUES (NULL, 0, 1); #idnode = 1
INSERT INTO `tree`.`node` VALUES (NULL, 0, 2); #idnode = 2
#add some children for the first node on the first level
INSERT INTO `tree`.`node` VALUES (NULL, 1, 1); #idnode = 3
INSERT INTO `tree`.`node` VALUES (NULL, 1, 2); #idnode = 4
#add some children for the node with idnode 2
INSERT INTO `tree`.`node` VALUES (NULL, 2, 1); #idnode = 5
INSERT INTO `tree`.`node` VALUES (NULL, 2, 2); #idnode = 6
INSERT INTO `tree`.`node` VALUES (NULL, 2, 3); #idnode = 7
#add a child for the node with idnode 7
INSERT INTO `tree`.`node` VALUES (NULL, 7, 1); #idnode = 8

Now the table looks like this:
idnode idnode_parent position
1 0 1
2 0 2
3 1 1
4 1 2
5 2 1
6 2 2
7 2 3
8 3 1
9 7 1

We want to delete:
– node 1, so we move its children (3, 4) up one level (idnode_parent changes from 1 to 0) and update their positions to the position of their parent (position changes from 1, 2 respectively to 1);
– node 7, so we move its children (8) up one level (idnode_parent changes from 7 to 2) and update their positions to the position of their parent (position changes from 1 to 3)

a) We try this query:

UPDATE node
SET idnode_parent = CASE(idnode_parent)
WHEN 1 THEN 0
WHEN 7 THEN 2
END,
position = CASE(idnode_parent)
WHEN 1 THEN 1
WHEN 7 THEN 3
END
WHERE idnode_parent IN (1, 7);

Running this query, MySQL says 3 rows were affectedand the table looks as follows:

idnode idnode_parent position
1 0 1
2 0 2
3 0 NULL
4 0 NULL
5 2 1
6 2 2
7 2 3
8 3 1
9 2 NULL

We can see that only the field idnode_parent updated as expected, the position field for the moved nodes being set to NULL.

b) We reset the table to the initial test data and we run the above query with the difference of using the ELSE clause in the CASE expression:

UPDATE node
SET idnode_parent = CASE(idnode_parent)
WHEN 1 THEN 0
WHEN 7 THEN 2
ELSE idnode_parent
END,
position = CASE(idnode_parent)
WHEN 1 THEN 1
WHEN 7 THEN 3
ELSE position
END
WHERE idnode_parent IN (1, 7);

The result is:

idnode idnode_parent position
1 0 1
2 0 2
3 0 1
4 0 2
5 2 1
6 2 2
7 2 3
8 3 1
9 2 1

So the idnode_parent field updates correctly, but position remains unchanged.

My conclusion is that that the query runs as if there were two different queries running over the bunch of rows resulted after evaluating the WHERE condition, the second CASE operator applying over the data modified by the first CASE operator:
1. WHERE condition is evaluated; resulted data set:

idnode idnode_parent position
3 1 1
4 1 2
9 7 1

2. idnode_parent is set by evaluating the first CASE expression:

idnode idnode_parent position
3 0 1
4 0 2
9 2 1
3. position is set by evaluating the second CASE expression:

a) Using the query without the ELSE condition, position is set to NULL for all the rows in the data set, as after running the first CASE expression there are no more rows with the idnode_parent needed for the second CASE expression:
idnode idnode_parent position
3 0 NULL
4 0 NULL
9 2 NULL

b) Using the query with the ELSE condition, position remains unchanged for all the rows in the data set, as there are no more rows with the needed idnode_parent, as they were modified by applying the previous CASE operator, and the ELSE condition is evaluated:
idnode idnode_parent position
3 0 1
4 0 2
9 2 1

So if we want the query to run correctly, we set the position first, and then the id of the parent node, as position does not modify data needed for subsequent idnode_parent updates in the same query:

UPDATE node
SET position = CASE(idnode_parent)
WHEN 1 THEN 1
WHEN 7 THEN 3
END,
idnode_parent = CASE(idnode_parent)
WHEN 1 THEN 0
WHEN 7 THEN 2
END
WHERE idnode_parent IN (1, 7);

We finally obtain the expected result:
idnode idnode_parent position
3 0 1
4 0 1
9 2 3