I really need to think of a clever name for my blog

Code samples, geeky links and other musings. Note this blog has recently moved from Posterous, so isn't fully back up to speed yet!

‘Deprecated’ error warnings – PHP 5.3

Just reviewing some sites in my portfolio, and I notice that a CubeCart installation on a shared host is broken. Oh dear…

Deprecated: Function set_magic_quotes_runtime() is deprecated in /path/to/domain/shop/ini.inc.php on line 114Warning: ini_set(): Cannot change zlib.output_compression - headers already sent in /path/to/domain/shop/ini.inc.php on line 118 Warning: Cannot modify header information - headers already sent by (output started at /path/to/domain/shop/ini.inc.php:114) in /path/to/domain/shop/index_enc_ion.php on line 31 Warning: Cannot modify header information - headers already sent by (output started at /path/to/domain/shop/ini.inc.php:114) in /path/to/domain/shop/index_enc_ion.php on line 32Deprecated: Function eregi() is deprecated in /path/to/domain/shop/includes/functions.inc.php on line 408

Ah, great. Without warning, we’ve been upgraded to PHP 5.3

Thanks for that…

Anyway, it’s easily solved.

With 5.3 a new error level has been introduced – E_DEPRECATED, so it’s easy to suppress deprecated errors:

In your scripts:
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);

In the case of CubeCart 4 this can be acheived in ini.inc.php line 101.

In php.ini:

error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECATED

in .htaccess:

php_value error_reporting 1

.htaccess requires the correct integer value equivalent of your chosen reporting level – these are a touch obscure, but setting it to 1 means report fatal run-time errors and unrecoverable errors, which will do the trick.

Resolving Canonical domains – Death to www!

Many moons ago, one of my webmastery guru’s told me that he considered www to be antiquated bullshit in a domain name – a waste of time and space. I agreed with his logic, and have supported the cause ever since.

The issue arose today when a client noted an issue with his Joomla sites – if you login on http://domain.tld, then click on a link that takes you to http://www.domain.tld, you will no longer be logged in, as the cookies are set for different domain names. To the casual user with or without www is the same thing, but as far as t’internet is concerned, www.domain.tld is actually a SUBDOMAIN of domain.tld.

It is also an issue for SEO and indexing, because as far as search engines are concerned, the ‘two’ sites are counted differently, meaning that links to one or t’other do not count towards a single total for page rank. It also means that the ‘two’ are considered duplicate content, reducing the perceived value of your data, especially as they both share an IP address so it looks to the search engines as if you are engaging in blackhat SEO techniques. This was certainly true in the past, and while I would have thought that search engines would be quite beyond such blatant foolishness, it’s best to play safe.

Luckily this is very easily cured.

If you ARE using Joomla and are not very technically minded, there is an SEO Canonicalisation Plugin plugin that will sort you out.

Wait, canonicalisation? REALLY? What kind of etymological rape have you people committed there? Can I suggest, I dunno, ‘canonifcation’ instead? But wait, it’s actually a real, technical term! It even has US and Anglicised versions, like a proper grown-up word and everything. Still, correct or not, it’s damn ugly, and blatantly coined by an American. However, it does not mean ‘to adjust the topography of an object in such a way as to cause it to resemble a big gun’.

Tragic that.

Haaaanyway, back to the point:
I personally would rather have less crap installed in Joomla, and want a solution that is not dependant on it.

.htaccess to the rescue! Feel the power of the rewrite rule!

What fun.

In your .htaccess file, ensure that you have ‘RewriteEngine On’ and add the necessary RewriteCond and RewriteRule. The rule tells the browser (and search engines) that the change is a 301 redirect, a very healthy way to go about things – html redirects, by contrast, being potentially indicative of blackhat behaviour.

Redirect www.domain to domain in .htaccess

RewriteEngine On# Redirect http://www.domain.tld requests to http://domain.tldRewriteCond %{HTTP_HOST} ^www.(.*)$ [NC]RewriteRule ^(.*)$ http://%1/$1 [R=301,L]

Bang. And the dirt is gone…

So, whagwandere? Well, RewriteEngine uses Regular Expressions (RegEx) to define the condition and the rule.

The Condition:

The condition says ONLY apply the following rule IF these conditions are met.

First we define variables:
%{HTTP_HOST} – A predifined variable meaning this domain name and tld without www or trailing slash

Then we define the conditions to match:
^www. –  An http request (which is all .htaccess will process) that starts (^ = start of a match) with the string www followed by a period (. – .= any character – the period is preceded by a backslash to ‘escape’ it, meaning ignore any special meaning of the following character)
(.*)$ – Any number (* = any number) of any characters (. = any character). The parentheses creates a group ensuring the asterisk only applies to the preceding period, not a larger string, and also creates a backreference. $ indicates the end of the match.
[NC] –  A flag telling Apache the rule is not case-sensitive

(.*) is an incredibly greedy regular expression, and should normally be avoided, but it is the right thing in this case, as we DO want to match absolutely ANYTHING after the www. and it is safe to use in this situation because we know precisely the nature of the input.

The Rule:

The rule consists of two parts, the match and the replacement. The match is pretty simple:
^(.*)$ – The greediest Regex EVER! It matches anything and everything. As we have already defined our condition, we know we want to replace EVERYTHING. It says start of match(^) followed by any number of any characters ((.*)) before the end of the match ($).
The replacement is slightly more complex:
http:// – string literal.
%1 – the first (in our case only) varable.
/ – string literal.
$1 – Backreference 1 defined by the parentheses in the condition regex.
[R=301,L] – Apache flags – R indicates which http status code to return, in this case 301 (Redirect: Permanently moved). L indicates that Apache should apply no more rules once this rule has bee applied.

 

What’s that? You want to direct domain to www.domain? Nob off. That’s not helping the cause. GIYF.

htscanner: Enabling php_admin directives in .htaccess under php-fastcgi (Plesk 9.x + CentOS 5)

[update 201107061858]
For per-domain php.ini under php-fastcgi see here
[/update]

Under Plesk running php-fastcgi  it is not possible to use php_admin_flag and php_admin_value directives in .htaccess files on a per-directory basis. Luckily this can be easily enabled with the htscanner extension.

All the information to get this working is out there, but as per usual, you have to piece it together from a variety of sources to get a complete picture. Here I shall provide a single complete set of instructions that have been proven to work on a CentOS5 box with Plesk 9 – although Plesk should be an irrelevance here, I mention it for completeness.

I am using PuTTY as my SSH client.

In order to install and use htscanner v1.0,0 , you must have the following things (aka dependancies):

PHP Version: PHP 5.1.0 or newer
PEAR Package: PEAR Installer 1.4.8 or newer

Odds of having >=PHP 5.1 without PEAR are slim to my knowledge, and installing it is beyond the scope of this post.

Got those? Ready to go!

To provide absolute clarity for inexperience bods, # is the SSH command prompt and shouldn’t be included in typed commands! And if you REALLY need your hand held, hit [enter] after each line. Just so you don’t sit there wondering why nothing is happening…

Download and extract htscanner

  1. SSH to your server with root access.
  2. Download the latest version of htaccess from http://pecl.php.net/package/htscanner currently 1.0.0
    #  wget http://pecl.php.net/get/htscanner-1.0.0.tgz
  3. Untar the file:
    # tar -xvsf htscanner-1.0.0.tgz

Compile and run installation

  1. Change to the newly created directory:
    # cd htscanner-1.0.0
  2. Run phpize:
    # phpize
  3. Run the configuration script with –enable-htscanner switch
    # ./configure --enable-htscanner
  4. Run make to build the installer:
    # make
  5. Run make install to actually install the extension
    # make install

Add htscanner settings

Either:

For systems that support it, you can simply copy htscanner.ini to your php conf.d directory. This is probably somwhere along the lines of /etc/php.d on CentOS 5 or perhaps for others /etc/httpd/conf.d but if you are having trouble finding it, run
# locate conf.d
You will find a bunch of them though, so make sure it’s the right one. You can also try simply googling your *nix distribution name and conf.d – for example “centos 5 conf.d”

Or:

If you are running SuSE or another flavour of Linux which doesn’t support this, you can add the contents of htscanner.ini to your php.ini file. To locate yours try the tips above for finding the php conf.d directory
The htscanner.ini file currently looks like this:
[htscanner]extension="htscanner.so"; The configuration file htscanner needs to scan for php_* directivesconfig_file=".htaccess"; The fallback docroot when htscanner can't determine the current docrootdefault_docroot="/"default_ttl=300; Stop when an error occured in RINIT (no document root, cannot get path_translated,...)stop_on_error = 0; Warn when an option cannot be setverbose = 0

You should check the contents of your htscanner.ini file though, to be safe.
This is simple enough, but for the sake of completeness and for any poor n00bs out there, to do this, and then add to php.ini using ‘vi’ text editor: 

  1. Open htscanner.ini:
    # vi docs/htscanner.ini
  2. Highlight all text to copy to the clipboard
  3. Exit vi by simply typing
    :q
    and hitting [Enter]
  4. Open php.ini:
    # vi /etc/php.ini
  5. Scroll to the bottom of the file with [pgdn] key
  6. Enter editing mode by hitting [i] key
  7. Press [->] Left arrow key to ensure you are at the end of the last line
  8. Hit [Enter] to start a new line
  9. Right-click the mouse to paste the htscanner.ini contents
  10. Exit editing mode by hitting [Esc] key
  11. Save and quit vi:
    :wq 
    and hit [Enter] 

Restart Apache

On CentOS 5 and similar distros:
#  service httpd restart
For other *nix versions, y’know, google it. Why not, sounds like fun to me?

And voila. You should now be up and running with per directory php_admin directives in your .htaccess files.