Tuesday 30 June 2009

Websiting and ponding

I spent nearly all this morning trying to work out why something on my website wasn't working properly. Eventually I tracked down part of the problem - I had a mysqli->multi_query($sql), and when specifiying the final SQL statement before the multi_query was executed, I had put $sql = 'blah blah...'; instead of $sql .= 'blah blah...';. So the none of the SQL statements before the final one were actually being executed.

But after fixing that, it still wasn't working. Eventually I tracked this down to my string replacement statement. What I was trying to do is rename a file when the title/Headline of the image had been changed, as I include the headline as part of the image filename. So I had
$filename = str_replace("$oldHeadlineForFileNames", "$headlineForFileNames", $d['f']); ($d['f'] is the current filename, $oldHeadlineForFileNames is the current headline, and $headlineForFileNames is the new headline).

So, for example, an image with a headline of 'hello' might be named 1-hello-640x480.jpg. If I then changed the headline to 'goodbye', I wanted to rename the image to 1-goodbye-640x480.jpg. The problem with my replacement code above is that if an image didn't have a headline, then I wanted to add one, it wouldn't work. The code when the variables are evaluated would basically look like:
$filename = str_replace('', "my-new-headline", $d['f']);
Which obviously won't work since it can't replace nothing with something. I had the same problem in my SQL query that updates the database with the new filename as well. So I just changed it to
$filename = str_replace("-$oldHeadlineForFileNames-", "-$headlineForFileNames-", $d['f']);
and the SQL to
$sql = "UPDATE img_dimensions_save
SET filename = REPLACE(filename, '-$oldHeadlineSQL-', '-$newHeadlineSQL-')";

and now it works properly.



In the afternoon and evening I just did some more work on my photo website. Then from about 8.00pm-9.30pm I did some more work on the pond in the garden. I did some more website stooef, then went to bed about 11.30pm.

The weather was very hot again, mostly sun with a couple of patches of cloud.

Food
Breakfast: Bowl of Frosties; cup o' tea.
Lunch: Ham with mustard, crispy salad and sliced cherry tomatoes sandwich; banana; Rocky; cup o' tea.
Dinner: Slice of ham quiche; cous cous; salad; Caesar salad dressing. Pudding was a pancake with heated golden syrup and banana slices. Coffee; Green & Black's Maya Gold.

Monday 29 June 2009

Websiting and ponding

Today I was just doing some more work on my website, changing the edit photo details page so that it will deal with desktop sized versions of an image.

Yesterday I tried to bid (on ebay) on a signed copy of Shenmue (jap version) for myself, and a signed copy of Space Channel 5 part 2 (jap DC version) for Moccle. However, they ended up selling for £205.05 + £5 P&P and £102.05 + £3 P&P respectively. And I thought we were in a recession!

In the evening I watched an episode of Satr Trk TOS with Moccle and L, then did some work on the pond until just after 10pm.

The weather today was really hot, and sunny most of the day. Sometimes it clouded over a bit, but was still really hot. In the evening there a was a large black cloud, which thundered a bit, but it only rained a couple of drops.

Food
Breakfast: Bowl of Frosties; cup o' tea.
Lunch: Ham with mustard, sliced cherry tomatoes, and crispy salad sandwich; home-made cheese straw; nectarine; 1½ pieces of Fabulous Bakin' Boys' oaty flapjack; Rocky; cup o' tea.
Afternoon snack: Bowl of vanilla ice cream; cup o' tea.
Dinner: Pasta twirls; cheese sauce; broccoli; peas; chicken nuggets; ground black pepper. Pudding was tinned fruit cocktail. Coffee.

Sunday 28 June 2009

Not much

This morning I woke up just before 6am, but I didn't get to sleep until about 1am, so I decided to stay in bed and try to get to some more sleep. It took me a while to get back to sleep (I guess I fell asleep again about 6.30am), but then I woke up again at 7am. So I decided I might as well get up.

I went on Animal Crossing, and watched some 星のカービィ with L, then went to Church. Moccle didn't go as he went to see his mates in Mansfield/Worksop on Friday evening.

After church I took L's insect tank outside as it had a daddy long-legs and a moth in there that I'd caught in my room yesterday evening. The daddy long legs was being annoying and constantly flying round, so I wanted to set it free and then see if I could get any photos of the moth. But when I let the daddy long legs out, the moth also flew away.

Normally when I release a moth during the day, it will just hide under the first leaf it can find and not fly or move about much. But this one kept flying about and flew all over the garden, then I think it went next door, but I couldn't really see as I didn't have my shoes on so I couldn't follow it. So I'm not sure it was actually a moth, could've been a butterfly.



After dinner I helped Clare and Ben re-do the pond. Yesterday Clare and Ben removed all the water from the pond, and today we removed all the soil from round the liner, and then Clare removed the liner.

After that I went on my comp, and checked Moose News blog, deviant art, dpreview, Nikon Rumors and Thom Hogan's site.

Then I watched a John Wayne film, The Comancheros, it wasn't particularly stupid, but they did kill lots of Indians, and John Wayne says that someone's parents didn't beat them enough when they were child. It was quite a good film anyway, so didn't really need to be stupid to make it good.

In the evening I did more website stuff, trying to get a div to wrap to its contents - I don't think it's possible.

Food
Breakfast: Bowl of Frosties; cup o' tea.
After church snack: Custard cream; milk chocolate digestive; coffee.
Dinner: Chinese chicken Stir fry; stir fried sliced mushrooms; soy sauce. Pudding was some posh nougat ice cream. Coffee.
Afternoon snack: Cheese straw; cup o' tea.
Tea: Honey roast Ham with mustard and crunchy salad sandwich; clementine; Snackie bar; cup o' tea.

Saturday 27 June 2009

Websiting

This morning I went on Animal Crossing, then watched an episode of 星のカービィ with L. After that I checked my email and also tried to find a question I posted on the jQuery Google groups ages ago to see if it had had any replies. Weirdly, searching the jQuery Google groups and also going on my posting history on google groups didn't come up with anything. But doing a normal google search did come up with the thread, and I hadn't got any replies.

I did some more work on my photo website, to try and get it so I could upload Desktop sized images along with my main full size image. I wanted to make sure that all metadata, embedded thumbnails and colour profiles etc. that might weight a Desktop sized image down, but shouldn't be needed, were stripped. Doing some googling, I found that ImageMagick has a command to do this, -strip, and the Imagick PHP extension has the same function available as Imagick::stripImage.

I wanted to make sure that stripping the metadata with ImageMagick wouldn't be lossy though, but googling about this, it seems it is a lossy operation - the article on the ImageMagick website about Digital Photo Orientation says
JPEG Format is Lossy



What this means is that any time you decode and save the JPEG file format you
will degrade the image slightly. As a general image processor, IM will always
completely decode and re-encode the format, as such it will always degrade
JPEG images when it re-saves the image.


Anyway, no problem as exiftool can do the job. I thought that using a PHP extension like Imagick would be faster than executing a shell command though, which is why I was hoping Imagick could do it.

During the afternoon and I did more work on my website, and I also checked Andy Rouse's blog and The Luminous Landscape.

In the evening I did some more website work, then went in the garden about 8.30pm - 9.45pm and took some photos. There wasn't much about to take photos of really, I mainly took more flea beetle photos, even though I've already got about a million. Still, at least the flea beetles now are a slightly different colour to the photos I took before. They're more browny now, when before they were orangey. There was lots of leaf hoppers around as well, but they were constantly hopping, so no hope for a photo.

After that I processed the RAWs into jpegs, then did some more website stuff.

I had some problem with javascript, when I assigned a value to a variable and then checked a property of that variable in the same if statement, I got an error that the variable was undefined.
Here's an example, which is designed to loop through my category elements:
for(var i=1, el; el=$('#category'+i) && el.length; i++)
{
alert(i);
}

Googling for the error that Firefox gives when you make an assignment inside an if statement Warning: test for equality (==) mistyped as assignment (=)?, I found this helpful page, which describes how to solve the problem: Warning: test for equality (==) mistyped as assignment (=)? All you need to do is add some brackets around the assignment, and then it works fine, like so:
for(var i=1, el; (el=$('#category'+i)) && el.length; i++)
{
alert(i);
}

I thought that javascript always evaluated the left side of an if statement first, but maybe it doesn't, and so you have to put brackets around the part of the statement you want evaluated first?

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: Mature cheddar cheese with crunchy salad sandwich made with fresh bread-maker-made bread; clementine; Trophy; cup o' tea.
Dinner: Mariner's pie; grated mature cheddar cheese; peas; ground black pepper; Crust of bread-maker-made bread with I cannae be-cheese it's nae butter jock; slice of bread-maker-made bread with grated mature cheddar cheese. Pudding was a raspberry ripple mousse.

Friday 26 June 2009

Michael Jackson is dead!

This morning I was doing some work on my photo website, testing different images to see what ICC Profile Description they had. While an image can have any ICC Profile (you can create your own profiles), since there's only a few different profiles that my images will have, I wanted to get a list of these. Then when updating the database, I can just SELECT the relevant profile from the colorSpace table, rather than having to first INSERT the value into the colorSpace table in case the color Profile value doesn't already exist.

I found that my Canon files, both processed through ACR and DPP had an ICC_Profile:Description of "Adobe RGB (1998)"
Nikon files processed through Capture NX (I didn't bother trying them with ACR) had a ICC_Profile:Description of "Nikon Adobe RGB 4.0.0.3000"
Images converted to sRGB in Photoshop had an ICC_Profile:Description of "sRGB IEC61966-2.1"
Files converted to sRGB by my website had an ICC_Profile:Description of "sRGB IEC61966-2-1 black scaled"

Looking in Photoshop under Edit>Convert to profile, there is a long list of different profiles, however, I think the 4 above will probably cover all my images. If I start using other color profiles, I can always just add the ones I need to the database manually.



Next, I wanted to deal with images that might have an EXIF:ColorSpace tag of "Adobe RGB", but no embedded color Profile. I thought that probably these files (I'm not sure if I actually have any files like this, but better safe than sorry), wouldn't convert to sRGB properly if they didn't have an embedded color profile.

You can see on the PHP Manual page for Imagick::profileImage that to get an image to convert properly, you should give it its correct Color Profile (if it doesn't have one) before converting to the new color Profile.

So to do this, I needed to get a copy of the Adobe RGB (1998) profile. Googling took me to a page on Adobe's website. On the download page it has 3 options, one each for Windows, Mac and Linux. After following through the Linux link, when it eventually got to the actual download page, it wasn't found and just went to the main Adobe download page.

So I went back and tried the page for Windows, since I don't think there could be any differences between the actual profile files for Windows, Mac or Linux. Thankfully following through the pages here did get me through to the actual download page.

When trying out a conversion on the AdobeRGB tagged image of the Maple leaves from Jeffrey Friedl's article on color spaces (the differences between sRGB and aRGB on that image are quite obvious, and so good for testing with), I found that the image still wasn't being converted to sRGB correctly. Looking at the exif with exiftool, I found that it wasn't using EXIF:ColorSpace to hold the color space value, but rather EXIF:InteropIndex

So now I've changed my code to check first ICC_Profile:Description, then if that isn't set, EXIF:InteropIndex, then finally if that isn't set, check EXIF:ColorSpace.

After lunch I went on Animal Crossing, checked my spleenmail, then did some more website stuff. I found that in IE6 part of my site wasn't working properly. When I clicked a link to change the size of image that is displayed, I got sent back to the home page. It should go back to the page I clicked the link on, except with the image size changed.

Doing some debugging, I found it was because I was using $_SERVER['HTTP_REFERER'] (apparently Referrer is mis-spelt in the HTTP specification!), and in IE6 this was blank for some cheesun. Weirdly, when trying my test page in IE6, $_SERVER['HTTP_REFERER'] was being filled in. Anyway, reading some stuff it seems that $_SERVER['HTTP_REFERER'] is sent by the Browser, and so the Browser may not send that header, or it may be stripped say by a firewall before reaching the Server, and so it's best not to use/rely on $_SERVER['HTTP_REFERER'].

I knew before that $_SERVER['HTTP_REFERER'] wasn't reliable from a security point of view since it can be spoofed, but I didn't realise that it might not get sent at all. Actually now I'm typing this, I seem to remember typing something like this before. Probably I did know it before, but forgot. Checking the HTTP headers in Fiddler confirmed that IE6 wasn't sending the Referer header for the page in question for some cheesun.

Anyway, to fix it, I just set a $_SESSION variable like $_SESSION['prevURL'] = $_SERVER['REQUEST_URI'];, then on the next page I can refer to $_SESSION['prevURL'] instead of $_SERVER['HTTP_REFERER'].

After dinner I was trying to work out how to get images to display centered vertically and horizontally. I had a load of anchor elements, and inside each anchor element was an image. I applied a fixed height and width to the anchors, and needed to get the images centered inside the anchors, but I didn't know the dimensions of the images as it varied for each image.

Eventually I worked it out, thanks partly to this article: Centering (horizontally and vertically) an image in a box.

That article, and also CSS: Centering things suggest using display: table-cell. However, there is a problem with this (at least in my case) that your 'table cells' are treated as being in a 'table row', and all items in that 'table row' are stuck on one line, rather than being wrapped and pushed down onto the line below when the viewport is small.

So if you have a large amount of images (or whatever) you'd end up with one long single row of images and a scrollbar. I can't find the page I read it from now, but the reason for this is that when you assign the CSS property 'display: table-cell' without assigning 'display: table-row' to its parent, and 'display: table' to the row's parent, the table row and table are created automatically.

So in my case, I would be assigning the CSS property 'display: table-cell' to a load of anchor elements, which are contained in a div. Because they are all contained in the same element, this means that the table and table row that automatically created by the browser, contain all of them. So I get the problem of them all being on one long row that doesn't wrap if the row is wider than the viewport or page width.

One solution, and the one used in the article Centering (horizontally and vertically) an image in a box is to wrap each anchor (or whatever element you're using to contain the centered image) with its own parent element. If you try making your viewport narrow while viewing that article, you'll see that the examples they've posted do wrap on to the next line when the viewport is too small.

If you view source on that article, you'll see why - they've wrapped each item they apply the CSS property 'display: table-cell' to in an <li> element. So the table and table row containing their 'table cell' div, is contained within the <li>:
<ul class="example uno">
<li><div class="wraptocenter"><span></span><img src="g101.gif" alt="" width="101" height="101"></div></li>
<li><div class="wraptocenter"><span></span><img src="g161.gif" alt="" width="161" height="161"></div></li>
</ul>


However, doing some experimenting, I found that setting the line-height works for all browsers apart from IE6 and IE7, and then the span set to display: inline-block fixes IE6 and IE7. So while you do have to add a useless span to your code to get it working, at least you don't have to add another element wrapping each of your elements that contain the centered element(s).

Here's my HTML
<div id="thumbsContainer">
<a href="/photos/1-."><span></span><img src="http://static2.photosite.com/Img/thumbs/1-..JPG" alt="" /></a>
<a href="/photos/2-"><span></span><img src="http://static2.photosite.com/Img/thumbs/2-.jpg" alt="" /></a>
<a href="/photos/3-"><span></span><img src="http://static2.photosite.com/Img/thumbs/3-.jpg" alt="" /></a>
<a href="/photos/4-"><span></span><img src="http://static2.photosite.com/Img/thumbs/4-.jpg" alt="" /></a>
<a href="/photos/5-"><span></span><img src="http://static2.photosite.com/Img/thumbs/5-.jpg" alt="" /></a>
<a href="/photos/6-"><span></span><img src="http://static2.photosite.com/Img/thumbs/6-.jpg" alt="" /></a>
</div>


and CSS:
#thumbsContainer a{
width: 180px;
height: 170px;
display: inline-block;
text-align: center;
background: #333;
line-height: 170px;
margin: 5px;
}

#thumbsContainer a span{ /*To make image center vertically in IE6 & 7*/
#display: inline-block; /*# targets IE6 & 7, best to put in IE only stylesheet served by conditional comments in real use*/
}
#thumbsContainer a img{
vertical-align: middle;
}


After that I had problems trying to get a div to wrap width-wise to its contents. Googling I found various solutions: display: table;, float: left;, display: inline-block;, and display: table-cell;, but none of them worked! I also found a post by someone else with the same problem as me (shrink div to fit contents), but no answers. I'll post a question at the web squeeze and hopefully get an answer there.

Hmm... Firefox is using nearly half a gig of RAM, so I better log off now and might as well go to bed.

The weather today was rainy and slightly foggy early in the morning, then overcast the rest of day. In the afternoon it rained a bit more, and there was even a bit of thunder. Then it was overcast the rest of the day.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: 2x cheese on toasts; crunchy salad; apple; satsuma; caramel Rocky; cup o' tea.
Dinner: Chicken & vegetable pie; potatoes; spaghetti hoops; fried sliced mushrooms. Pudding was Lemon pud with custard. Coffee.

Thursday 25 June 2009

Websiting and Dreamcasting

Today I was just doing some work on my photo website.

One problem I had was that when I did a GROUP_CONCAT on a column containing integers, it returned a Blob rather than the actual value (in PHPMyAdmin it said [BLOB - 1B]). Doing some googling I found an answer though - just perform a string operation on the GROUP_CONCAT, e.g.
Doesn't work:
SELECT GROUP_CONCAT( categories_id )
FROM img_categories
WHERE img_id =1
GROUP BY img_id

Does work:Doesn't work:
SELECT CONCAT(GROUP_CONCAT( categories_id ))
FROM img_categories
WHERE img_id =1
GROUP BY img_id


The other problem I had was with Color spaces and color profiles again. I decided it would be useful to store the color space/profile of the original image in the database. The Imagick PHP Extension has a function Imagick::getImageColorspace, which returns an integer value that corresponds to the value of one of the Imagick ColorSpace Constants.

The problem with this is that they don't seem to detected AdobeRGB, which is what most of my images in. They have constants for imagick::COLORSPACE_RGB and imagick::COLORSPACE_SRGB. I thought that maybe imagick::COLORSPACE_RGB means AdobeRGB, but I googling I couldn't see anywhere that said that.

Next I found that ExifTool can read ICC Profile tags, trying it out on an AdobeRGB image, I got found that -ICC_Profile:ProfileDescription had the value "Adobe RGB (1998)". So I thought I could use that to detect the image's color space. Then I tried an image from my Panasonic FZ-5 camera, and that didn't have an ICC Profile.

Looking at the exif though, the FZ-5 has a -EXIF:ColorSpace tag, so I guess I'll need to check both -EXIF:ColorSpace and -ICC_Profile:ProfileDescription. I also need to check a Nikon Image, processed through CaptureNX to check that fills in one or the other tags.

Also today, I went through my Dreamcast stuff to see if I had a spare Dreamcast cable that I could give to Moccle for his birthday, as his one is broken.
Dreamcast stuff
I found that I did have an Electronics Boutique SCART cable, when I tested it in Moccle's room, the sound would go on the TV, but not the picture. When I tried a different lead, an S-Video one, the TV didn't even detect that it was plugged in.

I moved the Dreamcast into L's room, and tried it with the same SCART lead on one of small TVs, and it worked fine, so it seems like the Dreamcast isn't compatible with Moccle's TV :(

Now I don't know what to get him for his birthday.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: Ham with mustard and salad sandwich; apple; satsuma; caramel Rocky; cup o' tea.
Dinner: Toad in the hole; peas; Broccoli; potatoes; mustard; gravy. Pudding was a Cherry bakewell with custard, and I also had a piece of Fabulous Bakin' boys' flapjack with custard. Coffee.
Supper: Milk chocolate digestive; malted milk; cup o' tea.

Wednesday 24 June 2009

Websiting

This morning I did some more work on my photo website.

After lunch I went on Animal Crossing. Sahara was there, and looking for carpets. Normally I ask all the animals and only one of them has an old carpet or wallpaper they'll give me, but today I got 5 old carpets! Agent S was ill and Merry was too busy going on about how grown up she is to drink coffee to even talk to me about old carpets, so I might have been able to get even more if those two weren't being so stupid and annoying.

I checked my email (which took a long time), then did some more website stuff.

After dinner I watched an episode of Satr Trk with Moccle and L, did some more website stuff, then watched an episode of The Office (US) with Moccle.

The weather today was mainly sunny with quite a bit of cloud about and probably a decent sunset.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: Ham with mustard sandwich; satsuma; slice of Madeira cake; caramel Rocky; cup o' tea.
Dinner: Mushrooms; baked beans; 1½ lamb burgers; mashed potato. Pudding was a slice of blackcurrant cheesecake. Coffee; 3 pieces of Sainsbury's caramel chocolate.
Supper: Chocolate crunch oat & raisin bar; cup o' tea.

Tuesday 23 June 2009

Hayfevering and websiting

This morning I went out to see if I could get any butterfly photos. By the time I'd finished checking my emails and got out the house, it was 10am and I think that probably this was too late really. I did see a lot of butterflies, but they were constantly flying around, so I didn't get too many photos. I spent most of the time blowing my nose.

When I got home I downloaded the pics I had taken to my comp, and then had lunch.

After lunch I played on Animal Crossing. It was raining, and then it started thundering. I couldn't see any lightning forks in the sky, but the ground lit up when it did lightning. It was quite good, because when you're in a building, the lightning flashes light up the windows. Also, I dug 6 gyroids and a fossil. Makes a big change to the past week or two when there haven't been any fossils most days, and just a pitfall each day.

I did some work on my photo website, changing the urls to be shorter, so rather than using the path to the category/image as part of the url, it now just contains the category name/image name.

Then I decided that it would be a good idea to store the url version of the category name in the database, so I didn't need to keep converting the category name to url format every time I needed. But before I could do that, I needed to decide what format my urls should be in.

I decided that I wanted spaces converted into hyphens, but what other characters, such as '?', and '&'? Question mark needs encoding as otherwise it means the start of a query string. And ampersand and friends need encoding as they're valid text in XML, so any links with an unencoded & would break the page.

I tried using urlencode(), which converts, the ? and & characters to hex values, but also converts any other non alphanumeric characters (except -_.) to hex values as well. So this can result in messy looking urls when using non alpha-numeric characters, and I don't know how Google treats url encoded characters.

Eventually after some testing and googling I settled on using htmlspecialchars() to encode ", <, >, and & characters, and manually urlencoding ? by using str_replace. I also found that I could set accept-charset="UTF-8" on the <form> element, and that htmlspecialchars() uses the ISO-8859-1 character set by default, so you need to tell it to use UTF-8.

Later in the evening I found that I couldn't view source in Internet Explorer, I just got a message saying "The XML source file is unavailable for viewing". Doing some googling I found session_start causes "The XML source file is unavailable for viewing" on IE, which says it's a problem with the cache headers, and Debugging the Internet Explorer View Source problem with Fiddler and fixing ASP.NET, which again points to the cache headers. Following the debugging procedure suggested in that second link, I deleted the cache headers that IE was receiving for the page, and then I could view source.

I haven't actually changed the cache headers being sent by the server yet, that's something for me to do later.

Food
Breakfast: Chocolate crunch oat cereal; cup o' tea.
Lunch: Ham with mustard and sweet & crunchy salad sandwich; satsuma; slice of madeira cake; Rocky; cup o' tea.
Afternoon snack: Lidl Cornetto; cup o' tea.
Dinner: Slice of Mozzarella pizza; slice of Spinach pizza; chips; peas; salt. Pudding was a Black cherry and chocolate Muller fruit corner. Coffee; 3 pieces of Sainsbury's caramel chocolate.
Supper: Milk chocolate digestive; malted milk; cup o' tea.

Monday 22 June 2009

Websiting

This morning I was listening to H-FM, and they played 'Tiny dancer' by Ironik. When I first heard it I thought it was Richard Blackwood. When I found out it wasn't Richard Blackwood, I was kind of suprised that a previously unknown artist with a relatively weak flow could be reasonably successful. I checked that it's not just me thinking Ironik's flow sounded weak, and its not just me.

The sad thing is that I hear Ironik songs (mainly "Stay with Me") more often that say Wiley tracks on the radio. And the only Wiley song they ever play is "Wearing my Rolex".

I spent the morning do some work on my photo website, changing the way that categories are extracted from the image's metadata and inserted into the database since I have changed the way the categories are saved in the image's metadata.

I spent the afternoon and evening trying to debug my code and find why it wasn't inserting the categories properly. Most of the problems were due to typos, but I did have one problem that took me quite a while to work out and wasn't a typo:

When I ran the query
INSERT INTO location SET City = 1
, ProvinceState = 1
, country = (SELECT country.id FROM country WHERE CountryName = 'United Kingdom')
, WorldRegion = (SELECT worldRegion.id FROM worldRegion WHERE WorldRegion = 'Europe')
ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id);
INSERT INTO img_locationCreated VALUES(1, LAST_INSERT_ID());
I was getting the error
Mysql Error: Cannot add or update a child row: a foreign key constraint fails (`dkphoto/img_locationCreated`, CONSTRAINT `fk_img_locationCreated_location` FOREIGN KEY (`location_id`) REFERENCES `location` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION)

I didn't understand how this error was happening. I checked that all my column types (unsigned ints) matched up, and they did, the column names were correct etc. I tried quite a few different things, but couldn't get any of them to work.

But when I was getting the CREATE TABLE sql to post on the mysql forums with my question about why it wasn't working, I noticed that the storage engine for the table was set to BerkeleyDB. This is because I wanted rows in this table to be UNIQUE, even if they contain NULL values. However, I think BerkeleyDB support has been dropped from MySQL, and the table was actually created with the MyISAM engine. Anyway, I changed the engine to InnoDB, and the problem disappeared.

After fixing that I watched an episode of Satr Trk with Moccle and L. Then I watched some youtube videos including:

2.3 avg. rating on IMDB and £60 +P&P on VHS from ebay!! Looks like the best film ever!!

Then I did some more website stuff and found my URLs were getting a bit long e.g. http://www.photosite.com/photos/Life/Plants, Animals, Fungi, Chromista, Protozoa/Plants/Flowering Plants/Dicots/Violales/Begonias/Begonia/2-Begonia-flower-close-up
Reading SEO Best Practices for URL Structure, it says you shouldn't have more than 5 words! So after all that time I spent trying to get my categories extracted with long paths, it seems it was a waste of time. Oh well.

Food
Breakfast: Chocolate crunch oat cereal; cup o' tea.
Lunch: 2x cheese-on-toasts; salad; apple; slice of Madeira cake; Rocky; cup o' tea.
Dinner: Chilli con carne; rice; tortilla chips; cheese. Pudding was a Strawberry Muller fruit corner. Coffee. 3 bits Sainsbury's caramel chocolate.

Sunday 21 June 2009

Bits of different stuff

This morning I went to Church with Moccle and Lad. After church I went on Animal Crossing.

After lunch I checked my email, Andy Rouse's blog, Moose Peterson's blog and The Luminous Landscape. After that I found that my custom XMP File Info Panel wasn't adding keywords from Hierarchical Keywords to an image properly. The problem was if the keyword already existed as part of a different keyword, then it wouldn't get added, e.g. if Begonias was already a keyword, then Begonia wouldn't be added.

The reason for this is that I was using indexOf() to check whether the keyword already existed. So I changed this to a regular expression, and this fixed it:
regex = new RegExp("\\b"+keyword+";","i");
if(!regex.test(keywords))
{keywords += keyword + "; ";}

After that I watched a John Wayne film. Weirdly he was mates with (American) Indians, and even had adopted an Indian as his son!?! He didn't even say much anti-women stuff. So it wasn't that funny, though there was a bit where John Wayne grabs a bloke, and the bloke says "Hey, I didn't do anything!". John Wayne says "Well, you should have!" and punches him. While the film was more politically correct than your average John Wayne film, it was still quite good.



I looked at Encyclopedia of Life again, and it seems that the Taxanomic hierarchy they use only uses the main Taxonomic ranks. I also noticed they have a an option to display Common names or Scientific names, the same as I'm planning to have on my site.

After tea I played on Animal Crossing for a bit. Then I found that my RegExp for extracting Hierarchical Keywords into normal keywords wasn't working. Eventually I figured it out - I had been using \b for a word boundary, but when you are writing a regex using the new RegExp() method, you need to escape the backslash with another backslash like \\b (I've corrected my code above).

After some more testing I found that if you have whitespace after a keyword, Bridge will strip the whitespace when saving the keyword, so I changed my regex to take account of this regex = new RegExp("\\b"+keyword+"\\s*;","i");

I did a bit more work on my website, then did a backup.

The weather today was mostly cloudy, with a bit of sun later in the afternoon, and a nice sunset.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Dinner: Chicken dippers; pasta; weird chicken soup stuff. Pudding was banana with ice cream, chocolate sauce and toffee sauce. Coffee; 3 pieces of Sainsbury's caramel chocolate.
Afternoon snack: Scone with butter and strawberry jam; cup o' tea.
Tea: Ham with mustard and sweet & crunchy salad sandwich; apple; slice of madeira cake; Rocky; cup o' tea.

Saturday 20 June 2009

Taxonomy and Hierarchical Keywords

This morning I checked my email and also did some more reading about Taxonomy and Hierarchical Keywords. Reading this thread Catalog Sets and hierarchical / non-hierarchical keywords, it seems that Microsoft Expression Media (formerly iView Media Pro) can do this, but unfortunately there wasn't any discussion in that thread about doing this in Adobe Bridge.



After some more googling I found that in Lightroom you can actually add synonyms for Hierarchical (or normal) keywords: Keywording Photographs, Part 2 Importing Keyword Files and Lightroom and Keywords Part V - Synonyms. Unfortunately it seems these synonyms are only stored in Lightroom's local database, and only added to an image as a normal keyword upon 'export'. If you will only ever use Lightroom to edit/view metadata on your images, then this is probably okay, but for me I need a way to extracting the Hierarchical keywords on the web server, plus I don't use Lightroom and don't like to be stuck using one program.

I think that probably what I will do is to arrange my Hierarchical keywords in the format Latin name (Common name; Alternate name 1), then in my custom XMP File Info panel, provide a way for extracting the individual keywords from the Hierarchical Keywords into the (normal) keywords field. This way the Hierarchical keywords maintain the link between the Latin name, common name and any alternate names.

Using the Begonia example again, the Hierarchical keywords would look like:


With the way I was previously intending to use Hierarchical Keywords to represent the taxonomy of the subject of an image, there was no way within the Hierarchical Keywords of showing that, say 'Plants' was a synonym of 'Plantae'. If you only have one taxonomic hierarchical category/keyword assigned to an image, it can be inferred that the top level Common name must be a synonym of the top level Latin name, and so on for lower category levels.

However, you would have a problem if your image featured multiple subjects that you wanted to add Taxonomic hierarchical keywords for, e.g. a photo of a duck and a pigeon


My plan was to use photoshop:SupplementalCategories to hold info on the lowest hierarchical level's Latin and Common names. When you know that the lowest levels of both the Common name and Latin name hierarchies are synonymous, then you can infer that hierarchical keywords in the upper levels for the Common name and Latin name hierarchies are also synonymous, e.g.


I don't think this method is that great though, which is why I think I'll probably go with Taxonomic Hierarchical keywords in the form I described earlier in this post.



After that I noticed that when I looked at the metadata for an image using my custom XMP File Info Panel in Bridge, the Lens used for taking the image was being added to the end of the list of possible lenses, rather than the existing entry for that lens being selected.

Looking at my code for the Lens combo box, I thought I had found the reason - in the list of lenses, the lens name starts with the Manufacturer, but the lens name recorded in the aux:Lens field of the XMP by ACR, didn't include the manufacturer.

So I changed my code to check whether the aux:Lens value existed anywhere in the list of lenses, rather than matching the whole field. I had quite a bit of trouble getting this to work, as I was using indexOf(), which I thought would return false if the Lens name didn't exist, but after a lot of messing about, turns out it returns -1 if the string can't be matched.

However, after working that out, I found the lens was still being added to the list. The problem was that the aux:Lens had the lens name as "EF100mm f/2.8 Macro USM", whilst I had the lens name as "Canon EF 100mm f/2.8 USM Macro". So the value Adobe Camera Raw had added to the image doesn't have a space between EF100mm, whilst the value in my list doesn't, hence they weren't matching.

So far as I'm aware, there should be a space between "EF" and "100mm", so rather than change my list values to match the ones given by ACR, I decided to just undo all my changes and put it back as it was before. It won't be hard to select all images and choose the lens used manually, rather than having my panel choose the value automatically from the value saved by ACR (which is what I was trying to do).

After lunch I went on Animal Crossing, and then wrote most of this blog post. When I was looking for the taxonomic hierarchy for a Wood Pigeon, I found that the hierarchy and Taxonomic names given by Fauna Europaea and Integrated Taxonomic Information System (ITIS) are quite different. There is also a slight difference between the ITIS and Encyclopedia of Life (EOL) Taxonomic hierarchies. For example, for Wood Pigeon:
  • Fauna Europaea (Taxonomic Hierarchy version 1.3) lists:
    Animalia
    Eumetazoa
    Chordata
    Vertebrata
    Gnathostomata
    Aves
    Passerae
    Columbimorphae
    Columbiformes
    Columbi
    Columboidea
    Columbidae
    Columba
    palumbus
  • Encycolpedia of Life lists:
    Animalia
    Chordata
    Aves
    Columbiformes
    Columbidae
    Columba
    Columba palumbus

    At the top right of the page it also says
    Showing authoritative information
  • Catalogue of Life lists:
    Animalia
    Chordata
    Aves
    Columbiformes
    Columbidae
    Columba
  • ITIS lists:
    Animalia
    Chordata
    Vertebrata
    Aves
    Columbiformes
    Columbidae
    Columbinae
    Columba Linnaeus
    Columba palumbus
  • Searching the International Commission on Zoological Nomenclature (ICZN) for "Columba palumbus", I just got three results about fleas.


The most notable difference between Fauna Europaea and the other sites is the subclass "Passerae". Looking it up on Wikipedia, it says
The "Passerae" were a proposed "parvclass" of birds in the Sibley-Ahlquist taxonomy. This taxon is a variation on the theme of "near passerines", birds that were - and often still are - believed to be close relatives of the passerines (perching birds, which include the songbirds). This proposed taxon was roundly rejected by subsequent cladistic analyses.
Yet according to Fauna Europaea, the taxonomic status of Passerae is valid.

Googling for "Passerae", I didn't come across any websites saying that it isn't a valid Taxon name, but I did find this website that does list it, plus a load of other Taxonomic ranks that none of the other websites I looked at featured: Ontology Online.

I was going to say that I'm inclined to use Fauna Europaea for Taxon ranks and names, ITIS and wikipedia for Common names / Synonyms of Latin/Scientific names, but I just noticed the last update on Fauna Europaea is 19 April 2007, whilst ITIS was last updated 08 January 2009, which, while not particularly recent, is still a lot more recent than April 2007.

Having said that, the data that ITIS uses seems to be mostly from before 2001. Fauna Europaea does also seem to make itself out to be an authoritative resource:
The Fauna Europaea project has assembled a database of all European land and freshwater animals. Experts in taxonomy have provided data of all species currently known on the European continent and associated areas. The main building-blocks of the Fauna Europaea database are the family taxa that have been established beforehand. The contributing experts delivered data on all taxa below the family level.

A default taxonomic higher hierarchy was thus needed to provide a framework for the lower taxa. This standard hierarchy has been established with the help of leading European taxonomists and reviewed by the Fauna Europaea Taxonomic Advisory Team.

Although limited by its original, practical scope (providing a management tool), its scientific scope (representing the temporal view of a restricted number of European experts), and its geographic scope (taxa not present within Europe are excluded, as are marine taxa), the taxonomic hierarchy thus established may serve as an authoritative standard for taxonomy in Europe.


I looked at WikiSpecies and Encyclopedia of Life. WikiSpecies seems to have many Taxanomic ranks, whilst EOL seems to only have a few Taxanomic ranks. WikiSpecies doesn't seem to have any particular people working on it (at least I didn't see it mentioned anywhere), while EOL says
The EOL staff is made up of scientists and non-scientists working from museums and research institutions around the world.


I think that maybe I will use EOL in organising my images by taxon.

As well as looking at that in the evening, I also changed my custom XMP File Info Panel so it had a button to get keywords from the Hierarchical Keywords already assigned to it.

The weather was a mixture of clouds and a bit of sun. It looked like there was a decent sunset.

Food
Breakfast: Blackcurrant jam toast sandwich; cup o' tea.
Lunch: Mature cheddar cheese with sweet & crunchy salad sandwich made with fresh bread-maker-made bread; honey on slice of fresh bread-maker-made bread; cherry; banana; Rocky; cup o' tea.
Dinner: Jacket potato; baked beans & sausages; grated mature cheddar cheese. Pudding was weird cherry stuff that Moccle and Lad made - kind of like bread & butter pudding except if the bread was all mushed up into the milky eggy stuff instead of being allowed to go a bit toasty/crispy in places, and with cherries. Coffee; 3 pieces of Sainsbury's caramel chocolate.
Supper: Coffee; choc chip cookie; nice.

Friday 19 June 2009

Walking and metadataring

This morning I went on a walk with Rad.

In the afternoon I checked my email, which took quite a long time. I also started trying to add some metadata to an image, and discovered some problems with my custom XMP File Info panel that I had to fix. I did this a bit in the evening as well.

Also in the evening I watched 2 episodes of The Office with Moccle, and read stuff about taxonomy and organising images. Unfortunately I couldn't find any examples of how other people organise their images with a Taxonomic hierarchy. At the moment I have 2 sets of Hierarchical keywords - one for common names and one for latin names.


The problem with this approach is that the 2 hierarchies are separate, really 'Plants' is just an alt name for 'Plantae'. It also means that I have to drill down through the different hierarchies for Latin Names until I get to the correct level, and also drill down through the Common Names, seperately. Some Hierarchy levels for Latin names don't have a corresponding Common name. At the moment, I'm using the Latin Name in the Common names hierarchy where this is the case (as can be seen above for 'Dilleniidae' and 'Violales').

I'm thinking that maybe I would be better off just having 1 set of hierarchical keywords, with each keyword in the form Latin name | Common name | Alternate common name 1. The problem with that approach though is that the keyword gets added to the image in that form, rather than the Latin name and common name being added to the (non hierarchical) keywords.

The weather today was mostly cloudy with the sun getting through a hole in the clouds every so often. I think there was probably a good sunset. It was reasonably windy.

Food
Breakfast: Blackcurrant jam toast sandwich; cup o' tea.
Lunch: Sliced peppery sausage with sliced cucumber, sliced cherry tomatoes, sliced peppers, cucumber, iceberg lettuce, and mayonnaise sandwich; satsuma; slice of Fabulous Bakin' boys' raspberry flavour flapjack; Rocky; cup o' tea.
Dinner: Battered fish portion with salt and ground black pepper; mashed potato; peas. Pudding was ⅘ of a Danish pastry. Coffee; Small chocolate egg.

Thursday 18 June 2009

Watching skilk 103.2 stooef

This mroning I checked my email, and then carried on with with getting Nginx, php-fcgi and spawn-fcgi set up.

I moved my server (virtualhost) configuration into a seperate file in a 'sites' directory, and then told Nginx to include all files in the sites directory. However, after making some more changes to the .conf files, I got the following error when trying to start Nginx:

Starting nginx: 2009/06/18 05:14:49 [warn] 22752#0: conflicting server name "mywebsite.com" on 0.0.0.0:port, ignored
2009/06/18 05:14:49 [emerg] 22752#0: could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
[FAILED]


After some messing about I discovered what had happened - I had been editing the site config file locally, and then uploaded the 'sites' folder to Nginx's conf directory. The sites directory that I uploaded included the previously saved version of my site config file (so it contained photosite.conf and photosite.conf~). Because I had just uploaded the directory, I hadn't noticed the extra file. So of course, Nginx was trying to load the site info from both files, which was breaking it.

After that I tried to copy one of my apache rewrite directives to Nginx, just a simple one that redirects page to page.php:
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,QSA,L]

However, I had some trouble with this as Nginx didn't like me have a nested if statement to check both RewriteConds. Luckily I found this website that describes the problem and how to get round it: Nginx Hacking Tips.

Then I tried to get Nginx working on my main domain, as previously I had just been testing it on a subdomain. However, when I tried this I got the error
2009/06/18 06:18:58 [emerg] 1690#0: could not build the server_names_hash, you should increase server_names_hash_bucket_size: 32
2009/06/18 06:18:58 [emerg] 1690#0: the configuration file /home/mysite/nginx/conf/nginx.conf test failed
The answer was to set
server_names_hash_bucket_size 1024;
in the http section of nginx.conf.


After lunch I played on Animal Crossing for a while, then carried on getting Nginx, php-fcgi and spawn-fcgi set up. When I tried to access my website, I found that PHP couldn't find any of the includes files that were beneath the site's root directory. So I edited php.ini and added the correct path to the include_path value. However, I was still getting the same problem.

I retarted Nginx, but PHP still couldn't find the includes files. I tried checking the phpinfo() page, and it didn't show the correct include_path that I had added to php.ini. I tried clearing my cache and refreshing the page, but it seemed that the php.ini file just wasn't being loaded. I checked the php.ini file on the server did have the include_path directive, and it did.

Then I remembered that the PHP process is actually managed by spawn-fcgi, not Nginx. So I restarted spawn-fcgi, and the php.ini file loaded okay. Yay!

The next problem I had was that files from my static subdomain were just giving a 403 Forbidden error. After some playing around and checking the logs, I found this was because I restricting access to my site by ip address, and that I needed to add the local loopback address as okay as well:
allow my.ip.address;
allow 127.0.0.1;
deny all;


After I'd got nginx, php-fcgi and spawn-fcgi seemingly up and working okay (though it did seem a bit slow), I checked my spleenmail. Then I wondered if it was possibly to do Client Side Includes so parts of a page could be loaded from a user's cache, in the same way that images, CSS and javascript are. I would have thought this should give a decent speed improvement as the Server would only have to process the CSI file once, and the client would only have download the CSI file once, no matter how many pages in the site they visit.

Googling for "Client Side Includes", I found quite a lot of info, though all the suggestion seemed to just be using javascript to insert the CSI. However, then I found this thread: [whatwg] Client-side includes proposal, which is a suggestion for having Client Side Includes in HTML5. Unfortunately reading that thread, and also What’s not in HTML 5? it seems unlikely that Client Sides Includes will make it into HTML5.

Most of the reasons against Client Side Includes seem to be that you can use Server Side Includes. However, if you're serving up a large hierarchical menu, then surely it would be much better to serve this once than with every pageview. The other alternative in this case would be to serve only one level of the menu at a time, and then get each sublevel of the menu as needed via AJAX. However, this would be far slower, slows the server down with even more HTTP requests, and non javascript users would need to reload the whole page each time they want to drill down a level in the menu.

I tried the following Client Side Include Methods:
<h2>Link</h2>
<link rel="html" type="text/html" href="/CSITest.html" />

<h2>Object</h2>
<object data="http://photosite.com/CSITest.html" type="text/html" width="200" height="100"></object>

<h2>XInclude</h2>
<div xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include href="http://photosite.com/CSITest.xml"/>
</div>
But only Object worked, and that didn't work in a suitable manner, it was just the same as an iframe.

After dinner I watched an episode of Fishing with John and an episode of Satr Trk with Moccle and Lad. Then I tried to solve a problem with some CSS on my website, but couldn't, so posted to the Web squeeze to see if anyone could help me.

Then I watched Transporter 3 with Moccle, which was quite good, but had some rubbish 'romantic' scenes, which were boring. Plus the woman in it was quite annoying, and Jason Statham didn't punch her :(

The weather today was overcast all day except about an hour before sunset. I'm not sure if sunset was visible or not, as it seemed to cloud over again around sunset. It was very windy as well.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: 2x cheese on toasts; salad; Plum; 3x cherries; Slice of Fabulous Bakin' Boys' Raspberry flavour flapjack; Orange Trophy; cup o' tea.
Dinner: Beef burger with processed cheese slice, tomato ketchup and salad in a bun; bowl of cream of vegetable soup; bun. Pudding was a small slice of Strawberry flan and a cherry bakewell. Coffee.
Supper: Choc chip cookie; fly biscuit; cup o' tea.

Wednesday 17 June 2009

Trying to install NGinX, PHP-fcgi and spawn-fcgi

Today I was trying to install NGinX, PHP-fcgi and spawn-fcgi on my hosting with webfaction. I spent most of the morning looking at different tutorials on installing Nginx with PHP. Patching PHP with PHP-FPM seemed to be the recommended option as opposed to running PHP through spawn-fcgi, though lots of tutorials did cover installing PHP with spawn-fcgi.

In the end I decided to go with spawn-fcgi as php-fpm hasn't been updated since December 2008.

After lunch I went on Animal Crossing as usual.

I spent most of the afternoon waiting for PHP to make and make test. make test isn't necessary, but as I was using a beta version of PHP (3.0RC3) I thought I might as well do it in case it was helpful to the developers. Having said that, I might not have done make test if I'd known quite how long it would take. While I was waiting I went on the pinternet and read the dpreview D5000 review and part of the Olympus EP-1 preview.

After dinner I watched an episode of Fishing with John, which was pretty funny. Then I carried on setting up Nginx, PHP-fcgi and spawn-fcgi. I had it working with static files okay, but when I tried to view a PHP page I got
Warning: Unknown: Filename cannot be empty in Unknown on line 0

Fatal error: Unknown: Failed opening required '' (include_path='.:/home/path/to/php/lib') in Unknown on line 0


Quite a cryptic error. I spent the rest of the evening trying to work out how to fix this - lots of googling, changing nginx.conf and fastcgi_params, and restarting nginx. Eventually I did get it working. I had copied the fastcgi_params from the Nginx Wiki FastCGI Example, but the line
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
needed to be changed to
fastcgi_param SCRIPT_FILENAME /path/to/website/document/root$fastcgi_script_name;
(In other words I needed to hardcode the document root into the SCRIPT_FILENAME fastcgi_param).

I found this out by copying the fastcgi_params provided at: nginx on FreeBSD with PHP, fastcgi, Drupal, MySQL. I'm not sure whether commenting out
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
as directed by the Nginx wiki article also breaks it, but PHP seems to be working at the moment including that that line (so not commenting it out or deleting it).

I also bid on a lot of 5 saturn games that included Panzer Dragoon Saga on ebay, but got outbid. It ended up going for something like £67 + £8 P&P. Quite a good deal since a PAL copy of Panzer Dragoon Saga sold recently for about £140. The same seller also had another lot of 6 games, which sold for about £80 + P&P. I guess that had a rare game in it as well (Burning Rangers maybe?)

The weather today was overcast all day and rained quite a bit. However, just before sunset the sun started shining, probably resulting in a great sunset, but I couldn't see it too well from here.

Food
Breakfast: Bowl of choco hoops; cup o' tea.
Lunch: Slice of Roma (I think) style ham with iceberg lettuce and sliced cherry tomatoes sandwich; nectarine; slice of home-made lemon sponge cake; orange Trophy; cup o' tea.
Afternoon snack: Slice of Fabulous bakin' boys raspberry flapjack; cup o' tea.
Dinner: Egg Pasta; bacon sauce stuff; ground black pepper. Pudding was strawberry flan. Coffee.

Tuesday 16 June 2009

Went on a walk

This morning I went on a walk with Rad. We went through 3 fields of bulls, but luckily they weren't chasing after you bulls (though they did follow us a little bit).

In the afternoon I took some photos of a moth I captured last night. It was quite weird behaviour wise in that it would sometimes flap its wings a bit and fall over onto its side, then just lie there like it was dead.

I did a bit more website stuff as well.

After dinner I watched Assembly with Moccle. Then after that I did a bit more website stuff.

Food
Breakfast: Blackcurrant jam toast sandwich; cup o' tea.
Lunch: Turkey with mayo and salad sandwich; ⅔ banana; 2 plums; Rocky; cup o' tea.
Dinner: Shepherd's pie; carrots; mashed swede; tomato ketchup; ground black pepper. Pudding was lemon sponge with lemon curd and custard. Coffee.
Supper: Cup o' tea; choc chip cookie.

Monday 15 June 2009

Getting rained on

This morning on HFM they said the weather was going to be very rainy, stormy and maybe even hailing in the afternoon, but not in Harborough. I wasn't sure whether the present was joking about the 'not in Harborough' bit, but as it was nice weather I thought I might as well go out just in case the weather was bad in the afternoon.

I walked up the old railway line again, by the time I had gone out it had clouded over, but was still reasonably bright. I didn't see any small butterflies, just larger ones, which kept flying away whenever I got near them. I also saw some scorpion flies. I didn't know they weren't dangerous until after I came home and looked them up on the pinternet, so I was very scared of them. Also a mosquito or something bit me while I was trying to take a photo of a male scorpion fly, then when I looked up it had disappeared.

I did see one person on my walk today.

On the way back home it started raining, and although I walked pretty quickly, myself and my camera did get quite wet (I didn't take my camera bag since there wasn't much point bringing it).

When I got back home I dried myself and the camera off, then did some more website work. I found that Nginx was loading files with the incorrect mime types. Doing some googling, I found this was because I didn't have include mime.types; in my Nginx server config. After adding this and restarting the server, it still didn't work though. After trying a few different things I finally found that Firefox was loading the page from cache (despite neither Nginx nor apache sending any cache/expires headers). So clearing Firefox's cache I could see Nginx was working correctly.

After getting that working, I tried to get Nginx to start when the machine was booted and try to start every 20mins in case it crashed and needed to be restarted. This took me quite a while, I did some googling on cron jobs, and got the cron job running, but nginx wasn't actually being started. When I ran the command from the user account that nginx was installed on, it worked okay. But when run from the cron job or a different user account, nothing happened.

Previously I was executing an nginx init script that I'd got from a website that had a tutorial on setting up nginx, and I'd modified the script slightly. So I tried using the init script for Ubuntu on the nginx wiki, obviously I had to modify that as well, but this would now work when called from a cron job.

I'm not sure why one script worked when the other didn't (even though it did actually work, just not from cron jobs or other user's accounts).

Lots of info I'd read on Nginx said it was faster running PHP with Nginx than with apache, though they didn't seem to have any actual tests, just anecdotal evidence. Further, most people were comparing apache with mod_php vs. Nginx with PHP FastCGI. My current PHP implementation at WebFaction is apache with mod_fcgid and PHP FastCGI. Though googling for that, I found a post (with test results) saying that PHP through mod_fcgid is slightly slower (though less resource intensive) than mod_php.

After dinner I watched an episode of Star Trek TOS with Moccle and L, then watched a Springwatch Special with L, Rad and Clare.

I was wondering about SEO/human friendly URLs, and whether it is okay to include the key of the page in the URL so you can look up the page contents easily from the database, or whether you shouldn't include the key of the page, and so would have to look it up in the database by doing a text search, e.g.
http://photosite.com/Animals/Birds/Thrushes/Blackbirds/20 (20 would be the id of the Blackbirds record in the database) vs.
http://photosite.com/Animals/Birds/Thrushes/Blackbirds (To get the page content you'd have to look up the record for Blackbirds in the database that had a parent of Thrushes that had a parent of Birds that had a parent of Animals - quite a bit of work for the database to do)

I was going to post on the websqueeze about this, but first did a quick check to see if it had already been covered, and it had: How To Build Up Your Search Engine Friendly Url's. So the advice seems to be that there's not much point removing the database record key from the url, as most people don't care too much about how a URL looks or whether it's easy to remember. If they want to remember it, they'll just add it to their favourites. So I'll stick with keeping the numbers in the URL.

The weather was sunny first thing, then overcast, then rainy, then sunny most of the afternoon, then overcast again around tea time and rained a bit more, then stayed reasonably cloudy, but it looked like there was a good sunset.

Food
Breakfast: Strawberry jam toast sandwich; cup o' tea.
Lunch: Mature cheddar cheese with iceberg lettuce sandwich; bag of barbecue flavour crisps; peach; Rocky; cup o' tea; small chocolate santa.
Dinner: slice of quiche (meant to be ham quiche but didn't have any ham in it); chips; salad. Pudding was 2x apple pies warmed in the oven with custard and cream. Coffee; Oreo; small chocolate santa.
Supper: ⅓ Malted milk; ½ nice; choc chip cookie; hot chocolate.

Sunday 14 June 2009

Configuring Apache to proxy requests to Nginx

This morning I went on Animal Crossing, then went to Church with L, as Moccle is visting Flukester in Man's field. After that I went on Animal Crossing a bit more, then it was dinner time.

After dinner I checked my email, then I went to bed as I was headachy and sleepy.

I got up again about 15.30, and went in the garden with Ben for a bit. There seemed to be plenty of different insects around.

Then I came back inside and decided to look at installing Nginx. I wanted to try installing it on my Ubuntu virtual machine first, which meant I needed to figure out how to get apache to proxy requests to another port or socket. First I needed to check that apache had mod_proxy installed, after a bit of searching I found where apache had stored its modules in Ubuntu: /usr/lib/apache2/modules.

I read quite a few of different articles on forwarding ports using Apache, but found this article most helpful: Using Apache Virtual Hosts and ProxyPass Together.

I did quite a bit of googling and reading on nginx, and got that installed. When I tested my page by going straight to the domain/port that Nginx was serving, I got the page okay.

But when I tried to access it without the port (so the address that apache should have been proxying to Nginx on the correct port), I just got a Forbidden page. So I guess I must have done something wrong in configuring Apache.

Doing some googling most suggestions about this problem were to do with missing the proxy module(s) from the apache httpd.conf file. My file didn't have any of the lines to load the modules, but I had done sudo a2enmod proxy etc. for the various proxy mods I needed, and restarted apache.

But one of the suggestions, said about checking the apache logs, so I did this and found
mod_proxy: client denied by server configuration: proxy:http://localhost:5678/
Googling for this I found this thread: mod_proxy: client denied by server configuration: proxy:http://otherserver. Editing /etc/apache/mods-available/proxy.conf, and changing 'Deny from all' to 'Allow from all' fixed it.

The weather today was (again) a blue sky with quite a bit of cloud, and sunny nearly all day. I didn't see much of the sunset, but it looked like it was probably quite good.

Food
Breakfast: Orange marmalade toast sandwich; cup o' tea.
Dinner: Nasi Goreng; noodles. Pudding was a slice of jam swiss roll with tinned pear halves and custard. Cup o' tea.
Tea: Mature cheddar cheese sandwich made with fresh bread-maker-made bread; slice of fresh bread-maker-made bread with orange marmalade; satsuma; apple pie; Rocky; cup o' tea; Oreo.

Saturday 13 June 2009

Websiting

This morning and quite a bit of the afternoon I was trying to work out why I was being redirected to www.mysite.com/Error.php from mysite.com/upload. According to my .htaccess rewrite rules, mysite.com/upload should 301 redirect to www.mysite.com/upload, and then that should internally redirect to www.mysite.com/upload.php, but this wasn't working somewhere.

I set my site to log rewrites with log level 3. First thing I found was lots of static files were still going through apache (and so being checked against the rewrite rules). So I uploaded my updated files, and had to do a few tests and make a few changes.

After that I found I was still getting the same problem. Looking at the rewrite logs, it seemed that mysite.com/upload was getting a 301 redirect to mysite.com/Error.php, but I couldn't work out why. When the Error.php page loaded, it didn't print any error/redirect code though (it was set to print the PHP value of $_SERVER['REDIRECT_STATUS']).

I commented out all the ErrorDocument directives in my .htaccess file, and then the page would redirect correctly. So I uncommented the ErrorDocument directives again, a couple at a time, and resting the page each time. Eventually I had all the ErrorDocument directives uncommented, but the page was still redirecting correctly, even though the .htaccess file was now exactly the same as it was when it wasn't working. Very annoying and weird!

It was the Harborough Carnival today, but I didn't go as I've still not processed the photos I took from last year's carnival yet.

Reading a bit more of the Yahoo Best Practices For Speeding Up Your Website, I noticed they present a good reason for using www. as your default website address - it allows you to keep cookies restricted to the www. subdomain.

After dinner I watched an episode of the Equalizer, then did some more website stuff, trying to upload an image to my test site and working out some problems with the SQL queries that are executed as part of the image upload process.

The weather today was a blue sky with quite a bit of cloud, and sunny nearly all day. I didn't see the sunset, but Clare said there was one, and it was quite nice.

Food
Breakfast: Orange marmalade toast sandwich; cup o' tea.
Lunch: Beef with mustard and iceberg lettuce sandwich; satsuma; banana; caramel Rocky; cup o' tea; Oreo.
Afternoon snack: Fly biscuit; choc chip cookie; cup o' tea.
Dinner: 2x delee pork & herb sausages; baked beans; mashed potato; tinned plum tomato. Pudding was home-made banoffee pie with cream and toffee sauce. Coffee; Small Chocolate Easter Bunny.

Friday 12 June 2009

Having a runny nose

This morning I checked my email, which took quite a while, and then went out to try and take some butterfly photos. One of the emails I got was from Pop Photo, which had a link to 20 Easy Techniques For Improving Your Photos. Normally I don't find Pop Photo's articles very interesting as they seem to be quite basic. But while this article was still reasonably basic, I did find it quite good, it's more 20 ideas for photographs than techniques for improving photos.

When I was out chasing butterflies (actually just one skipper I think), I had to constantly blow my nose and also my eyewater kept making it so I couldn't tell if what I was looking at through the camera's viewfinder was in focus or not. Eventually I came home as my handkerchiefs were just too wet and soggy from blowing my nose so much. It was very nice, warm and peaceful where I was though, and I didn't see anyone all the time I was out (maybe a couple of hours).

When I got home I copied the pics to my comp, processed them and sorted them (a bit), did a backup, and then had lunch.

After lunch I played on Animal Crossing for a bit, then I decided to do some more work on my website.

Now, as I thought, with the phpstack Webfaction have set up for me, I do have a copy of apache installed in there for use with my own sites, and they redirect any traffic for my sites to go through my copy of apache. See this post on the WebFaction forums, bear in mind that post is from 2006, I think maybe they now use Nginx to proxy requests to users' copies of apache.

Yesterday I set up 2 subdomains for my site in my WebFaction control panel, static1 and static2, as per the Yahoo guide Best Practices For Speeding Up Your Website. Today I was looking at how to actually implement this. First I found that WebFaction use Nginx to serve static pages (I had configured my static subdomains to use a 'app type' of 'Symbolic link to static-only app').This meant that I didn't get my normal 404 error page when calling a URL that doesn't exist.

I had pointed my static subdomains to the same site root as the main domain, and this meant that I could view/download .htaccess and PHP files when using the static subdomains. Also other apache directives, such as mod_rewrite and password protected directories didn't have any effect when browsing the site through the static subdomains. This is obvious when you think about it (you can't expect Nginx to enact apache directives), but I hadn't thought about it.

So I moved all my static files into a separate folder, and changed the site root for the subdomains to that folder. I'm not sure if it will be possible to protect images from being hotlinked when they're served as a static app. Nginx does have a rewrite module, but I think you have to specify your rewrite rules at the Server configuration level, rather than being able to have .htaccess files, and I doubt I would have access to the relevant Nginx configuration file to set this up.

The other thing I'm not sure about is how to set cache-control for files served statically. Ah - found the answer now, with WebFaction if you're serving static content, you can't set cache control/expires headers. I started reading this good article on caching, then it was dinner time.

After dinner I watched an episode of The Equalizer, then finished reading the article on Caching. From what it says there, it seems that if the server sends a Last Modified date header for an item, then the browser will check whether the item exists in its cache, and whether the one on the server is newer or not, and only download it if the version on the server is newer.

So there doesn't seem to be much point serving static content using WebFaction's 'static-only' app (through Nginx), unless you're serving static content that won't be loaded by the user again (can't think of any situations where this would happen).
I posted a question on the WebFaction forums about this to check whether I'm correct.

Food
Breakfast: Orange marmalade toast sandwich; cup o' tea.
Lunch: 2x cheese on toasts; sweet & crunchy salad; nectarine; plum; Trophy; cup o' tea; Chocolate Sanata.
Dinner: Breaded fish portion; mashed potato; peas; salt; vinegar; ground black pepper. Pudding was a creamy strawberry yoghurt. Coffee.
Supper: Choc chip cookie; malted milk; Oreo; cup o' tea.

Thursday 11 June 2009

Went on a walk

This morning I went on a walk with Rad.

After lunch I checked my email and downloaded the photos I'd taken to my comp. After that I put the washing out and found a dead beetle in the pond. I got in on a stick and took a few photos of it, but then it fell off the stick, which was annoying since I hadn't taken many photos of it. I couldn't get it to go back on the stick either.

After dinner I finished watching Indiana Jones and The Crystal Skull with Moccle and L. I thought it was really good, you can read my review here: Indiana Jones and The Crystal Skull Review. I went in the garden and took a few photos, then watched Springwatch with L, Rad and Moohar.

After Springwatch I did some googling to see if it was best to connect to MySQL via a socket or port (tcp). Searching for "MySQL socket port" and MySQL sock vs port" didn't come up with much comparing them speedwise, but according to the MySQL documentation, connecting via socket is faster than by port.

After that I tried to find out how to make sure I connect to the server using a socket when using the PHP mysqli extension. The MySQL page I linked to above says
A Unix socket file is used if you don't specify a host name or if you specify the special host name localhost.
Reading the PHP Manual page for mysqli, that says
When possible, pipes will be used instead of the TCP/IP protocol.
So it seems I need to make sure that I connect to localhost and also either specify the socket when connecting or set it as the default socket in php.ini.

It's only 22.23 but I'm feeling quite sleepy (I think it's something to do with hayfever), so I'll have to get that setup tomorrow as I'm going to go to bed now.

Food
Breakfast: Bowl of Choc crunch oat cereal; Cup o' tea.
After walk snack: Malted milk; choc chip cookie; coffee.
Lunch: Grated mature cheddar cheese with sweet & crunchy salad sandwich; apple; caramel Rocky; cup o' tea.
Dinner: Slice of spinach pizza with sliced pepperami added; sweet & crunchy salad; chips; salt. Pudding was a slice of mandarin cheese cake and a slice of Danube cake. Coffee; Chocolate santa.
Supper: Hot chocolate; malted milk; milk chocolate digestive.

Wednesday 10 June 2009

Finally got MySQL installed in my home directory on the web server okay

Today I had received a reply from WebFaction about how to install the mysqli PHP extension. They said I would need to rebuild PHP rather than just making the mysqli.so extension and pointing to it in php.ini.

So far as I can tell, when PHP is configured with an extension included, it kind of includes it internally, and doesn't produce an extension.so file. So I think you can either configure PHP with the extensions included, or configure it without extensions, then build each extension separately and include them via the php.ini file. I'm not sure on this though, maybe I'll ask on the Web Squeeze.

Anyway, I renamed the current PHP installation on the Web Server, and built the new version of PHP, then restarted the server, and amazingly it actually worked (as far as I could tell anyway). In phpinfo() the mysqli was listed as being for mysql version 5.4beta, when previously it was for mysql 5.04.



Another thing I don't understand is how I can start, stop, and restart the server (I'm on shared hosting, so obviously I can't stop, start and restart the whole server). So far as I can tell, WebFaction redirect traffic for my site to a local copy of Apache they've installed in my ~/webapps/phpstack folder.

Looking at my phpinfo() page entry for mysqli, I noticed that the MYSQLI_SOCKET value was /tmp/mysql.sock and the value for mysqli.default_port was 3306, both incorrect for the mysql I'd installed in my home directory.

After lunch I went on Animal Crossing for a bit, and then tried installing mysql and php again. This time when installing mysql, I made sure to configure it with --with-unix-socket-path=$HOME/webapps/mysql/mysql.sock --with-tcp-port=myport. I also changed it so that it would install in ~/webapps/mysql rather than just ~/mysql where I had installed it before.

Since I had specified the tcp port and unix socket when installing mysql, I wasn't sure if I needed to create a my.cnf file as described in the WebFaction tutorial How to install MySQL into your home directory, but I thought I might as well create the my.cnf file as described, just in case.



After that I had to delete my php installation I'd just done, and install it again so that the mysqli php extension would be compiled against mysql with the correct port and socket settings.

Configuring, making and make installing these things takes quite a while.

After installing php again, I restarted the server, and phpinfo() now showed MYSQLI_SOCKET pointing to my local mysql installation, but mysqli.default_port was still 3306. Googling for "mysqli.default_port", I found this page that has lots of info on mysqli configuration options. Basically, mysqli.default_port is an option that you can set in php.ini.

So I checked the phpinfo() page to check where the php.ini file was located. However, when trying to browse there in Filezilla, I couldn't see the folder that I'd installed PHP to. I tried browsing back a level, then back to PHP's parent folder, but still couldn't see the PHP installation directory. I scrolled up and down the list in case it was at the end of the filelist or some other random place in the directory listing, but nope, it wasn't there.

I tried disconnecting and reconnecting to the server a couple of times, but still couldn't see the PHP installation directory. In my shell session on the server, I checked the PHP installation directory was there, and it was, Filezilla just couldn't see it for some cheesun.

I closed Filezilla, opened it again and reconnected to the server, and now it could see the PHP installation directory. I guess I could have done this in the shell session, but I much prefer using a GUI, especially for editing text files.



So I created a php.ini file locally (no php.ini file existed after installing PHP), added mysqli.default_port=myport to it, then saved it and uploaded it to the correct place on the server. I restarted the server, and now mysqli.default_port was set to the correct port. Yay!

Now all I had to do was update phpMyAdmin's config.inc.php file so that $cfg['Servers'][$i]['socket'] was pointing to the correct place.

I also wrote down the whole procedure so it should make it easier if/when I need to do this again. I'm hoping to upgrade to PHP-5.3 when it's released as it has new mysql native drivers, which are apparently quite a bit faster/more efficient than the current mysql extensions.



Heh, I just found that Mickelmaus pretends to be asleep is linked to as a suggested video from The Worst Star Trek Music Video Ever. As I hoped it seems that watching a video and then searching or watching for another video links the two together. So watching the Worst Star Trek Music Video Ever and then Mickelmaus pretends to be asleep (or vice versa) enough times creates a strong enough link for one to be featured on the other's similar videos list. I'm not sure if doing it lots of times in a row has any affect, or if you should do it once every day to create the link. Obviously if you can get other people to do the same thing, it will be more effective and should work quicker.

Getting back to installing mysql and php, I checked the server error log and found there was a load of errors like
php-cgi: unable to close module modulename can't close resident module @ module.c/UnregisterModule
This error occured about 15 times with different module names in a row, and then this block of errors was repeated a few times throughout the error log. Googling for these errors didn't come up with anything.

Another error in the error log was
[error] server reached MaxClients setting, consider raising the MaxClients setting
Googling for this did come up with some info, even a post on the WebFaction forums, which was helpful [error] server reached MaxClients setting. So I changed the ServerLimit in the httpd.conf file as suggested, restarted the server, and this seemed to fix it, as well as the other errors I was getting (though I haven't done anything to test it other than log in to phpMyAdmin).

In the evening I started watched Indiana Jones & The Crystal Skull with Moccle and L, then watched Springwatch with L and McRad. After that I did some more website work. I found that when I uploaded my photosite database to the web server (via phpMyAdmin's import function), I got an error about the max length of a key being 1000 bytes.

Doing some googling I found the problem - in UTF-8 each character uses/has reserved for use 3 bytes, so the max key length is 333 characters. In my case I had a UNIQUE key on 2 varchar fields, each with a length of 255 chars (I didn't actually check, but presume that to be the case). So my key was 510 chars max length, when the maximum length I could have was 333 chars. So I had to modify the key so it took 25 chars from one column and 255 from the other, which keeps it under 333 chars, and that fixed it. Surprisingly I only had this problem on one column.

The other surprising thing was that I only had this problem when uploading the SQL to the web server. My local environment (MySQL 5.1 and an older version of phpMyAdmin than is on the server) didn't complain about the key length being too long.

After updating the database on the server and also updating one of the files on the server to take account of the different filepath on the server compared to my local testing environment, I tried my web page. Unfortunately it didn't work too well, as it couldn't find any of the PHP includes files.

I had forgotten to edit the php.ini file on the server so that php includes would look in the right place for the files to include. After updating that I tried the page again, and it worked, and could read and write to the database. But the jQuery didn't seem to be working.

The problem was with the AJAX calls, they were still calling to my local testing site's URL. So I edited my javascript file to use a variable for the site URL, uploaded it to the server, and the value of the site URL variable in the file on the server. I decided to try it from the www. URL, but I got a site not found, so I obviously need to set my site up properly. I'll probably do that tomorrow.

The weather today was overcast, with the occasional break in the clouds letting a bit of sunshine through for about a minute in the morning, and rain in the afternoon.

Food
Breakfast: Fruited tea cake; cup o' tea.
Lunch: Mature cheddar cheese with sweet & crunchy salad sandwich made with white granary bakery bread; clementine; honey on crust of white granary bakery bread; caramel Rocky; cup o' tea.
Dinner: Spaghetti; Lloyd Grossman chilli & tomato sauce; bacon; mixed veg. Pudding was a large slice of Danube cake stuff. Coffee; Oreo; Cadbury's Dairy milk.
Supper: Cup o' tea; fly biscuit.