Monday, August 29, 2011

JavaScript Array Scrambling

Ever need to randomly re-order an array in JavaScript? I have. And, unfortunately, there is no native support for a function like shuffle() in PHP.

I found a few people suggest this technique, but I have found it to not be very good. The elements weren't all that random especially for the first and last elements in particular (they were usually one of two values).

myArray.sort( function(a, b) {
return Math.round((Math.random() * 100) - 50);
});

It uses the native sort() function requires a function that will compare two values to determine which one comes first. If the number returned is negative it indicates that the 'a' item goes first and vice-versa if it is positive.

I found the following function to be more random:

function mixArray(arrayIn) {
var arrayOut = [];
var origLength = arrayIn.length;
for (var x = 0; x < origLength; x++) {
var randIndex = Math.floor(Math.random() * arrayIn.length);
if (randIndex == arrayIn.length) randIndex--;
arrayOut.push(arrayIn.splice(randIndex, 1)[0]);
}
return arrayOut;
};
myArray = mixArray(myArray);

Saturday, August 13, 2011

CentOS and "su: incorrect password"

I made a mistake. I was setting up CentOS and accidentily ran chown -R 0 /. Yep, a global & recursive ownership change. Not a good thing.

The first problem I noticed was that I couldn't use su -. It kept saying that I was using the "incorrect password" even though I was completely sure I was.

I after digging around, I found someone who had the same problem and a nice chap named Mike who, very impressively, pointed out the source of the problem (ie, the globaly recursive chown). His response: "He's got rather a mess, unfortunately." Uh oh.

Well, it seems that the mess wasn't as bad as I thought. After fretting and digging around the interwebs, I came across this article about resetting file permissions on RHEL (and CentOS by extension, of course). Hallelujah!!

Following the instructions there, I did this to fix my woes:

rpm --setperms -a

I am not convinced everything is back in its proper place and I will probably see more fallout from my careless command executing. BUT, I can successfully "su -" without any bogus password complaints. That I like.

Monday, August 8, 2011

Allstate's Roadside "Assistance"

UPDATE 8/9/11: Allstate tracked me down to make things right. They are refunding my payment and explained that things don't normally go this way. What an impressive response.

It should be called "Allstate's Roadside Torture". And, I should have just googled "tow truck" ... I would have saved a lot of wasted time. I need to rant, badly.

My wife is pregnant and stuck in a parking lot. She calls the number that Allstate gives us for roadside assistance and can't even get past the first robo-bot operator. So she calls me for help. So, I call Allstate's well-promoted "Good Hands Roadside Assistance"... this is how it went.

I call the phone number the publicize for the service (1-800-255-7828). It is answered by a machine that wants me to speak what I want. So I say "roadside assistance." "You want coporate?" replies the machine. No, "I want help". Not working, so it offers me a directory and of course there is no roadside assitance options. After some very unfruitful back and forth with this annoying bot, it sends me to an operator.

The nice foreign operator would like to validate my policy. He needs my name. Then my SSN last four. Then he needs to validate every other peice of information he can find. Gotta check my zip and address and phone and email address. Seriously!? I need help. And these are the things you want to ask me about?

When he finally finishes with his 20 questions, THEN he tells me I need to call another number. Call 1-877-248-1266. Great ok. Thanks for that.

Now I am on to this new number. And a new game. First I get a message about adverse weather conditions in my area... I live near Seattle and it is the middle of the summer. What adverse weather conditions? You mean the 70 degrees and overcast? Is this causing havoc on your systems? Now after explaining that I need help to a new telephone operator, he also tells me I need to call a different number. This is a joke, right? Nope, I have to call a new number: 1-877-266-7561.

On to the third operator. Now I am having fun. Now I need to give him my credit card, phone number, email address, home address, zip code and whatever else he could come up with. After 10 minutes of divulging personal information he can finally could get me assistance. He puts me on hold and then finds someone that can help within the next 50 minutes. 50 minutes?! I am in the middle of a urban shopping center and 50 minutes is their timeline? I am not in the mountains or in some rural community, I could understand, then. I guess it is the best they can do because of all this crazy weather (sarcasm).

I will NEVER use Allstate's roadside service again. EVER. And Allstate needs to try their own service before they sell it.

Friday, August 5, 2011

SE Linux and "Can't connect to MySQL server"

I've been setting up a server for the last few days for production. It is to be highly secure, so it is a real pain. Anyway, I ran into this problem where I could not connect to the remote database. It was driving me nuts. (I'm using CentOS by the way, and I was setting up a web server to connect to a remote MySQL database server.)

First, I checked that I was getting network connectivity by doing

telnet 10.0.0.1 3306

from the command line (where 10.0.0.1 is the IP of the database server). And, I got some gobbledygook that had the words "MySQL" in it, so I know that worked and the network was there.

Then, I checked the database's user list, to make sure connections were allowed from the user at my host. I did this by going into MySQL's CLI and entering

SELECT `Host`,`User` FROM mysql.user WHERE 1;

This printed out a list of all the users so I just made sure it and the host were correct. (There are more MySQL troubleshooting tips here.)

Then it finally hit me. What always causes problems for hours on end? SE Linux!! I know it is good for my server, but it sure does drive me nuts sometimes. If you want your web server to be able to connect to a remote DB, you have to give it rights with SE Linux. Run this at the command line:

setsebool -P httpd_can_network_connect_db on

and for good measure:

setsebool -P httpd_can_network_connect on

There, all fixed!

Update: HA HA! I've had this problem before and completely forgot about it.

Monday, August 1, 2011

PHP UTF-8 Script Input Cleaner

When you switch to UTF-8 on your website, there is a few things that everyone recommends (for good reason) like using multi-byte functions (e.g., mb_strlen()) and adding the HTTP-EQUIV attribute header. One of these commonly recommended things is that you should clean up all user-submitted input.

With UTF-8 comes the ability to submit a lot of crazy characters to the script, either by POST or GET. These crazy characters might be control characters, invalid UTF-8 characters or some other charset that was mixed in for good measure. So, I created the following function to help clean my inputs:

<?PHP

function cleanUTF8(&$input, $stripSlashes = true) {
 if ($stripSlashes) $stripSlashes = get_magic_quotes_gpc();
 if (is_array($input)) 
  foreach ($input as $k => $v) cleanUTF8($input[$k], $stripSlashes);
 else {
  if ($stripSlashes) $input = stripslashes($input);
  $input = mb_convert_encoding($input, "UTF-8", "UTF-8");
  $input = preg_replace('!\p{C}!u', '', $input);
 }
}

?>

It is a recursive function in that it will iterate into a variable if arrays exist, as they sometimes do. It will also strip slashes for you if your version of PHP still has magic quotes on.

It removes invalid characters through the mb_convert_encoding() function. Anything that is not UTF-8 is dropped. Lastly, the fancy preg_replace() function removes all control characters. (The \p{C} means "all control characters", the !! are delimiters the same as // or ##, and the last "u" modifier means "treat this as UTF-8.")

At the top of your script add this to iterate over the input array and clean up the data:

<?PHP

cleanUTF8($_POST);
cleanUTF8($_GET);

?>