I took a few minutes this morning to put a script together that would convert the comments from the old blog into the new WordPress format – another time-saving excercise that allowed me to convert 300+ comments in a few minutes.
The only hurdle I had with this was that the rowId for posts in the old table doesn’t marry up to the new one, so the process had to go something like this:
Get the entry lookup for a comment.
Find the titles of that entry from the old posts table.
Look for that title in the new posts table.
Grab the rowId from step 3.
Save the comment with the new lookup.
So! Comments are restored and visitors can continue their ranting and raving (especially on this post!), only with extra Spam protection for me, which is nice.
There comes a time when a list of records output by a MySQL query becomes too long to realistically display on a single page, and the programmer wants to break it up into pages. It might be log activity, forum posts or whatever, but the principle is the same – we only want to view a manageable section of the entire record list.
Let’s assume we’re dealing with a set of forum posts in a thread. Your query would take a unique number for the thread ($threadId) and you would pull out a list of posts like this:
<php
$postSQL="SELECT * FROM posts WHERE (THREAD=$threadId) ORDER BY ID";
$posts = mysql_query($postSQL) or die(mysql_error());
while($post=mysql_fetch_array($posts)) {
// display posts here
}
?>
This would return all of the posts for this thread in order of creation – ID being the master key for this table.
To split this into pages, we first need to decide how many posts we want per page. Once we have decided on this, we can see how many lines our mysql_query(), above, returns and calculate the number of pages. After that we can decide which page to show and calculate which posts go on that page.
Here’s the altered code:
<?php
$postSQL="SELECT * FROM posts WHERE (THREAD=$threadId) ORDER BY ID";
$posts = mysql_query($postSQL) or die(mysql_error());
$postCount =mysql_affected_rows();
$postsPerPage=25;
$pageCount =ceil($postCount/$postsPerPage);
$pageNum =min(max(1, (int)$_GET['page']), $pageCount);
$firstPost =($pageNum-1)*$postsPerPage;
$lastPost =min($firstPost+$postsPerPage, $postCount);
$posts = mysql_query("$postSQL LIMIT $firstPost, $postsPerPage")
or die(mysql_error());
while($post=mysql_fetch_array($posts)) {
// display posts here
}
?>
As you can see, we call mysql_query() twice now – the first time to get the total number of posts and the second time to get the subset of those posts once we have decided which ones we want. The highlighted green section shows what has been added, and I’ll go through them here:
$postCount =mysql_affected_rows();
Records the total number of posts returned. We need this so we can calculate how many pages we have in total using…
$postsPerPage=25;
This is how many posts we want on a single page. You can store this in a table for easy altering, or allow it to be overwritten from the URL so that users can decide on their own page sizes.
$pageCount =ceil($postCount/$postsPerPage);
The number of pages is the number of posts divided by the number of posts per page, and rounded up, so ‘30 posts at 25 posts per page’ would return two pages.
Slightly more tricky to read, this line limits the number of the page to be displayed between 1 and the total number of pages, taking into account any page number specified in the URL with ‘&page=’, even if a value is not given.
$firstPost =($pageNum-1)*$postsPerPage;
We need to know the record position – not the ID – of the first post so that we can tell MySQL where to start counting from. This number starts at zero whereas your ID would start at one.
We don’t actually need $lastPost for anything in this example, but it’s nice if you want to display a message along the lines of “Showing posts 25 to 50 of 376″. This value is the actual ID of the last post on the page, so it starts at one and never goes above $postCount.
$posts = mysql_query(“$postSQL LIMIT $firstPost, $postsPerPage”)
or die(mysql_error());
Finally we run your original SQL statement – here held in $postSQL – a second time but with our calculated limits applied.
After adding the comments the other day I noticed that the website code was, quite frankly, a mess, so I’ve taken a couple of hours out to rewrite the bl0g structure in Strict XHTML 1.0 as well as CSS v2.1 – this should make the site more compatible with more browsers (looking forward to IE8 here…) as well as cleaner and better for Search Engines.
The older content will most likely break all this, since much of it is HTML4, and probably not very legit at that, so I haven’t bothered linking to the validation for that reason. Any content from this entry forward, however, should be perfectly OK. I’ll probably run this through the w3c validators, JUST to be sure.
No, not this one. I’ve spent the weekend rewriting a jewellery website to make it ridiculously Search Engine friendly using mod_rewrite and anything else I can think of. It all came about when I asked a client of mine how she was doing with her Google Adwords and it transpired the site needed an overhaul – so away I went.
Since I’ve been practising SEO on this site and sharing info with K on the subject, it was fairly easy to start from scratch and put together the product category and viewing structure that was required. Every page in the category section has URLs that are rewritten from:
This means the Search Engines see the former, but my script is the latter and much, much easier to work with. Best of both worlds? Yes, but it requires a lot of though into how to structure your RewriteRules and even what order to place them in.
OK, so the page URLs can be fancy schmancy keyword-laden affairs, but you have to generate them as well, so a local version of Apache is essential because you don’t want to be configuring and restarting it on a live server in the hope that you got it right first time. It doesn’t help that I have no real clue how Regular Expressions work, either – most of mine are copy/paste.
For a project at work I had to create a true colour PNG from scratch using GD, copy a load of image files to it from various locations and then display it on-screen.
The code to create a transparent PNG turned out to be a litle complicated:
<?php
// create a true colour, transparent image
// turn blending OFF and draw a background rectangle in our transparent colour
$image=imagecreatetruecolor($iwidth,$iheight);
imagealphablending($image,false);
$col=imagecolorallocatealpha($image,255,255,255,127);
imagefilledrectangle($image,0,0,$iwidth,$iheight,$col);
imagealphablending($image,true);
// ^^ Alpha blanding is back on.
// insert image manipulation stuff in here
// output the results...
header("Content-Type: image/png;");
imagealphablending($image,false);
imagesavealpha($image,true);
imagepng($image);
?>
Important Note: If you output the image direct into the document stream as this example does, the PNG fix that uses bahaviours won’t work as it’s not a true PNG. For that, you’ll have to drop the header and give imagepng() a filename and show that file. Seems to work fine in other browsers, however.
So, I was mooching about on t’Internet with ZiKeS this morning, and I remembered that I had wanted to create some kind of Postocode Range Finder using the UK Postcode Database I’d snagged from jibble.org a long, long time ago.
The basic idea was to take a postcode, add a range, and return every postcode within that radius. Initially I was having nightmares about SIN() and COS() functions, but it turns out O-Level maths had some use after all, in the form of Pythagoras’ Triangle Thigummybob, the one that goes ‘The square of the side opposide the right-angle is equal to the sum of squares of the other two sides’. Something like that – we’re reaching into parts of my brain that have gone unused for quite some time here.
I figured I’d let the server do all the work, and the final SQL I came up with was:
SELECT POSTCODE,GRIDREFX,GRIDREFY FROM ukpostcodes
WHERE SQRT(
POW(ABS($xpos-GRIDREFX),2) +
POW(ABS($ypos-GRIDREFY),2)
) < $dist
$dist being the range required in metres and $xpos and $xpos being the Grid Ref X and Y thingies respectively from my ‘root’ postcode. The script seems to work, and returns the other postcodes within my specified range, though in no particular order. I guess ‘nearest first’ would be cool.
My next problem is to actually apply this to something, since I don’t actually have a project in mind for it. Initially I thought of something like Dating or maybe Car/House sales, or even an entire community thing which would let you see exactly what was available in your area. Stay tuned, folks – anything could happen in the next half hour few months.
Interesting PHP buglet of the month. I had a call from a client saying that the new prices he’d entered into his website’s admin area were coming back as £1 and £2 instead of the thousands that they should have been. I asked a few questions but it suddenly occurred to me that if you entered a comma in a number value, that would screw things up.
The client, of course, insisted that they were not entering commas into anything, but it transpires that when you pull a value from the DB and run it through number_format() (to get the value to two decimal places and present it as a currency) it actually seperates the groups of three digits with a comma. So:
$price=number_format(123450/100,2);
returns “1,234.50″ rather than the “1234.50″ I was expecting.
This is all well and good until you actually save it in a form, whereby the comma ends up sending two seperate values for the same variable. Since only the first is used, the PHP on the receiving end sees ‘1′ instead of ‘1234.50′ and all hell breaks loose.
Well not really – the problem was spotted after only four items had gone wonky and before they actually had any customers, so nothing was lost on this little voyage of discovery. I wonder if our contract contains a clause absolving us of responsibility for stuff like this?
Looking over the website counter area I’ve noticed an increasing number of people are searching for information on how to calculate the distance between two postcodes. My original post on the matter sent people off in the direction of jibble.org but I’ve had at least one person mention that the uk postcode database isn’t available anymore.
For that reason I’ve uploaded the UK Postcode Database (with grid references) to my NTL space, here:
UK Postocode Database
I’ve removed the link above since the legal status was questionable. A fully legal, open version of the postcode database can be found at New Popular Edition Maps.
Have a look at the page on jibble (link above) for further information.
Original Post
Currently I am mucking about with postcodes, converting them to coordinates that I can plonk onto a map of the UK, and maybe thereafter use to calculate straight-line distances between two codes. Lucky for me (yay me!) I found a free, plain-text database on jibble.org that already had the coords as metres – saving me 90% of the work I originally envisaged converting Grid References.
I’m plonking them into a simple MySQL table at the mo, then I’ll be able to get the positions by searching on the first half of someone’s postcode. It’s not accurate down to street level but it’s fine for someone looking the length of the country. The next stage will be to write a function that takes into account the size of my bitmap image of the UK, complete with various pixel offsets, and returns an X or Y position in pixels representing the location of that postcode. I don’t forsee any problems.
(Hopefully Google wil link to this page from now on…)
I was at a client’s last week and the guy who handles the email mentioned that they were getting a lot of spam from the same email addresses, all of which were at the default name of our server. I had a quick look and, sure enough, email was being sent through a mail script on the back end of my client’s Contact Us page. Because the To: address is hardwritten into the script, my client received copies of the spam as well as the injected recipients.
How the Email Injection Attack works…
The injection attack works with any mailing script that uses the PHP mail() function. If the script accepts a name and email address, and formats those into the From: field of your email, then they can be used to insert extra email addresses anonymously.
Ordinarily you would take a name ($name) and an email address ($email) and create a string like so:
$headers="From: $name <$email>\r\n";
which creates:
From: MyName <user@domain.tld>
followed by a ‘\r\n’, or Character Return+Line Feed.
Using a form on another server, or even the existing form if there’s no client-side length checking, the spammer submits the following as $name:
PHP’s mail() function puts these into the headers as usual, but the headers now contain an extra Subject: and Bcc: field that were not there before. Either the $name or $email variables (in our example) can be used for this, and there’s nothing to stop them attaching files using MIME.
So How to I Protect Against Email Header Injection Attacks?
Thankfully, protecting yourself is quite easy – probably the easiest way is for you to check the vulnerable fields for illegal content on receipt by your processing script. My approach was to write a simple function using a regular expression, thus:
If either ‘Cc:’, ‘Bcc:’ or ‘Subject:’ is found somewhere it shouldn’t be, the script generates an email containing the name of the script and the spammer’s IP address, sends it to spamcheck@domain.tld and promptly dies.
WordPress Comments Restored
May 20th, 2009I took a few minutes this morning to put a script together that would convert the comments from the old blog into the new WordPress format – another time-saving excercise that allowed me to convert 300+ comments in a few minutes.
The only hurdle I had with this was that the rowId for posts in the old table doesn’t marry up to the new one, so the process had to go something like this:
So! Comments are restored and visitors can continue their ranting and raving (especially on this post!), only with extra Spam protection for me, which is nice.
Edit:
Two posts in two days! We’re on a roll!
Tags: Comments, WordPress
Posted in Blog, PHP | No Comments »