Sunday, 31 August 2008

Googlebot, fdfdkll.html and Configuring 404 Page Not Found with PHP

After checking the logs for a website, I noticed Googlebot trying to access fdfdkll.html, which definately does not exist.

I assumed Googlebot hadn't gone mad so I did some investigations and found this is Googlebot trying to establish how the site handles invalid urls.

Thinking from the search engine perspective, this is important, as if a default page is served with a status of 200, page found, the invalid url would be listed.

This is exactly what I had done. Ooops. I had set htaccess to display the homepage if the requested page didn't exist. The site is small so a specifc error page is not really needed.

It is most likely this would effect the page rank so I really needed to change the return status to 404 if the page has been reached due to an invalid url.

The homepage is PHP, so I made the following changes:

Initial .htaccess extract

ErrorDocument 404 /home.php

I changed this to

ErrorDocument 404 /home.php?error=true

And added the following code to the start of the PHP homepage.

if($_GET['error']=='true')
header("HTTP/1.0 404 Not Found");

The header command needs to come before any output is written to the page.

So now if the homepage is accessed because the url in invalid, the error parameter is set and the status returned is 404, otherwise it is 200 as normal. From the user perspective, there is no difference, the homepage is displayed as normal.

fdfdkll.html ...Done.

Thursday, 28 August 2008

PHP: Read File of Name Value Pair Parameters into an Array

This is a simple code snippet, that can be dropped into any code, to read name value pair parameters from a file into an array, so that the parameter name is the array key.

Example params.txt file extract:
height=100
width=50

PHP code snippet:
$param = array();
$paramsFile = fopen('params.txt','r');
while(!feof($paramsFile))
{
$buffer = fgets($paramsFile);
list($name,$value) = split('=',trim($buffer));
$param[$name] = $value;
}
fclose ($paramsFile);

The array can then be referenced as:
echo $param['height'];

To use the tab character as the seperator instead of (=) equals, change the list line to:
list($name,$value) = split("\t",trim($buffer));

BlogEntry=Done

Tuesday, 19 August 2008

Java Node to String Conversion

When trying to convert a org.w3c.dom.Node to a string, I initial tried using toString(). I assumed toString() would give me text content of the XML contained in the node but it was not going to be that easy today, it gave me some kind of pointer gobbledeguck back.

OK then, with some investigation, I found that toString() shouldn't really be relied upon, so I have written the following method using StringWriter and Transform methods.

import org.w3c.dom.Node;

import java.io.StringWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;


private String nodeToString(Node node) {
StringWriter sw = new StringWriter();
try {
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.transform(new DOMSource(node), new StreamResult(sw));
} catch (TransformerException te) {
System.out.println("nodeToString Transformer Exception");
}
return sw.toString();
}

Node to String...Converted.

Monday, 18 August 2008

JSP Printing Escape Characters.

During some recent developing in Java/JSP, using the c taglib, I had an issue when I wanted to print characters that JSP interprited as escape characters.

To output an attribute stored in the request I was simply using

{$myAttribute}

This worked well until the escape character came into play.

After a bit of research, I found some instructions to change the code as follows.

<c:out escapeXml='false' value='$myAttribute'/>

This now outputs the attribute exactly as it was stored.

Done.

Thursday, 14 August 2008

Javascript Simple Image Slideshow; Take 2

This Javascript image slideshow expands on the previous version, See Here.
As in the previous version, the user navigates through the slideshow using previous and next buttons, however the previous version required images to be numbered in sequence, image1.jpg image2.jpg etc, this version allows any filename. It also makes use of the image preload code, See Here, so that the images are loaded with the page, so there is no waiting for them to during the slideshow.

<html>

<head>

<script type="text/javascript">

var imageFiles=[];
var imageIndex=0;

function imageSwitch(i,d)
{
imageIndex += d;
if(imageIndex >= imageFiles.length){imageIndex=0;}
else if(imageIndex < 0){imageIndex=imageFiles.length-1}
i.src = imageFiles[imageIndex].src;
}

function imagePreload()
{
for(i=0; i<arguments.length; i++)
{
imageFiles[imageFiles.length]=new Image();
imageFiles[imageFiles.length-1].src=arguments[i];
}
}

imagePreload('your.jpg','list.jpg','of.jpg','images.jpg','goes.jpg','here.jpg');


</script>

</head>

<body>

<h1>Switch Image Source 2</h1>

<input type="button" value="Prev" onClick="imageSwitch(document.getElementById('myImg'),-1);"/>
<input type="button" value="Next" onClick="imageSwitch(document.getElementById('myImg'),1);"/>
<br/><br/>
<img id="myImg" src="image0.jpg"/>

</body>

</html>

Much better version...Done.

Wednesday, 13 August 2008

PHP Copyright Year Trick

I found this snippet on a forum recently, it's so simple and obvious I wish I'd thought of it!

A lot of web pages have a copyright notice in the footer of the page with the year included. For server side scripts, instead of just writing the year in, you can replace it with code to dynamically write the year, so it's always up to date.

For PHP:

&copy;<?php print date("Y"); ?> My Company Ltd

You can use the same idea for other server side code, such as Java or Perl.

How Simple?

Tuesday, 12 August 2008

Generating Java Map List and Displaying with JSP

This example is to demonstrate recent investigations into outputting xml data to the page using a Java HTTPServlet and JSP with a Map List.

We want to output the id, description and size for each widget from the xml, to a form in html.
The id is stored in its own element but the description and size are name value pair properties.

<?xml version="1.0" encoding="UTF-8"?>
<widgetNode>
<widget>
<id>101</id>
<properties>
<property>
<name>description</name>
<value>Thingy Bolt</value>
</property>
<property>
<name>size</name>
<value>27</value>
</property>
</widget>
<widget>
<id>102</id>
<properties>
<property>
<name>description</name>
<value>Wotsit Nut</value>
</property>
<property>
<name>size</name>
<value>11</value>
</property>
</widget>
</widgetNode>


The Java extract here loops through each widget node, adding the values we want to Map, then adds that Map to a List.
The Map List is then added, as an attribute, to the request.

(Although unintended, this is also an example for XPath, which took a little investigation too)

...
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
...

private void processWidgetXml(HttpServletRequest request, String xml) {
List<Map<String,String>> widgets = new ArrayList<Map<String,String>>();
String expression = "/widgets/widget";
try {
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList nodes = (NodeList)xPath.evaluate(expression, new InputSource(new StringReader(xml)),XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
Map<String,String> widgetMap = new HashMap<String,String>();
widgetMap.put("id", (String)xPath.evaluate("id", node));
widgetMap.put("description", (String)xPath.evaluate("properties/property[name='description']/value", node));
widgetMap.put("size", (String)xPath.evaluate("properties/property[name='size']/value", node));
widgets.add(widgetMap);
}
request.setAttribute("widgets", widgets);
} catch (XPathExpressionException e) {
System.err.println("XPath expression invalid: "+e.getMessage());
e.printStackTrace();
}
}

Coming to the JSP, the following extract highlights the syntax for the Map List. It loops through all of the widgets, creating a form, with unique name, for each widget.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
...
<% int lc = 0; %>
<c:forEach var="widget" items="${widgets}">
<form name="myWidget<%= lc %>" action="/myActionPage" method="post">
<input type="hidden" name="widgetId" value="${widget['id']}"/>
<input type="submit" value="Select"/>
${widget['description']} : ${widget['size']}
</form>
<% lc++; %>
</c:forEach>


Done... (finally)