Turning the complier up to 11

I was tracking down a crash caused by memory not being released and I thought it would be helpful to turn on all the compiler options, thinking that maybe it would point to something I did wrong. It didn’t help, but it did generate around a thousand warnings. Only two were actual bugs in the code. Most of the rest were conversion warnings. The most common were defining variables as NSInteger when the method that used them was expecting a CGFloat. Second most common were things like this:


return [[[self fetchedResultsControllerForTableView:tableView] sections] count];

ObjectAtIndex is an unsigned integer so and count is an NSInteger so to get rid of the warning I just cast count to NSUInteger.

return [[[[self fetchedResultsControllerForTableView:tableView] sections] objectAtIndex:(NSUInteger)section] name];

And this


return [[[[self fetchedResultsControllerForTableView:tableView] sections] objectAtIndex:section] numberOfObjects];

which should return an NSInteger rather than an unsigned NSUInteger so here I cast the return value.


 return (NSInteger)[[[[self fetchedResultsControllerForTableView:tableView] sections] objectAtIndex:(NSUInteger)section] numberOfObjects];

Second most common warnings were for unused variables. Since I use the same code for 18 different games I have if statements that determine what the locations of buttons on the screen. Many of the buttons are not used in all of the games so the compiler gives an unused variable warning. To get rid of the warning, I use this line after the last redefinition of the variable. Just so I remember that I’m using it I put it just before I use the “unused” variable. The compiler still compiles correctly when the button is needed, it just doesn’t throw the warning.


  #pragma unused(showHideButtonX)
  #pragma unused(showHideButtonY)
  if ( DISPLAY_SHOWHIDE_BUTTON ) {
      CGRect showHideFrame = CGRectMake(showHideButtonX, showHideButtonY, buttonsSize, buttonsSize);

Checking the logs

We’ve been getting hit with SSH login attempts. Sometimes there were thousands per minute and they slowed the machine to a crawl. So we installed fail2ban and that has slowed the attempts considerably.

Recently one site has been hit with huge numbers of SQL injection attacks (18,000) per day. Right now, I trap them and return a static page.

Here’s what my URL looks like:

/products/product.php?id=1
This is what an attack looks like:


/products/product.php?id=-3000%27%20IN%20BOOLEAN%20MODE%29%20UNION%20ALL%20SELECT%2035%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C%27qopjq%27%7C%7C%27ijiJvkyBhO%27%7C%7C%27qhwnq%27%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35%2C35--%20

I know for sure that this isn’t just a bad link or fat-fingered typing so I don’t want to send them to an overview page. I also don’t want to use any resources on my site delivering static pages.

First I get the productID, then check to see if it is a number. If it is, all is good and I skip the rest of this code. If not, they might have an extra space in the URL from copying and pasting, so I give them the benefit of the doubt and strip them out. If productID is still not a number, I send the page not found response and kill the rest of the page load.


$productID = (isset($_GET['id']) ? mysql_real_escape_string($_GET['id']) : '55');

// Attempts have been made to exploit the database with long strings. 
// This stops it without filling up the error log.
if ( !is_numeric($productID) ) {
    $url = $_SERVER['REQUEST_URI'];
    $ref = $_SERVER['HTTP_REFERER'];
    $ip  = $_SERVER['REMOTE_ADDR'];
    error_log("long string in products.php: URL is $url and IP is $ip & ref is $ref");
    $productID=preg_replace('/[\s]+/','',$productID);
    if ( !is_numeric($productID) ) {
        error_log("Still a long string in products.php after replacement: URL is $url and IP is $ip & ref is $ref");
        header("HTTP/1.0 404 Not Found");
        die();
    }
}

The bot thinks that there isn’t a page there and usually goes away. Sometimes it tries a few more times, but not the thousands of times it used to.

Things I can’t remember—import SQL file to MySQL

I usually use phpMyAdmin to manipulate tables in my databases but sometimes the file I want to import is too big. In that case I use the command line to import the file.

In this line, I replace a database with formatted sql statements that I’ve edited by hand. the -p flag without an argument will prompt for the root password of the MySQL installation.

mysql -u root -p original_database < /Users/username/Desktop/edited_data.sql

Here I want to replace the entire MySQL database with the backup. I do this on my backup machine from time to time using the nightly My backup. This example shows the password after the flag.

mysql -u root -pYourPassword < mysql-backup.sql

Things I can’t remember—Apache and MySQL

Restarting Apache and MySQL is sometimes necessary when the site isn’t responding. I can never remember exactly where the commands are located on different flavors of Linux/Unix.

Gentoo

This is where the services are located on Gentoo.


sudo vi /etc/php/apache2-php5/php.ini 
sudo /etc/init.d/apache2 restart
sudo /etc/init.d/mysql restart 
sudo /etc/init.d/exim restart 

OSX Mountain Lion


sudo apachectl restart

sudo /usr/local/mysql/support-files/mysql.server stop
sudo /usr/local/mysql/support-files/mysql.server start 

Ubuntu

Automatically upgrade packages using Aptitude.


sudo aptitude safe-upgrade
sudo reboot

If Aptitude doesn’t work, then use apt-get.


sudo apt-get update
sudo apt-get upgrade

Restarting services is easier on Ubuntu since you don’t need to remember where they are. The /etc/init.d restart method used in Gentoo also works.


sudo service apache2 restart
sudo service ssh restart
sudo service mysql restart