This blog dates back to 2003 and is kept as an archive. The blog has now been moved to Wordpress.

https://apps.fuzzybuckets.uk/blog

April 20, 2015

Python MARC record cleaner

# -*- coding: UTF-8 -*-

from pymarc import MARCReader
from pymarc import Record, Field
#from abc import ABCMeta, abstractmethod

import re, string, os, json
import sys, time
from datetime import date

"""
Class for printing out colours on the CLI
"""

class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'
	
"""
Class for when we don't want colours (monkeys with 'more' use and puts garbage into files)
"""
class nocolors:
    HEADER = ''
    OKBLUE = ''
    OKGREEN = ''
    WARNING = ''
    FAIL = ''
    ENDC = ''
    BOLD = ''
    UNDERLINE = ''

class ChangeLogger:
	
	"""
	Class for delegating logging functions to.
	
	Returns the log as JSON.
	"""
	
	def __init__(self):
		try:
			testit = "%s" % self.list
		except:
			self.set_list()
	
	# Set up the log list
	def set_list(self):
		self.list = {}
	
	# Main function to add to the log
	def log(self, leader, field, message):
		if leader in self.list:
			blah = 1
		else:
			self.list[leader] = {}
				 
		try:
			self.list[leader][field].append(message)

		except:
			self.list[leader][field] = []
			self.list[leader][field].append(message)
	
	# Function to return the log as JSON				
	def get_log(self, leader):
			return json.dumps(self.list[leader])

class MARCParser():
	
	"""
	Generic (maybe later abstract) class with main MARC parser functions.
	"""
	
	def __init__(self):
		
		"""
		Instantiate the logger delegate object our colour writer and the deletions array.
		"""
		self.logger = ChangeLogger()
		
		self.bcolors = nocolors()
		
		self.deletions = ['520','533','655','776','505','500','588','590','980']
		
		self.additions = [{'tag' : "909", 'value' : "Coutts MARC record for shelf-ready print. Cleaned PH %s" % date.today().isoformat()}]
		
		self.sub_deletions = [{'tag' : '245', 'sub' : 'h'}, {'tag' : '490', 'sub' : 'x'}]
		
		self.format = "print"
			
	def process_record(self, record):
			
		"""
		Function for processing each record. This should be moved to the concrete classes only (later).
		"""
		
		# Important or printing using as_marc() otherwise you getting an encoding error 
		
		record.force_utf8 = 1
		
		#title = record['245']['a'].strip(' \r\n\t\/\:')
		
		if self.format == "print": self.deletions.append('856')
		
		# Print the leader for comparison *before* we amend it.
		
		#print self.bcolors.HEADER + "%s" % title + self.bcolors.ENDC
		
		print self.bcolors.HEADER + "%s" % record.leader + self.bcolors.ENDC
		
		# Amend the leaders for additions
		
		record.leader = string.replace(record.leader, 'nam', 'nad')
		record.leader = string.replace(record.leader, 'cam', 'nad')
		
		self.log(record, 'LDR', "Replaced cam/nam with nad in the Leader")
		
		# Print out the record before we start to amend it using the yellow WARNING colour:
		
		for field in record.get_fields():
				if not field == None: print self.bcolors.WARNING + "%s" % field + self.bcolors.ENDC
		
		# Tidy the call number in 082 to remove any separateor characters ' /
		
		record = self.clean_call_number(record)

		# Fix any editions entries and turn into an ordinal (e.g. 2nd) if necessary.
		
		record = self.fix_editions(record)
		
		# Remove any non-LCSH subject headings based on the value in the second sub-field indicator.
		
		for i in ['1','2','3','4','5','6','7']:
				record = self.nuke_field_based_on_indicator(record, '650', 2, i)
				
		# Remove copyright statement in 264 where the second indicator is a 4
				
		record = self.nuke_field_based_on_indicator(record, '264', 2, '4')
		
		# Add any additional fields as defined in our hash set in the __init__ function
		
		for i in self.additions:
			record = self.add_simple_field(record, i['tag'], i['value'])
		
		# Delete those sub-fields defined in our sub_deletions array. See __init__
		
		for i in self.sub_deletions:
			record = self.delete_subfield(record,  i['tag'], i['sub'])
		
		# Delete those whole fields defined in our deletions array. See __init__
		
		for deli in self.deletions:
				record = self.delete_field_by_tag(record, deli)
		
		# If we have an eBook set, process the 856s
		
		if self.format == 'ebooks':
			record = self.set_link_text(record)
			record = self.add_ezproxy(record)
		
		# Move any 440s into 490s
		
		record = self.switch_tag(record, '440', '490')
	
		print " "
		
		# Print out the processed record in white
		
		print self.bcolors.HEADER + "%s" % record.leader + self.bcolors.ENDC
		for field in record.get_fields():
				if not field == None: print "%s" % field
				
		print " "
		
		# Print out the log
		
		print self.bcolors.OKGREEN + self.logger.get_log(record.leader) + self.bcolors.ENDC
		
		print " "
		
		# Priint out the raw MARC
		
		print self.bcolors.OKBLUE + record.as_marc() + self.bcolors.ENDC
	
		return record
	
	def switch_tag(self, record, old, new):
	
		try:
			fields = record.get_fields(old)
		
		except:
			return record
		
		for field in fields:
			field.tag = new
		
		if(len(fields) > 0): self.log(record, old, "Switched contents of %s to %s." % (old, new))
		
		return record
	
	def add_ezproxy(self, record):
	
		"""
		Add the EZProxy prefix to the URL in 856 $u
		"""
		try:
			fields = record.get_fields('856')
		
			url = record['856']['u']
		
		except:
			return record
		
		record = self.delete_subfield(record, '856', 'u')
		
		for field in fields:
			field.subfields.append('u')
			field.subfields.append("http://ezproxy.lib.le.ac.uk/login?url=%s" % url)
			
		self.log(record, '856', "Prefixed URL with EZPRoxy.")
	
		return record
	
	def set_link_text(self, record):
	
		"""
		Add proper link text for hyperlink into 856 $z
		"""
	
		record = self.delete_subfield(record, '856', 'z')
	
		fields = record.get_fields('856')
		
		title = record['245']['a'].strip(' \r\n\t\/\:')
		
		for field in fields:
			# Override 
			field.indicators = ['4','0']
			field.subfields.append('z')
			field.subfields.append("Access the eBook \"%s\"" % title)
		
		self.log(record, '856', "Set the link text in 856 $z: Access the eBook \"%s\"" % title)
		
		return record
	
	def add_simple_field(self, record, tagl, value):
	
		"""
		Add a new field with just a $a subfield and no indicators
		"""
		
		self.log(record, tagl, "Added new field %s with value of: %s" % (tagl, value))
		
		subs = ['a', value]
		
		record.add_field(Field(
		tag = tagl,
		indicators = [' ', ' '],
		subfields = subs,
		))
		
		return record

	def delete_subfield(self, record, tagl, del_sub):
	
		"""
		Turn the array into a hash so we can nuke by key. Better (dust) better. Yeah.
		"""
		
		self.log(record, tagl, "Attempting to remove %s subfields from %s" % (del_sub, tagl))
		
		final = []
	
		for field in record.get_fields(tagl):
			hash = self.subfields_to_dict(field.subfields)
			
			for key in sorted(hash.keys()):
				if not key == del_sub:
					final.append(key)
					final.append(hash[key])
		
			#dicators = field.indicators
		
			#record.remove_field(field)
		
			"""record.add_field(Field(
				tag = tagl,
				indicators = dicators,
				subfields = final,
				))"""
				
			field.subfields = final
		
		return record
	
	def subfields_to_dict(self, l):
	
		return dict(zip(l[::2], l[1::2]))
	
	def delete_field_by_tag(self, record, tag):
			
		"""
		Pass the record and a tag and delete to field from the record
		"""
		try:
			fields = record.get_fields(tag)
				
		except:
			self.log(record, tag, "Tried deleting field(s) %s. None found." % tag)
			return record
		
		for field in fields:
			self.log(record, tag, "Deleted field(s) %s: %s" % (tag, field))
			record.remove_field(field)

		return record

	def clean_call_number(self, record):

		"""
		Strip separators such as ' and / from the call number in the 082 field
		"""

		try:
			field = record['082']

		except:
			return record

		try:
			subs = field.subfields
		except:
			return record

		#print "%s" % subs

		for strip in ["'","/"]:
			if strip in subs[1]:
				self.log(record, '082', "Found and stripped %s in 082" % strip)
				subs[1] = string.replace(subs[1], strip, "")

		return record

	def get_ordinal(self, value):
			
		try:
			value = int(value)
		except ValueError:
			return value

		if value % 100//10 != 1:
			if value % 10 == 1:
				ordval = u"%d%s" % (value, "st")
			elif value % 10 == 2:
				ordval = u"%d%s" % (value, "nd")
			elif value % 10 == 3:
				ordval = u"%d%s" % (value, "rd")
			else:
				ordval = u"%d%s" % (value, "th")
		else:
			ordval = u"%d%s" % (value, "th")

		return ordval
	
	def fix_editions(self, record):
			
		if not record['250']:
			self.log(record, '250', "Attempting to fix 250 but no 250 found.")
			return record
		
		pipe_a = record['250']['a']
		
		subs = record['250'].subfields
		
		self.log(record, '250', "Attempting to fix 250 value to ordinal: %s" % pipe_a)						
		
		subs[1] = string.replace(subs[1], pipe_a, self.get_ordinal(pipe_a))
		
		return record
	
	def print_fields_by_tag(self, record, tag):

		for fields in record.get_fields(tag):
			print self.bcolors.WARNING + "%s" % fields + self.bcolors.ENDC
				
	def nuke_field_based_on_indicator(self, record, tag, indicator, value):
			
		"""
		Given an indicator (1st or 2nd), nuke the field if it has the value in that position.
		
		i.e. 650 with a second indicator of 7 (MESH heading)
		"""
		
		tag_list = record.get_fields(tag)
		
		final_list = []
		
		for field in tag_list:
				
			ouch = 0
			
			indicators = field.indicators
			
			if indicator == 2:
				try:
					val = indicators[1]
				except:
					ouch = 1
					
			if indicator == 1:
				try:
					val = indicators[0]
				except:
					ouch = 1
			
			if ouch == 0:
				if str(val) != str(value):
					final_list.append(field)
				else:
					message = "Removed field %s as %s was present in indicator %s - %s" % (tag, value, indicator, field)
					self.log(record, tag, message)
							
			else: 
				message = "Removed field %s as %s was present in indicator %s - %S" % (tag, value, indicator, field)
				self.log(record, tag, message)
				
				final_list.append(field)
	
			record.remove_field(field)
								
		for field in final_list:
			record.add_field(field)
				
		return record
	
	def log(self, record, field, message):
			
		"""
		Function which hands off to logger delegate object
		"""
		self.logger.log(record.leader, field, message)
	
	def parse_run(self):
		counter = 0
		
		if len(sys.argv) > 2:
		
			if (sys.argv[2] == "--colour") or (sys.argv[2] == "--color") or (sys.argv[2] == "-c"):
				self.bcolors = bcolors()
				
			if (sys.argv[2] == "--print") or (sys.argv[2] == "-p"):
				self.format = "print"
				
			if (sys.argv[2] == "--ebooks") or (sys.argv[2] == "-e"):
				self.format = "ebooks"
		
		if len(sys.argv) > 3:
		
			if (sys.argv[3] == "--colour") or (sys.argv[2] == "--color") or (sys.argv[3] == "-c"):
				self.bcolors = bcolors()
				
			if (sys.argv[3] == "--print") or (sys.argv[2] == "-p"):
				self.format = "print"
				
			if (sys.argv[3] == "--ebooks") or (sys.argv[3] == "-e"):
				self.format = "ebooks"
		
		if len(sys.argv) < 2:
			print "Usage: python marc-parser.py  [-c for colour] [-p for print records] [-e for eBooks]"
			sys.exit
		else:
		
			try:
				with open(sys.argv[1], 'rb') as fh:
					reader = MARCReader(fh)
					outfile = string.replace(sys.argv[1], '.mrc', ".final.%s.CLI.marc" % self.format)
					
					if(os.path.isfile(outfile)):
						os.remove(outfile)
					
					out = open(outfile, 'wb')
			
					for record in reader:		
						counter = counter + 1
						print " "
						print self.bcolors.FAIL + "%s" % counter
						record = self.process_record(record)
						out.write(record.as_marc())
					
					out.close
					print  "Wrote file:" + self.bcolors.FAIL + " %s" % outfile + self.bcolors.ENDC
					
			except IOError as e:
				print self.bcolors.FAIL + "Unable to open file %s!" % sys.argv[1] + self.bcolors.ENDC

if __name__ == "__main__":
    
    parser  = MARCParser()
    
    parser.parse_run()

Tags: Python

Posted by Paul Hollands pj at 08:52 PM | Comments (0)

March 31, 2015

Some sample OS Ticket SQL

UPDATE ost_ticket 
SET status = 'open' 
WHERE staff_id = 1 
AND status = 'closed' 
AND ticket_id 
IN (SELECT DISTINCT ticket_id FROM ost_ticket_event WHERE staff = 'libper' AND state = 'closed' )

Tags: MySQL

Posted by Paul Hollands pj at 04:17 PM | Comments (0)

October 30, 2013

TAL on-error attribute

<dl class="definition_design clearfix">
<dt tal:condition="reg_reply">Reg. Status</dt>
<dd tal:condition="reg_reply" 
 tal:on-error="string:No status"   
 tal:content="reg_reply/status"></dd>		
</dl>

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 11:49 AM | Comments (0)

October 17, 2013

Tuning The Linux VM (memory) Subsystem

Linux Tuning The VM (memory) Subsystem

 

Posted by Paul Hollands pj at 02:20 PM | Comments (0)

March 08, 2013

Update one table from another

-- UG only
update dss_chapuza.proposal set proposal_title = tc.new_title from 
dss_marking.ug_title_change_feeder tc where tc.proposal_id = proposal.proposal_id

Tags: PostgreSQL

Posted by Paul Hollands pj at 01:06 PM | Comments (0)

March 07, 2013

Get BST dates in PostgreSQL

select 
date_trunc('month', (extract('year' from now()::timestamp)::text||'-03-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval + (((1 - 7 - to_char(date_trunc('month', (extract('year' from now()::timestamp)::text||'-03-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval,'D')::int) %7)||' days')::interval 
as last_sunday_march, 
date_trunc('month', (extract('year' from now()::timestamp)::text||'-10-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval + (((1 - 7 - to_char(date_trunc('month', (extract('year' from now()::timestamp)::text||'-10-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval,'D')::int) %7)||' days')::interval 
as last_sunday_october

Tags: PostgreSQL

Posted by Paul Hollands pj at 03:52 PM | Comments (0)

February 21, 2013

yum update with multilib errors

yum update --exclude \*.i686 --skip-broken

 

Posted by Paul Hollands pj at 12:50 PM | Comments (0)

February 08, 2013

Sort case where name includes more than one word

update scratch.student set forename=initcap(lower(forename))

Tags: PostgreSQL

Posted by Paul Hollands pj at 01:49 PM | Comments (0)

January 11, 2013

TopAlternatives

Tools for Time Management | TopAlternatives.com

 

Posted by Paul Hollands pj at 04:40 PM | Comments (0)

January 07, 2013

Postgres Array Functions

PostgreSQL: Documentation: 8.4: Array Functions and Operators

Tags: PostgreSQL

Posted by Paul Hollands pj at 12:28 PM | Comments (0)

December 24, 2012

CSS3 Tips

A List Apart: Articles: Learning to Love the Boring Bits of CSS

 

Posted by Paul Hollands pj at 11:15 AM | Comments (0)

December 17, 2012

Switch between ChromeOS and Chrubuntu

Right now, you're in ChrUbuntu but if you reboot, you'll be back in Chrome OS. To make ChrUbuntu the default, run:

sudo cgpt add -i 6 -P 5 -S 1 /dev/sda

(password is "user"). It should be possible to run this from ChrUbuntu or Chrome OS.
To make Chrome OS the default again, either turn off Developer Mode, or run:

sudo cgpt add -i 6 -P 0 -S 1 /dev/sda

Tags: ChromeOS

Posted by Paul Hollands pj at 06:55 PM | Comments (0)

December 13, 2012

Select options for this and next year

$yopts = just::options("

(select 

to_char(to_timestamp( now()::abstime::int4), 'YYYY')::integer as labello, 

'year_'||to_char(to_timestamp( now()::abstime::int4), 'YYYY')::integer::text as year)

union

(select (to_char(to_timestamp( now()::abstime::int4), 'YYYY')::integer) + 1 as labello,

'year_'||((to_char(to_timestamp( now()::abstime::int4), 'YYYY')::integer) + 1)::text as year)
"
, 'year', 'labello');

Tags: PostgreSQL

Posted by Paul Hollands pj at 12:49 PM | Comments (0)

December 09, 2012

Service Design vs Project Management

ITIL Service Design and Project Management – a contrast in execution - Program Delivery Effectiveness Group

 

Posted by Paul Hollands pj at 12:04 PM | Comments (0)

November 25, 2012

Learning Scrum

Today I have been mostly learning scrum in 10 minutes and looking at the OnTime project management tool.

Yesterday I finished and uploaded all my ILM work,

Tags: Mostly , Scrum

Posted by Paul Hollands pj at 12:34 PM | Comments (0)

Scrum in 10 minutes

What is the Agile Methodology? - Learn Agile Scrum in Under 10 Minutes - Agile Scrum Diagram

Tags: Scrum

Posted by Paul Hollands pj at 12:31 PM | Comments (0)

November 21, 2012

Pomodoro and Content Audit

Today I have been mostly following the Pomodoro methodology and both polishing off the new Research Group web page model and documenting my new Content Audit application.

Tags: Content Audit , Mostly

Posted by Paul Hollands pj at 07:43 PM

September 10, 2012

Casting and formatting dates in PostgreSQL

select to_char(to_timestamp(now()::abstime::int4), 'Day DD Month YYYY HH24:MI:SS') as "The Day Today"

Tags: PostgreSQL

Posted by Paul Hollands pj at 09:04 PM | Comments (0)

August 01, 2012

SVN update without a particular directory

$ rm -rf unwanted-directory
$ svn checkout url/to/repo/unwanted-directory unwanted-directory --depth empty
$ cd root/of/my/tree
$ svn update

Tags: Subversion

Posted by Paul Hollands pj at 08:10 AM | Comments (0)

July 27, 2012

Appending to an array column in PostgreSQL

update dss_change_request.change_request set approved_notes = approved_notes||ARRAY['Blah blah blah'] where change_request_id = 13

Tags: PostgreSQL

Posted by Paul Hollands pj at 03:05 PM | Comments (0)

June 08, 2012

Android IDE

Terminal IDE - Android Apps on Google Play

Terminal IDE

 

Posted by Paul Hollands pj at 09:08 PM | Comments (0)

April 10, 2012

Read a file from a Jython servlet

Using Jython servlets with WebSphere Application Server for more than system administration

 

Posted by Paul Hollands pj at 07:59 AM | Comments (0)

April 09, 2012

Getting Jython Django to talk to Postgres

Add the PostgreSQL jar into your CLASSPATH:

export CLASSPATH=$CLASSPATH:/opt/apache-tomcat-7.0.26/webapps/slides/WEB-INF/lib/postgresql-8.4-702.jdbc3.jar

Edit the settings.py file of your application:

#DATABASES = {
#    'default': {
#        'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.                                   
#        'NAME': '',                      # Or path to database file if using sqlite3.   
#        'USER': '',                      # Not used with sqlite3.   
#        'PASSWORD': '',                  # Not used with sqlite3.      
#        'HOST': '',                      # Set to empty string for localhost. Not used with sqlite3.
#        'PORT': '',                      # Set to empty string for default. Not used with sqlite3.
#    }
#}

DATABASE_ENGINE = 'doj.backends.zxjdbc.postgresql'
DATABASE_NAME = 'yourdb'
DATABASE_USER = 'youruser'
DATABASE_PASSWORD = 'yourpasswd'

 

Posted by Paul Hollands pj at 05:10 PM | Comments (0)

JSP Include

The JSP Include directive tutorial

 

Posted by Paul Hollands pj at 01:57 PM | Comments (0)

April 04, 2012

Using ZPT with Django

Zope.org - Django Page Templates

Tags: ZPT

Posted by Paul Hollands pj at 10:57 PM | Comments (0)

March 16, 2012

Fixing the scrollbar issue in GoogleMaps InfoWindow

<script type="text/javascript">
var contentString = '<div style="max-width: 200px; overflow: hidden; display: none;" id="noscroll"><h4>The Business School</h4>29 Buccleuch Place, EH8 9JS</div>';

jQuery(document).ready(function(){

    var latlong = new google.maps.LatLng(55.942802, -3.186896);


    var opts = { 
      zoom: 15, 
      center: new google.maps.LatLng(55.945000, -3.186896),
      mapTypeControl: false,
      disableDefaultUI: false,
      mapTypeId: google.maps.MapTypeId.ROADMAP, 
      scaleControl: true };

    var map = new google.maps.Map(document.getElementById("map"), opts);

    var infowindow = new google.maps.InfoWindow({ content: contentString, maxWidth: 100 });

    var marker = new google.maps.Marker({ position: new google.maps.LatLng(55.942802, -3.186896), map: map, title: "Business School" });


    infowindow.open(map, marker);

    });
</script>

The function call infowindow.open(map, marker) sets up your bubble content in two nested DIVs with overflow: auto styling set. This needs to be undone once the bubble is created. Hence the 2 second wait.

<script type="text/javascript">

var ns;

var flag = 0;

function fix_it(lag){

    setTimeout(function(){

        try{ 

            ns = document.getElementById('noscroll'); 

            var pops = ns.parentNode;

            var gramps = pops.parentNode;

            gramps.style.overflow = 'hidden';

            pops.style.overflow = 'hidden';

            ns.style.overflow = 'hidden';

            ns.style.display = 'block';

            }

        catch(e){ if(flag == 0){ flag = 1;  fix_it(2000); } }

        }, lag);

    }


jQuery(document).ready(function(){

    fix_it(2000);

    });

</script>

Tags: GoogleMaps , JavaScript

Posted by Paul Hollands pj at 10:42 PM | Comments (0)

March 14, 2012

HTML Tag Support Detection

HTML5 Day 3: Detecting HTML5 Support via JavaScript

 

Posted by Paul Hollands pj at 07:36 PM | Comments (0)

March 13, 2012

HTML5 and CSS3

HTML 5 and CSS 3: The Techniques You’ll Soon Be Using | Nettuts

 

Posted by Paul Hollands pj at 09:53 AM | Comments (0)

March 09, 2012

Tree Surgeons

Capital Tree Services Scotland - Edinburgh Based Tree Surgeons & Consultants Call: 0131 478 1641 or 07928 404 334

 

Posted by Paul Hollands pj at 09:48 AM | Comments (0)

March 05, 2012

OS X on VirtualBox

How to Run Mac OS X in VirtualBox on Windows

 

Posted by Paul Hollands pj at 07:43 PM | Comments (0)

February 28, 2012

Jython servlet and JSP for AJAX slide presentations

Servlet Code:

from javax.servlet.http import HttpServlet

from java.util import ArrayList

from java.util import HashMap

import re

import string

from just import just

class presentationXML(HttpServlet):

    def doGet(self,request,response):

        self.doPost (request,response)

    def doPost(self,request,response):

        response.setContentType ("text/plain")
        
        presentation_id = request.getParameter('presentation_id')
        
        presentation = self.get_presentation(presentation_id)
        
        prezs = presentation.get('rows')
        
        top_slide = prezs.get(0)
        
        request.setAttribute("top_title", top_slide['title'])
        
        request.setAttribute("top_author", top_slide['author'])
        
        request.setAttribute("top_desc", top_slide['description'])

        slides = self.get_slides(presentation_id)
        
        rows = slides.get('rows')
        
        columns = slides.get('columns')
        
        request.setAttribute("columns", columns)
        
        request.setAttribute("rows", rows)
        
        disp = request.getRequestDispatcher('presentation.xml.jsp')
        
        disp.forward(request, response)
        
    def build_slide(self, slide):
        
        title = slide['title']
        
        body = slide['body']

        slide_list = ""   

        for i in body.split("\n"):
            
            (tag, line) = i.split(':')
            
            slide_list = slide_list + "\n<" + tag + '><span class="red">»</span> ' + line + "</" + tag + ">"
        
        return {'title' : title, 'slide_list' : slide_list, 'example_url' : slide['example_url'] }

    def get_slides(self, pres_id):

        juice = just()    
        
        reply = juice.sql("select * from slides.slide where presentation_id = " + str(pres_id) + " order by sort_order asc")

        slides = []

        for row in reply['rows']:
            
            slide = self.build_slide(row)

            slides.append(slide)

        return( self.jhash(slides, ['title', 'slide_list', 'example_url' ]) )
        
    def get_presentation(self, pres_id):

        juice = just()    
        
        reply = juice.sql("select * from slides.presentation where presentation_id = " + str(pres_id) + "limit 1")

        return( self.jhash(reply['rows'], reply['columns']) )
        
    def jhash(self, rows, columns):
        
        results = HashMap()   
        
        jrows = ArrayList()
        
        jcols = ArrayList()
        
        for row in rows:
            
            res = HashMap()   
            
            for col in columns:
                
                jcols.add(col)   
                
                res.put(col, row[col])
                
            jrows.add(res)
        
        results.put('columns', jcols)
        
        results.put('rows', jrows)
            
        return results

JSP:

<?xml version="1.0" encoding="UTF-8"?>
<%@ page contentType="text/xml" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<?xml-stylesheet type="text/xsl" href="xslt/ajax-s-html.xml"?>
<ajax-s>
<pages>

<page>
<br/>
<br/>
<h2>${top_title}</h2>
    <h3>${top_desc}</h3>
    <h4><span class="red">&#187;</span> ${top_author}</h4>
</page>

<c:forEach items="${rows}" var="row">
 <page>
    <h2>${row['title']}</h2>
    <dl>
    <c:out value="${row['slide_list']}" escapeXml="false"/>
    </dl>
    <c:if test="${row['example_url'] != ''}">
    <p style="text-align: right"><a target="__newwin" href="${row['example_url']}">e.g. <span class="red">&#187;</span></a></p>
    </c:if>
  </page>
</c:forEach>
</pages>
</ajax-s>

DB Query Bean

import re

import string

import com.ziclix.python.sql as sql

class just:
        
    def sql(self, skewl):
        
        description, results = self.query(skewl)

        cols = []
        
        final = {}
        
        final['rows'] = []
        
        final['columns'] = []
        
        for i in description:
            
            cols.append(i[0])
        
        for i in results:
        
            row = list(i)
            
            r = {}  
            
            count = 0            
            
            for c in row:
                
                r[cols[count]] = c
                
                count = count + 1
            
            final['rows'].append(r)
        
        final['columns'] = cols
        
        return final
        
    def query(self, q):
        
        dburl, user, pw, drv = ("jdbc:postgresql://localhost:5432/roo","*****","*****","org.postgresql.Driver")
        
        db = sql.zxJDBC.connect(dburl, user, pw, drv)
        
        cursor = db.cursor()
        
        cursor.datahandler = sql.handler.PostgresqlDataHandler(cursor.datahandler)
        
        cursor.execute(q)

        columns = cursor.description

        results = cursor.fetchall()
        
        return (columns, results)

Tags: Jython

Posted by Paul Hollands pj at 03:05 PM | Comments (0)

LOM OAI-PMH Harvester in Python

import oaipmh

import os

import re

import sys

import string

import time

import httplib

import urllib

import libxml2

from read_config import read_config

import do_sql

#from read_file import read_file

from MySQLdb.cursors import DictCursor

#from split import split
from string import split

import ConfigParser

import lom_handlers

import normalize_harvest

debug = 1

harvest = {}

repository_definitions_map = read_config('repository_definitions.ini', debug)

time.sleep(5)

# Namespaces to be stripped out from the about section and replaced with a single default one
# ie. oaiabout:

namespace_list = ['rdn_dc','dcterms','dc','meg','rdnterms']

identifier_list = []

harvest_type = ''

try:

	repository_handle =  sys.argv[1]

except:

        MissingArgumentError = "\nUsage:\n\npython %s  \n" % sys.argv[0]

        raise MissingArgumentError

try:

        harvest_type = sys.argv[2]

except:

        MissingArgumentError = "\nUsage:\n\npython %s  \n" % sys.argv[0]

        raise MissingArgumentError

def get_last_harvest_date(repository_handle):

	sql = "select max(date_format(harvest_date,'%Y-%m-%dT%H:%i:%sZ')) as last_harvest_date from harvests where harvest_type = 'daily' and repository_handle = '" + repository_handle + "'"

	response = do_sql.do_sql_query('ltsn01_harvester',sql,debug)

	do_sql.check_status(response, debug)

	results = response['results']

	return results[0]['last_harvest_date']

def get_xpath_map():

	sql = 'select * from xpath_map'

	response = do_sql.do_sql_query('ltsn01_harvester',sql,debug)
        
	do_sql.check_status(response, debug)

	results = response['results']

	return results

def do_xpath_query(xml, xpath, label, identifier):

	# We need to strip out namespaces from the about section
	# for our xpath to work, as we will be adding ones back in

	for ns in namespace_list:

		xml = string.replace(xml, ns + ':','')

		label = string.replace(label, ns + ':','')
		
		xpath = string.replace(xpath, ns + ':','oaiabout:')

	xpath = string.replace(xpath, '//about','//oaiabout:about')

	final_dict = {}

	parsed_doc = libxml2.parseDoc(xml)

	if string.find(xpath, 'oaiabout') == -1:

		#xpath_elements = split('/', xpath)
		xpath_elements = split(xpath,'/')

		xpath = ''

		del xpath_elements[0]

		del xpath_elements[0]

		nspace = '/lom:'

		for el in xpath_elements:

			xpath = xpath + nspace + el

		xpath = '/' + xpath

		xpath = string.replace(xpath, 'lom:@','@')

		xpath = string.replace(xpath, 'about:@','@')

	if debug == 1: 

		print xpath

	ctx = parsed_doc.xpathNewContext() 

	ctx.xpathRegisterNs("lom", "http://ltsc.ieee.org/xsd/LOMv1p0")

	ctx.xpathRegisterNs("oaiabout", "http://www.openarchives.org/OAI/2.0/")

	final_dict[label] = [node.content for node in ctx.xpathEval(xpath)] 

	parsed_doc.freeDoc()

	if debug == 1: 

		print final_dict

	return final_dict

def classification_parser(xml, debug):

	# Special parser for the horribly nested classification section.
	# In order to get the proper nesting we need three passes:
	# 1) Grab the classification nodes
	# 2) For each classification node parse the taxonPaths
	# 3) For each taxonPath parse out the taxons

	parsed_doc = libxml2.parseDoc(xml)

	ctx = parsed_doc.xpathNewContext()
                
	ctx.xpathRegisterNs("lom", "http://ltsc.ieee.org/xsd/LOMv1p0")

	ctx.xpathRegisterNs("xsi", "http://www.w3.org/2001/XMLSchema-instance")

	xpath="//lom:lom/lom:classification"

	class_list = [ node for node in ctx.xpathEval(xpath)]

	count = 0

	node_values = []

	for snode in class_list:

		if debug == 1: print snode.serialize()

		node_dict = {}

		new_doc = libxml2.parseDoc(snode.serialize())

		ctx = new_doc.xpathNewContext()

		xpath="//classification/purpose/source"

		node_dict['classification_purpose_source'] = [ node.content for node in ctx.xpathEval(xpath)]

		xpath="//classification/purpose/value"

		node_dict['classification_purpose_value'] = [ node.content for node in ctx.xpathEval(xpath)]

		xpath="//classification/taxonPath"

		# Serialize the node back into XML for parse once again :)

		xml_path_list = [ node.serialize() for node in ctx.xpathEval(xpath)]

		node_dict['classification_taxonPaths'] = []

		for xml_path in xml_path_list:

			path = {}

			new_new_doc = libxml2.parseDoc(xml_path)

			ctx = new_new_doc.xpathNewContext()

			xpath="//taxonPath/source/string"

			path['source_string'] = [ node.content for node in ctx.xpathEval(xpath)]

			xpath="//taxonPath/taxon/id"

			path['taxon_id'] = [ node.content for node in ctx.xpathEval(xpath)]

			xpath="//taxonPath/taxon/entry/string"

			path['taxon_entry_string'] = [ node.content for node in ctx.xpathEval(xpath)]

			node_dict['classification_taxonPaths'].append(path)		

		node_values.append(node_dict)

		count = count + 1

	return node_values

if harvest_type == 'daily':

	harvest_from = get_last_harvest_date(repository_handle)

else:

	harvest_from = '2003-01-01T00:00:00Z'

lom_handlers.clear_tables(debug)

print "\n##Going to harvest the %s repository##\n" % repository_handle

try:

	repository_definition = repository_definitions_map[repository_handle]

except:

	BadHandleExceptionMessage = "Sorry there's no such repository definition as " + repository_handle + " in repository_definitions.ini:\n" + str(repository_defs.keys())

	raise BadHandleExceptionMessage


repository_domain = repository_definition['repository_domain']

uri_path = repository_definition['uri_path']

repository_uri = "http://%s%s" % (repository_domain,uri_path)

sesh = oaipmh.ServerProxy(repository_uri)

server_id = sesh.identify()

print server_id.repositoryName()

print server_id.adminEmails()

metadata_formats = sesh.listMetadataFormats()

if debug == 1:

	for format in metadata_formats:

		print format

all_identifiers = sesh.listIdentifiers(metadataPrefix='oai_dc', from_='2003-01-01T00:00:00Z')

all_ids_list = []

for header in all_identifiers:

	this_id = header.identifier()

        all_ids_list.append(this_id)

identifiers = sesh.listIdentifiers(metadataPrefix='oai_dc', from_=harvest_from)

xpath_map = get_xpath_map()

print xpath_map

sys.exit

xpath_query_list = {}

for map in xpath_map:

	xpath_query_list[map['xpath_query']] = 1

for header in identifiers:

	this_record = {}

	print "\n\n"

	this_id = header.identifier()

	identifier_list.append(this_id)

	print "\n %s" % this_id

	time.sleep(2)

	#sesh = httplib.HTTPConnection(repository_domain)

	#sesh.connect()

	#sesh.request('GET',uri_path + '?verb=GetRecord&metadataPrefix=lom&identifier=' + this_id)

	#response = sesh.getresponse()

	response = urllib.urlopen(repository_uri + '?verb=GetRecord&metadataPrefix=lom&identifier=' + this_id)

	xml = response.read()	

	# Fix for Nik's dodgy classification section

	xml = string.replace(xml, 'taxonpath', 'taxonPath')

	neat_xml = lom_handlers.mysql_tidy(xml)

	reply = do_xpath_query(xml, '//lom/general/title/string', 'main_title', this_id)

	main_title = lom_handlers.mysql_tidy(reply['main_title'][0])

	sql = "insert into xml_store(oai_identifier,xml_document,record_main_title) values('%s','%s','%s')" % (this_id,neat_xml,main_title)

	if debug == 1: print sql

	response = do_sql.do_sql('ltsn01_harvester',sql,debug)
        
	do_sql.check_status(response, debug)

	for query in xpath_query_list.keys():

		label = query

		label = string.replace(label,'//','')

		label = string.replace(label,'oaiabout:','')

		label = string.replace(label,'/','_')

		label = string.replace(label,'@','_')

		reply = do_xpath_query(xml, query, label, this_id)

		for ns in namespace_list:

			label = string.replace(label, ns + ':','')

		this_record[label] = reply[label]

	if debug == 1: 

		print "\nThis record:\n", this_record

		time.sleep(5)

	lom_resource_id = lom_handlers.add_main_title(this_id, debug, this_record)

	lom_handlers.add_title_added_entries(lom_resource_id, debug, this_record)

	lom_handlers.add_keywords(lom_resource_id, debug, this_record)

	lom_handlers.add_ISBNs(lom_resource_id, debug, this_record)

	lom_handlers.store_poi(lom_resource_id, debug, this_record)

	lom_handlers.lom_extra_languages(lom_resource_id, debug, this_record)

	lom_handlers.add_general_value(lom_resource_id, debug, 'lom_general_description_string', 'general_description', this_record)

	lom_handlers.add_general_value(lom_resource_id, debug, 'lom_general_coverage_string', 'general_coverage', this_record)

	lom_handlers.add_general_value(lom_resource_id, debug, 'lom_technical_otherPlatformRequirements_string', 'technical_otherPlatformRequirements', this_record)

	lom_handlers.add_authors(lom_resource_id, debug, this_record)

	lom_handlers.add_about(lom_resource_id, debug, this_record)

	lom_handlers.add_publishers(lom_resource_id, debug, this_record)

	lom_handlers.add_locations(lom_resource_id, debug, this_record)

	lom_handlers.add_formats(lom_resource_id, debug, this_record)

	lom_handlers.add_lr_types(lom_resource_id, debug, this_record)

	lom_handlers.add_educational_contexts(lom_resource_id, debug, this_record)

	lom_handlers.add_general_value(lom_resource_id, debug, 'lom_educational_description_string', 'educational_description', this_record)

	lom_handlers.add_general_value(lom_resource_id, debug, 'lom_rights_description_string', 'rights_description', this_record)

	if this_record['lom_rights_copyrightAndOtherRestrictions_value']:

		if this_record['lom_rights_copyrightAndOtherRestrictions_value'][0] == 'Yes' or this_record['lom_rights_copyrightAndOtherRestrictions_value'][0] == 'yes':

			lom_handlers.add_set_value(lom_resource_id, debug, 1, 'rights_restricted')

	lom_handlers.add_relations(lom_resource_id, debug, this_record)

	class_list = []

	class_list = classification_parser(xml, debug)

	this_record['lom_classification'] = class_list

	harvest[this_id] = this_record

	if debug == 1: 

		print class_list

		time.sleep(3)

	lom_handlers.add_classification(lom_resource_id, debug, class_list)

# Put the entry in the harvests logging table

harvest_identifiers = string.join(identifier_list, '::')

all_ids = string.join(all_ids_list, '::')

if harvest_type == 'daily':

	pass

else: harvest_type = 'complete'

sql = "insert into harvests(harvest_identifiers, all_identifiers, harvest_dictionary, harvest_type, repository_handle) values('" + harvest_identifiers + "','" + all_ids + "','" + lom_handlers.mysql_tidy(str(harvest)) + "','" + harvest_type + "','" + repository_handle  + "')"

response = do_sql.do_sql('ltsn01_harvester',sql,debug)

do_sql.check_status(response, debug)

normalize_harvest.normalize_data(debug)

normalize_harvest.handle_deletions(repository_handle, debug)

 

Posted by Paul Hollands pj at 02:54 PM | Comments (0)

Example OOP PHP Code

<?php

abstract class pid_entity{
    
    function details(){
        
        global $r;
        
        $r['dbname'] = 'uebs';
        
        $r['schema'] = 'pid';
    
        if(!$this->id){ return false; }
        
        if(!$this->table){ return false; }
    
        $reply = just::sql(sprintf('select * from %s.%s where %s_id = %d',$r['schema'] , $this->table, $this->table, $this->id));
        
        $this->details = $reply['first_row'];
        
        $this->row = $this->details;
        
        }
        
    function create(){
        
        if(!$this->table){ return false; }
        
        global $r;
        
        $r['dbname'] = 'uebs';
        
        $r['schema'] = 'pid';

        $this->id = just::add($this->table);
        
        }
    
    function set(){
        
        if(!$this->table){ return false; }
        
        global $r;
        
        $r['dbname'] = 'uebs';
        
        $r['schema'] = 'pid';
        
        if(!$this->id){ $this->create(); }
        
        $reply = just::update($this->table, $r, $this->id);
        
        $_SESSION['pid_set'] = $reply;
        
        $this->details();
        
        $this->row = $this->details;
        
        return $reply['status'];
        
        }
        
    function annotate(){
    
        global $r;
        
        $r['dbname'] = 'uebs';
        
        $r['schema'] = 'pid';
    
        $id = just::add('note');
        
        $r[$this->table.'_id'] = $this->id;
        
        $reply = just::update('note', $r, $id);
        
        return $reply['status'];
        
        }
        
    function get_notes(){
        
        global $r;
        
        $r['dbname'] = 'uebs';
        
        $r['schema'] = 'pid';
        
        $reply = just::sql(sprintf('select notes, to_timestamp(insert_date) as ts, insert_date from %s.note where expired_date is null and %s_id = %d order by insert_date desc', $r['schema'],  $this->table, $this->id ));
        
        return $reply['rows'];
        
        }
    
    }

interface pid_entity_if{

    function details();
    
    function create();
    
    function set();
    
    function add_child($object);
    
    function get_children();
    
    function calculate_start();
    
    function calculate_end();
    
    function annotate();
    
    function get_notes();
    
    }

class project extends pid_entity implements pid_entity_if{

    public $id;

    public $title;
    
    public $percent_complete;
    
    public $start_date;
    
    public $end_date;
    
    public $children;
    
    public $table = 'project';
    
    function __construct($key){
        
        if($key > 0){
            
            $this->id = $key; 
        
            $this->details();
            
            }
        
        }
    
    function add_child($object){}
        
    function get_children(){}
    
    function calculate_start(){}
    
    function calculate_end(){}
    
    }

class phase extends project{
    
    public $id;

    public $title;
    
    public $percent_complete;
    
    public $start_date;
    
    public $end_date;
    
    public $children;
    
    public $table = 'phase';
    
    function __construct($phase_id){
        
        parent::__construct($phase_id); 
        
        }
    
    }


class work_package extends project{
    
    public $id;

    public $title;
    
    public $percent_complete;
    
    public $start_date;
    
    public $end_date;
    
    public $children;
    
    public $table = 'work_package';
    
    function __construct($wp_id){
        
        parent::__construct($wp_id); 
        
        }
    
    }


class deliverable extends project{
    
    public $id;

    public $title;
    
    public $percent_complete;
    
    public $start_date;
    
    public $end_date;
    
    public $children;
    
    public $table = 'deliverable';
    
    function __construct($del_id){
        
        parent::__construct($del_id); 
        
        }
    
    }

/* End of /waf/classes/project_initiation.php */

DB Model:




    drop table if exists pid.project;
    create table pid.project
    (
    project_id serial unique not null, 
    project_type_id integer null,    
	name text null,
	purpose text null,
	background text null,
	assumptions text null,
	constraints text null,
	risks text null,
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (project_id)
    );



alter table pid.project drop project_type_id;




    drop table if exists pid.phase;
    create table pid.phase
    (
    phase_id serial unique not null, 
    phase_type_id integer null,    
	project_id integer null,
	phase_sort decimal null,
	name text null,
	description text null,
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (phase_id)
    );



alter table pid.phase drop phase_type_id;




    drop table if exists pid.work_package;
    create table pid.work_package
    (
    work_package_id serial unique not null, 
    work_package_type_id integer null,    
	phase_id integer null,
	dependent_on_package_id integer null,
	name text null,
	package_sort decimal null,
	description text null,
	start_date bigint null,
	length_days decimal null,
	completion_date bigint null,
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (work_package_id)
    );



alter table pid.work_package drop work_package_type_id;




    drop table if exists pid.staff;
    create table pid.staff
    (
    staff_id serial unique not null, 
    staff_type_id integer null,    
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (staff_id)
    );



alter table pid.staff drop staff_type_id;




    drop table if exists pid.note;
    create table pid.note
    (
    note_id serial unique not null, 
    note_type_id integer null,    
	project_id integer null,
	phase_id integer null,
	work_package_id integer null,
	notes text null,
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (note_id)
    );



alter table pid.note drop note_type_id;




    drop table if exists pid.deliverable;
    create table pid.deliverable
    (
    deliverable_id serial unique not null, 
    deliverable_type_id integer null,    
	work_package_id integer null,
	name text null,
	delivery_date bigint null,
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (deliverable_id)
    );



alter table pid.deliverable drop deliverable_type_id;




    drop table if exists pid.work_package_status;
    create table pid.work_package_status
    (
    work_package_status_id serial unique not null, 
    work_package_status_type_id integer null,    
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (work_package_status_id)
    );


        drop table if exists pid.work_package_status_type;
        create table pid.work_package_status_type
        (
        work_package_status_type_id serial unique not null,
        name text null,
        description text, 
        insert_by integer null,
        insert_date bigint null,
        update_by integer null,
        update_date bigint null,
        non_deletable boolean not null default true,
        expired_date bigint null,
        primary key (work_package_status_type_id) );


    drop table if exists pid.upload_file;
    create table pid.upload_file
    (
    upload_file_id serial unique not null, 
    upload_file_type_id integer null,    
	project_id integer null,
	phase_id integer null,
	work_package_id integer null,
	file_name text null,
	file_mime_type text null,
	file_length bigint null,
	file_data bytea null,
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key (upload_file_id)
    );



alter table pid.upload_file drop upload_file_type_id;




    drop table if exists pid.project_staff_link;   
    create table pid.project_staff_link
    (
    project_staff_link_id serial unique not null,
    project_id integer null,
    staff_id integer null,
    insert_by integer null,
    insert_date bigint null,
    update_by integer null,
    update_date bigint null,
    expired_date bigint null,
    primary key(project_staff_link_id) 
    );

Windows .ini file:


[schema]
default = pid

[table_list]
project = 0
phase = 0
work_package = 0
staff = 0
note = 0
deliverable = 0
work_package_status = 1
upload_file = 0

[upload_file]
project_id = integer
phase_id = integer
work_package_id = integer
file_name = text
file_mime_type = text
file_length = bigint
file_data = bytea

[work_package_status]
work_package_id

[note]
project_id = integer
phase_id = integer
work_package_id = integer
notes = text

[deliverable]
work_package_id = integer
name = text
delivery_date = bigint

[work_package]
phase_id = integer
dependent_on_package_id = integer
name = text
package_sort = decimal
name = text
description = text
start_date = bigint
length_days = decimal
completion_date = bigint

[project]
name = text
purpose = text
background = text
assumptions = text
constraints = text
risks = text

[phase]
project_id = integer
phase_sort = decimal
name = text
description = text

[staff]

[link_tables]
project:staff = 0
;programme:course = 0

Tags: PHP

Posted by Paul Hollands pj at 02:37 PM | Comments (0)

February 22, 2012

Request forwarding to JSP from Jython

Using JSP for HTML layout for a Jython Servlet

Tags: Jython

Posted by Paul Hollands pj at 04:35 PM | Comments (0)

December 20, 2011

rEFIt - Booting Linux with Bootcamp

rEFIt - An EFI Boot Menu and Toolkit

 

Posted by Paul Hollands pj at 01:10 PM | Comments (0)

December 07, 2011

Cast the results of a subquery as an array then join as a string

select p.*, 
array_to_string(array(select first_name||' '||last_name from publications.authors a where a.publication_id = p.id), ',') as aus ,
array_to_string(array(select first_name||' '||last_name from publications.editors e where e.publication_id = p.id), ',') as eds
from publications.publication_as_ris3 p
where p.av in ('Forthcoming','Published') and p.id in ((select publication_id from publications.authors where first_name = 'Tony' and last_name = 'Kinder')union(select publication_id from publications.editors where first_name = 'Tony' and last_name = 'Kinder'))

Tags: PostgreSQL

Posted by Paul Hollands pj at 12:31 PM | Comments (0)

November 26, 2011

Server replication in Postgres 9.1

Postgres slave server in five minutes

Files: Postgres_9.1_replication_standby_files.tar.gz

Binary Replication in 6 Steps

This 6-step guide, and all of the examples in this tutorial, assume that you have a master server at 192.168.0.1 and a standby server at 192.168.0.2 and that your database and its configuration files are installed at /var/lib/postgresql/data. Replace those with whatever your actual server addresses and directories are.

1. Edit postgresql.conf on the master to turn on streaming replication. Change these settings:

 listen_address = '*'
 wal_level = hot_standby
 max_wal_senders = 3

2. Edit pg_hba.conf on the master in order to let the standby connect.

 host  replication   all   192.168.0.2/32      trust

3. Edit recovery.conf and postgresql.conf on the standby to start up replication and hot standby. First, in postgresql.conf, change this line:

 hot_standby = on

Then create a file in the standby's data directory (which is often the same directory as postgresql.conf and pg_hba.conf, except on some Linux distributions such as Debian and Ubuntu), called recovery.conf, with the following lines:

 standby_mode = 'on'
 primary_conninfo = 'host=192.168.0.1'

4. Shutdown the master and copy the files. You want to copy most but not all files between the two servers, excluding the configuration files and the pg_xlog directory.

tar cvzhf /Users/paulhollands/Desktop/data.tgz --exclude 'pg_xlog' --exclude 'postgresql.conf' data/

5. Start the standby first, so that they can't get out of sync.

6. Start the master.

Tags: PostgreSQL

Posted by Paul Hollands pj at 12:10 PM | Comments (0)

November 25, 2011

Jython and Django Trial

# cd /Users/paulhollands/jython2.5.2/bin
# django-admin.py startproject dss
# jython manage.py runserver
Validating models...

0 errors found
Django version 1.3.1, using settings 'dss.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
[25/Nov/2011 23:00:47] "GET / HTTP/1.1" 200 2045

Tags: Jython

Posted by Paul Hollands pj at 11:02 PM | Comments (0)

November 23, 2011

Is Solaris running in 64bit mode?

isainfo -v

 

Posted by Paul Hollands pj at 02:20 PM | Comments (0)

November 05, 2011

Spine JS Framework

Spine

Tags: JavaScript

Posted by Paul Hollands pj at 05:40 PM | Comments (0)

November 01, 2011

Cast a date to Unix timestamp in Postgres

'2012-04-01'::timestamp::abstime::int4

Tags: PostgreSQL

Posted by Paul Hollands pj at 11:31 AM | Comments (0)

October 30, 2011

Detect an iPad and provide a non-Flash alternative

try{ ["iPad","iPod","iPhone"].each(

  function(i){

    if(navigator.userAgent.indexOf(i) > -1){

      //Do iPad stuff here

      }

   }); } catch(e){ var meh = 'meh'; }

Tags: JavaScript , jQuery

Posted by Paul Hollands pj at 08:40 PM | Comments (0)

October 28, 2011

Jython and Django

Chapter 14: Web Applications With Django — Jython Book v1.0 documentation

Tags: Jython

Posted by Paul Hollands pj at 10:00 PM | Comments (0)

Groooooooooovy

Groovy - Home

 

Posted by Paul Hollands pj at 09:41 PM | Comments (0)

October 26, 2011

Matrix Asset Map for iOS

Zed Said Studio - Squiz Matrix Asset Map for iOS

 

Posted by Paul Hollands pj at 09:55 PM | Comments (0)

October 21, 2011

Textastic for iPad

Textastic Code Editor for iPad on the iTunes App Store

 

Posted by Paul Hollands pj at 10:40 PM | Comments (0)

October 19, 2011

Alternately colour the rows in a table with jQuery

var color = '#efefef';

var counter = 0;

function switch_bg(counter){ 

    if(eval(counter/2) == eval(counter/2).toFixed(0)){ return color; } 

    else { return 'white'; } 

    }

jQuery('tbody tr').each(

	function(){ 
	
		counter++;  
		
		jQuery(this).find('td').each(
		
			function(){ 
			
				jQuery(this).css({ 'background-color' : switch_bg(counter) }); 
				
				}
			
			);
			
		}
			 
	);

Tags: jQuery

Posted by Paul Hollands pj at 06:42 PM

October 11, 2011

Student class needs to be adjusted

	function get_hash_by_uun($uun){
		
		return $this->get_hash_by_id($this->get_id_by_uun($uun)); 
		
		}

	function get_id_by_uun($uun){

		$m = (int) str_replace('s', '', $uun);
		
		$reply = just::sql(sprintf("select student_id from student_full where matriculation_number = %d", $m));
		
		return $reply['first_row']['student_id'];		

		}
		
	function get_uun_by_id($id){
	
		$reply = just::sql(
			sprintf("select case
			when char_length(matriculation_number::varchar) = 5 then 's00'||matriculation_number
			when char_length(matriculation_number::varchar) = 6 then 's0'||matriculation_number
			else 's'||matriculation_number end as uun from student_full where student_id = %d", (int) $id)
			);
	
		return $reply['first_row']['uun'];
	
		}

Tags: PHP

Posted by Paul Hollands pj at 06:42 PM | Comments (0)

October 10, 2011

Kill runaway Postgres threads

kill `ps -ef | grep [p]ostgres | awk '{print $2}'`

Tags: PostgreSQL

Posted by Paul Hollands pj at 05:05 PM | Comments (0)

September 28, 2011

Symfony Framework

Symfony - Home

Tags: PHP

Posted by Paul Hollands pj at 11:27 PM | Comments (0)

Casting Unix timestamps to PostgreSQL timestamps

select *, to_timestamp(insert_date) as inserted from test where 1 limit 1;

Data Type Formatting Functions

Tags: PostgreSQL

Posted by Paul Hollands pj at 12:55 PM | Comments (0)

September 17, 2011

I love Python

import glob, os, re, string

def rename(dir, pattern):

    for path_filename in glob.glob(os.path.join(dir, pattern)):

        title, ext = os.path.splitext(os.path.basename(path_filename))

	new_title = '''%s''' %(re.sub(r'[\W]+','-',title))

	print new_title.lower()

        os.rename(path_filename, os.path.join(dir, new_title.lower() + ext))

rename(r'/home/phollan2/crc_papers_2011',r'*.pdf')

Tags: Python

Posted by Paul Hollands pj at 01:28 PM | Comments (0)

September 03, 2011

Cosign with Django

Django | Authentication using REMOTE_USER | Django documentation

Tags: Python

Posted by Paul Hollands pj at 06:53 PM | Comments (0)

July 25, 2011

Link bare URLs in a HTML element

function link_em(da_id){

    try{ var tml = document.getElementById(da_id).innerHTML; } catch(e){ return false; }

    var reg = /[^href\=\"](http|https):\/\/([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?\/?/gm;

    var list = [];

    list = tml.match(reg);

    var count = 0;

    for(i in list){

       if(list[i]){ if(list[i] != document.getElementById(da_id).innerHTML){ if( parseInt(list[i]) + '' != list[i]){

          count++;

          tml = tml.replace(list[i].replace(/\(/,''), '<a href="' + list[i].replace(/\(/,'') + '">' + list[i].replace(/\(/,'') + '</a>');

          }}}

       }

try{ if(list[0]){    

       document.getElementById(da_id).innerHTML = tml;

       } } catch(e){ var blah = ''; }

    }


Tags: JavaScript

Posted by Paul Hollands pj at 04:38 PM | Comments (0)

July 12, 2011

Online IDE for Node.js

Interwebs IDE hits the mother Node • The Register

Tags: JavaScript

Posted by Paul Hollands pj at 06:20 PM | Comments (0)

June 13, 2011

IE 7 Zero Length Regex Matches

An IE lastIndex Bug with Zero-Length Regex Matches

 

Posted by Paul Hollands pj at 05:19 PM | Comments (0)

Detect curly quotes with JavaScript

function check_quotes(){
	
	var s = '';
	
	var regex = /\W/g;
	
	var m =  null;
	
	var text = null;
	
	var code = null;
	
	['asset_name','body','summary'].each(function(da_id){
	
		text = document.getElementById(da_id).value; 
		
		m = regex.exec(text);

		if(da_id == 'asset_name'){ da_id = 'title'; }
		
		var count = 0;
		
		while(m){
				
			code = m[0].charCodeAt(0);
			
			if(code > 8200){
			
			    s = s + "\n<li> Found  " + m + "  in " + da_id.split('_').join(' ') + " text</li>";
			    
				count++;
				
			   }

			count++;
 	
			m = regex.exec(text);
		
			}
			
		});
	
	if(s != ''){ poppy('Illegal characters found in your title or description:<br/><br/><ul>' + s + '</ul><br/>Delete and then re-type quotes and long dashes in the editor above before proceeding. Please try and avoid cutting and pasting from Word.'); return true; }
	
	return false;
	
	}

Tags: Curly quotes , JavaScript

Posted by Paul Hollands pj at 04:23 PM | Comments (0)

May 18, 2011

Remove from version control but keep the file

svn delete --keep-local filename

Tags: Subversion

Posted by Paul Hollands pj at 03:48 PM | Comments (0)

April 14, 2011

RIS format specification

RIS format specifications - AUBIB

 

Posted by Paul Hollands pj at 03:37 PM | Comments (0)

March 30, 2011

Doing foreach iteration in JavaScript


['email','first_name','last_name','photo_url'].each(function(i){ //Or forEach

			if(document.getElementById(i)){
			
				$jq('#' +i).attr({ 'readonly' : '' });

				$jq('#' + i).removeClass('readonly');

				}

		});

Tags: JavaScript

Posted by Paul Hollands pj at 03:31 PM | Comments (0)

Javascript array iteration

How many ways can you iterate over an array in JavaScript?

Tags: JavaScript

Posted by Paul Hollands pj at 01:30 PM | Comments (0)

March 29, 2011

CSS 3 Transforms

Using CSS3 Transitions, Transforms and Animation

 

Posted by Paul Hollands pj at 09:22 AM | Comments (0)

March 08, 2011

Shell script for killing all processes for an application on a particular day

kill -9 `ps -ef | grep [p]ostgres |  grep 'Nov 13' | awk '{print $2}'`

 

Posted by Paul Hollands pj at 06:53 PM | Comments (0)

March 01, 2011

Node.js

Node.js community wiki - GitHub

Also:

http://www.nakedjavascript.com/going-evented-with-nodejs

Tags: JavaScript

Posted by Paul Hollands pj at 10:37 PM | Comments (0)

January 04, 2011

Mandolin Scales

mandolin-scales.jpg

 

Posted by Paul Hollands pj at 07:23 PM | Comments (0)

December 17, 2010

A vint-i-cinq de desembre

A vint-i-cinq de desembre
Fum, fum, fum
A nascut un minyonet
Ros i blanquet, ros i blanquet
Fill de la Verge Maria
N’és nat en una establia
Fum fum fum.

Aquí a dalt de la muntanya
Fum, fum, fum
Si n’hi ha dos pastorets
Abrigadets, abrigadets
Amb la pell i la samarra
Mengen ous i botifara.
Fum, fum, fum

Nit enllà el sol desperta
Fum, fum, fum
Veuen l’angel resplendent
Que els va dient :
Ara es nat a l’establia
Deu infant fill de Maria
Fum, fum, fum

A vint-i-cinc de desembre
Fum, fum, fum
És el dia de Nadal
Molt principal
En sortint de les Maitines
Menjarem cosetas finas
Fum, fum, fum

Déu nos dó unes santes festes
Fum, fum, fum
Faci fred faci calor
Serà el millor, serà el millor
De Jesús fem gran memòria
Perqué ens vulgui dar la Glòria
Fum, fum, fum

 

Posted by Paul Hollands pj at 08:15 PM | Comments (0)

October 27, 2010

SPARQL Toot

SPARQL Tutorial | AllegroGraph 4.1

Tags: RDF

Posted by Paul Hollands pj at 12:56 PM | Comments (0)

October 26, 2010

PHP script to run SPARQL queries against a 4store triple store

<?php

error_reporting(E_ERROR | E_PARSE);

require_once "HTTP/Request.php";

if($_GET['format']){

	header('Content-type: text/plain');

	} else { 

	header('Content-type: text/xml');

	}

$sparql = sprintf("PREFIX rss: <http://purl.org/rss/1.0/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX dubco: <http://purl.org/dc/elements/1.1/>
PREFIX ev: <http://purl.org/rss/1.0/modules/event/>

select * { 
        ?item rss:title ?title . 
        ?item rss:link ?link . 
        ?item dc:date ?date .
        ?item dubco:description ?description .
	?item ev:location ?location .
        FILTER regex(str(?title), \"%s?\", 'i') . 
        } ORDER BY ?title", $_GET['query']);

$req = &new HTTP_Request('http://172.20.36.113:8080/sparql/'); 

if($_GET['format']){ $req->addHeader("Accept", "application/".$_GET['format']); }

$req->setMethod(HTTP_REQUEST_METHOD_POST);
$req->addPostData("query", $sparql);
$req->sendRequest();

$response = $req->getResponseBody();

print $response;

print '<!--'.$sparql.'-->';

?>

 

Posted by Paul Hollands pj at 03:46 PM | Comments (0)

October 25, 2010

XSLT Date and Time Processing Examples

Date and time processing

Tags: XSLT

Posted by Paul Hollands pj at 12:40 PM | Comments (0)

October 23, 2010

Keep it quiet

Bicycle Bike Noises, Clicks, Ticks, Creaks, Clunks, Knocks And Repair by Jim Langley

 

Posted by Paul Hollands pj at 12:49 PM | Comments (0)

October 18, 2010

Checking PHP form array has a value

function valet(els){

	if(validate(els)){
	
		var checks = document.getElementsByName('category[]');
	
		for (i = 0; i < checks.length; i++){ 
		
			if(checks[i].checked == true){ return true; } 

			}

		poppy('You need to choose at least one Region or Sector.'); return false; 
	
		}

	return false;

	}

Tags: JavaScript

Posted by Paul Hollands pj at 01:11 PM | Comments (0)

September 23, 2010

Puurrrty

Nirve Brookhurst 7-Speed Urban Bike - Radfieber, your beachcruiser and chopper bike specialist from the heart of Cologne

 

Posted by Paul Hollands pj at 09:52 AM | Comments (0)

September 15, 2010

Anstruther

http://www.undiscoveredscotland.co.uk/anstruther/anstruther/index.html

 

Posted by Paul Hollands pj at 08:38 PM | Comments (0)

August 04, 2010

Firing up and querying 4store

4s-backend staff

4s-query staff 'select ?firstname, ?lastname { ?person <http://xmlns.com/foaf/0.1/lastName> ?lastname . ?person <http://xmlns.com/foaf/0.1/firstName> ?firstname }'

Tags: RDF

Posted by Paul Hollands pj at 02:22 PM | Comments (0)

July 13, 2010

Twins!

PREFIX dbo: <http://dbpedia.org/ontology/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>

SELECT ?person, ?birth, ?death, ?name, ?first, ?last, ?description, ?place {
     ?person rdf:type dbo:PlayboyPlaymate .
     ?person dbo:birthDate ?birth .
     OPTIONAL{ ?person dbo:birthPlace ?place. }
     ?person foaf:name ?name .
     OPTIONAL { ?person foaf:givenname ?first . }
     OPTIONAL { ?person foaf:surname ?last . }
     OPTIONAL{ ?person dbo:deathDate ?death . }
     OPTIONAL{ ?person dbo:nationality ?nationality . }
     OPTIONAL{ ?person dbo:ethnicGroup ?race . }
     OPTIONAL{ ?person dc:description ?description . }
     FILTER regex(str(?name), " and ") .
}

Twins!

Tags: RDF

Posted by Paul Hollands pj at 04:16 PM | Comments (0)

DBpedia Mapings

All pages (OntologyClass namespace) - DBpedia Mappings

 

Posted by Paul Hollands pj at 03:03 PM | Comments (0)

June 17, 2010

Ext JS Mobile App Framework

Sencha — Sencha Touch

 

Posted by Paul Hollands pj at 11:16 AM | Comments (0)

June 09, 2010

RDFS Schema for GP Salaries

Fuzzy Buckets: GP Salary RDF Schema

Tags: RDF

Posted by Paul Hollands pj at 09:03 PM | Comments (0)

Funding opportunities RDF example

<?xml version='1.0'?>
<rdf:RDF
	xml:base="http://www.medev.ac.uk/fundops_example.rdf"
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
	xmlns:owl="http://www.w3.org/2002/07/owl#"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
	xmlns:fundops="http://www.medev.ac.uk/interoperability/rss/1.0/modules/fundops/rss1.0fundopsmodule#"
	xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"
	xmlns:dcterms="http://purl.org/dc/terms/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:event="http://purl.org/rss/1.0/modules/event/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:cc="http://web.resource.org/cc/"
	xmlns:rss="http://purl.org/rss/1.0/"
	xmlns="http://purl.org/rss/1.0/"
	>
	<owl:Ontology rdf:about="http://www.medev.ac.uk/fundops_example.rdf"/>
	
	<cc:License rdf:nodeID="license">
		<dc:identifier rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.0/"/>
		<cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
		<cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
		<cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
		<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
		<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
		<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>
		<cc:prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/>
	</cc:License>
	
	<channel rdf:about="http://www.medev.ac.uk/fundops_example.rdf">
		<dc:title xml:lang="en-GB">Sample fundops RSS 1.0 feed.</dc:title>
		<dc:description xml:lang="en-GB">
	  		Sample fundops module feed using new schema definition.
		</dc:description>
		<link rdf:resource="http://www.medev.ac.uk/resources/fundops/"/>
		<dc:date rdf:value="2005-06-16T15:55:00Z"/>
		<items>
		<rdf:Seq>
		<rdf:li rdf:resource="http://www.britishendodonticssociety.org/awards.htm#harty"/>
		</rdf:Seq>
		</items>
		<cc:license rdf:nodeID="license"/>
	</channel>
	
	<item rdf:about="http://www.britishendodonticssociety.org/awards.htm#harty">
		<dc:format>text/html</dc:format>
		<dc:date>2004-03-03T17:30:00Z</dc:date>
		<dc:source rdf:resource="http://www.medev.ac.uk/resources/fundops/"/>
		<title xml:lang="en-GB">The Harty Prize: Student essay prize in endodontics</title>
		<description xml:lang="en-GB">
			The British Endodontic Society aims to support: High standards of endodontic 
treatment; research in the field of endodontics; undergraduate elective period projects in endodontics; 
continuing education for general practitioners.

			The title of the essay is: Student Perceptions of Teaching and Learning in 
Endodontology.

			The closing date is 30th March each year. The student who submits the winning 
essay will be invited to the Spring Scientific Meeting, in March, for the presentation of the prize. 
Registration, accommodation and travel costs will be paid. Please see website for full restrictions and 
application details.

			The prize will be open to any undergraduate dental student in a dental school 
within the United Kingdom or a dental graduate from one of these schools who has been on the Dentist's 
Register for no more than one year on 30th June in each year of application.
			Closing date for applications: Tuesday 30th March 2004
			Contact: brett.robinson@kcl.ac.uk
		</description>
		<dc:subject xml:lang="en-GB"
			rdf:value="HEALTH CARE / MEDICINE / HEALTH & SAFETY" 
  rdf:type="http://www.learndirect-advice.co.uk/provider/standardsandclassifications/classpage/bigdoc.pdf"/>
		<dc:subject xml:lang="en-GB"
			rdf:value="DENTAL SERVICES"
  rdf:type="http://www.learndirect-advice.co.uk/provider/standardsandclassifications/classpage/bigdoc.pdf"/>
	</item>

	<fundops:Opportunity rdf:about="http://www.britishendodonticssociety.org/awards.htm#harty">
		<fundops:type xml:lang="en-GB">prize or funding</fundops:type>
		<fundops:programme xml:lang="en-GB">
		  The British Endodontic Society Awards and Prizes
		</fundops:programme>
		<fundops:frequency xml:lang="en-GB">annual</fundops:frequency>
		<fundops:deadline rdf:nodeID="deadline_1"/>
		<fundops:sponsor rdf:nodeID="sponsor_1"/>
		<fundops:applyto rdf:nodeID="applyto_1"/>
		<fundops:budget rdf:nodeID="budget_1"/>
		<fundops:purpose xml:lang="en-GB">
			To reward the dental student or recent dental graduate who writes the best essay on 
the subject of 'Coronal restoration is more relevant than root filling for the ultimate endodontic success'.
		</fundops:purpose>
		<fundops:targetsector rdf:nodeID="HE"/>
		<fundops:targetgroup rdf:nodeID="targetgroup_1"/>
		<fundops:awardconditions xml:lang="en-GB">
			The prize will be awarded by the Council of the British Endodontic Society on the 
recommendation of the examiners. The Council reserves the right to withhold the prize if the standard of 
the essays submitted is not of sufficient merit.

			The value of the prize shall be GBP 500. The Harty Medal shall also be awarded to 
the prize winner. There are also six runner-up prizes of a year's free membership to the Society.

			The prize will be open to any undergraduate dental student in a dental school within 
the United Kingdom or a dental graduate from one of these schools who has been on the Dentist's Register for 
no more than one year on 30th June in each year of application. All essays, apart from that of the winner, 
will be returned to the writers. Only the name of the prize winner will be published.

			The essay must be written in English and shall not exceed 3000 words. It must be 
typed on one side of the paper only, size A4, in double spacing. Pages must be fixed together and preceded 
by a title page. One copy of the essay shall be submitted.
		</fundops:awardconditions>
		<fundops:howtoapply xml:lang="en-GB">
			Each entry must be written under a pseudonym. The student's full name, address and 
dental school must accompany the essay in a sealed envelope bearing the pseudonym. Essays should be 
submitted to the Assistant Secretary.
		</fundops:howtoapply>
		<fundops:duration rdf:nodeID="duration_1"/>
	</fundops:Opportunity>

	<fundops:Deadline rdf:nodeID="deadline_1">
		<event:startdate>2004-02-03T08:30:00Z</event:startdate>
		<event:enddate>2004-03-03T17:30:00Z</event:enddate>
	</fundops:Deadline>
	
	<fundops:Sponsor rdf:nodeID="sponsor_1">
		<fundops:organization rdf:resource="http://www.britishendodonticssociety.org/"/>
	</fundops:Sponsor>

	<fundops:Organization rdf:about="http://www.britishendodonticssociety.org/">
		<vcard:ORG rdf:parseType="Resource">
			<vcard:Orgname xml:lang="en-GB">The British Endodontic Society</vcard:Orgname>
		</vcard:ORG>
		<vcard:ADDR rdf:parseType="Resource">
			<vcard:Street xml:lang="en-GB">
			  The King's Dental Institute, King's Campus, Denmark Hill
			</vcard:Street>
			<vcard:Locality xml:lang="en-GB">London</vcard:Locality>
			<vcard:Pcode>SE5 9RW</vcard:Pcode>
			<vcard:Region 
  rdf:type="http://www.rdn.ac.uk/publications/rdn-ltsn/geographic-coverage/" xml:lang="en-GB" rdf:value="UK"/>
		</vcard:ADDR>
	</fundops:Organization>
		
	<fundops:ApplyTo rdf:nodeID="applyto_1">
		<fundops:person rdf:resource="mailto:brett.robinson@kcl.ac.uk"/>
	</fundops:ApplyTo>
	
	<fundops:Person rdf:about="mailto:brett.robinson@kcl.ac.uk">
		<foaf:name xml:lang="en-GB">Brett Robinson</foaf:name>
		<foaf:mbox>mailto:brett.robinson@kcl.ac.uk</foaf:mbox>
		<vcard:TEL rdf:parseType="Resource">
			<rdf:value>0207 346 3585</rdf:value>
			<rdf:type rdf:resource="http://www.w3.org/2001/vcard-rdf/3.0#voice"/>
			<rdf:type rdf:resource="http://www.w3.org/2001/vcard-rdf/3.0#work"/>
		</vcard:TEL>
	</fundops:Person>
		
	<fundops:Budget rdf:nodeID="budget_1">
		<fundops:currency rdf:value="GBP"/>
		<fundops:totalbudget><xsd:integer rdf:value="500"/></fundops:totalbudget>
		<fundops:minvalue><xsd:integer rdf:value="500"/></fundops:minvalue>
		<fundops:maxvalue><xsd:integer rdf:value="500"/></fundops:maxvalue>
		<fundops:availableawards><xsd:integer rdf:value="1"/></fundops:availableawards>
	</fundops:Budget>
	
	<fundops:TargetSector rdf:nodeID="HE" xml:lang="en-GB" rdf:value="Higher Education"/>

	<fundops:TargetGroup rdf:nodeID="targetgroup_1">
		<dc:description>
			The prize will be open to any undergraduate dental student in a dental school within 
the United Kingdom or a dental graduate from one of these schools who has been on the Dentist's Register for 
no more than one year on 30th June in each year of application. All essays, apart from that of the winner, 
will be returned to the writers. Only the name of the prize winner will be published.
		</dc:description>
	</fundops:TargetGroup>
	
	<fundops:Duration rdf:nodeID="duration_1">
		<event:startdate>2004-03-04T08:30:00Z</event:startdate>
		<event:enddate>2005-03-03T17:30:00Z</event:enddate>
		<fundops:minduration><xsd:integer rdf:value="365"/></fundops:minduration>
		<fundops:maxduration><xsd:integer rdf:value="365"/></fundops:maxduration>
	</fundops:Duration>

	<item rdf:about="http://www.bad.org.uk/doctors/fellowships/index.htm">
		<dc:format>text/html</dc:format>
		<dc:date>2004-03-31T00:00:00</dc:date>
		<dc:source>http://www.ltsn-01.ac.uk/resources/fundops/index_html</dc:source>
	<title>Medical student projects</title>
	<link>
	http://www.bad.org.uk/doctors/fellowships/index.htm
	</link>
	<description>
		To encourage students to undertake small research projects or optional period in the study of topics 
related to dermatology or skin biology. With recent changes in the undergraduate curriculum in medicine many 
medical students have the opportunity of spending a few months studying a particular topic in detail. 10 
awards are available. Single Payment Funding of 500 GBP towards student research projects. 
	Closing date for applications: Wednesday 31st March 2004
	</description>
	</item>

</rdf:RDF>

Tags: RDF

Posted by Paul Hollands pj at 11:04 AM | Comments (0)

XSLT to turn RDFS into an HTML view

rdfs2html.xsl

<xsl:stylesheet version="1.0" id="my_style" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:owl="http://www.w3.org/2002/07/owl#" xmlns:xsd="http://www.w3.org/2001/XMLSchema#" xmlns:dubcore="http://dublincore.org/2003/03/24/dces#" xmlns:dc="http://orlando.drc.com/SemanticWeb/DAML/Ontology/DC/ver/0.1.0/dces-ont#" xmlns:ves="http://orlando.drc.com/SemanticWeb/DAML/Ontology/VES/ver/0.1.0/drc-ves-ont#" xmlns:event="http://purl.org/rss/1.0/modules/event/" xmlns:foaf="http://xmlns.com/foaf/0.1/" xmlns:fundops="http://www.medev.ac.uk/interoperability/rss/1.0/modules/fundops/rss1.0fundopsmodule#">

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no"/>

<!-- <xsl:strip-space elements ="*" /> -->

<xsl:template match="/">
<div id="schema" xmlns="http://www.w3.org/1999/xhtml" class="example">
 <xsl:apply-templates/>
</div>

</xsl:template>

<xsl:template match="owl:Ontology">
 <h3><xsl:value-of select="@dubcore:title"/></h3>
 <p><xsl:value-of select="rdfs:comment"/></p>
</xsl:template>

<xsl:template match="rdfs:Class">
	<xsl:if test="@rdfs:label">
		<h4><xsl:value-of select="@rdfs:label"/> Class</h4>
		<p><xsl:value-of select="@rdfs:comment"/></p>
	</xsl:if>
	<xsl:if test="rdfs:label">
		<h4><xsl:value-of select="rdfs:label"/> Class</h4>
		<p><xsl:value-of select="rdfs:comment"/></p>
	</xsl:if>

	<xsl:if test="rdfs:subClassOf">
	
		<p>This is a sub-class of:</p>

		<ul>
		<xsl:for-each select="rdfs:subClassOf">
			<li><xsl:value-of select="./@rdf:resource"/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>

	<xsl:if test="rdfs:isDefinedBy">
	
		<p>Class defined by:</p>

		<ul>
		<xsl:for-each select="rdfs:isDefinedBy">
			<li><xsl:value-of select="./@rdf:resource"/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>

	<xsl:if test="rdfs:domain">
	
		<p>This class is in the following domains:</p>

		<ul>
		<xsl:for-each select="rdfs:domain">
			<li><xsl:value-of select="./@rdf:resource"/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>

	<xsl:if test="rdfs:range/owl:oneOf">
	
		<p>Range should be one of:</p>

		<ul>
		<xsl:for-each select="rdfs:range/owl:oneOf/owl:Thing">
			<li><xsl:value-of select="./@rdf:about"/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>
	<xsl:if test="rdfs:range/owl:someValuesFrom">
	
		<p>Range should be some values from:</p>

		<ul>
		<xsl:for-each select="rdfs:range/owl:someValuesFrom/owl:Thing">
			<li>
			<xsl:value-of select="./@rdf:about"/>
			<xsl:if test="./rdf:value"><xsl:value-of select="./rdf:value"/></xsl:if>
			</li>
		</xsl:for-each>
		</ul>
	</xsl:if>
	<xsl:if test="owl:equivalentClass">
	
		<p>This class is an equivalent of:</p>

		<ul>
		<xsl:for-each select="owl:equivalentClass">
			<li>
			<xsl:value-of select="./@rdf:resource"/>
			</li>
		</xsl:for-each>
		</ul>
	</xsl:if>
	<xsl:if test="owl:disjointWith">
	
		<p>This class is disjoint with:</p>

		<ul>
		<xsl:for-each select="owl:disjointWith">
			<li>
			<xsl:value-of select="./@rdf:resource"/>
			</li>
		</xsl:for-each>
		</ul>
	</xsl:if>
</xsl:template>

<xsl:template match="rdf:Property">
	<xsl:if test="@rdfs:label">
		<h4><xsl:value-of select="@rdfs:label"/> property</h4>
		<p><xsl:value-of select="@rdfs:comment"/></p>
	</xsl:if>
	<xsl:if test="rdfs:label">
		<h4><xsl:value-of select="rdfs:label/@rdf:value"/> property</h4>
		<p><xsl:value-of select="@rdfs:comment"/></p>
	</xsl:if>
	<xsl:if test="rdfs:subPropertyOf">
	
		<p>This is a sub-property of:</p>

		<ul>
		<xsl:for-each select="rdfs:subPropertyOf">
			<li><xsl:value-of select="./@rdf:resource"/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>

	<xsl:if test="rdfs:isDefinedBy">
	
		<p>Property defined by:</p>

		<ul>
		<xsl:for-each select="rdfs:isDefinedBy">
			<li><xsl:value-of select="./@rdf:resource"/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>

	<xsl:if test="rdfs:domain">
	
		<p>Property is in the following domains:</p>

		<ul>
		<xsl:for-each select="rdfs:domain">
			<li><xsl:value-of select="./@rdf:resource"/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>

	<xsl:if test="rdfs:range/@rdf:resource">
	<p>Is in the range of:</p>

		<ul>
		<xsl:for-each select="rdfs:range/@rdf:resource">
		<li><xsl:value-of select="."/></li>
		</xsl:for-each>
		</ul>
	</xsl:if>
	<xsl:if test="rdfs:range/owl:oneOf">
	
		<p>Range should be one of:</p>

		<ul>
		<xsl:for-each select="rdfs:range/owl:oneOf/owl:Thing">
			<li>
			<xsl:value-of select="./@rdf:about"/>
			<xsl:if test="./rdf:value"><xsl:value-of select="./rdf:value"/></xsl:if>
			</li>
		</xsl:for-each>
		</ul>
	</xsl:if>
	<xsl:if test="rdfs:range/owl:someValuesFrom">
	
		<p>Range should be some values from:</p>

		<ul>
		<xsl:for-each select="rdfs:range/owl:someValuesFrom/owl:Thing">
			<li>
			<xsl:value-of select="./@rdf:about"/><xsl:if test="./rdf:value">
			<xsl:value-of select="./rdf:value"/></xsl:if>
			</li>
		</xsl:for-each>
		</ul>
	</xsl:if>
	<xsl:if test="owl:equivalentProperty">
	
		<p>This property is an equivalent of:</p>

		<ul>
		<xsl:for-each select="owl:equivalentProperty">
			<li>
			<xsl:value-of select="./@rdf:resource"/>
			</li>
		</xsl:for-each>
		</ul>
	</xsl:if>
	<xsl:if test="owl:disjointWith">
	
		<p>This property is disjoint with:</p>

		<ul>
		<xsl:for-each select="owl:disjointWith">
			<li>
			<xsl:value-of select="./@rdf:resource"/>
			</li>
		</xsl:for-each>
		</ul>
	</xsl:if>
</xsl:template>

</xsl:stylesheet>

Tags: RDF

Posted by Paul Hollands pj at 10:53 AM | Comments (0)

June 01, 2010

Querying OWL

Salmon Run: Using Neo4J to load and query OWL ontologies

Tags: OWL

Posted by Paul Hollands pj at 09:44 AM | Comments (0)

May 20, 2010

Overlapping dates revisited

select distinct s1.resident_slot_id 

from eclub.resident_slot s1,  eclub.resident_slot s2 

where 

s1.start_time < s2.end_time 

and 

s2.start_time < s1.end_time 

and 

s1.resident_id = s2.resident_id 

and 

s1.resident_slot_id != s2.resident_slot_id 

and s2.expired_date is null and s1.expired_date is null

Tags: PostgreSQL

Posted by Paul Hollands pj at 04:21 PM | Comments (0)

May 13, 2010

jQuery Gallery with Flikr hooks

Galleria — A JavaScript gallery for the Fastidious

Tags: JavaScript

Posted by Paul Hollands pj at 03:35 PM | Comments (0)

Creating a YouTube Gallery using jQuery Fancybox

Creating a YouTube Gallery using jQuery Fancybox - Aaron Benson | DFW Interactive Designer/Developer | Flash Enthusiast

Tags: jQuery

Posted by Paul Hollands pj at 03:34 PM | Comments (0)

May 07, 2010

JQuery $.get() caching in IE 7

Having extensively used jQuery AJAX all over the site we built in Feb have now discovered that IE 7 caches GET requests if the URL is the same? WTF? That's helpful for regularly updated feeds. Thanks MS. My day will now consist of finding every GET call in every CMS page and application script and pasting { blah : 1 , 'random' : Math.floor(Math.random()*1000 ) } into it. RSI here we come.

Tags: jQuery

Posted by Paul Hollands pj at 01:22 PM | Comments (0)

April 23, 2010

Email address regex

This fails for paul,hollands@thingmail.com as it still matches on a substring hollands@thingmail.com:
onblur="if(/[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/
.match(this.value)){ var blah = ''; } else { poppy('Your email address appears to be invalid.'); this.value = ''; }"
This fixes the issue.
onblur="if(/[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?/
.exec(this.value) == this.value){ var blah = ''; } else { poppy('Your email address appears to be invalid.'); this.value = ''; }"

 

Posted by Paul Hollands pj at 10:50 AM | Comments (0)

April 22, 2010

Mortgage Calculator

Mortgage Calculator

 

Posted by Paul Hollands pj at 08:04 AM | Comments (0)

April 16, 2010

NiceEdit WYSIWYG Editor

NicEdit - WYSIWYG Content Editor, Inline Rich Text Application

 

Posted by Paul Hollands pj at 03:17 PM | Comments (0)

April 05, 2010

O2 Dongle on Ubuntu

O2 Forum :: View topic - PAYG E160 in Ubuntu 8.10


Number: *99#
Username: o2web
Password: password
APN: m-bb.o2.co.uk

 

Posted by Paul Hollands pj at 09:02 AM | Comments (0)

March 27, 2010

Last resort for metacharacters

PHP: mb_convert_encoding - Manual

 

Posted by Paul Hollands pj at 11:30 AM | Comments (0)

February 18, 2010

JS to make one button the same size as another

var padme = $('m_butt').offsetWidth - $('sum_butt').offsetWidth;

// The 3 is the padding applied to the first element, 
// which needs to be added to the difference

$('sum_butt').style.paddingRight = (padme + 3) + 'px';

Tags: JavaScript

Posted by Paul Hollands pj at 09:45 AM | Comments (0)

January 30, 2010

She's a mystery to me

Darkness falls and she
Will take me by the hand
Take me to some twilight land
Where all but love is gray
Where I can't find my way
Without her as my guide

Night falls, I'm cast beneath her spell
Daylight comes, our heaven turns to hell
Am I left to burn, and burn eternally?
She's a mystery to me

She's a mystery girl
She's a mystery girl
She's a mystery girl
She's a mystery girl

In the night of love
Words tangled in her hair
Words soon to disappear
A love so sharp it cut
Like a switchblade to my heart
Words tearing me apart

She tears again my bleeding heart
I wanna run, she's pulling me apart
Fallen angel cries
And I just melt away
She's a mystery to me

She's a mystery girl
She's a mystery girl
She's a mystery girl
She's a mystery girl

Haunted by her side
It's a darkness in her eyes
That so enslaves me
But if my love is blind
Then I don't want to see
She's a mystery to me

Night falls, I'm cast beneath her spell
Daylight comes, our heaven turns to hell
Am I left to burn, and burn eternally?
She's a mystery to me

She's a mystery girl
She's a mystery girl
She's a mystery girl
She's a mystery girl
She's a mystery girl
She's a mystery girl
She's... a mystery girl

She's a mystery girl
She's a mystery girl

She's... a mystery girl

 

Posted by Paul Hollands pj at 06:43 PM | Comments (0)

January 18, 2010

Using SVN switch

svn switch

Tags: Subversion

Posted by Paul Hollands pj at 05:07 PM | Comments (0)

January 04, 2010

Diff of my iTunes Libraries on various computers

List of Songs by Computer and Album

Tags: Music

Posted by Paul Hollands pj at 07:05 PM | Comments (0)

December 23, 2009

Keyword Modifiers

Anton Palitsyn - MySource Matrix 3.26.0 RC1

 

Posted by Paul Hollands pj at 06:22 PM | Comments (0)

December 12, 2009

4 Store Triple Store

4store - Scalable RDF storage

Tags: Atom , FOAF , RDF

Posted by Paul Hollands pj at 05:52 PM | Comments (0)

XML_FOAF PEAR Package

http://pear.php.net/package/XML_FOAF

Also:

http://pear.php.net/package/XML_FOAF/docs/0.3.0/__filesource/fsource_XML_FOAF__XML_FOAF-0.3.0docsexamplesexample1.php.html

 

Posted by Paul Hollands pj at 04:33 PM | Comments (0)

XML :: PEAR Packages

XML :: PEAR Packages

Tags: PHP

Posted by Paul Hollands pj at 04:33 PM | Comments (0)

Social Graph API

About the Social Graph - Social Graph API - Google Code

Tags: FOAF

Posted by Paul Hollands pj at 04:12 PM | Comments (0)

FOAF in RDFa

Getting started with RDFa: Creating a basic FOAF profile | webBackplane

Tags: FOAF

Posted by Paul Hollands pj at 04:10 PM | Comments (0)

December 10, 2009

FullCalendar Code

This is a genius piece of jQuery:

http://arshaw.com/fullcalendar/

<script type="text/javascript">
var events = 
[
{ title: 'Dummy', start: new Date(1900,1,1)}
,{
title: "Reuters Datastream Training",
start: "2009-09-22T16:00:00+01:00",
end: "2009-09-22T17:00:00+01:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/reuters-datastream-training"
}

,{
title: "Pom tiddly pom",
start: "2009-11-23T10:59:00+00:00",
end: "2009-11-23T12:49:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/pom-tiddly-pom"
}

,{
title: "Management of R and D and Product Innovation",
start: "2009-02-16T16:10:00+00:00",
end: "2009-02-16T18:00:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/management-of-r-and-d-and-product-innovation2"
}


];
</script>
<script type="text/javascript">
var recurrences = 
[
{ title: 'Dummy' }
,{
title: "Foundations of Finance Theory",
start: "2009-09-22T14:00:00+01:00",
end: "2009-09-22T15:50:00+01:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/foundations-of-finance-theory",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20091201T000000",
stop_date: "2009-12-01T00:00:00+00:00"
}

,{
title: "Analysis of Corporate Financial Information Lecture",
start: "2009-09-24T11:10:00+01:00",
end: "2009-09-24T13:00:00+01:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/analysis-of-corporate-financial-information-lecture",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20091203T000000",
stop_date: "2009-12-03T00:00:00+00:00"
}

,{
title: "My test title",
start: "2009-12-02T16:00:00+00:00",
end: "2009-12-02T17:50:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/my-test-title",
frequency: "FREQ=WEEKLY;INTERVAL=2;UNTIL=20100324T000000",
stop_date: "2010-03-24T00:00:00+00:00"
}

,{
title: "Derivatives Tutorial Group 1",
start: "2010-01-11T09:00:00+00:00",
end: "2010-01-11T10:00:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/derivatives-tutorial",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20100221T000000",
stop_date: "2010-02-21T00:00:00+00:00"
}

,{
title: "Management of R and D and Product Innovation",
start: "2010-01-12T16:10:00+00:00",
end: "2010-01-12T18:00:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/management-of-r-and-d-and-product-innovation",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20100214T000000",
stop_date: "2010-02-14T00:00:00+00:00"
}

,{
title: "Doing Business Projects in Emerging Markets",
start: "2010-01-11T09:00:00+00:00",
end: "2010-01-11T10:50:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/doing-business-projects-in-emerging-markets",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20100221T000000",
stop_date: "2010-02-21T00:00:00+00:00"
}

,{
title: "Derivatives Tutorial Group 2",
start: "2010-01-11T10:00:00+00:00",
end: "2010-01-11T11:00:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/derivatives-tutorial-group-2",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20100221T000000",
stop_date: "2010-02-21T00:00:00+00:00"
}

,{
title: "Corporate Strategy",
start: "2010-01-11T21:00:00+00:00",
end: "2010-01-11T22:50:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/corporate-strategy",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20100221T000000",
stop_date: "2010-02-21T00:00:00+00:00"
}

,{
title: "Advertising Management",
start: "2010-01-11T14:00:00+00:00",
end: "2010-01-11T15:50:00+00:00",
allDay: false,
url: "http://www.business-school.ed.ac.uk/mybiz/msc-accounting-and-finance/my-study/timetables/msc-accounting-and-finance/advertising-management",
frequency: "FREQ=WEEKLY;INTERVAL=1;UNTIL=20100221T000000",
stop_date: "2010-02-21T00:00:00+00:00"
}


];

function get_event_recurrences(recurrences, events){

    var end_date;

    for(i in recurrences){

      if(i > 0){

        var this_one = recurrences[i];

        var number_of_days = 7;

        if(this_one['frequency'].match(/DAILY/)){ number_of_days = 1; }
        if(this_one['frequency'].match(/MONTHLY/)){ number_of_days = 30; }
        if(this_one['frequency'].match(/WEEKLY/)){ number_of_days = 7; }

        var stop_date = eval($.fullCalendar.parseDate(this_one['stop_date']).getTime()) / 1000;

        end_date = eval($.fullCalendar.parseDate(this_one['end']).getTime()) / 1000;

        var start_date = eval($.fullCalendar.parseDate(this_one['start']).getTime()) / 1000;

        var interval = (60 * 60 * 24) * number_of_days * extract_interval(this_one['frequency']);

        //alert((eval(stop_date) - eval(start_date)) / interval);

        for(d = start_date; d < stop_date; d = d + interval){

          var start = d;

          var new_oc = {};

          new_oc['title'] = this_one['title'];

          new_oc['url'] = this_one['url'];
          
          new_oc['allDay'] = this_one['allDay'];

          new_oc['start'] = new Date(start*1000);

          new_oc['end'] = new Date(end_date*1000); 

          end_date = end_date + interval;

          events.push(new_oc);

          } 
        
        }

      }

      return events;

    }

function extract_interval(frequency){

    var da_list = frequency.split(';');

    var interval = da_list[1];

    var da_number = interval.split('=');

    return eval(da_number[1]);

    }


</script><script type="text/javascript">

var now = new Date();

$(document).ready(

    function(){

        $('#calendar').fullCalendar(
{header: {left: 'prev,next today',center: 'title', right: 'month,agendaWeek,agendaDay'},
columnFormat: {
        week: 'ddd d MMM', // Mon 9/7
        day: 'dddd d MMM'  // Monday 9/7
},

editable: false,
firstHour: 9, //eval(now.getHours()),
minTime: '8:30am',
maxTime: '8:30pm',
timeFormat: 'H:mm',
firstDay: 1,
defaultView: 'agendaWeek',
currentTimezone: 'Europe/London',
events: get_event_recurrences(recurrences, events)});

        }
);
</script>

Tags: jQuery

Posted by Paul Hollands pj at 04:42 PM | Comments (0)

November 19, 2009

Indo European Language Google Site

Europe's Indo-European Language - Northwestern Proto-Indo-European (Indo-European Language)

 

Posted by Paul Hollands pj at 09:23 PM | Comments (0)

November 18, 2009

iCal Validator

iCalendar Validator

 

Posted by Paul Hollands pj at 01:49 PM | Comments (0)

November 14, 2009

Staggolee


It was early, early one morning
When i heard my bulldog bark,
T’was staggolee and billy delyon
Squabbling in the dark.

Staggolee told billy delyon
“what do you think of that?
You win all my money, lord!
You spit in my stetson hat"

Staggolee were walking
In the red hot brawling sun,
Says: “bring me my six-shooter,
Lord i wants my fourty-one"

Staggolee were walking
Through the mud and through the sand
Says: “i feel mistreated this morning,
I could kill most any man"

Billy delyons told staggolee:
“please don’t take my life,
I got three helpless children,
One poor, beautiful wife"

“i don’t care nothing ‘bout your children
And nothing about your wife
You done mistreated me, billy,
And i’m bound to take your life".

He shot him three times in the shoulder, lord,
He shot him three times in the side.
Well, the last time he shot him
Caused billy lyons to die.

Staggolee told mrs. billy:
“you don’t believe your man is dead?
Come on into the barroom,
See the hole i shot in his head!"

The high-sheriff told the deputies:
“get your pistols and come with me!
We got to go’n arrest the bad man
Known as staggolee"

The deputies took their pistols
They laid them on the shelf,
“if you want that bad man staggolee
You have to arrest him yourself!"

The high-sheriff asked the bartender
“who can that bad man be?"
“speak softly!?, said the bartender,
“that bad man’s staggolee"

He touched old stag on the shoulder,
“say, stag, why do you run?"
“i don’t run, white folk,
When i got my fourty-one"

The hangman put the mask on,
Tied his hands behind his back,
Sprung the trap on staggolee,
But his neck refused to crack.

The hangman, he got frightened,
Said: “chief, you see how it be,
I can’t hang this man, lord,
You better set him free"

Three-hundred dollar funeral,
Thousand dollar hearse,
Satisfaction! “undertaker,
Put stag on down in the earth!"

Staggolee told the devil:
“say, come on and have some fun!
You stick me with your pitchfork,
And i’ll shoot you with my fourty-one"

Staggolee took the pitchfork
And he laid it on a shelf,
He says: “stand back, tom devil, lord,
I’m gonna rule hell by myself."


 

Posted by Paul Hollands pj at 12:06 AM | Comments (0)

November 13, 2009

Really fast Ajax

Ajax/load - jQuery JavaScript Library

Tags: AJAX , JavaScript

Posted by Paul Hollands pj at 04:24 PM | Comments (0)

Yeti USB Mic

Blue Microphones Yeti USB Microphone: Amazon.co.uk: Electronics & Photo

 

Posted by Paul Hollands pj at 02:26 PM | Comments (0)

October 29, 2009

Indigetes

Indigetes - Wikipedia, the free encyclopedia

 

Posted by Paul Hollands pj at 02:20 AM | Comments (0)

Iberian language

Iberian language - Wikipedia, the free encyclopedia

 

Posted by Paul Hollands pj at 01:21 AM | Comments (0)

Languages of Iberia

Languages of Iberia - Wikipedia, the free encyclopedia

 

Posted by Paul Hollands pj at 01:20 AM | Comments (0)

October 28, 2009

Vulgar Latin - Wikipedia

Vulgar Latin - Wikipedia, the free encyclopedia

 

Posted by Paul Hollands pj at 02:03 AM | Comments (0)

Catalan personal pronouns

Catalan personal pronouns - Wikipedia, the free encyclopedia

 

Posted by Paul Hollands pj at 12:46 AM | Comments (0)

October 26, 2009

Thickbox and Prototype

getting thickbox, jquery, and prototype to play together nicely | disjoint thoughts

Tags: JavaScript

Posted by Paul Hollands pj at 11:22 AM | Comments (0)

October 19, 2009

PostgreSQL 7.4: Mathematical Functions and Operators

PostgreSQL: Documentation: Manuals: PostgreSQL 7.4: Mathematical Functions and Operators

-43

Tags: PostgreSQL

Posted by Paul Hollands pj at 04:55 PM | Comments (0)

October 16, 2009

iCalendar Recurrence Reference and Examples

4.8.5.4 Recurrence Rule


   Property Name: RRULE

   Purpose: This property defines a rule or repeating pattern for
   recurring events, to-dos, or time zone definitions.

   Value Type: RECUR

   Property Parameters: Non-standard property parameters can be
   specified on this property.

   Conformance: This property can be specified one or more times in
   recurring "VEVENT", "VTODO" and "VJOURNAL" calendar components. It
   can also be specified once in each STANDARD or DAYLIGHT sub-component
   of the "VTIMEZONE" calendar component.

   Description: The recurrence rule, if specified, is used in computing
   the recurrence set. The recurrence set is the complete set of
   recurrence instances for a calendar component. The recurrence set is
   generated by considering the initial "DTSTART" property along with
   the "RRULE", "RDATE", "EXDATE" and "EXRULE" properties contained
   within the iCalendar object. The "DTSTART" property defines the first
   instance in the recurrence set. Multiple instances of the "RRULE" and
   "EXRULE" properties can also be specified to define more
   sophisticated recurrence sets. The final recurrence set is generated
   by gathering all of the start date/times generated by any of the
   specified "RRULE" and "RDATE" properties, and excluding any start
   date/times which fall within the union of start date/times generated
   by any specified "EXRULE" and "EXDATE" properties. This implies that
   start date/times within exclusion related properties (i.e., "EXDATE"
   and "EXRULE") take precedence over those specified by inclusion
   properties (i.e., "RDATE" and "RRULE"). Where duplicate instances are
   generated by the "RRULE" and "RDATE" properties, only one recurrence
   is considered. Duplicate instances are ignored.






Dawson & Stenerson          Standards Track                   [Page 117]

 
RFC 2445                       iCalendar                   November 1998


   The "DTSTART" and "DTEND" property pair or "DTSTART" and "DURATION"
   property pair, specified within the iCalendar object defines the
   first instance of the recurrence. When used with a recurrence rule,
   the "DTSTART" and "DTEND" properties MUST be specified in local time
   and the appropriate set of "VTIMEZONE" calendar components MUST be
   included. For detail on the usage of the "VTIMEZONE" calendar
   component, see the "VTIMEZONE" calendar component definition.

   Any duration associated with the iCalendar object applies to all
   members of the generated recurrence set. Any modified duration for
   specific recurrences MUST be explicitly specified using the "RDATE"
   property.

   Format Definition: This property is defined by the following
   notation:

     rrule      = "RRULE" rrulparam ":" recur CRLF

     rrulparam  = *(";" xparam)

   Example: All examples assume the Eastern United States time zone.

   Daily for 10 occurrences:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=DAILY;COUNT=10

     ==> (1997 9:00 AM EDT)September 2-11

   Daily until December 24, 1997:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=DAILY;UNTIL=19971224T000000Z

     ==> (1997 9:00 AM EDT)September 2-30;October 1-25
         (1997 9:00 AM EST)October 26-31;November 1-30;December 1-23

   Every other day - forever:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=DAILY;INTERVAL=2
     ==> (1997 9:00 AM EDT)September2,4,6,8...24,26,28,30;
          October 2,4,6...20,22,24
         (1997 9:00 AM EST)October 26,28,30;November 1,3,5,7...25,27,29;
          Dec 1,3,...

   Every 10 days, 5 occurrences:




Dawson & Stenerson          Standards Track                   [Page 118]

 
RFC 2445                       iCalendar                   November 1998


     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=DAILY;INTERVAL=10;COUNT=5

     ==> (1997 9:00 AM EDT)September 2,12,22;October 2,12

   Everyday in January, for 3 years:

     DTSTART;TZID=US-Eastern:19980101T090000
     RRULE:FREQ=YEARLY;UNTIL=20000131T090000Z;
      BYMONTH=1;BYDAY=SU,MO,TU,WE,TH,FR,SA
     or
     RRULE:FREQ=DAILY;UNTIL=20000131T090000Z;BYMONTH=1

     ==> (1998 9:00 AM EDT)January 1-31
         (1999 9:00 AM EDT)January 1-31
         (2000 9:00 AM EDT)January 1-31

   Weekly for 10 occurrences

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=WEEKLY;COUNT=10

     ==> (1997 9:00 AM EDT)September 2,9,16,23,30;October 7,14,21
         (1997 9:00 AM EST)October 28;November 4

   Weekly until December 24, 1997

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=WEEKLY;UNTIL=19971224T000000Z

     ==> (1997 9:00 AM EDT)September 2,9,16,23,30;October 7,14,21
         (1997 9:00 AM EST)October 28;November 4,11,18,25;
                           December 2,9,16,23
   Every other week - forever:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=WEEKLY;INTERVAL=2;WKST=SU

     ==> (1997 9:00 AM EDT)September 2,16,30;October 14
         (1997 9:00 AM EST)October 28;November 11,25;December 9,23
         (1998 9:00 AM EST)January 6,20;February
     ...

   Weekly on Tuesday and Thursday for 5 weeks:

    DTSTART;TZID=US-Eastern:19970902T090000
    RRULE:FREQ=WEEKLY;UNTIL=19971007T000000Z;WKST=SU;BYDAY=TU,TH
    or



Dawson & Stenerson          Standards Track                   [Page 119]

 
RFC 2445                       iCalendar                   November 1998


    RRULE:FREQ=WEEKLY;COUNT=10;WKST=SU;BYDAY=TU,TH

    ==> (1997 9:00 AM EDT)September 2,4,9,11,16,18,23,25,30;October 2

   Every other week on Monday, Wednesday and Friday until December 24,
   1997, but starting on Tuesday, September 2, 1997:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=WEEKLY;INTERVAL=2;UNTIL=19971224T000000Z;WKST=SU;
      BYDAY=MO,WE,FR
     ==> (1997 9:00 AM EDT)September 2,3,5,15,17,19,29;October
     1,3,13,15,17
         (1997 9:00 AM EST)October 27,29,31;November 10,12,14,24,26,28;
                           December 8,10,12,22

   Every other week on Tuesday and Thursday, for 8 occurrences:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=8;WKST=SU;BYDAY=TU,TH

     ==> (1997 9:00 AM EDT)September 2,4,16,18,30;October 2,14,16

   Monthly on the 1st Friday for ten occurrences:

     DTSTART;TZID=US-Eastern:19970905T090000
     RRULE:FREQ=MONTHLY;COUNT=10;BYDAY=1FR

     ==> (1997 9:00 AM EDT)September 5;October 3
         (1997 9:00 AM EST)November 7;Dec 5
         (1998 9:00 AM EST)January 2;February 6;March 6;April 3
         (1998 9:00 AM EDT)May 1;June 5

   Monthly on the 1st Friday until December 24, 1997:

     DTSTART;TZID=US-Eastern:19970905T090000
     RRULE:FREQ=MONTHLY;UNTIL=19971224T000000Z;BYDAY=1FR

     ==> (1997 9:00 AM EDT)September 5;October 3
         (1997 9:00 AM EST)November 7;December 5

   Every other month on the 1st and last Sunday of the month for 10
   occurrences:

     DTSTART;TZID=US-Eastern:19970907T090000
     RRULE:FREQ=MONTHLY;INTERVAL=2;COUNT=10;BYDAY=1SU,-1SU

     ==> (1997 9:00 AM EDT)September 7,28
         (1997 9:00 AM EST)November 2,30



Dawson & Stenerson          Standards Track                   [Page 120]

 
RFC 2445                       iCalendar                   November 1998


         (1998 9:00 AM EST)January 4,25;March 1,29
         (1998 9:00 AM EDT)May 3,31

   Monthly on the second to last Monday of the month for 6 months:

     DTSTART;TZID=US-Eastern:19970922T090000
     RRULE:FREQ=MONTHLY;COUNT=6;BYDAY=-2MO

     ==> (1997 9:00 AM EDT)September 22;October 20
         (1997 9:00 AM EST)November 17;December 22
         (1998 9:00 AM EST)January 19;February 16

   Monthly on the third to the last day of the month, forever:

     DTSTART;TZID=US-Eastern:19970928T090000
     RRULE:FREQ=MONTHLY;BYMONTHDAY=-3

     ==> (1997 9:00 AM EDT)September 28
         (1997 9:00 AM EST)October 29;November 28;December 29
         (1998 9:00 AM EST)January 29;February 26
     ...

   Monthly on the 2nd and 15th of the month for 10 occurrences:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=2,15

     ==> (1997 9:00 AM EDT)September 2,15;October 2,15
         (1997 9:00 AM EST)November 2,15;December 2,15
         (1998 9:00 AM EST)January 2,15

   Monthly on the first and last day of the month for 10 occurrences:

     DTSTART;TZID=US-Eastern:19970930T090000
     RRULE:FREQ=MONTHLY;COUNT=10;BYMONTHDAY=1,-1

     ==> (1997 9:00 AM EDT)September 30;October 1
         (1997 9:00 AM EST)October 31;November 1,30;December 1,31
         (1998 9:00 AM EST)January 1,31;February 1

   Every 18 months on the 10th thru 15th of the month for 10
   occurrences:

     DTSTART;TZID=US-Eastern:19970910T090000
     RRULE:FREQ=MONTHLY;INTERVAL=18;COUNT=10;BYMONTHDAY=10,11,12,13,14,
      15

     ==> (1997 9:00 AM EDT)September 10,11,12,13,14,15



Dawson & Stenerson          Standards Track                   [Page 121]

 
RFC 2445                       iCalendar                   November 1998


         (1999 9:00 AM EST)March 10,11,12,13

   Every Tuesday, every other month:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=MONTHLY;INTERVAL=2;BYDAY=TU

     ==> (1997 9:00 AM EDT)September 2,9,16,23,30
         (1997 9:00 AM EST)November 4,11,18,25
         (1998 9:00 AM EST)January 6,13,20,27;March 3,10,17,24,31
     ...

   Yearly in June and July for 10 occurrences:

     DTSTART;TZID=US-Eastern:19970610T090000
     RRULE:FREQ=YEARLY;COUNT=10;BYMONTH=6,7
     ==> (1997 9:00 AM EDT)June 10;July 10
         (1998 9:00 AM EDT)June 10;July 10
         (1999 9:00 AM EDT)June 10;July 10
         (2000 9:00 AM EDT)June 10;July 10
         (2001 9:00 AM EDT)June 10;July 10
     Note: Since none of the BYDAY, BYMONTHDAY or BYYEARDAY components
     are specified, the day is gotten from DTSTART

   Every other year on January, February, and March for 10 occurrences:

     DTSTART;TZID=US-Eastern:19970310T090000
     RRULE:FREQ=YEARLY;INTERVAL=2;COUNT=10;BYMONTH=1,2,3

     ==> (1997 9:00 AM EST)March 10
         (1999 9:00 AM EST)January 10;February 10;March 10
         (2001 9:00 AM EST)January 10;February 10;March 10
         (2003 9:00 AM EST)January 10;February 10;March 10

   Every 3rd year on the 1st, 100th and 200th day for 10 occurrences:

     DTSTART;TZID=US-Eastern:19970101T090000
     RRULE:FREQ=YEARLY;INTERVAL=3;COUNT=10;BYYEARDAY=1,100,200

     ==> (1997 9:00 AM EST)January 1
         (1997 9:00 AM EDT)April 10;July 19
         (2000 9:00 AM EST)January 1
         (2000 9:00 AM EDT)April 9;July 18
         (2003 9:00 AM EST)January 1
         (2003 9:00 AM EDT)April 10;July 19
         (2006 9:00 AM EST)January 1

   Every 20th Monday of the year, forever:



Dawson & Stenerson          Standards Track                   [Page 122]

 
RFC 2445                       iCalendar                   November 1998


     DTSTART;TZID=US-Eastern:19970519T090000
     RRULE:FREQ=YEARLY;BYDAY=20MO

     ==> (1997 9:00 AM EDT)May 19
         (1998 9:00 AM EDT)May 18
         (1999 9:00 AM EDT)May 17
     ...

   Monday of week number 20 (where the default start of the week is
   Monday), forever:

     DTSTART;TZID=US-Eastern:19970512T090000
     RRULE:FREQ=YEARLY;BYWEEKNO=20;BYDAY=MO

     ==> (1997 9:00 AM EDT)May 12
         (1998 9:00 AM EDT)May 11
         (1999 9:00 AM EDT)May 17
     ...

   Every Thursday in March, forever:

     DTSTART;TZID=US-Eastern:19970313T090000
     RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=TH

     ==> (1997 9:00 AM EST)March 13,20,27
         (1998 9:00 AM EST)March 5,12,19,26
         (1999 9:00 AM EST)March 4,11,18,25
     ...

   Every Thursday, but only during June, July, and August, forever:

     DTSTART;TZID=US-Eastern:19970605T090000
     RRULE:FREQ=YEARLY;BYDAY=TH;BYMONTH=6,7,8

     ==> (1997 9:00 AM EDT)June 5,12,19,26;July 3,10,17,24,31;
                       August 7,14,21,28
         (1998 9:00 AM EDT)June 4,11,18,25;July 2,9,16,23,30;
                       August 6,13,20,27
         (1999 9:00 AM EDT)June 3,10,17,24;July 1,8,15,22,29;
                       August 5,12,19,26
     ...

   Every Friday the 13th, forever:

     DTSTART;TZID=US-Eastern:19970902T090000
     EXDATE;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=MONTHLY;BYDAY=FR;BYMONTHDAY=13




Dawson & Stenerson          Standards Track                   [Page 123]

 
RFC 2445                       iCalendar                   November 1998


     ==> (1998 9:00 AM EST)February 13;March 13;November 13
         (1999 9:00 AM EDT)August 13
         (2000 9:00 AM EDT)October 13
     ...

   The first Saturday that follows the first Sunday of the month,
    forever:

     DTSTART;TZID=US-Eastern:19970913T090000
     RRULE:FREQ=MONTHLY;BYDAY=SA;BYMONTHDAY=7,8,9,10,11,12,13

     ==> (1997 9:00 AM EDT)September 13;October 11
         (1997 9:00 AM EST)November 8;December 13
         (1998 9:00 AM EST)January 10;February 7;March 7
         (1998 9:00 AM EDT)April 11;May 9;June 13...
     ...

   Every four years, the first Tuesday after a Monday in November,
   forever (U.S. Presidential Election day):

     DTSTART;TZID=US-Eastern:19961105T090000
     RRULE:FREQ=YEARLY;INTERVAL=4;BYMONTH=11;BYDAY=TU;BYMONTHDAY=2,3,4,
      5,6,7,8

     ==> (1996 9:00 AM EST)November 5
         (2000 9:00 AM EST)November 7
         (2004 9:00 AM EST)November 2
     ...

   The 3rd instance into the month of one of Tuesday, Wednesday or
   Thursday, for the next 3 months:

     DTSTART;TZID=US-Eastern:19970904T090000
     RRULE:FREQ=MONTHLY;COUNT=3;BYDAY=TU,WE,TH;BYSETPOS=3

     ==> (1997 9:00 AM EDT)September 4;October 7
         (1997 9:00 AM EST)November 6

   The 2nd to last weekday of the month:

     DTSTART;TZID=US-Eastern:19970929T090000
     RRULE:FREQ=MONTHLY;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-2

     ==> (1997 9:00 AM EDT)September 29
         (1997 9:00 AM EST)October 30;November 27;December 30
         (1998 9:00 AM EST)January 29;February 26;March 30
     ...




Dawson & Stenerson          Standards Track                   [Page 124]

 
RFC 2445                       iCalendar                   November 1998


   Every 3 hours from 9:00 AM to 5:00 PM on a specific day:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=HOURLY;INTERVAL=3;UNTIL=19970902T170000Z

     ==> (September 2, 1997 EDT)09:00,12:00,15:00

   Every 15 minutes for 6 occurrences:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=MINUTELY;INTERVAL=15;COUNT=6

     ==> (September 2, 1997 EDT)09:00,09:15,09:30,09:45,10:00,10:15

   Every hour and a half for 4 occurrences:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=MINUTELY;INTERVAL=90;COUNT=4

     ==> (September 2, 1997 EDT)09:00,10:30;12:00;13:30

   Every 20 minutes from 9:00 AM to 4:40 PM every day:

     DTSTART;TZID=US-Eastern:19970902T090000
     RRULE:FREQ=DAILY;BYHOUR=9,10,11,12,13,14,15,16;BYMINUTE=0,20,40
     or
     RRULE:FREQ=MINUTELY;INTERVAL=20;BYHOUR=9,10,11,12,13,14,15,16

     ==> (September 2, 1997 EDT)9:00,9:20,9:40,10:00,10:20,
                                ... 16:00,16:20,16:40
         (September 3, 1997 EDT)9:00,9:20,9:40,10:00,10:20,
                               ...16:00,16:20,16:40
     ...

   An example where the days generated makes a difference because of
   WKST:

     DTSTART;TZID=US-Eastern:19970805T090000
     RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=MO

     ==> (1997 EDT)Aug 5,10,19,24

     changing only WKST from MO to SU, yields different results...

     DTSTART;TZID=US-Eastern:19970805T090000
     RRULE:FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU
     ==> (1997 EDT)August 5,17,19,31




Dawson & Stenerson          Standards Track                   [Page 125]

 
RFC 2445                       iCalendar                   November 1998

 

Posted by Paul Hollands pj at 09:26 AM | Comments (0)

October 15, 2009

iCalendar Recurrence

RFC 2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar)

 

Posted by Paul Hollands pj at 04:56 PM | Comments (0)

This is so cool

Delicious Library 2

 

Posted by Paul Hollands pj at 04:51 PM | Comments (0)

Prototype-based Carousel

Prototype: Carousel

Tags: JavaScript

Posted by Paul Hollands pj at 11:46 AM | Comments (0)

October 09, 2009

PostgreSQL version of do_sql.py

import sys

import postgresql

from read_config import read_config

import time

import string

import re

def parse_insert_sql(sql):

	response = {}

	da_list = re.split("[\s\(\)]+", sql.lower().strip())
	
	print(da_list)

	ma_table = da_list[2]

	if da_list[0] == 'insert':
	
		response['is_insert'] = 1
		
		if "returning %s_id" % (ma_table) in da_list:
		
			response['sql'] = sql
			
		else:
		
			response['sql'] = sql + " returning %s_id as insert_id" % (ma_table)
			
	else:
	
		response['is_insert'] = 0
	
		response['sql'] = sql
			
	return response

def do_sql_query(db_config_file, sql, debug):

	response = {}

	results = ()

	"""

	Takes config file name, your SQL and a debug parameter.

	Returns a dictionary with a boolean, an error and a warning string and 
	a list of results dictionaries.

	"""

	connection_map = read_config('%s.ini' % db_config_file, debug)

	(host, user, passwd, db) = (connection_map['connection_parameters']['host'],
	connection_map['connection_parameters']['user'],
	connection_map['connection_parameters']['password'],
	connection_map['connection_parameters']['db']) 
	
	connection = postgresql.open("pq://%s:%s@%s/%s" % (user, passwd, host, db))
	
	insert_response = parse_insert_sql(sql)
		
	if insert_response['is_insert'] == 1:

		sql = insert_response['sql']
	
	try:
		
		results = connection.prepare(sql)

		response['results'] = results

		response['status'] = 1

		if insert_response['is_insert'] == 1:
	
			response['insert_id'] = results.first()

		return(response)		

	except: 
	
		if debug == 1: 

			print ("\nPostgreSQL error: %s\n" % (sql))

		response['status'] = 0

		response['error'] = "\nPostgreSQL error: %s\n" % (sql)

		response['results'] = results

		return(response)	
	
if __name__ == "__main__":

	response = do_sql_query('waf_common', "insert into stuff(stuff_id, nonsense) values(nextval('stuff_seq'::regclass), 'Glug')", 0)

	print (response['insert_id'])
		
	response = do_sql_query('waf_common', "select * from staff limit 10", 0)

	print (response['results'].first())
	
	for record in response['results']:
	
		for column in record.column_names:
		
			print("%s : %s" % (column, record[column]))
			
		print("\n ----------- \n")
	

Tags: Python

Posted by Paul Hollands pj at 05:00 PM | Comments (0)

October 01, 2009

De-dupe but leave one of each with one SQL query

Using sick sub-queries:

delete from ug_abstract where ug_abstract_id in 

-- Get a list of duplicated rows based upon a comparison of the title

(

select ug.ug_abstract_id 
from ug_abstract ug, ug_abstract ag 
where ug.title = ag.title  and ug.ug_abstract_id != ag.ug_abstract_id and ug.ug_abstract_id not in 


-- Get the PK from one of each of the rows that have been duplicated
-- then exclude them from the delete run with a "not in"

(select max(ug.ug_abstract_id) as ug_abstract_id 
from ug_abstract ug, ug_abstract ag 
where ug.title = ag.title  and ug.ug_abstract_id != ag.ug_abstract_id group by ug.title) 


group by ug.title, ug.ug_abstract_id order by ug.title

)

Tags: PostgreSQL

Posted by Paul Hollands pj at 04:23 PM | Comments (0)

September 25, 2009

Mental BST events SQL with cluster tags included

-- All dates are plus one hour to accomodate BST '1970-01-01 01:00:00 GMT'

select distinct e.event_id, e.event_name, e.event_start_date, e.event_start_time, t.asset_id, '1970-01-01 01:00:00 GMT'::timestamp + 
((e.event_start_date::bigint)::text)::interval as ma_date, 

-- Get the day from the date and pad it with a leading zero if less than 10

case when extract('day' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval) < 10 then
'0'||extract('day' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval)::text else 
extract('day' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval)::text end 
as ma_day, 

-- Get the month from the date and pad it with a leading zero if less than 10

case when extract('month' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval) < 10 then
'0'||extract('month' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval)::text else 
extract('month' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval)::text end 
as ma_month, 

-- Get the year from the date

extract('year' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval) as ma_year,

-- Get the hours and minutes from the date + the start time and pad them with a leading zeros if less than 10

case when extract('hour' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint + (e.event_start_time * 60 * 60))::text)::interval) < 10 then 
'0'||extract('hour' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint + (e.event_start_time * 60 * 60))::text)::interval)::text
else extract('hour' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint + (e.event_start_time * 60 * 60))::text)::interval)::text end 
as start_hour,

case when extract('minute' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint + (e.event_start_time * 60 * 60))::text)::interval) < 10 then
'0'||extract('minute' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint + (e.event_start_time * 60 * 60))::text)::interval)::text
else extract('minute' from '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint + (e.event_start_time * 60 * 60))::text)::interval)::text end as start_min,

-- Get two tags

max(rc.research_cluster_name) as tag_one,
min(rc.research_cluster_name) as tag_two

from event e 

-- left join in the research cluster (tag) table

left join event_research_cluster_link ecl on (ecl.event_id = e.event_id and ecl.expired_date is null) 

left join research_cluster rc on (ecl.research_cluster_id = rc.research_cluster_id and ecl.expired_date is null), 

-- Join on the heading and transaction table (latter for the asset_id)

event_heading_link l, heading h, transaction t where l.event_id = e.event_id and l.heading_id = h.heading_id and l.heading_id in (2) 
and t.event_id = e.event_id and t.asset_id is not null

-- Check that the event_start_date is in British Summer Time

and ('1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval between 

-- Get the last Sunday in March

date_trunc('month', (extract('year' from now()::timestamp)::text||'-03-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval + (((1 - 7 - to_char(date_trunc('month', (extract('year' from now()::timestamp)::text||'-03-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval,'D')::int) %7)||' days')::interval 

and 

-- Get the last Sunday in October

date_trunc('month', (extract('year' from now()::timestamp)::text||'-10-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval + (((1 - 7 - to_char(date_trunc('month', (extract('year' from now()::timestamp)::text||'-10-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) - '1 day'::interval,'D')::int) %7)||' days')::interval )

-- This is an archive so the start date must be before now

and '1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval < current_timestamp

group by e.event_start_date, e.event_start_time, e.event_name, t.asset_id, e.event_id

order by e.event_start_date desc, e.event_start_time desc

Tags: PostgreSQL

Posted by Paul Hollands pj at 02:32 PM | Comments (0)

September 24, 2009

Is this date during BST?


-- Check that the event_start_date is in British Summer Time

and ('1970-01-01 01:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval between

-- Get the last Sunday in March

date_trunc('month', (extract('year' from now()::timestamp)::text||'-03-01 00:00:00 GMT'::text)::timestamp + 
'1 month'::interval) - '1 day'::interval + 
(((1 - 7 - to_char(date_trunc('month', (extract('year' 
from now()::timestamp)::text||'-03-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) 
- '1 day'::interval,'D')::int) %7)||' days')::interval

and

-- Get the last Sunday in October

date_trunc('month', (extract('year' from now()::timestamp)::text||'-10-01 00:00:00 GMT'::text)::timestamp + 
'1 month'::interval) - '1 day'::interval + 
(((1 - 7 - to_char(date_trunc('month', (extract('year' 
from now()::timestamp)::text||'-10-01 00:00:00 GMT'::text)::timestamp + '1 month'::interval) 
- '1 day'::interval,'D')::int) %7)||' days')::interval )

-- The 1 specifies Sunday

 

Posted by Paul Hollands pj at 11:23 PM | Comments (0)

September 23, 2009

Code for detecting if it's BST

http://www.devscripts.net/browse/116.php

Tags: PHP

Posted by Paul Hollands pj at 03:45 PM | Comments (0)

Getting a date from a bigint in PostgreSQL

'1970-01-01 00:00:00 GMT'::timestamp + ((e.event_start_date::bigint)::text)::interval 
as ma_date

 

Posted by Paul Hollands pj at 12:19 PM | Comments (0)

August 06, 2009

Ajax URL Checker

The JS goes like this:

function check_url(me_url){

	$('url_message').innerHTML = '';

	var url_match = /https?:\/\/([-\w\.]+)+(:\d+)?(\/([\w/_\.]*(\?\S+)?)?)?/;

	if(url_match.test(me_url)){ poppy('URL is well-formed.'); $('url_warning').style.display = "none"; }
	
	else{ poppy('The URL entered appears to be invalid. Please ensure it begins with http:// or https://!'); $('url_warning').style.display = 'block'; return false; }

	$('url_message').style.display = 'inline';

	$('url_message').innerHTML = ' <strong style="text-decoration: blink;">Checking Link..</strong>';

    var da_url  = 'check_url.php';
    var params = '?url=' + me_url;
    var myAjax = new Ajax.Request(
                        da_url,
                        {
                                method: 'get',
                                parameters: params,
                                onComplete: success
                        });
						
		function success(this_request){
		
			try{ 
			
				var reply = this_request.responseText.evalJSON(true);  
				
				if(reply['status_code']){ 
				
					if( reply['status_code'] < 400){ $('url_message').innerHTML = ' <strong style="color: green">Link OK: Code ' + reply['status_code']+ '</strong>'; }
				
					else{ $('url_message').innerHTML = ' <strong style="color: red">Broken: Code ' + reply['status_code'] + '</strong>'; }
					
					} else { $('url_message').innerHTML = ' <strong style="color: red">No Such Site.</strong>'; }
				
				} catch(e){ blah = ''; }
		
			}	

	}

The PHP goes like this:

<?

require_once "HTTP/Request.php";

$req =& new HTTP_Request($_REQUEST['url']);

$response = $req->sendRequest();

header('Status:'.$req->getResponseCode());

print json_encode(array("status_code" => $req->getResponseCode()));

?>

Tags: JavaScript

Posted by Paul Hollands pj at 01:15 PM | Comments (0)

August 04, 2009

New Chuck Stuff

RELEASE INFO - Cooking Vinyl UK

 

Posted by Paul Hollands pj at 11:27 PM | Comments (0)

July 31, 2009

CSS baseline reset

CSS Tools: Reset CSS

 

Posted by Paul Hollands pj at 08:47 PM | Comments (0)

July 29, 2009

Matrix Javascript API

Zed Said Studio | MySource Matrix Javascript API Asset Released in 3.22.2

Tags: MySource Matrix

Posted by Paul Hollands pj at 06:58 PM | Comments (0)

July 23, 2009

MSM Developer's Blog

Aleks Bochniak writes...

Tags: MySource Matrix

Posted by Paul Hollands pj at 11:42 AM | Comments (0)

July 22, 2009

AJAX / PHP / MySQL Calendar

AJAX Calendar with PHP and mySQL - Blog, Articles and Discussions - OpenCrypt Membership Software

Tags: AJAX

Posted by Paul Hollands pj at 11:52 PM | Comments (0)

July 15, 2009

AJAX Term

Index of /software/ajaxterm

Tags: AJAX

Posted by Paul Hollands pj at 04:28 PM | Comments (0)

XML schema for site maps

sitemaps.org - Protocol

Tags: XML

Posted by Paul Hollands pj at 12:15 PM | Comments (0)

jQuery powered inline HTML editing

WYSIWYG Inline Edit with Jeditable

Tags: JavaScript

Posted by Paul Hollands pj at 09:54 AM | Comments (0)

July 13, 2009

jQuery sprintf and editable areas

Plugins | jQuery Plugins

Tags: JavaScript

Posted by Paul Hollands pj at 07:37 PM | Comments (0)

Mirroring repositories with svnsync

Mirroring repositories read-only

Tags: Subversion

Posted by Paul Hollands pj at 11:06 AM | Comments (0)

July 09, 2009

PEAR CSS Builder

Manual :: features and usage patterns

Tags: PHP

Posted by Paul Hollands pj at 03:55 PM | Comments (0)

PEAR Calendar

Manual :: Calendar

Tags: PHP

Posted by Paul Hollands pj at 03:48 PM | Comments (0)

Installing Spredsheet_Excel_Writer PEAR module

/opt/php/bin/pear install channel://pear.php.net/OLE-1.0.0RC1
/opt/php/bin/pear install channel://pear.php.net/Spreadsheet_Excel_Writer

Tags: PHP

Posted by Paul Hollands pj at 12:01 PM | Comments (0)

July 03, 2009

SQL for clearing out Events webservice transactions

delete from transaction where add_edit_flag = 'edit'; update transaction set asset_id = null, expired_date = null

 

Posted by Paul Hollands pj at 03:18 PM | Comments (0)

jQuery JSON and AJAX for off-domain content

Your jQuery code looks like this:

$.ajax({
	dataType: "jsonp",  
	json: "callback",  
	url: "http://<?=$paths['host']?>/event_registration/how_many_registered.ws.php?event_id=<?=$event['event_id']?>",
	success: function(json){
		if(json["max"] > 0){
			if(json["status"] == "open"){
				document.getElementById("registration_container").innerHTML = document.getElementById("registration_container").innerHTML + " - " + json["spaces"] + " places left.";
				}
			else{ 
				document.getElementById("registration_container").innerHTML = "%lt;a name=\"sorry\" style=\"color: #ee174c\">Sorry. Registration closed. This event is full</a>"; 
				}
			}
		}
	});

The PHP looks like this (where $r == $_REQUEST):

print $r['callback'].'( '.json_encode($reply).' )';

Tags: JSON

Posted by Paul Hollands pj at 10:37 AM | Comments (0)

July 02, 2009

Limonade Framework

Limonade - PHP micro-framework

Tags: PHP

Posted by Paul Hollands pj at 10:06 PM | Comments (0)

jQuery JSON security

funkatron.com : Safely parsing JSON in JavaScript

 

Posted by Paul Hollands pj at 07:18 PM | Comments (0)

June 27, 2009

Famous Hostels

Book the Best Hostel in Europe - Europe's Famous Hostels

 

Posted by Paul Hollands pj at 12:56 PM | Comments (0)

June 26, 2009

Caching the date info for MSM Single Calendar Events


require_once $SYSTEM_ROOT.'/packages/calendar/calendar_event/calendar_event.inc';

.....................

function cache_calendar_dates($asset_id, $add_edit){

    $cal = $GLOBALS['SQ_SYSTEM']->am->getAsset($asset_id);
    
    if($add_edit == 'add'){ return $cal->cacheCalendarData(FALSE); }
    
    else{ return $cal->cacheCalendarData(TRUE); }
    
    }

 

Posted by Paul Hollands pj at 11:42 PM | Comments (0)

Calendar date functions in MSM

In /mysource_matrix/packages/calendar/calendar_event/calendar_event.inc

	/**
	* Cache the calendar data's stuff
	*
	* The return value indicates the success
	*
	* @param boolean	$updating	are we updating (TRUE) or inserting a new record
	*								(FALSE - set only in create() call)
	*
	* @return boolean
	* @access public
	*/
	function cacheCalendarData($updating=TRUE)
	{
		$GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
		$db = MatrixDal::getDb();

		$date_values = Array();

		foreach (Array('start_date', 'end_date') as $date_comp) {
			$iso = $this->attr($date_comp);

			if (iso8601_time_component($iso) === FALSE) {
				if (($date_comp == 'end_date') && (iso8601_date_component($iso) !== FALSE)) {
					$iso = substr($iso, 0, 10).' 24:00:00';
				}
			} else {
				// we know the seconds aren't going to be there, so zero them so we can
				// use the getDate() niceness
				$iso = substr($iso, 0, 16).':00';
			}

			// we have the best, now get the rest
			$date_values += Calendar_Common::getDateComponents($iso, $date_comp.'_');
		}

		// frequency field => blank for standard events, overridden in recurring
		$date_values['frequency'] = '';

		$GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');

		if (!$updating) {
			// set the asset ids
			$date_values['assetid'] = $this->id;

			for (reset($date_values); NULL !== ($key = key($date_values)); next($date_values)) {
				if (is_null($date_values[$key]))
					$date_values[$key] = 'NULL';
				else
				$date_values[$key] = MatrixDAL::quote($date_values[$key]);
			}
			$val_string = implode(',', $date_values);

			$sql = 'INSERT INTO
						sq_cal_date_val
						(
							'.implode(',', array_keys($date_values)).'
						)
						VALUES
						(
							'.$val_string.'
						)';

			try {
				$query = MatrixDAL::preparePdoQuery($sql);
				MatrixDAL::execPdoQuery($query);
			} catch (Exception $e) {
				throw new Exception($e->getMessage());
			}
		} else {
			// asset id becomes a where condition
			$sql = 'UPDATE
						sq_cal_date_val
					SET ';

			$set_array = Array();
			foreach ($date_values as $key => $value) {
				$set_array[] = $key.' = '.((is_null($value)) ? 'null' : MatrixDAL::quote($value));
			}
			$sql .= implode(',', $set_array);
			$sql .=' WHERE
						assetid = :assetid';

			try {
				$query = MatrixDAL::preparePdoQuery($sql);
				MatrixDAL::bindValueToPdo($query, 'assetid', $this->id);
				MatrixDAL::execPdoQuery($query);
			} catch (Exception $e) {
				throw new Exception($e->getMessage());
			}
		}

		$GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
		$GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();

		return TRUE;

	}//end cacheCalendarData()

 

Posted by Paul Hollands pj at 10:53 PM | Comments (0)

Syncing code between two repositories

cd /opt/coolstack/apache2/htdocs; svn export --force svn://172.20.52.51:8081/svn-repository/waf .; svn commit -m=""; chown -R webservd *

Tags: Subversion

Posted by Paul Hollands pj at 12:03 PM | Comments (0)

June 20, 2009

What's On - Edinburgh

Music, Edinburgh | Events | The List

 

Posted by Paul Hollands pj at 11:07 AM | Comments (0)

June 13, 2009

Pop Art Canvases

steve mcqueen pop art design.php

 

Posted by Paul Hollands pj at 10:15 PM | Comments (0)

June 01, 2009

XSL for transforming RSS 2.0 to RSS 1.0

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" id="rss2to1"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
                xmlns:dc="http://purl.org/dc/elements/1.1/"
                xmlns="http://purl.org/rss/1.0/"
                >
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/rss"><xsl:apply-templates/></xsl:template>
<xsl:template match="channel">
<rdf:RDF>
    <channel rdf:about="{link}">
    <title><xsl:value-of select="title"/></title>  
    <description><xsl:value-of select="description"/></description>  
    <link><xsl:value-of select="link"/></link>    
    <items>
        <rdf:Seq>
            <xsl:for-each select="item"><rdf:li  rdf:resource="{link}"/></xsl:for-each>
        </rdf:Seq>
    </items>
   </channel>
    <xsl:for-each select="item">
    <item rdf:about="{link}">
        <title><xsl:value-of select="title"/></title>  
        <description><xsl:value-of select="description"/></description>  
        <link><xsl:value-of select="link"/></link>
        <dc:date><xsl:call-template name="FormatDate"><xsl:with-param name="DateTime"  select="pubDate"/></xsl:call-template></dc:date>
    </item>
    </xsl:for-each>
    </rdf:RDF>
</xsl:template>
  <xsl:template name="FormatDate">
    <xsl:param name="DateTime" />
    <!-- new date format 2006-01-14T08:55:22Z -->
    <xsl:variable name="mo">
      <xsl:value-of select="substring($DateTime,9,3)" />
    </xsl:variable>
    <xsl:variable name="day">
      <xsl:value-of select="substring($DateTime,6,2)" />
    </xsl:variable>
    <xsl:variable name="year">
      <xsl:value-of select="substring($DateTime,13,4)" />
    </xsl:variable>
    <xsl:variable name="time">
      <xsl:value-of select="substring($DateTime,18,8)" />
    </xsl:variable>
    <xsl:variable name="hh">
      <xsl:value-of select="substring($time,1,2)" />
    </xsl:variable>
    <xsl:variable name="mm">
      <xsl:value-of select="substring($time,4,2)" />
    </xsl:variable>
    <xsl:variable name="ss">
      <xsl:value-of select="substring($time,7,2)" />
    </xsl:variable>
    <xsl:value-of select="$year"/>
    <xsl:value-of select="'-'"/>
    <xsl:choose>
      <xsl:when test="$mo = 'Jan'">01</xsl:when>
      <xsl:when test="$mo = 'Feb'">02</xsl:when>
      <xsl:when test="$mo = 'Mar'">03</xsl:when>
      <xsl:when test="$mo = 'Apr'">04</xsl:when>
      <xsl:when test="$mo = 'May'">05</xsl:when>
      <xsl:when test="$mo = 'Jun'">06</xsl:when>
      <xsl:when test="$mo = 'Jul'">07</xsl:when>
      <xsl:when test="$mo = 'Aug'">08</xsl:when>
      <xsl:when test="$mo = 'Sep'">09</xsl:when>
      <xsl:when test="$mo = 'Oct'">10</xsl:when>
      <xsl:when test="$mo = 'Nov'">11</xsl:when>
      <xsl:when test="$mo = 'Dec'">12</xsl:when>
    </xsl:choose>

    <xsl:value-of select="'-'"/>
    <xsl:if test="(string-length($day) < 2)">
      <xsl:value-of select="0"/>
    </xsl:if>
    <xsl:value-of select="$day"/>
    <xsl:value-of select="'T'"/>
    <xsl:value-of select="$hh"/>
    <xsl:value-of select="':'"/>
    <xsl:value-of select="$mm"/>
    <xsl:value-of select="':'"/>
    <xsl:value-of select="$ss"/>
    <xsl:value-of select="'Z'"/>
  </xsl:template>

</xsl:stylesheet>

Tags: RSS , XSLT

Posted by Paul Hollands pj at 09:02 PM | Comments (0)

XSL for formatting a date

XSLT - format date

Tags: XSLT

Posted by Paul Hollands pj at 04:02 PM | Comments (0)

RSS 1.0 Job Vacancy Schema

RDF Site Summary 1.0 Modules: Job Vacancies - Version 0.1

Authors

Paul Hollands

URI

http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/

Previous version

http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/

Revision

$Revision: 0.1 $

Last update

$Date: 2005/07/14 21:58:18.295 GMT $

Status

Draft

Rights

Copyright © 2004-2005 Paul Hollands

Available under a Creative Commons License. Some rights reserved by the author.

Creative Commons License

Description

RSS 1.0 module, for sharing information about UK Higher Education job vacancies.

While this module is primarily designed to allow interoperation and sharing of funding opportunity information among the UK Higher Education Academy it's use further abroad would be most welcome.

Example feed:

An example feed can be found at: http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/jobs_example.rdf

Namespace decalaration

  • <xmlns:fundop=http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#/>

RDF Schema definition document

The following RDFS document is embedded in this page: http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule

RSS 1.0 module for job vacancies in UK higher education

RSS 1.0 module, for sharing information about UK Higher job vacancies.

Vacancy Class

The overarching class for job vacancies

This is a sub-class of:

  • http://purl.org/rss/1.0/Item
  • http://www.w3.org/2000/01/rdf-schema#Resource

Class defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Organization Class

An organization to be used as an object of vacancy with or apply to properties

This is a sub-class of:

  • http://www.w3.org/2000/01/rdf-schema#Resource

Class defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#
  • http://www.w3.org/2001/vcard-rdf/3.0#
  • http://xmlns.com/foaf/0.1/Organization

This class is an equivalent of:

  • http://xmlns.com/foaf/0.1/Organization

This class is disjoint with:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Person

Person Class

A person node to be used as an object for the apply to property

This is a sub-class of:

  • http://www.w3.org/2000/01/rdf-schema#Resource

Class defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#
  • http://www.w3.org/2001/vcard-rdf/3.0#
  • http://xmlns.com/foaf/0.1/Person

This class is an equivalent of:

  • http://xmlns.com/foaf/0.1/Person

This class is disjoint with:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Organization

ApplicationDeadline Class

Node for the deadline start and end dates for applications

This is a sub-class of:

  • http://www.w3.org/2000/01/rdf-schema#Resource

Class defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Range should be some values from:

  • http://purl.org/rss/1.0/modules/event/startdate
  • http://purl.org/rss/1.0/modules/event/enddate

SalaryRange Class

The salary range for this vacancy.

This is a sub-class of:

  • http://www.w3.org/2000/01/rdf-schema#Resource

Class defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Range should be some values from:

  • #minimumsalary
  • #maximumsalary

minimumsalary property

Minimum value in the salary range.

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#SalaryRange

Range should be one of:

  • http://www.w3.org/2001/XMLSchema#integer
  • Negotiable

maximumsalary property

Maximum value in the salary range.

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#SalaryRange

Range should be one of:

  • http://www.w3.org/2001/XMLSchema#integer
  • Negotiable

currency property

The currency which the salary is offered in. Use ISO 4217 currency codes. Default is GBP.

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#SalaryRange

Is in the range of:

  • http://www.w3.org/2000/01/rdf-schema#Literal

furtherdetails property

The URI of the web page describing this vacancy

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Vacancy

Is in the range of:

  • http://www.w3.org/2000/01/rdf-schema#Resource

contractduration property

Duration of contract in days.

This is a sub-property of:

  • http://www.w3.org/2001/XMLSchema#integer

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Vacancy

Range should be one of:

  • http://www.w3.org/2001/XMLSchema#integer
  • Permanent

furtherdetails property

Item property to hold Vacancy reference

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://purl.org/rss/1.0/item

Is in the range of:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Vacancy
  • http://www.w3.org/2000/01/rdf-schema#Resource

salaryrange property

Property pointing to a SalaryRange node

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Vacancy

Is in the range of:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#SalaryRange
  • http://www.w3.org/2000/01/rdf-schema#Resource

applicationdeadline property

Property pointing to an ApplicationDeadline node

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Vacancy

Is in the range of:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#ApplicationDeadline
  • http://www.w3.org/2000/01/rdf-schema#Resource

vacancywith property

Property pointing to an Organization node

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Vacancy

Is in the range of:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Organization
  • http://www.w3.org/2000/01/rdf-schema#Resource

percentagefte property

The precentage of FTE (Full Time Equivalent)

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#SalaryRange

Is in the range of:

  • http://www.w3.org/2000/01/rdf-schema#Literal

Range should be one of:

  • http://www.w3.org/2001/XMLSchema#integer
  • http://www.w3.org/2001/XMLSchema#float

localreference property

Reference number assigned by advertiser

Property defined by:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#

Property is in the following domains:

  • http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#Vacancy

Is in the range of:

  • http://www.w3.org/2000/01/rdf-schema#Literal

Example feed:

An example feed can be found at: http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/jobs_example_rdf

<?xml version="1.0"?>
<rdf:RDF
	xml:base="http://minnesota.ncl.ac.uk/fundops_example.owl"
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
	xmlns:owl="http://www.w3.org/2002/07/owl#"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
	xmlns:jobs="http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule#"
	xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"
	xmlns:dcterms="http://purl.org/dc/terms/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:event="http://purl.org/rss/1.0/modules/event/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:cc="http://web.resource.org/cc/"
	xmlns:rss="http://purl.org/rss/1.0/"
	xmlns="http://purl.org/rss/1.0/"
>

	<cc:License rdf:nodeID="license">
		<dc:identifier rdf:resource="http://creativecommons.org/licenses/by-nc-sa/2.0/"/>

		<cc:requires rdf:resource="http://web.resource.org/cc/Attribution"/>
		<cc:requires rdf:resource="http://web.resource.org/cc/Notice"/>
		<cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/>
		<cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/>
		<cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/>
		<cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/>

		<cc:prohibits rdf:resource="http://web.resource.org/cc/CommercialUse"/>
	</cc:License>
	
	<channel rdf:about="http://www.medev.ac.uk/interoperability/jobs_example.owl">
		<title xml:lang="en-GB">Sample jobs RSS 1.0 feed.</title>
		<description xml:lang="en-GB">

			Sample jobs feed using new schema definition.
		</description>
		<link>http://www.medev.ac.uk/resources/news/jobs/</link>
		<dc:date>2005-06-16T15:55:00Z</dc:date>
		<items>

			<rdf:Seq>
				<rdf:li rdf:resource="http://www.jobs.ac.uk/jobfiles/TH558.html"/>
			</rdf:Seq>
		</items>
		<cc:license rdf:nodeID="license"/>
	</channel>

	
	<item rdf:about="http://www.jobs.ac.uk/jobfiles/TH558.html">
		<dc:format>text/html</dc:format>
		<dc:date>2004-07-30T17:30:00Z</dc:date>
		<dc:source rdf:resource="http://www.medev.ac.uk/resources/fundops/"/>
		<title xml:lang="en-GB">Clinical Lecturer in Endocrinology / 
		Diabetes, Division Of Medical Sciences</title>

		<description xml:lang="en-GB">
		Applications are invited for the post of Clinical Lecturer with a special interest 
		in Endocrinology/ Diabetes. Possession of MRCP is essential. The post represents 1 
		of 4 General Medicine Endocrinology and Diabetes, which together provide a programme
		for higher medical training in these specialities. The successful applicant is 
		likely to rotate between UHB Trust and Heartlands Trust.

		The post holder will have responsibility for the care of inpatients 
		and outpatients with general medicine and diabetic and/ or endocrine problems, 
		teaching of medical students and postgraduate students, and co-ordination of
		undergraduate medical examinations.

		Research is an important component of this post and it is hoped that the successful 
		candidate will be able to join a programme of research in line with the current 
		activities of the Division. At the last RAE, the University scored a 5 in hospital 
		based clinical subjects and 6 in laboratory sciences establishing the Medical School
		in Birmingham as one of the premier in the UK.
		</description>
		<dc:subject>Medical Education</dc:subject>
		<jobs:advertises rdf:nodeID="vacancy_0"/>
	</item>

	
	<jobs:Vacancy rdf:nodeID="vacancy_0">
		<title xml:lang="en-GB">Clinical Lecturer in Endocrinology / 
		Diabetes, Division Of Medical Sciences</title>
		<jobs:contractduration><xsd:integer rdf:value="1695"/></jobs:contractduration>
		<jobs:salaryrange rdf:nodeID="salary_range_0"/>
		<jobs:applicationdeadline rdf:nodeID="application_deadline_0"/>

		<jobs:vacancywith rdf:resource="http://www.bham.ac.uk/"/>
		<jobs:applyto rdf:resource="http://www.personnel.bham.ac.uk/"/>
		<jobs:localreference rdf:value="M1012"/>
	</jobs:Vacancy>
	
	<jobs:SalaryRange rdf:nodeID="salary_range_0">
		<jobs:minimumsalary><xsd:integer rdf:value="28307"/></jobs:minimumsalary>

		<jobs:maximumsalary><xsd:integer rdf:value="49042"/></jobs:maximumsalary>
		<jobs:currency rdf:value="GBP"/>
		<jobs:percentagefte><xsd:integer rdf:value="100"/></jobs:percentagefte>
	</jobs:SalaryRange>
	
	<jobs:ApplicationDeadline rdf:nodeID="aplication_deadline_0">

		<event:enddate rdf:value="2004-07-30T17:30:00Z"/>
	</jobs:ApplicationDeadline>
	
	<jobs:Organization rdf:about="http://www.bham.ac.uk/">
		<vcard:ORG rdf:parseType="Resource">
			<vcard:Orgname xml:lang="en-GB">The University of Birmingham</vcard:Orgname>

		</vcard:ORG>
	</jobs:Organization>
	
	<jobs:Organization rdf:about="http://www.personnel.bham.ac.uk/">
		<vcard:ORG rdf:parseType="Resource">
			<vcard:Orgname xml:lang="en-GB">Personnel Services</vcard:Orgname>

		</vcard:ORG>
		<vcard:ADDR rdf:parseType="Resource">
			<vcard:Street xml:lang="en-GB"> The University of Birmingham,
				Edgbaston
			</vcard:Street>
			<vcard:Locality xml:lang="en-GB">Birmingham</vcard:Locality>

			<vcard:Pcode>B15 2TT</vcard:Pcode>
			<vcard:Region 
		rdf:type="http://www.rdn.ac.uk/publications/rdn-ltsn/geographic-coverage/" 
		xml:lang="en-GB" rdf:value="UK"/>
		</vcard:ADDR>
		<vcard:TEL rdf:parseType="Resource">
			<rdf:value>0121 415 9000</rdf:value>

			<rdf:type rdf:resource="http://www.w3.org/2001/vcard-rdf/3.0#voice"/>
			<rdf:type rdf:resource="http://www.w3.org/2001/vcard-rdf/3.0#work"/>
		</vcard:TEL>
	</jobs:Organization>
		
</rdf:RDF>

Tags: RSS

Posted by Paul Hollands pj at 12:51 PM | Comments (0)

May 29, 2009

Getting GET parameters with JavaScript and setting them in a cookie

var queryString = window.top.location.search.substring(1);

function getParameter ( queryString, parameterName ) {

	// Add "=" to the parameter name (i.e. parameterName=value)
	var parameterName = parameterName + "=";

	if ( queryString.length > 0 ) {

		// Find the beginning of the string
		begin = queryString.indexOf ( parameterName );

		// If the parameter name is not found, skip it, otherwise return the value
		if ( begin != -1 ) {

			// Add the length (integer) to the beginning
			begin += parameterName.length;

			// Multiple parameters are separated by the "&" sign
			end = queryString.indexOf ( "&" , begin );

			if ( end == -1 ) {

				end = queryString.length

				}

			// Return the string
			return unescape ( queryString.substring ( begin, end ) );

			}

		// Return "null" if no parameter has been found
		return false;
		
		}
	}

function get_start_date(queryString){

	var start_date = getParameter(queryString, 'SQ_CALENDAR_DATE')

	if(start_date){ return start_date; }

	return false;

	}


function get_view(queryString){

	var view = getParameter(queryString, 'SQ_CALENDAR_VIEW')

	if(view){ return view; }

	return false;

	}

function create_cookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
        
        }

function read_cookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0){   
                
                    //alert(c.substring(nameEQ.length,c.length));
                
                    return c.substring(nameEQ.length,c.length);
	
                    }
        
        }
	return false;
        }


//If we don't have a start date in the URL, try getting the cookie and if we have one redirect back to ourselves including the start_date in the URL

if(get_start_date(queryString) == false){

        var bicky = read_cookie('start_date');

        if(bicky != false){ document.location.href = document.location.href + '?SQ_CALENDAR_DATE=' + bicky; }

        }

//Otherwise we have a start date in the URL query so grab it and slot it into a cookie

else{ create_cookie('start_date', get_start_date(queryString), 1); }

//If we have called a day view then redirect us to the day view asset

if(get_view(queryString) == 'day'){ document.location = 'day'; }

if(get_view(queryString) == 'week'){ document.location = 'week'; }

if(get_view(queryString) == 'month'){ document.location = 'month'; }

//alert(read_cookie('start_date'));

Tags: JavaScript

Posted by Paul Hollands pj at 09:54 PM | Comments (0)

Get query string with JS

Using JavaScript to get the Query_String from a frameset (Page 2)

Tags: JavaScript

Posted by Paul Hollands pj at 12:47 PM | Comments (0)

Speed Test

Broadband Speed test

 

Posted by Paul Hollands pj at 08:31 AM | Comments (0)

May 26, 2009

MySource Matrix Keywords

Matrix Secrets - Keywords

Tags: MySource Matrix

Posted by Paul Hollands pj at 09:38 AM | Comments (0)

May 21, 2009

Create a new asset in MySource Matrix

MySource Matrix Open Source CMS - Introduction

 

Posted by Paul Hollands pj at 04:29 PM | Comments (0)

Example: Loading binary image files into a PostgreSQL OID (blob)

Large Objects (BLOBs)

Tags: PostgreSQL

Posted by Paul Hollands pj at 02:22 PM | Comments (0)

Adding MySQL-like date functions with custom functions in PostgreSQL

How to add unix_timestamp() and from_unixtime() to PostgreSQL?

Tags: PostgreSQL

Posted by Paul Hollands pj at 10:17 AM | Comments (0)

May 17, 2009

Cycle routes in Edinburgh

Cycling Routes and Cycle Trails in Edinburgh & The Lothians - Cycling Scotland

 

Posted by Paul Hollands pj at 01:17 PM | Comments (0)

May 16, 2009

Mac PHP Postgres Bundle

BitNami :: MAPPStack

Tags: PHP

Posted by Paul Hollands pj at 10:36 PM | Comments (0)

May 12, 2009

Mac Cufflinks

Handmade Geekery on Etsy - mac daddy cufflinks by pixelparty

 

Posted by Paul Hollands pj at 12:25 AM | Comments (0)

April 15, 2009

Building Application DB Tables with tables.ini and create_database.php

The framework requires that each table in the database has a core set of columns in order to work. Also, there are some rules about how tables should be defined.

  1. Primary and foreign key columns should be set as int(10) and listed at the top.
  2. All columns apart from the primary key should be set as null by default.
  3. Date columns are set as int(20) and dates should be inserted as unix timestamps.
  4. Varchar columns are always set as varchar(255).
  5. Enumerations shouldn't be used with the framework.
  6. Every table should contain an expired_date column which will normally be set to null. If you want to remove a row from view, set the expired_date to a timestamp.

For speed tables for an application can be defined with a couple of framework tools. In each application directory, there is an /sql sub-directory. You will find two files in here, create_database.php and tables.ini.

The script parses the tables.ini file which contains the table definitions in Windows .ini format and prints the SQL necessary to create the tables out to the browser.

N.B. The script does not create the tables, it only generates the SQL to do so. This can then be pasted into PHPMyAdmin.

The tables.ini file looks like this:

[table_list]
panel = 0
panel_group = 0
panel_content = 0
panel_location = 0


; The above defines the tables to be created. The 1 or 0 value is 
; significant. 1 means that a corresponding type table is created and 
; a foreign key column for it is included in the main table.
; 0 means that no type table is created. Also the type table foreign
; key column is dropped after the table is created thus:
; alter table `panel` drop `panel_type_id`;


[panel_location]
panel_location_name = text;

[link_tables]
panel:panel_group = 0
user:panel_group = 0
panel:panel_content = 0
panel_group:panel_content = 0


; If you want to create link tables between others defined herein, you 
; can using the syntax shown above. Table names are separated by a 
; colon.


[panel]
panel_location_id = "int(10)"
panel_name = "varchar(255)"
panel_description = text
ip_address = "varchar(255)"


; Each table has a section which defines extra columns to be included
; above and beyond the default. In the resulting SQL these columns are 
; indented to differenciate them from the defaults:
;
;    drop table if exists `panel`;
;    create table `panel`
;    (
;    `panel_id` int(10) primary key auto_increment not null, 
;    `panel_type_id` int(10) default null, 
;	`panel_location_id` int(10) default null,
;	`panel_name` varchar(255) default null,
;	`panel_description` text default null,
;	`ip_address` varchar(255) default null,
;    `insert_by` int(10) default null,
;    `insert_date` int(20) default null,
;    `update_by` int(10) default null,
;    `update_date` int(20) default null,
;    `expired_date` int(20) default null );
; 
 


[panel_group]
panel_group_name = "varchar(255)"
panel_group_description = text

[panel_content]
panel_id = "int(10)"
panel_group_id = "int(10)"
content_title = text
content_description = text
content_html = text
content_html_url = text
content_stylesheet_url = text
content_image_url = text
content_image_type = "varchar(255)"
content_image_name = text
content_image_size = "int(20)"
content_image_data = longblob
priority "int(1)"
start_date = "int(20)"
end_date = "int(20)"

This generates the following output:



    drop table if exists `panel`;
    create table `panel`
    (
    `panel_id` int(10) primary key auto_increment not null, 
    `panel_type_id` int(10) default null, 
	`panel_location_id` int(10) default null,
	`panel_name` varchar(255) default null,
	`panel_description` text default null,
	`ip_address` varchar(255) default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );



alter table `panel` drop `panel_type_id`;




    drop table if exists `panel_group`;
    create table `panel_group`
    (
    `panel_group_id` int(10) primary key auto_increment not null, 
    `panel_group_type_id` int(10) default null, 
	`panel_group_name` varchar(255) default null,
	`panel_group_description` text default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );



alter table `panel_group` drop `panel_group_type_id`;




    drop table if exists `panel_content`;
    create table `panel_content`
    (
    `panel_content_id` int(10) primary key auto_increment not null, 
    `panel_content_type_id` int(10) default null, 
	`panel_id` int(10) default null,
	`panel_group_id` int(10) default null,
	`content_title` text default null,
	`content_description` text default null,
	`content_html` text default null,
	`content_html_url` text default null,
	`content_stylesheet_url` text default null,
	`content_image_url` text default null,
	`content_image_type` varchar(255) default null,
	`content_image_name` text default null,
	`content_image_size` int(20) default null,
	`content_image_data` longblob default null,
	`priority` int(1) default null,
	`start_date` int(20) default null,
	`end_date` int(20) default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );



alter table `panel_content` drop `panel_content_type_id`;




    drop table if exists `panel_location`;
    create table `panel_location`
    (
    `panel_location_id` int(10) primary key auto_increment not null, 
    `panel_location_type_id` int(10) default null, 
	`panel_location_name` text default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );



alter table `panel_location` drop `panel_location_type_id`;




    drop table if exists `panel_panel_group_link`;   
    create table `panel_panel_group_link`
    (
    `panel_panel_group_link_id` int(10) primary key auto_increment not null,
    `panel_id` int(10) default null,
    `panel_group_id` int(10) default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );


    drop table if exists `user_panel_group_link`;   
    create table `user_panel_group_link`
    (
    `user_panel_group_link_id` int(10) primary key auto_increment not null,
    `user_id` int(10) default null,
    `panel_group_id` int(10) default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );


    drop table if exists `user_panel_link`;   
    create table `user_panel_link`
    (
    `user_panel_link_id` int(10) primary key auto_increment not null,
    `user_id` int(10) default null,
    `panel_id` int(10) default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );


    drop table if exists `panel_panel_content_link`;   
    create table `panel_panel_content_link`
    (
    `panel_panel_content_link_id` int(10) primary key auto_increment not null,
    `panel_id` int(10) default null,
    `panel_content_id` int(10) default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );


    drop table if exists `panel_group_panel_content_link`;   
    create table `panel_group_panel_content_link`
    (
    `panel_group_panel_content_link_id` int(10) primary key auto_increment not null,
    `panel_group_id` int(10) default null,
    `panel_content_id` int(10) default null,
    `insert_by` int(10) default null,
    `insert_date` int(20) default null,
    `update_by` int(10) default null,
    `update_date` int(20) default null,
    `expired_date` int(20) default null );

Note the drop table statement before each creation statement. If you want to change the structure of a table after the fact, ensure you dump the data out before you do otherwise it will be destroyed.

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 11:19 AM | Comments (0)

Using prototype.js For Faster JS Development and AJAX

The prototype.js JavaScript framework is used extensively throughout the framework. Further information can be found on the website:

http://www.prototypejs.org/learn

The single most useful feature is the $('blah') function which replaces document.getElementById('blah').

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 11:04 AM | Comments (0)

April 14, 2009

Using JavaScript Validation For Mandatory Form Elements

When forms are built using the interface_functions.php functions a mandatory red asterisk is added to the markup but hidden in the HTML this can be used to flag mandatory elements and also for validation checking:

<script type="text/javascript">

var els = new Object();

els['start'] = 'Start Time';

els['duration'] = 'Duration';

els['purpose'] = 'Purpose of booking';

els['course_code'] = 'Course Code';

els['booker_name'] = 'Your Name';

els['email1'] = 'Your email address';

function check_mandatory(els){

    var popper = new Array();

    for(i in els){ if($(i).value == ''){ popper.push("<strong>" + els[i] + "</strong>"); $(i).style.border = '1px solid red'; } }
    
    if(popper.length > 0){ poppy("<p>You must provide the following information:</p><ol><li>" + popper.join('</li><li>') + "</li></ol><p>[Click in this box to hide it.]</p>"); return false; }

    else{ return true; }

    }

</script>

Call the function with an onsubmit="" event handler:

<form
    class="content nothing_added"
    style="width: 900px; text-align: left; height: 320px; vertical-align: top; clear: both; display: block;"
    action="booking_details_doozer.php"
    method="post"
    id="booking_details_form"
    onsubmit="return check_mandatory(els)"
    >

To mark the required form elements as mandatory use the following code (make sure your JS is called after all the relevant form elements have been rendered, i.e. at the bottom of the page):


<script type="text/javascript">

for(i in els){ $(i + '_mandatory').style.display = 'inline'; }

</script>

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 02:29 PM | Comments (0)

Populating Select Element Option Lists with option_switcher.php

<select/> form elements that are included with a select or select_noadd directive in a .skini need to be populated with options.

This is achieved via the common_php/option_switcher.php script and the options_switcher() function.

    switch($form){
        
        case 'room_details':

        switch($label){
    
            case 'Location': return get_options(just_sql("select ID as location_id, name from location order by name"), "location_id", "name");
            case 'Bookable?' : return '<option value="1"/> Yes'."\n".'<option value="-1"/> Staff Only';
            case 'Equipment': return get_options(just_sql("select * from equipment where expired_date is null order by name"), "equipment_id", "name");
            case 'Remove from view?' : return '<option value="'.mktime().'" style="color: red;"/> Yes'."\n".'<option value="nulled"/> No';
            
            }
            
        case 'booking_details':

        switch($label){
    
            case 'Start Time': return get_start_times($day);
            
            case 'Duration': return get_durations();
            
            case 'Your email address' : return '<option value="@cumbria.ac.uk" selected="true"/> @cumbria.ac.uk';
            
            }
...........................
    }

You will need to add a case with your .skini file name stump and then a switch / case block for each of the select form elements in the form. These are designated by the label you gave them in the .skini file.

Most of the examples you will come across make use of the get_options(just_sql("select * from blah"), $value, $label) function. This takes a just_sql() function call reply and an argument for the column names in the results which go to populate the option value and label respectively.

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 11:53 AM | Comments (0)

April 13, 2009

Sarmatian Connection

Historical basis for King Arthur - Wikipedia, the free encyclopedia

 

Posted by Paul Hollands pj at 10:36 PM | Comments (0)

Cycling in the Trossachs

Killin Weekend Routes


http://www.walkhighlands.co.uk/lochlomond/glen-ogle.shtml

 

Posted by Paul Hollands pj at 08:19 PM | Comments (0)

March 31, 2009

Building Forms With interface_functions.php & .skini Files

There are a set of functions for rapidly building web forms to work with the SQL functions. These are found in the common_php/interface_functions.php.

The build_form($form_name, $entity) Function

This is the guts of the interface system and allows you to build web forms quickly and consistently and avoids problems caused by typos in hand coded mark-up.

The function takes a filehandle for a skins/blah.skini file, and a hash to populate the form with values if required. I have avoided doing this however, in favour of using AJAX for populating forms when required instead.

build_form('panel_form');

This will look for and read a file in the skins directory called panel_form.skini and build the form based upon the settings found therein.

The .skini Configuration File Format

These files are in Windows .ini format:


; Each form element should have its own section block.
;
; Sections must be uniquely named as id attributes are assigned 
; based upon them
;
; A 1 means that the section is displayed as a block and 0
; means it is displayed inline. Inline display is trixy and 
; requires extra CSS jiggery pokery more often than not.

[sections]
current_panels = 1
name_section = 1
description_section = 1
location_section = 1
ip_address_section = 1


; For each item under the 'sections' heading there needs to be a 
; separate configuration block.
; 
; The block description should include a label entry (usually label_italic)
; and then the form element included in that section. 


[current_panels]
label_italic = "Edit Existing Panel"
current_panel_id = select_noadd
panel_id = hidden


; If you want to add extra attributes to a form element's tag then 
; you can by defining a section headed as below. This is useful for 
; adding classes, style attributes or JS event handlers:


[current_panel_id]
class = four_c
onchange = "get_panel_details()"

[name_section]
label_italic = "Panel Name"
panel_name = text

[panel_name]
class = four_c

[description_section]
label_italic = "Panel Description"
panel_description = textarea

[panel_description]
class = four_c

[location_section]
label_italic = "Panel Location"
panel_location_id = select_noadd

[panel_location_id]
class = four_c

[ip_address_section]
label_italic = "IP Address"
ip_address = text

[ip_address]
class = four_c

The build_repeating_form($form_name, $entity, $the_count) Function

If you need to build more than one instance of the same form in a single document then you should use this function. This adds the value passed into the third parameter onto the end of all id attributes in the form, separated by an underscore. This is so that we don't duplicate ids.

The get_hour_options() & get_minute_options() Function

To be used along with common_php/option_switcher.php for when you need to choose hours and minutes from <select/> elements.

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 12:51 PM | Comments (0)

Common Header & Footer Includes

All the applications in the framework share the same header and footer with a simple PHP include, although this is not mandatory, but the header sets up all sorts of JavaScripty and CSS goodness required for the framework.

The files are held in the root.

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 11:56 AM | Comments (0)

March 30, 2009

Doing Database "Create Review Update Delete" With Functions In add_update.php

There are a set of functions for abstracting DB CRUD functions in the common_php/add_update_functions.php script.

The add_new_row($table_name) function

This function adds a new row into the table specified, populating only the insert_by and insert_date columns and returning the new primary key value.

The update_table($table_name, $r, $primary_key) Function

This function is for applying updates to individual rows in a table. It is typically used to update a row with the $r / $_REQUEST hash from a form submission. The last argument is the primary key of the row in question, which may have been derived from calling the add_new_row() function.

In the following doozer example code snippet, the same piece of code can be used to either insert a new row or update an existing one depending on whether or not a primary key has been passed in the request:

if(!$r['page_id']){ $r['page_id'] = add_new_row('simple_page'); }

$reply = update_table('simple_page', $r, $r['page_id']);

This function can also be used to delete / expire a row thus:

$reply = update_table('simple_page', array('expired_date' => mktime()), $r['page_id']);

If you want to set a NULL value in a column, for example to undelete / unexpire a row, use:

$reply = update_table('simple_page', array('expired_date' => 'nulled'), $r['page_id']);

This function can also be used to delete / expire a row thus:

$reply = update_table('simple_page', array('expired_date' => mktime()), $r['page_id']);

The update_table_extra($table_name, $r, $where, $primary_key) Function

This function behaves in the same way as the above but allows you to add an extra where clause into the SQL.

$reply = update_table('simple_page', array('expired_date' => mktime()), "page_tags not like '%Public%Document%'", $r['page_id']);

This code expires a particular row in the simple_pages table but only if it hasn't been tagged as a public document.

The date_splitter('publication_date') Function

The interface code returns dates in dd/mm/yyyy format and this needs to be turned into a unix timestamp for storage (date columns should be set as int(20)).

This function takes a date in the $r hash and converts it into a timestamp. The function call is a little unusual in that the function doesn't return anything. So where you have a date in $r['publication_date'] call:

date_spliter('publication_date');
$reply = update_table('my_pages', $r, $page_id);

The call above extracts the date from $r and resets the value with the corresponding timestamp:

function date_splitter($key){

    global $r;

    $b = explode('/', $r[$key]);

    $ts = mktime(0,0,0, $b[1], $b[0], $b[2]);
    
    $r[$key] = $ts;
    
    //print_r($r);
    
    }

The get_options($reply, $value_column, $label_column) Function

This functions more properly belongs in the interface_functions.php file as it is related to form building. Its purpose is to populate <select/> form elements with a list of options.

It takes a reply hash from just_sql() as it's first argument, the second two parameters are the column names you want to map to the value and label of the option respectively. The function can be called like so:

return get_options(just_sql("select * from panel_group where expired_date is null order by panel_group_name"), "panel_group_id", "panel_group_name");

The function is used extensively in option_switcher.php which determines what the option list should be for any <select/> elements in forms generated by build_form($skini_handle).

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 04:05 PM | Comments (0)

Authentication (Login / Logout) & Sessions

Authentication runs of off one table called user and is based upon email address and a password stored as a hash. Once authenticated the user_id from the table is passed around using PHP's $_SESSION variable and relies on cookies.

Sessions are trixy in PHP and you may benefit from referring to the manual - http://uk.php.net/session. You have no real control over the session timeout length for example and currently the user can get unceremoniously dumped out to the login page when the session expires.

The login_doozer.php script handles registration of new users too. This invloves the user being provided with a registration key from the system administrator. If you wish to change your password or have forgotten it, this same mechanism will do the job. Your old row will be expired and a new one created. The system would benefit from an email verification function.

Once you have logged in your user_id from the user table will be used as insert_by and update_by values when doing DB inserts and updates from the system and is encoded in the $user_id variable.

See the login_doozer.php and logout.php scripts in one of the example applications for more details.

For an authenticated script your should include the following lines:

<?
include("paths.inc.php");

session_start();

if(!$_SESSION['user_id']){ header('Location: login.php'); }

$user_id = $_SESSION['user_id'];
................................
?>

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 03:18 PM | Comments (0)

The just_sql() Function & The $reply Hash

The SQL facility for querying the database and getting results back has been abstracted into one function. This presumes that your application has its tables in a single database. If this is not the case you can use the do_sql($db, $sql, $debug) function to specify which db credentials .ini file to use for the query where it is different from the value set in $db_name.

The main function for running a query is just_sql(sprintf("select * from foo where bar = %d", $bar_id)). I tend to use this function in conjunction for sprintf() for extra security.

The $reply Hash

The following code:

$reply = just_sql("select * from equipment where expired_date is null order by update_date desc limit 3");

$rows = $reply['rows'];

header('Content-type: text/plain');

print_r($reply);

produces the following reply hash:

Array
(
    [num_of_rows] => 3
    [rows] => Array
        (
            [0] => Array
                (
                    [equipment_id] => 31
                    [name] => DVD Player
                    [description] => 
                    [insert_by] => 1
                    [insert_date] => 1228746274
                    [update_by] => 1
                    [update_date] => 1228746274
                    [expired_date] => 
                )

            [1] => Array
                (
                    [equipment_id] => 30
                    [name] => Portable Video Conferencing Equipment
                    [description] => 
                    [insert_by] => 1
                    [insert_date] => 1226590805
                    [update_by] => 1
                    [update_date] => 1226590805
                    [expired_date] => 
                )

            [2] => Array
                (
                    [equipment_id] => 29
                    [name] => 7 X PCs
                    [description] => 
                    [insert_by] => 1
                    [insert_date] => 1226327521
                    [update_by] => 1
                    [update_date] => 1226327521
                    [expired_date] => 
                )

        )

    [first_row] => Array
        (
            [equipment_id] => 31
            [name] => DVD Player
            [description] => 
            [insert_by] => 1
            [insert_date] => 1228746274
            [update_by] => 1
            [update_date] => 1228746274
            [expired_date] => 
        )

    [status] => 1
    [message] => OK
    [sql] => select * from equipment where expired_date is null order by update_date desc limit 3
)

N.B. The where clause of the query includes expired_date is null. Every table should have a number of common columns, including an expired_date. This is set with a unix_timestamp() when the row is to be deleted from the DB. In other words, no rows are ever truly deleted, merely expired. You need this test in your where clauses to exclude "deleted" rows.

The result rows are found in $reply['rows'] as a list of hashes. The first row is found in $reply['first_row'] too in case that's all you need. $reply['num_of_rows'] tells you how many rows were returned and the original query SQL is included in $reply['sql'] for easier debugging of dynamic queries.

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 01:52 PM | Comments (0)

The $r / $_REQUEST Shortcut

Each web application built with the framework has its own paths.inc.php file for setting up common variables and paths for the application.

paths.inc.php should be the first include in any application script. One of the roles it performs is to alias the $_REQUEST global variable. A copy of this variable is created and named $r. This is for the sake of pith and saves typing as much as anything else.

$r is used quite extensively in the SQL functions. Elements in application web forms should be named the same as their corresponding DB columns. That way the $_REQUEST/$r hash can then be passed to the SQL functions to do quick and easy inserts and updates such as in the example below for adding a new user:

$userid = add_new_row('user');
        
$r['user_password'] = sha1($r['user_password']);
        
$reply = update_table('user', $r, $userid);

Tags: Lightweight OOP Framework , Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 12:17 PM | Comments (0)

Getting MySQL-python-1.2.2 to work on Fedora

You need to install mysql-devel:

su
cd 
yum install mysql-devel

Then you need to make sure your /usr/lib/mysql directory is linked under /usr/local/lib

ln -s /usr/lib/mysql /usr/local/lib/.

Now you can install the library

cd MySQL-python-1.2.2
python setup.py install

 

Posted by Paul Hollands pj at 11:29 AM | Comments (0)

March 29, 2009

Getting MySQL-python-1.2.2 to work with XAMPP

I'm trying to get the Python MySQLdb library to talk to my XAMMP MySQL. Here's how:

1. Before you build the db adaptor, change the site.cfg file to point to XAMMP's mysql_config

# The path to mysql_config.
# Only use this if mysql_config is not on your PATH, or you have some weird
# setup that requires it.
mysql_config = /Applications/xampp/xamppfiles/bin/mysql_config

2. Link the dylib

cp /Applications/xampp/xamppfiles/lib/mysql/libmysqlclient.15.dylib /usr/local/mysql/lib/mysql/libmysqlclient_r.15.dylib 

mkdir /Applications/xampp/xamppfiles/include
ln -s /usr/local/mysql-5.1.32-osx10.5-powerpc/include /Applications/xampp/xamppfiles/include/mysql

3. You have to point your script to the localhost using the machines acutally IP address as if it was a remote server.

Tags: MySQL , Python , XAMPP

Posted by Paul Hollands pj at 11:59 AM | Comments (0)

CherryPy HTMLTemplate

HTMLTemplate - CherryPy Tools - Trac

Tags: Python

Posted by Paul Hollands pj at 02:15 AM | Comments (0)

ZPT with CherryPy

ZPT - CherryPy Tools - Trac

svn co svn://svn.zope.org/repos/main/zpkgtools/trunk

Tags: ZPT

Posted by Paul Hollands pj at 12:05 AM | Comments (0)

March 27, 2009

Setting Up Database Connection Credentials With .ini Files

Database credentials are stored in the common_php directory in Windows .ini format files.

[connection_parameters]

user = youruser
password = yourpasswordhere
host = localhost
type = mysql
db = blah

This file should be saved as a .ini file in common_php, and usually with the name of your DB. So for a db named blah, you would name the file blah.ini, and also set $db_name = 'blah'; in your applications paths.inc.php file.

If for extra security you want to name your .ini file something else then that's fine as long as to set $db_name to that.

When the just_sql() function is called it looks for a .ini file named after whatever $db_name is set to, and then parses the contents of that file into a hash to extract the connection credentials and open up a connection before performing the SQL transaction.

The .ini files are protected from view from the webserver using a .htaccess file:

<Files *.ini>
order deny,allow
deny from all
</Files>

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 05:22 PM | Comments (0)

Setting Environment Paths With paths.inc.php

Paths for each individual application are set withing the application directory itself in a file called paths.inc.php.

<?php

$r = $_REQUEST;

global $debug;

$paths = array();

if(file_exists("H:\\xampp\\htdocs\\")){ $docroot = "H:\\xampp\\htdocs\\"; }
if(file_exists("/Applications/xampp/htdocs/")){ $docroot = "/Applications/xampp/htdocs/"; }
if(file_exists("/userdata/home/depts/lis/")){ $docroot ="/userdata/home/depts/lis/"; }

$paths["host"] = $_SERVER["HTTP_HOST"];

$paths["baseref"] = "http://".$paths["host"]."/lis/simple_pages/";

$paths["js"] = "http://".$paths["host"]."/lis/js/";

$paths["js_path"] = $docroot."js/";

$paths["images"] = "http://".$paths["host"]."/lis/images/";

$paths["docroot"] = $docroot;

$config['BaseAddress'] = $paths['baseref'];

$asterix = '<span class="mandatory" style="color: red;">*</span>';

$db_name = 'libfaq';

$user_id = 1;

?>

This should be the first include in any application script:

<?

include("paths.inc.php");

session_start();

if(!$_SESSION['user_id']){ header('Location: login.php'); }

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past

# Turn off warnings

error_reporting(E_ERROR | E_PARSE);

$debug = false;

$title = "LIS Simple Pages Site - Table of Contents";
.........

The script does several things. Firstly, it creates the $paths hash. Secondly, it aliases $_REQUEST to $r. N.B. If your name any other variable $r things will go bady for you. $r can be used with the add / update functions to add and update rows in a table where the column names match the web form elements.

$booking_id = add_new_row('booking);

$reply = update_table('booking', $r, $booking_id);

The $db_name filehandle is also set here (as opposed to in db_name.inc.php as previously). This refers to the .ini file name stump where your DB settings and credentials are stored. This is usually named after the database itself, but doesn't have to be.

Note also that a default $user_id is set here too. This is important for the add / update functions to work in applications where no user_id is set in the session. Normally this is picked up from the session after login and is the user_id from the user table, in which case this value gets overwritten.

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 11:34 AM | Comments (0)

March 26, 2009

Python script for producing svn diffs


import os

my_file = open('changed_files.txt','r')

lines = my_file.readlines()

for line in lines:

  plode = line.strip()

  els = plode.split('/')
    
  os.popen("svn diff -r 455 " + line.strip() + " > " + "_".join(els) + ".diff")

  print "svn diff -r 455 " + line.strip() + " > " + els[-1] + ".diff"


Tags: Python , Version Control

Posted by Paul Hollands pj at 09:31 PM | Comments (0)

.htaccess Tips and Tricks

.HTACCESS files useful tips and tricks

Tags: Apache stuff

Posted by Paul Hollands pj at 08:56 PM | Comments (0)

March 24, 2009

HTML tags you need to know about

10 Rare HTML Tags You Really Should Know - Nettuts

 

Posted by Paul Hollands pj at 03:35 PM | Comments (0)

CherryPy does ZPT

ChoosingATemplatingLanguage - CherryPy - Trac

Tags: Python

Posted by Paul Hollands pj at 11:14 AM | Comments (0)

March 23, 2009

The common_php directory

The common_php directory contains a number of common function files that need to be included in each script in any application. It includes PHP files with one or more functions related either to the application framework or to individual web applications.

add_update_functions.php
book_request_functions.php
calendar.php
calendar_style.css
check_url.php
cip_functions.php
convert_line_breaks.php
date_parser.php
db_name.inc.php
do_sql.php
email_functions.php
has_value.php
interface_functions.php
is_even.php
kpi_functions.php
libfaq.ini
option_switcher.php
quote_me.php
read_config.php
read_file.php
round_me.php
target_use_attributes.php
upload_file.php
user_functions.php
Framework Specific Files
  • .htaccess
    protection for the credentials files
  • add_update_functions.php
    Functions for adding and updating rows in MySQL tables with the contents of the $_REQUEST hash ($r).
  • calendar.php
    A calendar pop-up used to populates date fields in the interface.
  • calendar_style.css
    Stylesheet for the above
  • check_url.php
    Contains one function for validating URLs
  • convert_line_breaks.php
    Converts new lines to <br/> tags.
  • db_name.inc.php
    Formally a holder for the database name for a single application, but now deprecated. File still needs to be present though.
  • do_sql.php
    Holds a number of key functions related to SQL querying including just_sql($sql) which is used extensively in every application.
  • email_functions.php
    Functions for building multipart email headers for sending attachments and HTML email.
  • has_value.php
    One function of the same name which runs the gauntlet of PHP tests to determine if a value is or isn't set for a particular variable. Note that if a value of zero is set it returns false. Be careful when trying to set zero as a value in SQL transactions.

    In terms of MySQL zero is a value (as different from NULL). Because PHP values are scalar and typing is dynamic this can get you into all kinds of trouble if you are testing a value from a MySQL row as a boolean, (zero == false in PHP).
    function has_value($var){
    
            if(is_array($var)){ return has_value($var[0]); }
    
    	if(!isset($var)){ return(false); }
    
    	if(is_null($var)){ return(false); }
    
    	if($var === 0){ return(false); }
    
    	if($var === NULL){ return(false); }
    
    	if($var === 'NULL'){ return(false); }
    
    	if($var === 'null'){ return(false); }
    
    	if($var === ""){ return(false); }
    
    	preg_match('/\w/', $var, $matches);
    
    	if(count($matches) == 0){ return(false); }
    
    	return(true);
    
    	}
  • interface_functions.php
    Functions for building HTML forms from .skini definitions in the skins/ directory. These are written in Windows .ini file format. Picklists in <select/> elements are handled separately by functions in the option_switcher.php file.
  • is_even.php
    Two functions, one to tell if a number is odd or even and the other to set the style class for alternating rows in a table.
  • libfaq.ini
    DB connection definition and credentials store in a windows .ini file (ensure this file type is excluded from display in the Apache configuration). Used by the functions in do_sql.php.
    [connection_parameters]
    
    user = youruser
    password = yourpasswordhere
    host = localhost
    type = mysql
    db = yourdbnamehere
    
  • option_switcher.php
    Used to define the <options/> for any select form elements built using the interface functions.
  • quote_me.php
    Contains a function of the same name which properly escapes MySQL inserts automatically detecting for get_magic_quotes_gpc to avoid double escaping.
  • read_config.php
    Contains one function of the same name and is used for pulling the contents of a Windows .ini file into a hash.
  • read_file.php
    Functions for reading a file into a string or a list of lines.
  • round_me.php
    An attempt at a function which correctly rounds monetary values to 2 decimal places as PHP's round function does odd things which might be mathematically more accurate but are annoying in the context of pounds and pence and lead to inaccuracies. I'm not clear whether this solves the issue, and it is a work in progress. Use with caution.
  • upload_file.php
    Functions related to uploading files once they get to the server. You need to read the PHP manual to see what extra elements to include in your form for the process to work. The error reporting functions in this code don't work properly.
  • user_functions.php
    Some basic user functions, including functions to determine if the user is an administrator.

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 04:43 PM | Comments (0)

File Structure of the Framework

The file structure for the framework is quite shallow. The root includes the following files and folders:

common_php/
js/
skins/
upload_temp/
header.php
footer.php

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 03:54 PM | Comments (0)

Lightweight PHP Web Application Framework - Contents

File Structure of the Framework

Function Include Files in common_php

Setting Environment Paths With paths.inc.php

Setting Up Database Connection Credentials With .ini Files

The $r / $_REQUEST Shortcut

The just_sql() Function & The $reply Hash

Authentication (Login / Logout) & Sessions

Doing Database "Create Review Update Delete" With Functions In add_update.php

Common Header & Footer Includes

Building Forms With interface_functions.php & .skini Files

Populating select Element Option Lists with option_switcher.php

Using the poppy() JavaScript Function For Application Alerting

Using JavaScript Validation For Mandatory Form Elements

Using prototype.js For Faster JS Development and AJAX

Building Application DB Tables with tables.ini and create_database.php

Tags: Lightweight PHP Web Application Framework

Posted by Paul Hollands pj at 03:41 PM | Comments (0)

Google API Translation

Fuzzy Buckets: Translation Tools

 

Posted by Paul Hollands pj at 12:28 AM | Comments (0)

March 18, 2009

Google Language API Docs

Developer's Guide - Google AJAX Language API - Google Code

 

Posted by Paul Hollands pj at 04:59 PM | Comments (0)

March 17, 2009

Dell Mini Running Mac OS X

How To: Hackintosh a Dell Mini 9 Into the Ultimate OS X Netbook

 

Posted by Paul Hollands pj at 11:04 AM | Comments (0)

March 16, 2009

Edinburgh Kung Fu

Yee's Hung Ga Kung Fu Edinburgh - Home

 

Posted by Paul Hollands pj at 11:09 PM | Comments (0)

March 15, 2009

My Jython Regex Servlet

The servlet:

from javax.servlet.http import HttpServlet

import re

import string

class regexTest(HttpServlet):

    def doGet(self,request,response):

        self.doPost (request,response)

    def doPost(self,request,response):
    
        #param_names = request.getParameterNames()

        writer = response.getWriter()

        response.setContentType ("text/plain")
        
        try: expr = request.getParameterValues("expr")[0]

        except:
            
            final_hash = { "errors" : ['']}
            
            final_hash['errors'][0] = 'You must enter an expression.'

            writer.println(final_hash)

            sys.exit

        try: this_text = request.getParameterValues("text")[0]

        except:
            
            final_hash = { "errors" : ['']}
            
            final_hash['errors'][0] = 'You must enter some text.'

            writer.println(final_hash)
            
            sys.exit

        reg = regexTest()

        try: final_hash = reg.test_it(expr, this_text)
        
        except:
            
            final_hash = { "errors" : ['']}
            
            final_hash['errors'][0] = 'Failed to run test.'

            writer.println(final_hash)
            
            sys.exit
        
        #except: writer.println('')
        
        #writer.println('')

        writer.println(final_hash)
        

                
    #def __init__(self, text="Stuff"):
        
    #    self.text = text
        
    def test_it(self, exp, text):
        
        final_hash = {}
        
        try: this_reg = re.compile(exp) 
        
        except:
            
            final_hash['error'] = ['Your expression did not compile'] 
        
            return final_hash
        
        #print this_reg
        
        this_match = this_reg.findall(text)
        
        final_hash["results"] = this_match 
        
        if this_match:
        
            return final_hash
        
        else:
        
            final_hash['error'] = ['Your expression found no matches']
            
            return final_hash

#if __name__ == "__main__":
    
#    reg = regexTest()
    
#    print reg.test_it('[\d]+', 'These are words and phone 07590 574469')


The JSP with the JSON:

<%@ page contentType="text/html" %>
<!-- %@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" % -->
<html>
<head>
    <link rel="stylesheet" href="styles.css" type="text/css" media="all"/>    
    <script type="text/javascript" src="js/prototype.js"></script>
    <script type="text/javascript" src="js/set_date.js"></script>
    <script type="text/javascript">
    function do_regex(){
    
        if(($('text').value == '') || ($('regex').value == '')){ alert('You must enter some text and an expression'); return false; }
    
        var url  = 'regexTest.py';
        var params = '?text=' + escape($('text').value) + '&expr=' + escape($('regex').value);
        var myAjax = new Ajax.Request(
                            url,
                            {
                                    method: 'get',
                                    parameters: params,
                                    onComplete: show_response
                            });
    
        function show_response(this_request){
        
            this_result = this_request.responseText;
        
            $('regex_here').value = this_result;
            
            }

        }

    </script>
    <title>Regular Expression Test Harness</title>
</head>
<body>
<h2 style="margin-left: 1em;">Regex Test Harness</h2>
<form action="#" method="post" style="width: 80%; margin: 2em; border: 1px solid #dcdcdc;">

<p style="margin-left: 1em;">
<label id="text_block_label" class="label_italic">Text
<em class="astrix" id="text_mandatory" style="display: none;">*</em></label>
<br/>
<em id="text_outer">
<input type="text" name="text" id="text"  class="four_c" value=""/>
</em>
</p>

<p style="margin-left: 1em;">
<label id="regex_block_label" class="label_italic">Regex
<em class="astrix" id="regex_mandatory" style="display: none;">*</em></label>
<br/>
<em id="regex_outer">
<input type="regex" name="regex" id="regex"  class="four_c" value="" onblur="do_regex()"/>
</em> <input type="button" value="Go»" class="button" onclick="do_regex()"/>
</p>

<form>
<textarea style="height: 100px; width: 400px; margin: 1em; color: red;" id="regex_here">
</textarea>
</form>

</form>
</body>
</html>

Tags: Jython , Tomcat

Posted by Paul Hollands pj at 10:01 PM | Comments (0)

March 14, 2009

phpPGAdmin

SourceForge Site

 

Posted by Paul Hollands pj at 03:37 PM | Comments (0)

March 12, 2009

BibClassify Keyword Extraction into SKOS RDF

Atlantis Institute of Fictive Science: BibClassify Admin Guide

Tags: RDF

Posted by Paul Hollands pj at 03:10 PM | Comments (0)

March 09, 2009

Getting PyServlet and Jython working

After a couple of days of hairloss I put the following into the container web.xml:

<servlet>
    <servlet-name>PyServlet</servlet-name>
    <servlet-class>org.python.util.PyServlet</servlet-class>
    <param-name>python.home</param-name>
    <param-value>/usr/local/jython</param-value>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>PyServlet</servlet-name>
    <url-pattern>*.py</url-pattern>
</servlet-mapping>

Also I had to link:

/usr/local/jython/Lib to /Library/Tomcat/Home/conf/common/lib/Lib

and do the same for my application lib directory.

Now my jylets work.

Tags: Jython

Posted by Paul Hollands pj at 11:37 AM | Comments (0)

March 07, 2009

Regular Expressions in JavaScript

Regular Expressions in JavaScript | evolt.org

 

Posted by Paul Hollands pj at 10:32 PM | Comments (0)

Jython Webapp Tutorial

Jython Webapp Tutorial - Part 1 - Writing Servlets in Jython

Tags: Jython

Posted by Paul Hollands pj at 03:41 PM | Comments (0)

Mo' Web Hooks

Web Hooks / FrontPage

 

Posted by Paul Hollands pj at 10:19 AM | Comments (0)

What the hell are webhooks?

Web Hooks

 

Posted by Paul Hollands pj at 10:17 AM | Comments (0)

March 05, 2009

XSL for Twitter to RDF

twitter-rdf.xsl at a0ec36781e3af9995a3bccb228e48dd51692b814 from tommorris's twitter-rdf - GitHub

Tags: RDF

Posted by Paul Hollands pj at 09:47 PM | Comments (0)

March 01, 2009

Web Curator Tool

Web Curator Tool

 

Posted by Paul Hollands pj at 08:15 PM | Comments (0)

February 25, 2009

FOP Apache XSL-FO processor

FOP: Quick Start Guide

 

Posted by Paul Hollands pj at 10:43 PM | Comments (0)

Command line backup tool

backup2l - low-maintenance backup/restore tool

 

Posted by Paul Hollands pj at 10:34 AM | Comments (0)

February 21, 2009

Hoodoo Nation Sack

Nation Sack

 

Posted by Paul Hollands pj at 09:53 PM | Comments (0)

February 17, 2009

Disk Partitioning

Linux Tips - Disk Partitioning

Tags: Linux

Posted by Paul Hollands pj at 09:12 PM | Comments (0)

Webserver File Permissions

Joomla Tutorials - Joomla and Unix file permissions - Explanation

 

Posted by Paul Hollands pj at 11:51 AM | Comments (0)

EPrints Romeo AJAX lookup widget

EPrints Romeo AJAX lookup widget - IE Demonstrator - Confluence

 

Posted by Paul Hollands pj at 11:10 AM | Comments (0)

February 16, 2009

Tour of California

Tour of California

 

Posted by Paul Hollands pj at 11:02 PM | Comments (0)

February 09, 2009

Planet Feed Aggregator

Planet Feed Reader

Tags: RSS

Posted by Paul Hollands pj at 11:53 AM | Comments (0)

February 05, 2009

John Heussenstamm

John Heussenstamm

 

Posted by Paul Hollands pj at 12:08 AM | Comments (0)

Pentatonic Licks

YouTube - minor pentatonic riff #2

 

Posted by Paul Hollands pj at 12:00 AM | Comments (0)

February 02, 2009

AC / DC You Shook Me All Night Long

Ac Dc - ( You Shook Me All Night Long tab )

 

Posted by Paul Hollands pj at 09:01 PM | Comments (0)

PHP, MySQL and Tomcat

PHP and MySQL in Tomcat with Quercus � Net Wolf’s Blog

Tags: Tomcat

Posted by Paul Hollands pj at 02:57 PM | Comments (0)

Using PHP with Tomcat

UsingPhp - Tomcat Wiki

Tags: Tomcat

Posted by Paul Hollands pj at 02:54 PM | Comments (0)

January 28, 2009

Emptees

Emptees - Tees

 

Posted by Paul Hollands pj at 07:44 AM | Comments (0)

January 23, 2009

Vintage Ukelele

DJM Music Ltd - VUK15N - Ukulele - Vintage Natural

 

Posted by Paul Hollands pj at 11:02 PM | Comments (0)

January 21, 2009

MySource Matrix

MySource Matrix Open Source CMS - Home

 

Posted by Paul Hollands pj at 09:00 PM | Comments (0)

January 19, 2009

The chili scale

 

Posted by Paul Hollands pj at 08:45 PM | Comments (0)

Using PHP and PGP

Kelv's Programming Area - How to use PGP / GnuPG with PHP

Tags: PHP

Posted by Paul Hollands pj at 04:05 PM | Comments (0)

Uploading file into a MySQL BLOB

Uploading Files To MySQL Database - PHP MySQL Tutorial

 

Posted by Paul Hollands pj at 03:07 PM | Comments (0)

December 21, 2008

Robot Access How-to

Managing Robot's Access To Your Website

Tags: Apache stuff

Posted by Paul Hollands pj at 05:54 PM | Comments (0)

December 15, 2008

PHP / SWF graphing

PHP/SWF Charts > Introduction

Tags: PHP

Posted by Paul Hollands pj at 11:05 AM | Comments (0)

November 19, 2008

Getting highlighted text with Javascript

CodeToad - Javascript Get Selected Text.

Sometimes you want to know what

Tags: JavaScript

Posted by Paul Hollands pj at 11:12 AM | Comments (0)

November 15, 2008

In Memoriam

John Peel

Picture originally published on http://www.picturesofwalls.com/..

 

Posted by Paul Hollands pj at 12:03 AM | Comments (0)

November 14, 2008

Unversion an SVN working copy

unversion a working copy | TortoiseSVN

Tags: Subversion

Posted by Paul Hollands pj at 10:53 AM | Comments (0)

November 09, 2008

Chuck Norris Eye Drops

 

Posted by Paul Hollands pj at 06:28 PM | Comments (0)

October 23, 2008

MTB Cumbria

RADS - Mountain Biking in Cumbria

 

Posted by Paul Hollands pj at 09:58 PM | Comments (0)

October 16, 2008

La Crema Carnela

Restaurante Crema Canela

 

Posted by Paul Hollands pj at 07:13 PM | Comments (0)

iTunes XML Parser in PHP

Code Triangle :: iTunes XML Parser for PHP

Tags: PHP

Posted by Paul Hollands pj at 03:21 PM | Comments (0)

October 11, 2008

POSH

Plain Old Semantic HTML - Microformats

 

Posted by Paul Hollands pj at 09:19 AM | Comments (0)

October 08, 2008

Nickel Creek - The Fox

YouTube - The Fox

 

Posted by Paul Hollands pj at 03:15 PM | Comments (0)

September 17, 2008

O2 Wireless Hotspots

Wireless Hotspots - Mobilise your laptop - Mobilise your office - SME - Business - O2

 

Posted by Paul Hollands pj at 02:05 PM | Comments (0)

September 14, 2008

ARC RDF classes for PHP

Easy RDF and SPARQL for LAMP systems - ARC RDF Classes for PHP

 

Posted by Paul Hollands pj at 08:27 PM | Comments (0)

September 11, 2008

Copac Z39.50 Interface

Copac Z39.50 Interface

Address: z3950.copac.ac.uk
Port: 210
Database name: COPAC
Record syntax: XML, GRS-1 or SUTRS

 

Posted by Paul Hollands pj at 03:59 PM | Comments (0)

September 08, 2008

Online PFM

Buxfer: Summary

 

Posted by Paul Hollands pj at 09:30 PM | Comments (0)

September 07, 2008

Sparrow Guitars

Sparrow Guitars' latest slideshow on Flickr

 

Posted by Paul Hollands pj at 07:24 PM | Comments (0)

September 04, 2008

Tangle Wood Resonator

BEM MUSIC : Resonators - TBS 900 VS Acoustic Resonator

BEM MUSIC : Resonators - TBS 800 ANS Slim Semi-Acoustic Resonator

 

Posted by Paul Hollands pj at 07:44 PM | Comments (0)

September 03, 2008

Palin vs Bears

Palin vs Bears

 

Posted by Paul Hollands pj at 10:29 PM | Comments (0)

August 31, 2008

Mondeca Ontology Software

Mondeca ITM, ontology management, ontology software, ontology editor, SKOS, OWL, RDF, - Mondeca

Tags: OWL

Posted by Paul Hollands pj at 09:21 AM | Comments (0)

August 30, 2008

Woodpigeon

MySpace.com - woodpigeon - calgary, CA - Indie / Alternative / Pop - www.myspace.com/woodpigeon

 

Posted by Paul Hollands pj at 10:50 PM | Comments (0)

August 28, 2008

Ride the Alps

Ride The Alps :: The Mountain Bike Specialist

 

Posted by Paul Hollands pj at 10:00 PM | Comments (0)

August 26, 2008

Flickr Developer Blog

Code: Flickr Developer Blog - API Responses as Feeds

 

Posted by Paul Hollands pj at 09:02 AM | Comments (0)

August 22, 2008

Problems with pound signs with Apache serving UTF-8

Put the following in the header:

<? header("Content-Type: text/html; charset=ISO-8859-1"); ?>

 

Posted by Paul Hollands pj at 11:57 AM | Comments (0)

Rainer Ptacek

YouTube - Rainer Ptacek - Life Is Fine - on Jools Holland in 1993

 

Posted by Paul Hollands pj at 10:44 AM | Comments (0)

August 20, 2008

Attempting to install PHP YAZ

# There's no PECL
yum install php-pecl-apc
# Cool but there's no phpize
yum -y install php-devel
# Cool so now let's try YAZ
/usr/bin/pecl install yaz
# Hmm but there's no YAZ
links http://ftp.indexdata.dk/pub/yaz/yaz-3.0.34.tar.gz
# Builds it
untar | ./configure | make | make install
# Try again 
/usr/bin/pecl install yaz
# Path to YAZ
/usr/local/bin
# Edit /etc/php.ini add in the extension=yaz.so line

 

Posted by Paul Hollands pj at 03:44 PM | Comments (0)

August 18, 2008

A JS function to stop access to external links

Cumbria BBC
<script type="text/javascript">
function is_external(url){

if(url.indexOf('cumbria.ac.uk') > -1){ return true; }

else{ alert("Sorry! You can't access external links from here."); return false; }
}
</script>

<p>
<a href="http://www.cumbria.ac.uk" onclick="return is_external(this.href + '')">Cumbria</a>
 <a href="http://www.bbc.co.uk" onclick="return is_external(this.href + '')">BBC</a>
</p>

 

Posted by Paul Hollands pj at 10:30 AM | Comments (0)

August 07, 2008

Bloody Apple crappy syslogd nearly fried my new poota

Temp got up to about 80 ° :(

launchctl stop com.apple.syslogd; 
rm /var/log/asl.db; 
rm /var/log/system.log;
launchctl start com.apple.syslogd

And in /System/Library/LaunchDaemons/com.apple.syslogd.plist :

<string>/usr/sbin/syslogd</string> <string>-c</string> <string>0</string>

 

Posted by Paul Hollands pj at 03:14 PM | Comments (0)

August 06, 2008

iPhone Atlas

iPhone Atlas - iPhone guides, help, applications, news and more, updated daily.

 

Posted by Paul Hollands pj at 07:16 PM | Comments (0)

Git Book

The Pragmatic Bookshelf | Pragmatic Version Control Using Git

 

Posted by Paul Hollands pj at 04:49 PM | Comments (0)

Git version control software documentation

Git - Fast Version Control System

 

Posted by Paul Hollands pj at 04:32 PM | Comments (0)

August 05, 2008

MCPA Mechanical License Request Form

MPCA Mechanical License Request

 

Posted by Paul Hollands pj at 10:40 PM | Comments (0)

COPAC Z39.50 targets

Copac SRU Interface

Tags: Digital Libraries

Posted by Paul Hollands pj at 03:30 PM | Comments (0)

Rock Shox Tora Fork Oil Leak Issue

Heads up for Rockshox owners with newer forks - Dirt Rag Forums

05-13-2008, 07:55 PM

http://www.dirtragmag.com/forums/showthread.php?t=17308

I'm not sure if this has been posted previously but I figure its important. There is a problem with the damper leg of newer RS forks with external rebound adjust. Apparently, the O ring that is used as a seal on the bottom of that leg is defective resulting in oil leaking out through the adjuster knob. Currently its showing up mostly on the Tora's and Dart's but it's possible that the problem extends throughout the line. If you own one of these forks, check the damper adjust for any sign of leakage. If you have a leak take it to your shop and have it sent away for repair. You or the shop will have to pay for shipping but the repair should be covered by the distributer. As far as I know, Sram has not issued a recall as of yet, and is having the distributers deal with it on a case by case basis. The problem is not restricted to a couple of bike lines, it is anything that is speccing the forks. The shop I work for currently has about 20 bikes from 2 different lines sitting with the fork stripped off and out for repair.

 

Posted by Paul Hollands pj at 10:19 AM | Comments (0)

August 04, 2008

Karen A. Coombs' Web API code

Karen A. Coombs' Web API code:

http://www.librarywebchic.net/presentations/ala2008/worldcat_search.txt

 

Posted by Paul Hollands pj at 12:50 PM | Comments (0)

Library Web Chic

Library Web Chic WorldCat Wordpress Widget

Tags: Digital Libraries

Posted by Paul Hollands pj at 12:49 PM | Comments (0)

WorldCat Developer Site

Main Page - WorldCat Developers' Network

Tags: Digital Libraries

Posted by Paul Hollands pj at 12:40 PM | Comments (0)

WorldCat Union Catalogue

WorldCat Affiliate Tools [WorldCat.org]

Tags: Digital Libraries

Posted by Paul Hollands pj at 12:11 PM | Comments (0)

August 02, 2008

Transparent PNGs in IE 6

24 ways: Transparent PNGs in Internet Explorer 6

Tags: Surface plane / Visual design

Posted by Paul Hollands pj at 04:45 PM | Comments (0)

July 31, 2008

Mac boot loader

rEFIt - An EFI Boot Menu and Toolkit

 

Posted by Paul Hollands pj at 10:46 PM | Comments (0)

AIR for AjAX

Adobe - Adobe AIR for Ajax Developers

Tags: AJAX

Posted by Paul Hollands pj at 10:32 PM | Comments (0)

More jailbreaking

Hack that iPhone and iTouch: Jailbreak, Hack and Unlock 3g iPhone and Apple Gadgets: How to Jailbreak Your 2.0 3G iPhone (Mac)

 

Posted by Paul Hollands pj at 10:13 AM | Comments (0)

PDF on iPhone How-To

Georg Fankhauser's Blog: Perfect Way to read PDF, DOC OFFLINE on Iphone

 

Posted by Paul Hollands pj at 09:48 AM | Comments (0)

July 30, 2008

'Get Twitter RSS with authentication' script for Mac OS RSS screen saver

<?
$url = "http://twitter.com/statuses/friends_timeline.rss";
$ch = curl_init();    
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
curl_setopt($ch, CURLOPT_URL, $url); 
curl_setopt($ch, CURLOPT_USERPWD, "your@email.here:password"); 
$result = curl_exec($ch); 
curl_close($ch); 
echo $result; 
?>

Tags: Syndication

Posted by Paul Hollands pj at 03:31 PM | Comments (0)

July 29, 2008

MP3 ringtones on your iPhone

Got GarageBand? Create a new music project. Drag and drop your tune in as a new track. Trim it to less than 40 seconds. Choose

Share > Send Ringtone to iTunes

You're done.

 

Posted by Paul Hollands pj at 07:04 PM | Comments (0)

July 28, 2008

Drupal on XAMPP

How to Install Drupal on an XAMPP installation | drupal.org

Tags: PHP

Posted by Paul Hollands pj at 12:43 PM | Comments (0)

Collective Yesness?

Good Times!! : thechampionsoftheworld.org

 

Posted by Paul Hollands pj at 12:34 PM | Comments (0)

Justin Townes Earle

Bloodshot Records: Justin Townes Earle

 

Posted by Paul Hollands pj at 09:44 AM | Comments (0)

July 24, 2008

CrossOver Windows Games via Wine

Windows Games Seamlessly Integrated on Mac or Linux - CrossOver Games

 

Posted by Paul Hollands pj at 10:38 PM | Comments (0)

JSON Validator

JSONLint - The JSON Validator.

Tags: JSON

Posted by Paul Hollands pj at 01:29 PM | Comments (0)

July 23, 2008

Boosh Tour

The Mighty Boosh Tour 2008 Tickets

 

Posted by Paul Hollands pj at 11:12 AM | Comments (0)

July 22, 2008

JANET txt service

JANET txt: SMS Software for education, SMS for students- PageOne

 

Posted by Paul Hollands pj at 12:21 PM | Comments (0)

SAML

SAML XML.org | Online community for the Security Assertion Markup Language (SAML) OASIS Standard

Also:

Ten things you should know about SAML

 

Posted by Paul Hollands pj at 09:11 AM | Comments (0)

July 21, 2008

XSLT for Amazon AWS book search to JSON

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" id="amazon2json"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:aws="http://webservices.amazon.com/AWSECommerceService/2008-06-26"
                >
    <xsl:output method="text" indent="yes"/> 
    <xsl:strip-space elements="*" /> 
    <xsl:template match="/aws:ItemSearchResponse">
        {
        <xsl:apply-templates/>
        }
    </xsl:template>
    <xsl:template match="aws:Items">
        <xsl:for-each select="aws:Item">
            "<xsl:value-of select="aws:ASIN"/>" : {
            "isbn" : "<xsl:value-of select="aws:ASIN"/>",
            <xsl:if test="aws:ItemAttributes/aws:Author">"authors" : [
            <xsl:for-each select="aws:ItemAttributes/aws:Author">
                "<xsl:value-of select="."/>"
                <xsl:if test="position() != last()">
                <xsl:text>,</xsl:text>
                </xsl:if>
            </xsl:for-each>
                ],</xsl:if>
            <xsl:if test="aws:ItemAttributes/aws:Author">
            "author" : "<xsl:for-each select="aws:ItemAttributes/aws:Author">
                <xsl:value-of select="."/>
                <xsl:if test="position() != last()">
                <xsl:text>, </xsl:text>
                </xsl:if>
            </xsl:for-each>",</xsl:if>
            "publisher" : "<xsl:value-of select="aws:ItemAttributes/aws:Manufacturer"/>",
            "title" : "<xsl:value-of select="aws:ItemAttributes/aws:Title"/>",
            "url" : "<xsl:value-of select="aws:DetailPageURL"/>",
            "price" : "<xsl:value-of select="aws:ItemAttributes/aws:ListPrice/aws:FormattedPrice"/>",
            "format" : "<xsl:value-of select="aws:ItemAttributes/aws:Binding"/><xsl:text> </xsl:text><xsl:value-of select="aws:ItemAttributes/aws:ProductGroup"/>",
            "publication_date" : "<xsl:value-of select="aws:ItemAttributes/aws:PublicationDate"/>",
            "edition" : "<xsl:value-of select="aws:ItemAttributes/aws:Edition"/>",
            "thumbnail" : "<xsl:value-of select="aws:MediumImage/aws:URL"/>"
            }
            <xsl:if test="position() != last()">
            <xsl:text>,</xsl:text>
            </xsl:if>
        </xsl:for-each>
    </xsl:template>
    <xsl:template match="aws:OperationRequest">
    </xsl:template>
    <xsl:template match="aws:ItemLinks">
    </xsl:template>
</xsl:stylesheet>

Tags: XSLT

Posted by Paul Hollands pj at 03:21 PM | Comments (0)

July 18, 2008

Amazon's Web Services and XSLT

XML.com: Amazon's Web Services and XSLT

 

Posted by Paul Hollands pj at 04:44 PM | Comments (0)

XML to JSON in PHP

Convert XML to JSON in PHP

Tags: PHP

Posted by Paul Hollands pj at 02:59 PM | Comments (0)

Example Amazon AWS search URL string

http://ecs.amazonaws.com/onca/xml?Service=AWSECommerceService&AWSAccessKeyId=YOURKEYHERE&Operation=ItemSearch&SearchIndex=Books&Title=Drupal

 

Posted by Paul Hollands pj at 01:58 PM | Comments (0)

Amazon Web Services

Amazon Web Services Developer Connection : Making Money with the Associates Program, and PHP

 

Posted by Paul Hollands pj at 01:52 PM | Comments (0)

MARC21.py

MARC v1.0.0

 

Posted by Paul Hollands pj at 10:57 AM | Comments (0)

TikiWiki Documentation

doc.tw.o : Tikiwiki Documentation : HomePage

Tags: Wikis

Posted by Paul Hollands pj at 10:28 AM | Comments (0)

Wiki Software Comparisons

Comparison of wiki software - Wikipedia, the free encyclopedia

Tags: Wikis

Posted by Paul Hollands pj at 10:02 AM | Comments (0)

July 17, 2008

Buddy Jesus

http://en.wikipedia.org/wiki/Buddy_Christ

http://jayandsilentbob.com/budchrisdass1.html

 

Posted by Paul Hollands pj at 11:13 PM | Comments (0)

Atom Categories

Tip: Organize content with Atom categories

Tags: Atom

Posted by Paul Hollands pj at 04:49 PM | Comments (0)

Atom Syndication Format - Introduction

AtomEnabled / Developers / Atom Syndication Format

Atom Syndication Format - Introduction

Tags: Atom

Posted by Paul Hollands pj at 04:10 PM | Comments (0)

AtomServer incorporating OpenSearch over REST

AtomServer; Getting Started

Tags: Atom

Posted by Paul Hollands pj at 04:06 PM | Comments (0)

July 16, 2008

The RDF API for PHP

Introduction to RAP

Also and more usefully:

http://www4.wiwiss.fu-berlin.de/bizer/rdfapi/tests.html

Tags: PHP , RDF

Posted by Paul Hollands pj at 01:37 PM | Comments (0)

Drupal RDF Project Page

Resource Description Framework (RDF) | drupal.org

Also information about the four published modules themselves:

http://drupal.org/node/222788

 

Posted by Paul Hollands pj at 12:49 PM | Comments (0)

Flikr Machine Tags

Flickr: Discussing Machine tags in Flickr API

 

Posted by Paul Hollands pj at 12:43 PM | Comments (0)

July 15, 2008

Semantic Media Wiki

Semantic MediaWiki - semanticweb.org

 

Posted by Paul Hollands pj at 04:47 PM | Comments (0)

Drupal DOES use PHPtal

PHPTAL theme engine | drupal.org

Tags: PHP

Posted by Paul Hollands pj at 09:35 AM | Comments (0)

July 14, 2008

Screen resolution in X-Windows


http://muffinresearch.co.uk/archives/2006/08/13/running-ubuntu-under-parallels-desktop-for-mac/

 

Posted by Paul Hollands pj at 02:15 PM | Comments (0)

Running iTunes on Linux

Wine Reviews: Wine-Reviews.net | Winehq, Bordeaux, CodeWeavers, Darwine, Cedega, PlayOnLinux, winetricks, Wine-Doors, Linux, Ubuntu, Mac, OpenSolaris, Debian, FreeBSD, Windows

 

Posted by Paul Hollands pj at 01:40 PM | Comments (0)

iCal creator class in PHP

iCalcreator

 

Posted by Paul Hollands pj at 12:14 PM | Comments (0)

Drupal FAQ module

FAQ_Ask - "Ask the Expert" | drupal.org

 

Posted by Paul Hollands pj at 11:21 AM | Comments (0)

Semantic markup for FAQs

Creating a semantic FAQ page with definition lists and advanced CSS, Part 1 | A Padded Cell

Tags: Semantic Markup (divless)

Posted by Paul Hollands pj at 10:50 AM | Comments (0)

July 11, 2008

IEs on Linux

How to run Internet Explorer 7 in Mandriva 2007

 

Posted by Paul Hollands pj at 04:02 PM | Comments (0)

July 10, 2008

RDF for Glossary Entries

<rdf:Description rdf:about="http://example.org/specGL/20030210#discretionaryChoices">
  <rdfs:label xml:lang="en">discretionary choices</rdfs:label>
  <rdfs:comment>a value or behavior may be chosen from a well-defined enumerated set of two or more possibilities</rdfs:comment>
  <rdfs:isDefinedBy rdf:resource="http://www.w3.org/TR/2003/WD-qaframe-spec-20030210/"/>
  ...
</rdf:Description>

See also:

http://www.w3.org/TR/2001/REC-ruby-20010531/


http://www.w3.org/2003/03/glossary-project/analysis

Tags: RDF

Posted by Paul Hollands pj at 11:19 AM | Comments (0)

July 09, 2008

Google Code - rdflib

rdflib - Google Code

 

Posted by Paul Hollands pj at 11:21 PM | Comments (0)

RDFLib Python Libraries

RDFLib: Home

Tags: RDF

Posted by Paul Hollands pj at 11:14 PM | Comments (0)

3store

AKT - Technologies - 3store from The University of Southampton

Tags: RDF

Posted by Paul Hollands pj at 11:09 PM | Comments (0)

Redland Paper by Dajobe

Redland RDF Storage

Tags: RDF

Posted by Paul Hollands pj at 11:07 PM | Comments (0)

July 08, 2008

Mandolin Chord Builder

Ukulele Mandolin Banjo Bass Pipa Bouzouki Chords Generator

 

Posted by Paul Hollands pj at 10:04 PM | Comments (0)

dLCMS based on Silva

ETH - dLCMS - dynamic Learning Content Management System

Tags: Learning Objects

Posted by Paul Hollands pj at 01:37 PM | Comments (0)

July 07, 2008

XCRI-CAP

Online Services at the OU : Course Data Feeds : XCRI CAP/OCCAM Project

Also:

XCRI: eXchanging Course-Related Information

 

Posted by Paul Hollands pj at 09:52 AM | Comments (0)

July 02, 2008

SWORD

Main Articles: 'SWORD: Simple Web-service Offering Repository Deposit', Ariadne Issue 54

 

Posted by Paul Hollands pj at 09:02 PM | Comments (0)

Command line client which allows you to sedn attachments in email

Cleancode.org >> Projects >> email

 

Posted by Paul Hollands pj at 02:27 PM | Comments (0)

FORESITE OAI-ORE project

FORESITE

Tags: OAI-PMH

Posted by Paul Hollands pj at 10:20 AM | Comments (0)

RT FAQ Manager

rtfm-2.0-manual-v1.0.pdf (application/pdf Object)

 

Posted by Paul Hollands pj at 10:15 AM | Comments (0)

OAI-ORE

Open Archives Initiative Protocol - Object Exchange and Reuse

Tags: OAI-PMH

Posted by Paul Hollands pj at 10:14 AM | Comments (0)

Content negotiation with IE 6

How to Use Different CSS Style Sheets For Different Browsers (and How to Hide CSS Code from Older Browsers) (thesitewizard.com)

 

Posted by Paul Hollands pj at 09:08 AM | Comments (0)

RSP - Harvesting Repositories and OAI-PMH

RSP - Harvesting Repositories and OAI-PMH

 

Posted by Paul Hollands pj at 09:07 AM | Comments (0)

June 01, 2008

Oh Sleeper - The Lonesome Sisters

Doves are mourning way up in the lattice
The night folds back its starry wings
And I'm thinking of you in the twilight
Among the shadows the angels it brings

Oh sleeper now your heart is waking
As you leave me on this silent shore
And the chords of your soul that once were broken
Will ring across the waves now ever more

One terrible beautiful morning
As a bird shakes off the rain of dawn
I'll shake off time from this body
And meet you in that eternal home

Doves are mourning way up in the lattice
The night folds back its starry wings
And I'm thinking of you in the twilight
Among the shadows the angels it brings

 

Posted by Paul Hollands pj at 09:43 PM | Comments (0)

May 21, 2008

OpenSearch

XML.com: Introducing OpenSearch

 

Posted by Paul Hollands pj at 10:08 PM | Comments (0)

May 19, 2008

Using Range to get selected text in JS

Introduction to Range

Tags: JavaScript

Posted by Paul Hollands pj at 01:04 PM | Comments (0)

XML.com: Building Metadata Applications with RDF

Tags: RDF

Posted by Paul Hollands pj at 12:59 PM | Comments (0)

May 18, 2008

Talis Platform Wiki

Main Page - n� wiki

 

Posted by Paul Hollands pj at 07:40 PM | Comments (0)

May 06, 2008

How can LIS use web technology to support learning in a distributed university?

 

Posted by Paul Hollands pj at 10:15 PM | Comments (0)

April 20, 2008

ONLamp.com -- Improve Your Build Process with Ant

Tags: PHP

Posted by Paul Hollands pj at 08:05 PM | Comments (0)

April 15, 2008

Python script for getting changed files

The following Python script gets you a list of files changed between two subversion revisions:

import sys
import os
import re

lines = []

for counter in range(int(sys.argv[1]) - 1, int(sys.argv[2]) + 1):
    lines.append(os.popen('/usr/local/bin/svn log -vv -r  ' + str(counter)));

tally = {}

for results in lines:
    for line in results:
        reg = re.compile("svn-repository")
        if reg.search(line):
            tally[line] = 1

final = tally.keys()

final.sort()

print " " + " ".join(final)

 

Posted by Paul Hollands pj at 05:06 PM | Comments (0)

Academi version of add_update_functions

function date_splitter($key){

    global $r;

    $b = explode('/', $r[$key]);

    $ts = mktime(0,0,0, $b[1], $b[0], $b[2]);
    
    $r[$key] = $ts;
    
    }

function get_options($reply, $vcol, $lcol){
    
    $opts = array();
    
    if(count($reply['rows']) > 0){ foreach($reply['rows'] as $row){
        
        $opts[] = '

 

Posted by Paul Hollands pj at 04:24 PM | Comments (0)

Coniston version of email_functions with BCC

function get_mail_headers($from){

    $boundary = "boundary_".mktime();
    
    $headers['boundary'] =  '--'.$boundary;
    
    $headers['endary'] =  '--'.$boundary.'--';
    
    $head = array();
    
    $head[] = 'MIME-Version: 1.0';
    
    $head[] = "From : ".$from;
    
    $head[] = "Bcc : ".$from;
    
    $head[] = 'Content-Type: multipart/mixed; '."\r\n\t".'boundary="'.$boundary.'"';
    
    $head[] = 'Content-Transfer-Encoding: 8bit';
    
    $head[] = "\r\n";
    
    $headers['head'] = $head;
    
    $headers['printable'] = implode("\r\n", $headers['head']);
    
    return $headers;
    
    }

 

Posted by Paul Hollands pj at 04:18 PM | Comments (0)

February 24, 2008

Presentation - What value can learning technologies add to student learning when embedded within the curriculum & integrated within flexible learning spaces?

What do learning technologies add? - Paul Hollands 2008

 

Posted by Paul Hollands pj at 01:34 PM | Comments (0)

January 30, 2008

How to disable third party cookies in Firefox

The developers of Firefox removed the option to disable third party cookies in firefox 2.0 stating the reason that it was not possible to block all third party cookies with this function. Third Party Cookies are mainly cookies that track user behavior, the big ad networks for instance like to use them a lot. There are basically two options to disable third party cookies in Firefox.

The first would be to disable it manually by opening about:config from the address bar. Search for network.cookie.cookieBehavior and take a look a the value. If it is set to 0 you accept all cookies, 1 means you only accept cookies from the same server, 2 means you disable all cookies. Setting it to 1 has the same effect that the option in the old firefox browsers had: it disables third party cookies.

 

Posted by Paul Hollands pj at 11:07 AM | Comments (0)

January 16, 2008

This is kewl

Pashua

Library for adding Aqua GUIs to Python scripts etc.

Tags: MacOS X

Posted by Paul Hollands pj at 12:36 PM | Comments (0)

PDF to Text Conversion

pdftotext

 

Posted by Paul Hollands pj at 12:28 PM | Comments (0)

December 15, 2007

PHP SVN bindings

PECL :: Package :: svn

FlexySvn

Tags: Subversion

Posted by Paul Hollands pj at 10:20 AM | Comments (0)

How can I make the live site automatically update after every commit?

subversion: Subversion FAQ

How can I make the live site automatically update after every commit?

 

Posted by Paul Hollands pj at 10:10 AM | Comments (0)

December 14, 2007

Crazy Train

YouTube - Ozzy Osbourne - Crazy Train(Live) with Randy Rhoads

 

Posted by Paul Hollands pj at 09:16 PM | Comments (0)

We're not worthy!

YouTube - Ozzy & Randy Rhoads- I Don't know

 

Posted by Paul Hollands pj at 09:12 PM | Comments (0)

pysvn Programmer's Guide

pysvn: pysvn Programmer's Guide

Tags: Python , Subversion

Posted by Paul Hollands pj at 09:03 PM | Comments (0)

December 13, 2007

JS URI parser

parseUri: Split URLs in JavaScript

Tags: JavaScript

Posted by Paul Hollands pj at 12:34 PM | Comments (0)

December 07, 2007

If Jesus could play guitar he'd sound like Chuck Prophet

Chuck Prophet Tickets

 

Posted by Paul Hollands pj at 12:03 PM | Comments (0)

I think this is what CPanel uses for file upload

Yahoo! UI Library: Connection Manager

Tags: Content Management Systems

Posted by Paul Hollands pj at 12:36 AM | Comments (0)

November 26, 2007

PHP JSON support

omar kilani - projects - php-json

Tags: AJAX

Posted by Paul Hollands pj at 11:13 AM | Comments (0)

November 21, 2007

SQL for checking event overlap

$sql = sprintf("select d.diary_entry_id, 
from_unixtime(d.start_date) as start_time, 
from_unixtime(d.end_date) as end_time, 
concat(u.forename,' ',u.surname) as user_name 
from diary_entry d, diary_user_entry due, user u, diary_entry_status des  where (
(d.start_date between %s and %s) or 
(d.end_date between %s and %s) or
((%s between d.start_date and d.end_date) and (%s between d.start_date and d.end_date)) or
((d.start_date between %s and %s) and (d.end_date between %s and %s))
)
and d.diary_entry_id = due.diary_entry_id
and due.user_id in(%s)
and due.end_date is null and due.user_id = u.user_id and due.accepted_flag = 1
and d.diary_entry_id = des.diary_entry_id and des.end_date is null
and des.diary_entry_status_type_id != 3 order by u.surname",
$module['start_date'], $module['end_date'],
$module['start_date'], $module['end_date'],
$module['start_date'], $module['end_date'],
$module['start_date'], $module['end_date'],
$module['start_date'], $module['end_date'], 
$r['user_id']);

Errmmm.. Except that..

 if(($r['date_absent_from']) && ($r['to_date'])){
        
        $where = array();
        
        $where[] = sprintf("(
       (%d <= (a.date_absent_from + 86400)) and (%d >= a.date_absent_from)
        )", $r['date_absent_from'], $r['to_date']);
        
        }

Tags: MySQL

Posted by Paul Hollands pj at 10:49 AM | Comments (0)

November 15, 2007

Jython FTP Client

I've lashed together the following in Jython:

ftp_upload.py

ftp_upload.jar

To compile:

/Users/paulhollands/jython2.2.1/jythonc -j ftp_upload.jar --all ftp_upload.py

Tags: Jython

Posted by Paul Hollands pj at 05:09 PM | Comments (0)

November 14, 2007

FTP Python Library

18.8 ftplib -- FTP protocol client

 

Posted by Paul Hollands pj at 08:34 PM | Comments (0)

Jython FTP example


import snpsftp
ftp = snpsftp.SnpsFTP('10.254.1.26','userid','password')
ftp.setmode('BINARY')
ftp.mput('file')
ftp.close

 

Posted by Paul Hollands pj at 08:27 PM | Comments (0)

Jyhon applet example

Button Example

Something has gone wrong loading this applet.

 

Posted by Paul Hollands pj at 08:19 PM | Comments (0)

November 13, 2007

Java FTP reviewed

Java FTP client libraries reviewed - Java World

 

Posted by Paul Hollands pj at 09:49 PM | Comments (0)

November 12, 2007

Parsing mail messages with PHP

PHP: Mailparse Functions - Manual

Tags: PHP

Posted by Paul Hollands pj at 08:27 PM | Comments (0)

October 04, 2007

JS for iterating through all document elements

JS to select the options in all the select-one document elements where the text (as opposed to the value) == the value passed:

function select_option_by_text(my_text){

	var els = document.getElementsByTagName('*');
	
	//var regex = new RegExp(my_text + '.');

	for(var i  = 0; i < els.length; i++){
	
		if(els[i].type == 'select-one'){
		
			var opts = els[i].options;
		
			for(var o  = 0; o < opts.length; o++){
			
				var label = opts[o].text;
				
				if(label == my_text){ opts[o].selected = true; }
		
				}
	
			}

		}

	
	}

Tags: JavaScript

Posted by Paul Hollands pj at 09:51 AM | Comments (0)

September 27, 2007

Another HTML to PDF converter

html2ps and html2pdf - Convert HTML to PostScript or PDF. Supports over 500 HTML and CSS tags and properties.

 

Posted by Paul Hollands pj at 12:51 PM | Comments (0)

Printing to PDF from HTML using gecko

Michele Baldessari - Homepage

 

Posted by Paul Hollands pj at 12:43 PM | Comments (0)

September 12, 2007

Garage Band Noodlings

I've been playing with Garage Band and here are the first fruits of my noodlings:

Hypertufa

Playing in time with a bluetooth Apple keyboard is a bit of a challenge!

The file Hypertufa.mp3 identified by urn:sha1:DATMGKZRIX6ECBEONUC5KN5EU53GFROB is licensed to the public under the Attribution-Noncommercial-No Derivative Works 3.0 Unported license.

Bonatti Pillar

The file Bonatti Pillar.mp3 identified by urn:sha1:5L5YLVW7TG4EUUDQZMIQSE3MMLRXLK6U is licensed to the public under the Attribution-Noncommercial-No Derivative Works 3.0 Unported license.

Creative Commons License

Handful of Dust

Tags: Music

Posted by Paul Hollands pj at 10:42 AM | Comments (0)

July 23, 2007

Subversion pre-commit script in Python

A Subversion Pre-Commit Hook

Tags: Pre-commit Hooks , Subversion

Posted by Paul Hollands pj at 04:35 PM | Comments (0)

July 05, 2007

Transparent PNG Generator

Transparent PNG Generator

 

Posted by Paul Hollands pj at 11:58 AM | Comments (0)

July 04, 2007

Color Wheel

4096 Color Wheel Version 2.1

 

Posted by Paul Hollands pj at 05:30 PM | Comments (0)

CSS 2 Opacity

Mandarin Design: CSS Opacity and Transparency

 

Posted by Paul Hollands pj at 03:27 PM | Comments (0)

July 03, 2007

Doing JSON with Prototype.js

Prototype JavaScript framework: Introduction to JSON

 

Posted by Paul Hollands pj at 02:13 PM | Comments (0)

June 20, 2007

ReWrite Examples

Module Rewrite - URL Rewriting guide.

RewriteRule ^.*$ http://www.domain.com/ [R,L]

Tags: Apache stuff

Posted by Paul Hollands pj at 05:30 PM | Comments (0)

June 18, 2007

REST and PHP

How To: Making a PHP REST client to call REST resources

Tags: REST

Posted by Paul Hollands pj at 03:19 PM | Comments (0)

PHP and SOAP article on ADC

Using SOAP with PHP

Tags: PHP

Posted by Paul Hollands pj at 02:58 PM | Comments (0)

June 06, 2007

Secure SOAP in PHP tutorial

Calling secured Web services methods from PHP

Tags: Web Services

Posted by Paul Hollands pj at 03:08 PM | Comments (0)

Article about SOAP and PHP

ONLamp.com: A PHP Web Services Client

Tags: Web Services

Posted by Paul Hollands pj at 02:55 PM | Comments (0)

May 19, 2007

iCalendar Spec

iCalendar Specification Excerpts

Tags: Calendaring

Posted by Paul Hollands pj at 11:30 PM | Comments (0)

PHP iCalendar API

Bennu - PHP iCalendar library

Tags: Calendaring

Posted by Paul Hollands pj at 05:25 PM | Comments (0)

May 18, 2007

AJAX HTML slideshow

AJAX-S

Tags: AJAX

Posted by Paul Hollands pj at 08:43 PM

May 17, 2007

Styling Safari buttons

Style Form Buttons In Safari | Wiki | ExpressionEngine

 

Posted by Paul Hollands pj at 12:37 PM | Comments (0)

May 10, 2007

LEFT JOINS and MySQL 5+

I've had some problems porting SQL which works fine on MySQL 4+ to version 5. It is more picky about your left join syntax and any SQL you have which uses them will break if moved to 5 unless you do the folowing:

The column you want to do your first LEFT JOIN on needs to be LAST in your FROM statement list:

FROM diary_entry_type det, diary_user_entry due, user u,
diary_location dl, diary_entry_status des, diary_entry_status_type
dest, diary_entry d
LEFT JOIN diary_entry deto ON(deto.master_diary_entry_id =
d.diary_entry_id AND deto.diary_entry_type_id = 3)

Will work.

FROM  diary_entry d, diary_entry_type det, diary_user_entry due, user
u, diary_location dl, diary_entry_status des, diary_entry_status_type
dest
LEFT JOIN diary_entry deto ON(deto.master_diary_entry_id =
d.diary_entry_id AND deto.diary_entry_type_id = 3)

Will not. However you can also use brackets thus:

FROM  (diary_entry d, diary_entry_type det, diary_user_entry due, user
u, diary_location dl, diary_entry_status des, diary_entry_status_type
dest)
LEFT JOIN diary_entry deto ON(deto.master_diary_entry_id =
d.diary_entry_id AND deto.diary_entry_type_id = 3)

Tags: MySQL

Posted by Paul Hollands pj at 12:59 PM | Comments (0)

April 26, 2007

Sending plain text and HTML version in the same email

Sending HTML/Plain text Emails - PHP

$boundary = "nextPart";

$headers = "FROM: [email]me@fromme.com[/email]\r\n";

$headers .= "MIME-Version: 1.0\r\n";

$headers .= "Content-Type: multipart/alternative; boundary = $boundary\r\n\r\n";

$headers .= "This is a MIME encoded message.\r\n\r\n";

//text version

$headers .= "--$boundary\n

            Content-Type: text/plain; charset=ISO_8859-1\r\n

            Content-Transfer_Encoding: 7bit\r\n\r\n";

$headers .= "This is the plain version\r\n\r\n";



// html version

$headers .= "--$boundary\r\n

            Content-Type: text/html; charset=ISO_8859-1\r\n

            Content-Transfer_Encoding: 7bit\r\n\r\n";

$headers .= "This is the HTML version";

mail("me@myemail.com", "An HTML Message", "", $headers); 

Tags: PHP

Posted by Paul Hollands pj at 10:58 AM | Comments (0)

April 23, 2007

NTLM transaction using CURL

<?
$ch = curl_init("http://88.108.214.235:81/Lists/Items/Search%20Results.aspx");

curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_USERPWD, 'username:passwd');
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_NTLM);

print curl_exec($ch);

curl_close($ch);
?>

 

Posted by Paul Hollands pj at 03:34 PM | Comments (0)

Doing crap IIS NTLM authentication in PHP

Accessing NTLM secured resources with PHP - ThinkPHP /dev/blog

 

Posted by Paul Hollands pj at 03:20 PM | Comments (0)

April 18, 2007

utf8_unicode_ci vs utf8_general_ci

MySQL AB :: MySQL 5.0 Reference Manual :: 10.10.1 Unicode Character Sets

 

Posted by Paul Hollands pj at 11:08 AM | Comments (0)

PHP and MySQL and Unicode

Unicode Data with PHP 5 and MySQL 4.1

Tags: PHP

Posted by Paul Hollands pj at 11:01 AM | Comments (0)

MySQL and Unicode

MySQL AB :: Unicode and Other Funny Characters

Also:

10.3. Specifying Character Sets and Collations

Tags: MySQL

Posted by Paul Hollands pj at 10:56 AM | Comments (0)

March 30, 2007

Article about Prototype.js and AJAX

XML.com: Prototype: Easing AJAX's Pain

 

Posted by Paul Hollands pj at 04:34 PM | Comments (0)

March 22, 2007

Image crop and resize

Crop & Resize with JavaScript, PHP, and ImageMagick - Monday By Noon

Tags: JavaScript

Posted by Paul Hollands pj at 06:41 PM | Comments (0)

March 21, 2007

Scheduling software for AppleScript

Main Page - ProxiPedia

Using it to run the folliwng script to tell Skype what iTunes is playing:

http://www.johnwilker.com/j/index.cfm/2007/1/12/Skype-and-iTunes-a-modification-of-Seans-code

 

Posted by Paul Hollands pj at 11:45 AM

February 21, 2007

New RDF syntax embedded in XHTML attributes

XML.com: Introducing RDFa

See also The Primer:

http://www.w3.org/TR/xhtml-rdfa-primer/

Tags: RDF

Posted by Paul Hollands pj at 10:28 AM | Comments (0)

February 06, 2007

Tableless CSS book

Browse :: The Register Books - IT and Computer Book specialists

Tags: Web user experience

Posted by Paul Hollands pj at 08:37 PM

AJAX book

Browse :: The Register Books - IT and Computer Book specialists

Tags: AJAX

Posted by Paul Hollands pj at 08:31 PM

CrossOver Linux

CrossOver Linux allows you to install many popular Windows productivity applications, plugins and games in Linux, without needing a Microsoft Operating System license. CrossOver includes an easy to use, single click interface, which makes installing a Windows application simple and fast. Once installed, your application integrate seamlessly with your Gnome or KDE environment. Just click and run your application, exactly as you would in Windows, but with the full freedom of Linux.

 

Posted by Paul Hollands pj at 03:26 PM

February 04, 2007

The Jake

Kona Jake - BIKEmagic BM reviews

 

Posted by Paul Hollands pj at 07:13 PM

January 24, 2007

PHP HTTP functions list

Some really useful stuff in here I wasn't aware of:


PHP: HTTP - Manual

Tags: PHP

Posted by Paul Hollands pj at 12:31 PM

December 14, 2006

Try Tequila

Do you suffer from shyness? Try tequila!

 

Posted by Paul Hollands pj at 11:02 PM

Web App framework using XML and JS compiled into Flash

XML.com: Introducing OpenLaszlo

Tags: JavaScript , XML

Posted by Paul Hollands pj at 10:33 PM

Semantic extensions to MediaWiki

Semantic MediaWiki - Ontoworld.org

Tags: RDF

Posted by Paul Hollands pj at 09:42 PM

December 12, 2006

Some groovy & free icons

Mini Pixel Icons

Tags: Surface plane / Visual design

Posted by Paul Hollands pj at 05:56 PM

November 13, 2006

Applet for file uploading which gets around PHP file size limit

SourceForge.net: Open Discussion

Tags: PHP

Posted by Paul Hollands pj at 11:50 AM | Comments (0)

November 10, 2006

The Who - Live8

YouTube - the who

 

Posted by Paul Hollands pj at 11:49 PM

There Must Be An Angel on Parky

YouTube - Eurythmics - There Must Be An Angel ('live' on Parkinson)

 

Posted by Paul Hollands pj at 11:47 PM

November 08, 2006

PEAR iCal library

PEAR :: PEPr :: Details :: iCal

 

Posted by Paul Hollands pj at 01:12 PM

November 07, 2006

Getting the checked radio button when there's only one

If I only have one radio button, JS decides it ain't a list and won't give you a length for it, so you have to trap for this:

limit = document.forms[1].customer_id.length;

if(limit){ for(i = 0; i < limit; i++){

        if(document.forms[1].customer_id[i].checked == true){

                this_id = document.forms[1].customer_id[i].value; }

                }

        }

else { this_id = document.forms[1].customer_id.value; }

window.opener.document.location='index.php?customer_id=' + this_id; 

window.close();

Tags: JavaScript

Posted by Paul Hollands pj at 04:01 PM

SVN RSS and Atom feeds


svn2feed.py

Tags: Syndication

Posted by Paul Hollands pj at 03:46 PM

September 24, 2006

Web site analysis in PHP

phpOpenTracker

Tags: PHP

Posted by Paul Hollands pj at 08:51 PM

September 19, 2006

Safe backups and copying for MySQL

O'Reilly Network: Data Protection for LAMP Applications

Tags: MySQL

Posted by Paul Hollands pj at 12:15 PM | Comments (0)

August 21, 2006

TurboGears Web App Framework

Getting Started with TurboGears

 

Posted by Paul Hollands pj at 08:47 PM

August 11, 2006

More about the Python in PHP project

PiP - Python in PHP

Tags: Python

Posted by Paul Hollands pj at 10:06 AM | Comments (0)

Python interpreter embedded in PHP

PECL :: Package :: python

Tags: PHP , Python

Posted by Paul Hollands pj at 10:03 AM | Comments (0)

August 08, 2006

Calling DTML from within ZPT

<tal:block 
    tal:define="header python:root.standard_html_header(context); 
    footer python:root.standard_html_footer(context)">
<tal:block tal:replace="structure header"/> 

....

<tal:block tal:replace="structure footer"/>
</tal:block>

Tags: ZPT

Posted by Paul Hollands pj at 11:55 AM | Comments (0)

August 07, 2006

A brief history of some subversion transactions

svn import /cygdrive/e/svn-projects/finance_admin  \

svn://172.16.0.82/storage/svn-repository/finance_admin -m \

"Initial import fwl_finance_admin"

mv finance_admin finance_admin.old

svn checkout svn://172.16.0.82/storage/svn-repository/finance_admin \
finance_admin

 

Posted by Paul Hollands pj at 04:11 PM | Comments (0)

August 06, 2006

New do_sql.php

I've rewritten my do_sql.php code to work with the Pear DB library and refactored everything while I was at it:

<?php

require "DB.php";

include("read_config.php");

function sql_doozer($db, $sql, $is_query, $debug){

	if($debug == true){ print $sql; }

	# Set up the reply array

	(array) $reply;

	# Get our database connection details from the INI config file

	(array) $config = read_config($db.".ini");

	if($debug == true) { print_r($config); }

	$conf = $config["connection_parameters"];

	# Build the connection URL
	
	$db_url = $conf["type"]."://".$conf["user"].":".$conf["passwd"].
	"@".$conf["host"]."/".$conf["db"];

	if($debug == true){ print $db_url; }

	# Create our connection

	$connection = DB::Connect($db_url);

	if(DB::isError($connection)){

		$reply["status"] = false;

		$reply["message"] = $connection->getMessage();		

		return($reply);

		}

	(array) $reply["rows"];

	# Do the query

	$cursor = $connection->query($sql);

	if(DB::isError($cursor)){

		$reply["status"] = false;

		$reply["message"] = $cursor->getMessage()." - ".$sql;		

		return($reply);

		}

	$count = 0;

	# If this is an SQL query get the results back

	if($is_query == true){

		$reply["num_of_rows"] = $cursor->numRows();

		if(DB::isError($cursor)){

			$reply["status"] = false;

			$reply["message"] = $cursor->getMessage();

		
			return($reply);

			}

		while($this_row = $cursor->fetchRow(DB_FETCHMODE_ASSOC)){

			if(DB::isError($this_row)){

				$reply["status"] = false;

				$reply["message"] = $this_row->getMessage();		

				return($reply);

				}

			$reply["rows"][$count] = $this_row;

			$count++;

			}

		}

	if($debug == true){ print_r($reply["rows"]); }

	$reply["first_row"] = $reply["rows"][0];

	$reply["status"] = true;

	$reply["message"] = "OK";

	return($reply);

	}

function is_query($sql){

	# Check to see if our SQL is an insert or update statement

	$sql_list = explode(" ",$sql);

	if((strtolower($sql_list[0]) == "insert") 
	or (strtolower($sql_list[0]) == "update") 
	or (strtolower($sql_list[0]) == "create") 
	or (strtolower($sql_list[0]) == "alter")){

		return(false);

		}

	return(true);

	}

function do_sql($db, $sql, $debug){

	$is_query = is_query($sql);

	return(sql_doozer($db, $sql, $is_query, $debug));

	}

function do_sql_query($db, $sql, $debug){

        return(sql_doozer($db, $sql, true, $debug));

        }

function do_sql_insert($db, $sql, $debug){

        return(sql_doozer($db, $sql, false, $debug));

        }

function do_sql_update($db, $sql, $debug){

        return(sql_doozer($db, $sql, false, $debug));

        }

?>

Tags: PHP

Posted by Paul Hollands pj at 03:32 PM | Comments (0)

August 03, 2006

Parsing mutliple date formats in Python

try:
    date_time = datetime.datetime(*time.strptime(this_val, "%d/%m/%Y")[0:5])
except:
    pass
try:
    date_time = datetime.datetime(*time.strptime(this_val, "%B %Y")[0:5])
except:
     pass
try:
     date_time = datetime.datetime(*time.strptime(this_val, "%Y")[0:5])
except:
     pass
print "<!--" + str(date_time) + "-->"

Tags: Python

Posted by Paul Hollands pj at 02:58 PM | Comments (0)

Very cunning Python based Universal Feed Parser

Universal Feed Parser

Tags: Atom , Python , RSS , Syndication

Posted by Paul Hollands pj at 12:51 PM | Comments (0)

August 02, 2006

Introduction to Bash scripting

Introduction To Bash Shell Scripting (2004.11.06)

 

Posted by Paul Hollands pj at 12:33 PM | Comments (0)

July 31, 2006

Unit tests in PHP

ONLamp.com: Testing PHP Code with PHPUnit

Tags: PHP

Posted by Paul Hollands pj at 10:14 PM

Relationship extension to FOAF

RELATIONSHIP: A vocabulary for describing relationships between people

Tags: FOAF

Posted by Paul Hollands pj at 08:22 PM

July 26, 2006

Bundle for Apache, PHP and MySQL

apache friends - xampp

Tags: PHP

Posted by Paul Hollands pj at 11:43 AM | Comments (0)

July 19, 2006

Java bean for getting VAT values from a database table and splitting the figure over the number of transactions

InvoiceItemsVAT.java

Tags: Java

Posted by Paul Hollands pj at 10:35 AM | Comments (0)

JSP / XSLT combo

The following is an XSLT sheet dynamically generated from JSP and demonstrating use of <xsl:sort/> and batching:

<xsl:sort select="metadata/dc:title"
order="ascending"
data-type="text"/>
<xsl:if test="position() >= ($page * $pagesize) + 1">
<xsl:if test="position() <= $pagesize + ($pagesize * $page)">
<xsl:apply-templates/>
</xsl:if>
</xsl:if>

keys.xsl.jsp

Tags: JSP , XSLT

Posted by Paul Hollands pj at 10:06 AM | Comments (0)

July 18, 2006

Rounding monetary values to two decimal places in Java

/*Use banker's rounding to round the value to two decimal places. Multiply by 100 then use Math.rint to round to nearest integer, then finally divide by 100 again.*/

return(Math.rint(addedVat*100.0)/100.0);


Tags: Java

Posted by Paul Hollands pj at 04:15 PM | Comments (0)

July 12, 2006

Rapid Java Development Using Spring, Hibernate, Eclipse and Other Open Source Tools

Amazon.co.uk: Rapid Java Development Using Spring, Hibernate, Eclipse and Other Open Source Tools: Books: Anil Hemrajani

Tags: Java

Posted by Paul Hollands pj at 01:28 PM

July 04, 2006

We love PHPTAL

PHPTAL :: Template Attribute Language for PHP

Tags: PHP

Posted by Paul Hollands pj at 01:40 PM | Comments (0)

Creative Commons UK

Creative Commons UK : CCUK

Tags: Creative Commons

Posted by Paul Hollands pj at 11:19 AM | Comments (0)

MSc in e-learning at Edinburgh

MSc in E-learning: about the programme

 

Posted by Paul Hollands pj at 10:18 AM | Comments (0)

June 27, 2006

Open Source Mac Software Listing

Open Source Mac - Free, Open-Source software for OS X

 

Posted by Paul Hollands pj at 10:12 AM | Comments (0)

June 13, 2006

Macally iBook power adaptor replacement

MacHeaven - Macally UK Power Adapter for G4 PowerBook & iBook (PS-AC4-UK)

 

Posted by Paul Hollands pj at 03:21 PM | Comments (0)

June 12, 2006

The Prototype JavaScript Framework

Prototype JavaScript Framework: Class-style OO, Ajax, and more

Tags: AJAX

Posted by Paul Hollands pj at 02:50 PM | Comments (0)

June 11, 2006

LVM article

LinuxDevCenter.com: Managing Disk Space with LVM

Tags: Linux

Posted by Paul Hollands pj at 06:55 PM

June 06, 2006

What Linux kernel version am I running?

echo `uname -r`

Tags: Linux

Posted by Paul Hollands pj at 12:07 PM | Comments (0)

May 30, 2006

Google Web Toolkit

Google Web Toolkit - Build AJAX apps in the Java language

Tags: AJAX

Posted by Paul Hollands pj at 08:28 PM

Haystack Project - PIM using RDF

Haystack Project

Tags: RDF

Posted by Paul Hollands pj at 03:39 PM | Comments (0)

May 26, 2006

A first crack a showing a citations path in RDF

citations.owl

Tags: OWL

Posted by Paul Hollands pj at 05:59 PM | Comments (0)

Qualified DC RSS module

RDF Site Summary 1.0 Modules: Qualified Dublin Core

Tags: RDF

Posted by Paul Hollands pj at 11:21 AM | Comments (0)

May 25, 2006

Change management for OWL and RDFS

Change Management for RDFS/OWL Ontologies :: Part 1.

Change Management for RDFS/OWL Ontologies :: Part 2. Metadata

 

Posted by Paul Hollands pj at 08:32 PM

DRC Ontologies page including VES

Ontologies

 

Posted by Paul Hollands pj at 02:41 PM | Comments (0)

May 24, 2006

AWStats with Tomcat

Using AWStats with Tomcat

Also more information and the .war file can be found elsewhere..

 

Posted by Paul Hollands pj at 04:40 PM | Comments (0)

May 23, 2006

Jython servlet version of AsciiDammit

I've turned AsciiDammit.py into a Jython servlet using Netbeans and Coyote.

Get the source curlyQuoteParser.py or get the .war Quote.war.

You'll need Jython 2.1 in /usr/local/jython-2.1

Tags: Curly quotes , Jython

Posted by Paul Hollands pj at 03:39 PM | Comments (0)

May 22, 2006

Notes for using Python urllib2

urllib2 - The Missing Manual

Tags: Python

Posted by Paul Hollands pj at 12:43 PM | Comments (0)

Coyote project rolls Jython support into Netbeans

Coyote: Dynamic language support in NetBeans

Watch out though. It breaks a projects web.xml by adding multiple <context-param/> nodes when you make the project Jython enabled.

This needs to be fixed in the XML by hand.

Tags: Jython

Posted by Paul Hollands pj at 10:59 AM | Comments (0)

May 19, 2006

AsciiDammit.py

Download file

Tags: Curly quotes

Posted by Paul Hollands pj at 10:09 PM | Comments (0)

May 18, 2006

Jesse James Garretts Website User Experience design panes diagram

From his Elements of User Experience book:

elements_simpleplanes.pdf

Tags: Web user experience

Posted by Paul Hollands pj at 06:49 PM | Comments (0)

May 16, 2006

Chris Shiflett: Convert Smart Quotes with PHP

http://shiflett.org/archive/165

Tags: Curly quotes

Posted by Paul Hollands pj at 09:18 AM | Comments (0)

May 15, 2006

Straighten curly quotes in JS

Straighten Smart Quotes

Tags: Curly quotes

Posted by Paul Hollands pj at 07:21 PM

Discussion of curly / smart quotes in XML

XML.com: SVG and Typography: Characters

Tags: Curly quotes

Posted by Paul Hollands pj at 06:57 PM

Curly Quotes

Curling Quotes in HTML, XML, and SGML

Tags: Curly quotes

Posted by Paul Hollands pj at 04:57 PM | Comments (0)

URL encoding list

Flash Bible - Database - URL Encoding

 

Posted by Paul Hollands pj at 12:03 PM | Comments (0)

MySQL tutorial including iteration through batches using LIMIT and HAVING

Using MySQL, Part 3 - Manipulating Data

 

Posted by Paul Hollands pj at 10:54 AM | Comments (0)

Java iCalendar API

iCal4j - Introduction

Tags: Calendaring , Java

Posted by Paul Hollands pj at 10:23 AM | Comments (0)

May 10, 2006

Running JSP Through Apache with mod_jk2

Running JSP Through Apache with mod_jk2

Tags: Tomcat

Posted by Paul Hollands pj at 03:40 PM | Comments (0)

May 08, 2006

Partitioning and formatting a RAID disk post installation under Linux

You need to use the 'fdisk' command to create the partitions, for example:

- fdisk /dev/sda

- Type n to create the new partition.

- Select Primary

- Set up the partition size and accept the default start cylinder size then enter the size you wish to make the partition.

- Type p to review the partition table

- If everything is to your liking type w to write the changes and exit fdisk

- Reboot the system so the partition table is re-read.

- Then create the filesystem, for example, to create an ext 3 filesystem:

- Once the filesystem is created you need to mount it.

- Create a mount point:

mkdir /storage (or whatever)

- Now mount the new disk:

mount /dev/sda1 /storage

- Copy some files to the new mount point to verify it's working

If you want the new disk to come up on every reboot you need to make a label and add an entry to /etc/fstab:

- run the following command: umount /storage

- then run: e2label /dev/sda1 /storage

- open /etc/fstab in your preferred text editor and add the following line:

LABEL=/storage /storage ext3 defaults 1 2

- Save /etc/fstab

- Mount the new filesystem again by running:

mount /storage

Tags: Linux

Posted by Paul Hollands pj at 04:10 PM | Comments (0)

May 04, 2006

QuirksMode Javascript Tutorials

http://www.quirksmode.org/js/

Tags: JavaScript

Posted by Paul Hollands pj at 12:24 PM | Comments (0)

How to do hashes properly in JavaScript

JavaScript - Objects as associative arrays : http://www.quirksmode.org/js/associative.html

Tags: JavaScript

Posted by Paul Hollands pj at 12:16 PM | Comments (0)

April 27, 2006

JyUnit - Jython PyUnit

Burgaud.com - JyUnit

Tags: Test Driven Development

Posted by Paul Hollands pj at 09:04 PM

ONLamp.com: Test-Driven Development in Python

http://www.onlamp.com/lpt/a/5463

And part two:

http://www.onlamp.com/lpt/a/5584

Tags: Test Driven Development

Posted by Paul Hollands pj at 03:37 PM | Comments (0)

JUnit Test Infected: Programmers Love Writing Tests

http://junit.sourceforge.net/doc/testinfected/testing.htm

Tags: JUnit

Posted by Paul Hollands pj at 03:33 PM | Comments (0)

Guide to test driven development

http://www.agiledata.org/essays/tdd.html

Tags: Test Driven Development

Posted by Paul Hollands pj at 03:31 PM | Comments (0)

April 25, 2006

A nice PHP CMS

Textpattern

Tags: Content Management Systems

Posted by Paul Hollands pj at 09:09 PM

April 18, 2006

Mac OS X, Linux and XP on an Intel Mac

Triple Boot via BootCamp - OnMac.net Wiki

 

Posted by Paul Hollands pj at 07:31 PM

April 17, 2006

Developing Ajax Applications That Preserve Standard Browser Functionality

http://dev2dev.bea.com/pub/a/2006/01/ajax-back-button.html

 

Posted by Paul Hollands pj at 10:04 PM

April 06, 2006

VMWare equivalent for Intel Macs

Experience the First Virtualization Solution for Intel-powered Macs!

Tags: MacOS X

Posted by Paul Hollands pj at 07:40 PM

April 05, 2006

The Unofficial Fedora FAQ

http://www.fedorafaq.org/

Tags: Linux

Posted by Paul Hollands pj at 04:18 PM

March 30, 2006

Handling cookies in JavaScript

JavaScript - Cookies

Tags: JavaScript

Posted by Paul Hollands pj at 10:02 AM

March 29, 2006

Windows XP on a MacBook Pro how-to

OnMac.net: Windows XP on Intel Macs

Tags: MacOS X

Posted by Paul Hollands pj at 09:11 PM

March 13, 2006

Setting firewall rules on Fedora Core 4

Use the following utility:

system-config-securitylevel

Tags: Linux

Posted by Paul Hollands pj at 12:25 PM

March 09, 2006

Issues getting the Tomcat bundled with Magnolia to start

I kept getting an error message saying that the BASEDIR environment variable was incorrectly set. This went away once I'd made lots of stuff executable in the Tomcat bin directory.

This was a weird file permissions thang!

Tags: Content Management Systems

Posted by Paul Hollands pj at 11:24 AM

JavaScript code for base64 encoding and decoding mailto URLs

//First things first, set up our array that we are going to use.
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + //all caps
"abcdefghijklmnopqrstuvwxyz" + //all lowercase
"0123456789+/="; // all numbers plus +/=
//Heres the encode function
function base64_encode(inp)
{
var out = ""; //This is the output
var chr1, chr2, chr3 = ""; //These are the 3 bytes to be encoded
var enc1, enc2, enc3, enc4 = ""; //These are the 4 encoded bytes
var i = 0; //Position counter
do { //Set up the loop here
chr1 = inp.charCodeAt(i++); //Grab the first byte
chr2 = inp.charCodeAt(i++); //Grab the second byte
chr3 = inp.charCodeAt(i++); //Grab the third byte
//Here is the actual base64 encode part.
//There really is only one way to do it.
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;

if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
//Lets spit out the 4 encoded bytes
out = out + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) +
keyStr.charAt(enc4);
// OK, now clean out the variables used.
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < inp.length); //And finish off the loop
//Now return the encoded values.
return out;
}
//Heres the decode function
function base64_decode(inp)
{
var out = ""; //This is the output
var chr1, chr2, chr3 = ""; //These are the 3 decoded bytes
var enc1, enc2, enc3, enc4 = ""; //These are the 4 bytes to be decoded
var i = 0; //Position counter
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
var base64test = /[^A-Za-z0-9\+\/\=]/g;
if (base64test.exec(inp)) { //Do some error checking
alert("There were invalid base64 characters in the input text.\n" +
"Valid base64 characters are A-Z, a-z, 0-9, ?+?, ?/?, and ?=?\n" +
"Expect errors in decoding.");
}
inp = inp.replace(/[^A-Za-z0-9\+\/\=]/g, "");
do { //Here’s the decode loop.
//Grab 4 bytes of encoded content.
enc1 = keyStr.indexOf(inp.charAt(i++));
enc2 = keyStr.indexOf(inp.charAt(i++));
enc3 = keyStr.indexOf(inp.charAt(i++));
enc4 = keyStr.indexOf(inp.charAt(i++));
//Heres the decode part. There’s really only one way to do it.
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
//Start to output decoded content
out = out + String.fromCharCode(chr1);
if (enc3 != 64) {
out = out + String.fromCharCode(chr2);
}
if (enc4 != 64) {
out = out + String.fromCharCode(chr3);
}
//now clean out the variables used
chr1 = chr2 = chr3 = "";
enc1 = enc2 = enc3 = enc4 = "";
} while (i < inp.length); //finish off the loop
//Now return the decoded values.
return out;
}
function encode(text){
    document.write(base64_encode(text));
    }
function decode(text){
    document.write(base64_decode(text));
    }
function decode_mailto(text){
    dato = new Date();
    email = base64_decode(text);
    email2 = email.replace('@',"@");
    email3 = email2.replace('.',".");
    //alert(email3);
    document.write('' + email3 + '');
    }
function decode_link_mailto(text){
    dato = new Date();
    email = base64_decode(text);
    email2 = email.replace('@',"@");
    email3 = email2.replace('.',".");
    //alert(email3);
    document.write('<a href="mailto:' + email +'">' + email3 + '</a>');
    }

Tags: JavaScript

Posted by Paul Hollands pj at 10:22 AM

March 07, 2006

Magnolia docs

Magnolia CMS developer documentation

 

Posted by Paul Hollands pj at 07:59 PM

Open Source Java CMS

Magnolia Content Management Suite

 

Posted by Paul Hollands pj at 04:15 PM

Getting JSTL EL working on Tomcat 5.0.x

I copied my content into the correct folder but some of my EL expressions weren't working.

This is because I needed namespace declarations in the <web-app/> tag in the web.xml file:

<web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4">

Tags: Tomcat

Posted by Paul Hollands pj at 01:55 PM

February 27, 2006

JSP 2.0 Expression Language Tutorial

Expression Language

Tags: JSP

Posted by Paul Hollands pj at 09:37 AM

February 24, 2006

How to deal with strings that have been URI escaped mulitple times

ONLamp.com: A Canary Trap for URI Escaping

Tags: Parsing HTML

Posted by Paul Hollands pj at 12:19 PM

February 23, 2006

ROME - a Java feed parser

XML.com: ROME in a Day: Parse and Publish Feeds in Java

Tags: Java , Syndication

Posted by Paul Hollands pj at 10:10 AM

February 22, 2006

Really good JSP 2.0 / JSTL cheat sheet

JSP XML CheatSheet

Tags: JSP

Posted by Paul Hollands pj at 05:04 PM

February 13, 2006

Woz

Woz

 

Posted by Paul Hollands pj at 08:16 PM

February 11, 2006

Best of current trends in web-design

Current style in web design

Tags: Surface plane / Visual design

Posted by Paul Hollands pj at 05:49 PM

January 26, 2006

HTTP headers beyond Content-Type in JSP/JSTL

Use setHeader before the contentType statement:

<%
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setHeader("Content-disposition","attachment; filename=annual_finance_report.csv"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>

<%@ page contentType="application/vnd.ms-excel"%>

Though you can't do CSV in JSTL because of whitespace issues.

Tags: JSP

Posted by Paul Hollands pj at 03:19 PM

January 24, 2006

XML parsing in JavaScript

Started playing with parsing and extractin information from XML documents with JavaScript:

This XML is parsed by this page..

Tags: JavaScript

Posted by Paul Hollands pj at 05:17 PM

January 16, 2006

Python charting interface

PyGDChart2 - http://www.nullcube.com/software/pygdchart2/doc/index.html

Tags: Python

Posted by Paul Hollands pj at 08:32 PM

December 15, 2005

Converting iTunes protected files m4p to mp3 files

bpurcell.org - Converting Itunes protected files m4p to mp3 files

Tags: MacOS X

Posted by Paul Hollands pj at 12:49 PM

December 13, 2005

Ajax JSP Tag Library

http://ajaxtags.no-ip.info/

Tags: AJAX , Java

Posted by Paul Hollands pj at 09:21 AM

December 02, 2005

RSS 0.91 to 1.0 converter

http://blogspace.com/rss/rss2rdf

Tags: RSS

Posted by Paul Hollands pj at 12:04 PM

December 01, 2005

A Java RSS feed parser

java.net: Using RSS in JSP pages

Tags: RSS

Posted by Paul Hollands pj at 04:26 PM

November 24, 2005

Wikipedia definition of Tag Soup

Tag soup - Wikipedia, the free encyclopedia

Here's the QA stuff from the W3C:

http://www.w3.org/QA/Tips/

Tags: HTML to XHTML conversion

Posted by Paul Hollands pj at 08:45 PM

Doing CGI with Windows executables on Tomcat 5

There's a how-to document on the Tomcat site. The interface is managed by a JAR:

http://tomcat.apache.org/tomcat-5.0-doc/cgi-howto.html

The executable parameter needs to be set as follows:

<servlet>
<servlet-name>cgi</servlet-name>
<servlet-class>org.apache.catalina.servlets.CGIServlet</servlet-class>
<init-param>
<param-name>clientInputTimeout</param-name>
<param-value>100</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>6</param-value>
</init-param>
<init-param>
<param-name>executable</param-name>
<param-value>cmd /c</param-value>
</init-param>
<init-param>
<param-name>cgiPathPrefix</param-name>
<param-value>WEB-INF/cgi</param-value>
</init-param>
<load-on-startup>5</load-on-startup>
</servlet>

Tags: Tomcat

Posted by Paul Hollands pj at 09:27 AM

November 16, 2005

Parsing dates in Python

Dates and Times

Tags: Python

Posted by Paul Hollands pj at 03:42 PM

November 14, 2005

Doing dynamic regex replacements with JavaScript

A script used by HTML Dog to do inline replacements in HTML.

 

Posted by Paul Hollands pj at 11:40 AM

Getting the browser window size with Javascript

JavaScript tutorial - Obtaining the browser window size

document.body.clientHeight/Width

 

Posted by Paul Hollands pj at 11:32 AM

November 04, 2005

Google SiteMaps and OAI-PMH

Inside Google Sitemaps: Using OAI-PMH with Google Sitemaps

See also this article:

http://www.xml.com/lpt/a/2005/10/26/google-site-maps.html

Tags: OAI-PMH

Posted by Paul Hollands pj at 09:36 PM

Information about installing MySQL and DBD::MySQL on Cygwin

search.cpan.org: INSTALL - How to install and configure DBD::mysql

The trick is, once installed, it needs to be run thus:

cd /usr/local/mysql/bin
./mysql -h 127.0.0.1

Tags: Cygwin

Posted by Paul Hollands pj at 02:01 PM

Setting up ProFTPd as a Windows service under Cygwin

In order to run ProFTPd as a Windows service under Cygwin the following needs to be set in the /etc/proftpd.conf file:

# Set the user and group under which the server will run.
User                            SYSTEM
Group                           Administrators

# To cause every FTP user to be "jailed" (chrooted) into their home
# directory, uncomment this line.
DefaultRoot ~

The server can then be run as a service:

cygrunsrv --install proftpd \
          --path /usr/sbin/proftpd.exe \
          --args "--nodaemon" \
          --type manual \
          --disp "CYGWIN proftpd" \
          --desc "ProFTPd FTP daemon"

Then it needs to be run:

cygsrunsrv --start proftpd

Tags: Cygwin

Posted by Paul Hollands pj at 09:19 AM

November 02, 2005

How to add new users in Cygwin for SFTP access

In Windows, under Control Panel \ Administrative Tools \ Computer Management add a new user. If our new user is thingy

In cygwin as Administrator, type:

mkpasswd -l | grep thingy >> /etc/passwd

This adds a line to the passwords file for the new user.

You can then go in and change the user's home directory entry to the folder you wish them to access via sftp.

Tags: Cygwin

Posted by Paul Hollands pj at 05:17 PM

November 01, 2005

Tutorial about servlets in Jython

Jython Webapp Tutorial - Part 1 - Writing Servlets in Jython

Tags: Jython

Posted by Paul Hollands pj at 08:45 PM

October 30, 2005

An LDAP server as a jar

Apache Directory Project - Apache Directory Server

Tags: Apache stuff

Posted by Paul Hollands pj at 10:34 AM

October 21, 2005

The Ruby on Rails homepage

Ruby on Rails

 

Posted by Paul Hollands pj at 07:28 PM

Article about best practice with REST

XML.com: Implementing REST Web Services: Best Practices and Guidelines

Tags: REST

Posted by Paul Hollands pj at 02:08 PM

October 14, 2005

Tomcat Tips

ONJava.com: Top Ten Tomcat Configuration Tips

Tags: Tomcat

Posted by Paul Hollands pj at 02:14 PM

October 12, 2005

More on entity codes

Index of HTML 4.0 Character Entity References

Tags: Parsing HTML

Posted by Paul Hollands pj at 02:31 PM

October 11, 2005

How to do Apache Rewriting

URL Rewriting Guide - Apache HTTP Server

Tags: Apache stuff

Posted by Paul Hollands pj at 09:59 AM

October 07, 2005

More about Eclipse developments

ONJava.com: Eclipse Web Tools

http://www.eclipse.org/webtools/

Tags: Java

Posted by Paul Hollands pj at 06:21 PM

October 04, 2005

Mozilla Web Standards Guide

Using Web Standards in Your Web Pages

Tags: Web user experience

Posted by Paul Hollands pj at 02:14 PM

September 29, 2005

HTML character entity code list

Numeric Code Character Entities

Tags: Parsing HTML

Posted by Paul Hollands pj at 09:27 AM

September 28, 2005

Blojsom: A Java based blog system that implements the Atom API

http://wiki.blojsom.com/

Tags: Blogging , Java

Posted by Paul Hollands pj at 10:57 AM

September 23, 2005

First crack at finance database LDS

-- phpMyAdmin SQL Dump
-- version 2.6.4-pl1
-- http://www.phpmyadmin.net
-- Host: localhost
-- Generation Time: Sep 23, 2005 at 08:32 PM
-- Server version: 3.23.56
-- PHP Version: 4.4.0
-- Database: `fwl_finance`
-- 
-- Table structure for table `category`
-- 
CREATE TABLE category (
  category_id int(10) NOT NULL auto_increment,
  category_label text NOT NULL,
  category_description text,
  category_is_parent tinyint(1) NOT NULL default '0',
  category_parent_id int(10) NOT NULL default '0',
  PRIMARY KEY  (category_id)
) TYPE=MyISAM AUTO_INCREMENT=1 ;
-- 
-- Table structure for table `recipient`
-- 
CREATE TABLE recipient (
  recipient_id int(10) NOT NULL auto_increment,
  rec_organization_name text,
  rec_person_title enum('Mr','Mrs','Miss','Ms','Dr','Professor') NOT NULL default 'Dr',
  rec_person_first_name varchar(255) NOT NULL default '',
  rec_person_last_name varchar(255) NOT NULL default '',
  rec_contact_address text NOT NULL,
  rec_email varchar(255) NOT NULL default '',
  PRIMARY KEY  (recipient_id)
) TYPE=MyISAM AUTO_INCREMENT=1 ;
-- 
-- Table structure for table `transaction`
-- 
CREATE TABLE transaction (
  trans_id int(10) NOT NULL auto_increment,
  trans_record_created_date timestamp(14) NOT NULL,
  trans_record_last_modified datetime NOT NULL default '0000-00-00 00:00:00',
  trans_date datetime NOT NULL default '0000-00-00 00:00:00',
  trans_category_id int(10) NOT NULL default '0',
  trans_amount_in int(10) NOT NULL default '0',
  trans_amount_out int(10) NOT NULL default '0',
  trans_payment_type enum('Invoice','FBA credit card','Cash','Cheque') NOT NULL default 'Invoice',
  trans_date_invoiced datetime default '0000-00-00 00:00:00',
  trans_date_paid datetime default '0000-00-00 00:00:00',
  trans_payment_recipient_id int(10) default '0',
  PRIMARY KEY  (trans_id),
  KEY trans_category_id (trans_category_id,trans_amount_in,trans_amount_out)
) TYPE=MyISAM AUTO_INCREMENT=1 ;
-- 
-- Table structure for table `event`
-- 

CREATE TABLE `event` (
  `event_id` int(10) NOT NULL auto_increment,
  `event_title` text NOT NULL,
  `event_description` text NOT NULL,
  `event_start_date` date NOT NULL default '0000-00-00',
  `event_end_date` date NOT NULL default '0000-00-00',
  `event_record_created_date` timestamp(14) NOT NULL,
  `event_type` enum('meeting','conference','training','item purchase','hospitality') NOT NULL default 'meeting',
  PRIMARY KEY  (`event_id`)
) TYPE=MyISAM AUTO_INCREMENT=1 ;

Tags: MySQL

Posted by Paul Hollands pj at 08:33 PM

Broke my GRUB

I ran the Fedora up2date tool on my desktop against kernel packages today and broke GRUB so my machine wouldn't boot.

I used the installation disk to boot from, fired up rescue mode and typed the following:

grub
grub> root (hd0,2)
grub> setup (hd0)
grub> quit

Once I rebooted, this fixed things.

Tags: Linux

Posted by Paul Hollands pj at 01:08 PM

September 14, 2005

Python Library for reading and writing CSV stuff

12.20 csv -- CSV File Reading and Writing

 

Posted by Paul Hollands pj at 02:48 PM

Parsing binary data with Python

4.3 struct -- Interpret strings as packed binary data

Another alternative library is also available:

- http://www.nightmare.com/software.html

Tags: Python

Posted by Paul Hollands pj at 11:49 AM

September 12, 2005

Starting MySQL with max_allowed_packet size setting

mysqld_safe --max_allowed_packet=1012MB

Sets to a GB. Onyl works in MySQL 4.0 or greater.

Tags: MySQL

Posted by Paul Hollands pj at 09:42 AM

September 09, 2005

File partition problems with Fedora Core 4 / Windows XP dual-boot installation

I've been having some difficulty getting Grub to see my Windows NTFS partition after I used partition magic to resize it and then DiskDruid as part of the Fedora install.

Grub wasn't seeing the Windows partition.

Disk /dev/sda: 160.0 GB, 160000000000 bytes
255 heads, 63 sectors/track, 19452 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1               1           7       56196    6  FAT16
/dev/sda2               8        9729    78091965    7  HPFS/NTFS
/dev/sda3   *        9730       19388    77585917+  83  Linux
/dev/sda4           19389       19452      514080   82  Linux swap / Solaris

This was because the Windows partition (/dev/sda2) was flagged as hidden.

Grub therefore didn't write this into the grub.conf file on installation

I used parted to switch the hidden setting off:

[root@fba-pc04 dev]# parted /dev/sda
GNU Parted 1.6.22
Copyright (C) 1998 - 2005 Free Software Foundation, Inc.
This program is free software, covered by the GNU General Public License.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Public License for more details.

Using /dev/sda
(parted) print
Disk geometry for /dev/sda: 0.000-152587.890 megabytes
Disk label type: msdos
Minor    Start       End     Type      Filesystem  Flags
1          0.031     54.909  primary   fat16
2         54.910  76316.594  primary   ntfs        hidden
3      76316.594 152084.091  primary   ext3        boot
4     152084.092 152586.123  primary   linux-swap
(parted) set 2 hidden off
(parted) print
Disk geometry for /dev/sda: 0.000-152587.890 megabytes
Disk label type: msdos
Minor    Start       End     Type      Filesystem  Flags
1          0.031     54.909  primary   fat16
2         54.910  76316.594  primary   ntfs
3      76316.594 152084.091  primary   ext3        boot
4     152084.092 152586.123  primary   linux-swap
(parted)

I then changed the /boot/grub/grub.conf file as follows and it all now works:

# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You do not have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /, eg.
#          root (hd0,2)
#          kernel /boot/vmlinuz-version ro root=/dev/sda3
#          initrd /boot/initrd-version.img
#boot=/dev/sda3
default=0
timeout=20
splashimage=(hd0,2)/boot/grub/splash.xpm.gz
hiddenmenu
title Fedora Core (2.6.11-1.1369_FC4smp)
        root (hd0,2)
        kernel /boot/vmlinuz-2.6.11-1.1369_FC4smp ro root=LABEL=LINUX rhgb quiet
        initrd /boot/initrd-2.6.11-1.1369_FC4smp.img
title Fedora Core-up (2.6.11-1.1369_FC4)
        root (hd0,2)
        kernel /boot/vmlinuz-2.6.11-1.1369_FC4 ro root=LABEL=LINUX rhgb quiet
        initrd /boot/initrd-2.6.11-1.1369_FC4.img
title Windows XP
        map (hd0,0) (hd0,1)
        map (hd0,1) (hd0,0)
        rootnoverify (hd0,1)
        chainloader +1

This was quite useful for explaining the syntax in the grub.conf file:

- http://www.tldp.org/HOWTO/Linux+Win9x+Grub-HOWTO/proc.html#AEN54

Tags: Linux

Posted by Paul Hollands pj at 11:33 AM

August 10, 2005

Ooh, this is new..

O'Reilly CodeZoo

Tags: Languages

Posted by Paul Hollands pj at 11:31 AM

August 09, 2005

mysql_robot2.py site indexing script

I've uploaded a copy of my mysql_robot2.py site indexing script for safe keeping.

And here's the DB structure:

mysql_robot.sql

Tags: Python

Posted by Paul Hollands pj at 10:40 AM

Table for mysql_robot2.py

The ltsn01_ng.web_site_text table:

CREATE TABLE `web_site_text` (
  `link_id` int(10) NOT NULL auto_increment,
  `link_title` text NOT NULL,
  `link_base_href` text NOT NULL,
  `link_url` text NOT NULL,
  `link_scheme` varchar(255) NOT NULL default '',
  `link_host` varchar(255) NOT NULL default '',
  `link_path` text NOT NULL,
  `link_query` text NOT NULL,
  `link_params` text NOT NULL,
  `link_fragment` varchar(255) NOT NULL default '',
  `link_content_type` varchar(255) NOT NULL default '',
  `link_html` text NOT NULL,
  `link_xhtml` text NOT NULL,
  `link_text` text NOT NULL,
  `response_code` varchar(255) NOT NULL default '',
  `link_date_stamp` timestamp(14) NOT NULL,
  `link_type` enum('internal','external','broken_internal','mailto') NOT NULL default 'internal',
  PRIMARY KEY  (`link_id`),
  KEY `response_code` (`response_code`)
) TYPE=MyISAM
CREATE TABLE `referer_refered_link` (
  `rrl_id` int(10) NOT NULL auto_increment,
  `referer_url` text NOT NULL,
  `rrl_link_url` text NOT NULL,
  PRIMARY KEY  (`rrl_id`)
) TYPE=MyISAM

 

Posted by Paul Hollands pj at 10:37 AM

July 22, 2005

No proxy support for MT-Blacklist

I've been trying to get MT-Blacklist working on Caduceus but it refused to play ball because it couldn't download the initial blacklist from some website or other.

It appears this is because there is no proxy support roled into its LWP code.

I've hacked ../plugins/Blacklist/lib/Blacklist/App.pm to contain the following after line 191 ..oh and 301...sloppy coding..:

my $proxy = new URI::URL('http://wwwcache.ncl.ac.uk:8080/');

my @no_proxy = ('medev.ac.uk','ncl.ac.uk');

$ua->proxy('http',$proxy);

$ua->no_proxy(@no_proxy);

$ua->timeout(20);

Now it works..

Hmmm.. Same problem in MT itself.. in lib/MT/App/CMS.pm and lib/MT/App/Comments.pm, which is weird coz they have support for proxies in the Trackback stuff.

Tags: Blogging

Posted by Paul Hollands pj at 01:35 PM

July 20, 2005

MT login really slow on Caduceus

I've set up MT on Caduceus so that we can move the blogs off of minnesota onto it in due course.

The process seems quite straightforward. I can dump the database as follows:

mysqldump --no-defaults --compatible=mysql40 moveable_type > moveable_type_dump.19-07-2005.sql

I then have to comment out the LOCK and UNLOCK lines before and after inserts as phpMyAdmin didn't like these.

Once I'd changed the weblog config settings and rebuilt them it all worked fine and dandy, APART from the fact that logging in was REALLY slow.

This it appears, is because the script was failing to pull an MT news feed into this page, probably because the proxy environment variable isn't set for the Apache user.

The following is the solution, put:

NewsboxURL disable

into you mt.cfg file.

Logging in is slow and takes too long

Tags: Blogging

Posted by Paul Hollands pj at 11:01 AM

July 17, 2005

Yet another Python Web Framework

Django | The Web framework for perfectionists with deadlines

Tags: Python

Posted by Paul Hollands pj at 02:38 PM

July 14, 2005

RSS 1.0 job vacancies module

I've put together an RSS 1.0 extension module for job vacancies:

- produced an RDFS definition for the module: http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/rss1.0jobsmodule

- produced a new example document: http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/fundops_example_rdf

- wrote the whole thing up on the MEDEV site:
http://www.medev.ac.uk/interoperability/rss/1.0/modules/jobs/

Tags: RSS

Posted by Paul Hollands pj at 03:31 PM

July 01, 2005

Securing DB authentication credentials in PHP

I want to use Windows .ini style files for DB configuration settings in PHP. This is an approach I already use in Python.

Because these files are going to contain usernames and passwords I can't have them in the webserver file system as they would be visible to the web. However, if they aren't where the webserver can see them then PHP won't open them while running in safe mode.

My solution is to use a local .htaccess file with the following:

<Files ~ "\.ini$">
Order allow,deny
Deny from all
</Files>

Tags: PHP

Posted by Paul Hollands pj at 12:54 PM

June 28, 2005

This is quite Star Trek..

Perl.com: Data Munging with Sprog

 

Posted by Paul Hollands pj at 08:53 PM

June 23, 2005

SKOS - An RDF schema for thesaural representations

XML.com: Introducing SKOS

Tags: RDF

Posted by Paul Hollands pj at 10:07 PM

June 22, 2005

Re-working the funding opportunities RSS module

I've spent the last week and a half re-working the funding opportunities RSS module so that the syntax fits with the rdf:nodeID way of doing things on the recommendation of Libby Miller. As part of this work for the DEL project I have:

- produced an RDFS definition for the module: http://www.medev.ac.uk/interoperability/rss/1.0/modules/fundops/rss1.0fundopsmodule

- produced a new example document: http://www.medev.ac.uk/fundops_example.rdf

- written some XSLT to transform the comments and specs in the RDFS into HTML:
http://www.medev.ac.uk/rdfs2html.xsl

- written the whole thing up on the MEDEV site:
http://www.medev.ac.uk/interoperability/rss/1.0/modules/fundops/0.2/

Tags: RSS

Posted by Paul Hollands pj at 03:44 PM

June 15, 2005

More RDF play things for Eclipse

A suite of RDF type plug-ins for Eclipse:

RDFX

Tags: RDF

Posted by Paul Hollands pj at 03:03 PM

Eclipse and Jython

Apparently there are Jython plug-ins for Eclipse too:

Eclipse Integration

Tags: Jython

Posted by Paul Hollands pj at 01:09 PM

June 14, 2005

Eclipse and SWeDE

I was looking for an IDE for Java development on Mac OS X yesterday and came across Eclipse:

- http://www.eclipse.org/

Had a tinker with it and it was pretty good. Then this morning I needed an RDFS or OWL editor to start designing the funding opportunities schema. Then I discovered SWeDE:

- http://projects.semwebcentral.org/projects/owl-eclipse/

This is a plug-in application for Eclipse! Hurrah!

Tags: Java , OWL

Posted by Paul Hollands pj at 03:39 PM

June 08, 2005

Nodemap for the new website

I've produced the first page of a nodemap for the new website:

- nodemap page 1

- resources section nodemap

- acitvities section nodemap

Tags: Information architecture

Posted by Paul Hollands pj at 04:37 PM

Wireframes for the new website

The wireframes for the new web site are here:

- homepage

- other site pages

Tags: Skeleton plane

Posted by Paul Hollands pj at 01:06 PM

June 03, 2005

Website workpackages - Draft v 4

WP 1 - Joint MEDEV and HS&P portal site located at www.health.ac.uk

1.1 Determine portal site functional requirements (SSADM?)

1.2 Produce a node map (site map) on paper

1.3 Produce a wireframe for the home page and one for other types of pages

1.4 Investigate options for combining / aggregating multiple RSS feeds into one and implement findings

1.5 Investigate options for allowing personalized portal views

1.6 Finalize and implement the outcomes of the portal navigation WP 3

1.7 Finalize and implement the outcomes of the portal branding WP

1.8 Finalize wireframes and content and produce structural layout CSS for home and other page types

1.9 Implement final site

WP 2 - New MEDEV site located at www.medev.ac.uk

2.1 Determine site functional requirements (SSADM?)

2.2 Produce a node map (site map) on paper

2.3 Produce a wireframe for the home page and one for other types of pages

2.4 Investigate options for allowing personalized portal views

2.5 Finalize and implement the outcomes of the navigation WP

2.6 Finalize and implement the outcomes of the branding WP

2.7 Finalize wireframes and content and produce structural layout CSS for home and other page types

2.8 Produce a low-fi styled site mock up to test content combinations

2.9 Implement final site

WP 3 - Portal navigation design

3.1 Determine landmark navigation and courtesy navigation menu content and information architecture informed by WP 1.2

3.2 Investigate use of MovableType categories for use as contextual navigation elements informed by WP 1.2 and implement findings

3.3 Invsestigate approaches for wayfinding (breadcrumb trail generation) and implement findings

WP 4 - MEDEV site navigation design

4.1 Determine landmark navigation menu content and information architecture informed by WP 2.2

4.2 Investigate use of MovableType categories for use as contextual navigation elements informed by WP 2.2 and implement findings

4.3 Investigate approaches for breadcrumb trail generation and implement findings

WP 5 - Portal site visual design and branding

5.1 Commission a new design and brand for the HEALTH portal site

5.2 Finalise branding and produce and implement CSS

WP 6 - MEDEV site visual design and branding

6.1 Commission a new design and brand for the MEDEV site

6.2 Finalise branding and produce and implement CSS

WP 7 - Generic web form handler project

7.1 SSADM evaluation of requirements

7.2 Set of generic form content checks (dates, URLs, email addresses, MS special chars, post codes, HTML etc.) specified and implemented

7.3 Generic solution (possibly using Python Archetypes developed)

7.4 New table structures developed for all content currently managed in MySQL

7.5 Forms developed using new tools and new DB structures for all content currently managed in MySQL

WP 8 - RSS and iCalendar feeds

8.1 Develop new RSS events RSS feeds based upon new table structure and the RSS 1.0 Event module

8.2 Develop new RSS funding opportunities RSS feeds based upon the new fund ops RSS module defined as part of the DEL work

8.3 Refine iCalendar view of events

8.4 Determine which other RSS feeds to include on the site and incorporate using Feed2JS or similar

8.5 Hack Feed2JS or MagpieRSS to handle the new RSS formats

WP 9 - MovableType work

9.1 Investigate the use of MT for classification of resources informed by WP 4.2 and implement findings

9.2 Hack MT QuickPost functions or use the Atom API to ensure URL of the posted resource is available as an access key for navigation purposes

WP 10 - Portal / MEDEV site and resource searching

10.1 Investigate the functional requirements for site searching in all areas

10.2 Investigate the whether the OpenObjects search engine will fulfill the requirements generated from 10.1

10.3 Implement findings

WP 11 - Porting content over to the new site

11.1 Audit and prioritise the porting of key website sections, candidates to include:

- Workshop bookings and publication
- Contact details administration and user checking
- Group management
- Workshop proposals
- Mini-project proposals
- Publication requests
- Newsletter publication process
- Uploading resources
- FAQs,glossary, projects, special reports, best practice

11.2 Implement new content using outcomes of WP 7

WP 12 MEDEV site information architecture

12.1 Based upon outcomes of 11.1, 2.3, WP 4, WP 8 and WP9, develop a new information architecture for the site, with particular focus on resources (using 'set pattern' for navigation)

Tags: Web user experience

Posted by Paul Hollands pj at 01:02 PM

June 02, 2005

Auditing and classifying content on an existing web-site for improved access

Website information architecture is the business of deciding where each document sits within a website and what it links from and to. It is about determining what the context of the information should be.

It is also about the navigational elements of a site and the topics or subject headings documents are listed under.

According the the World Wide Web Consortium's good practice guidelines, the location of each resource within its parent site should be reflected in its URL or web address. In other words the way that your website is organised into hierarchies of documents should reflect the nature of the information published therein.

A news item about health should sit with other items of the same topic in the relevant section, giving a URL perhaps like the following:

http://mysite.org/news/topics/health/cold_cures.html

Further, each resource should have its own unique URL which should ideally be readable by humans who may need to remember or re-type it:

http://www.w3.org/QA/Tips/readable-uri

This worked well and was relatively straight forward to achieve when web sites were collections of HTML files in a series of nested directories or folders on a webserver. It is also still possible with modern content management systems which replicate the folder and file model. Things are less easy with database driven websites which rely on session IDs and so forth.

The BBC News website is a good example of how this can be done well:

http://news.bbc.co.uk

It is my experience however, that no matter how well intentioned and clear the rules about the organisation of information on a site are at the start of its life, in the rush to publish and meet deadlines, over time, ad hoc decisions about the location of documents result in a slow but steady degradation the quality of the information architecture.

Also, the larger the site the worse things get.

The MEDEV website <http://www.medev.ac.uk/> has reached the point where the organisation of information on the site has become unwieldy.

We are in the process of designing and building a new website for the subject centre and are therefore taking the opportunity to do an audit of the information we currently publish on the site so that the new information architecture can reflect the information on the site, rather than having to shoe horn documents into an increasingly baroque information architecture as best we can.

A major inconsistency has developed between actual arrangement of information at the folder level of the site and the way this is reflected to the user in what is known as the landmark navigation menu on the top right of each page.

The landmark menu should appear consistently on each page and allow the user to navigate easily between the major sections of the site.

You will notice that there is a Resources menu option which leads the user to the http://www.medev.ac.uk/resources/ section of the site.

There are also links to the main News, Events, Discussion, Funding and Links sections of the site, which should correspond to the main sections of the website information architecture, the top level folders if you will.

You would expect that the News section would have the following URL therefore:

http://www.medev.ac.uk/news/

In fact, the News section is in a sub-folder of the Resources section:

http://www.medev.ac.uk/resources/news/

This is the same for the Events, Discussion, Funding and Links sections of the site.

Given that there are now between two and three thousand resources published on the site and somewhere around seventy two thousand links between those documents, making any changes to the information architecture is a major undertaking if we want to move large sections around without breaking huge swathes of links.

In order to re-organise what information sits where we need to get a grip on the real scope of the information now published on our site. In order to facilitate this I have begun an audit of the information we currently publish there.

In order to determine the context of any documents (including those being generated from databases) and determine where they are linked from and where they link to, I have written a web crawler or robot script. This crawls our own website performing a number of different tasks as it goes:

1. It turns the HTML of each document into plain text and then inserts that text into a MySQL table so that we can quickly do free text searching across everything published on our site.

2. It gathers lists of all the links contained in that document and inserts that information into another table so that by searching with URLs we can quickly determine all the places where a particular document is linked from, in case we wish to change its URL as part of our re-organisation.

3. It also gathers information about the types of links (internal, external, mailto and so forth) and the content-type of each document (whether it is an HTML document, a PDF, a Word document and so forth.)

4. It produces a separate list of links to documents external to our site and checks that they are still active and not broken, logging the HTTP response code for each URL in our database to aid fixing of broken links.

Having knowledge of the full scope of the site is very powerful in that we can now determine which sections have the largest number of resources in them and this will help us in prioritizing which sections to move onto the new site first and what our new bottom up information architecture might look like. We can also tell more easily which sections are redundant or anachronistic so that these can be archived off on the old site.

Having a full text index of the whole site also makes the second step in this process much easier. I'm refering to the job of classifying each resource on the new site according to a given set of subject headings or topics.

Essentially we are talking about cataloguing all of the resources on our current site, to produce metadata for each. This metadata could form the basis of a very simplistic ontology layer, a browsable tree of subject based navigation to ease access to all of the information held on our site for our users.

In the parlance of services like del.icio.us and flickr we will be tagging our resources. Basically, categorising them.

We have a number of ready made vocabularies that we use for cataloguing and categorisation within the subject centre, including MeSH (Medical Subject Headings) and Higher Education Academy Pedagogy and Policy themes, but our topics vocabulary also needs to be adaptable without breaking anything or the need for major re-classification.

If we can develop a robust set of classifications for our resources then this can form a major new element of our information architecture.

Given that we now have an index of the all the text on the site, and once we have our vocabulary figured out, it might be possible to do some of the categorisation automatically. There are some very exciting developments in the area of auto-classification using Bayesian algorithms and there are tools available for filtering email spam using these techniques which might be re-tasked for this purpose:

http://spambayes.sourceforge.net/

Nevertheless, the bulk of the work will probably need to be done by hand and certainly for new resources added to the site after it has gone live. The cataloguing process therefore needs to be quick and easy, taking up the minimum of time while still capturing metadata of suitable quality.

Fortunately myself and my colleagues are already very familiar with software which allows the "cataloguing" and classification of resources quickly and effectively. We use MovableType for blogging useful resources.

Using the MT quickpost facility we can describe, classify and quickly add a basic entry for the resource we currently have in our browser window into our blog. Further, MT stores all the entries in a MySQL database as well as the categories available to classify each resource.

On a vanilla MT blog page the classification terms form a key part of the navigation for users and is the basis for the whole blog information architecture.

Being based in MySQL and also having a good deal of flexibility in terms of publishing chunks of blog content, it would be trivial to incorporate this menu / hierarchy of category terms into the information architecture of our new site.

Further, MT includes lots of options for the syndication in formats such as RSS and Atom. We are intending to incorporate the blog RSS feed to form a 'Latest additions to this site' information pod on the new site home page.

We could also use the MT facilities to allow comments and trackbacks about resources on our site.

Finally, MT produces Dublin Core metadata for each entry added expressed as RDF.

<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<rdf:Description
rdf:about="http://minnesota.ncl.ac.uk/fuzzybuckets/archives/2005/06/article_about_u.html"
trackback:ping="http://minnesota.ncl.ac.uk/cgi-bin/moveabletype/mt-tb.cgi/1146"
dc:title="Article about using patterns to improve web navigation"
dc:identifier="http://minnesota.ncl.ac.uk/fuzzybuckets/archives/2005/06/article_about_u.html"
dc:subject="Navigation design"
dc:description="Improving Web Information Systems with Navigational Patterns..."
dc:creator="pj"
dc:date="2005-06-01T16:30:54+00:00" />
</rdf:RDF>

Tags: Information architecture , Interaction design , Organisation of information

Posted by Paul Hollands pj at 12:44 PM

June 01, 2005

Article about using patterns to improve web navigation

Improving Web Information Systems with Navigational Patterns

Tags: Navigation design

Posted by Paul Hollands pj at 04:30 PM

Website workpackages - third draft

Workpackage 1 - Joint MEDEV / HS&P portal demonstrator page at http://www.health.ac.uk

- Determine portal page functional requirements

- Produce a non-styled mock-up to test content combinations

- Produce a wireframe for the page

- Finalise and implement outcomes of navigation WP

- Finalise content and wireframe and produce CSS

- Investigate combining / aggregating multiple RSS feeds into one

- Investigate options for allowing personalized views

- Implement final demonstrator page


Workpackage 2 - New MEDEV website

- Determine functional requirements

- Produce a non-styled mock-up to test content combinations

- Produce a wireframe for the page

- Finalise and implement outcomes of navigation WP

- Produce a node / site map on paper

- Finalise content and wireframe and produce CSS

- Implement final site

Workpackage 3 - Navigation design

- Develop and model demonstrator navigation elements (such as breadcrumbs) for portal page

- Develop and model final MEDEV site navigation

- Implement navigational elements

Workpackage 4 - MEDEV site visual design and branding

- Commission a new design and brand for the website

- Finalise branding for MEDEV website

- Request all necessary logos from Academy

- Produce CSS to implement MEDEV site branding

Workpackage 5 - RSS and iCalendar feeds

- Finalise events database table structure

- Develop new events RSS feeds using the Event module

- Develop new fund ops RSS feeds using new schema

- Refine iCalendar view of events

- Build movabletype Latest additions consumer pod into MEDEV homepage

- Forms for event information entry to include appropriate publishing and editorial controls using outcomes of WP 11

- Forms for fund ops information entry to include appropriate publishing and editorial controls using outcomes of WP 11

- Include feeds from mini-projects RSS and a number of blogs (to be determined)

- Hack Feed2JS or MagpieRSS tools to handle the new RSS formats

Workpackage 6 - MovableType work

- Investigate the strengths and threats of using MT for classification over and above a home grown DB approach

- Implement a movabletype blog for Latest additions blogging and feed (to double for classification of resources too)

Workpackage 7 - Portal / MEDEV site and resource searching

- Investigate the functional requirements for site searching in all areas

- Investigate use of OpenObjects search engine

- Implement according to findings of the above

Workpackage 8 - DTML to ZPT and / or Plone porting

- Generic form builder and manager DTML

- Workshop proposals

- Mini-project proposals

- Publication requests

- Workshop publishing

- Workshop bookings

- Contact details administration

- Contact details user checking

- Newsletter publication process

- Uploading of resources for MPs and WSs

- FAQ, glossary, project reports and websites, special reports and best practice

Workpackage 9 - XSLT based RSS to HTML conversion

- Develop Zope / Python based tools for running XSLT transformations on the various flavours of RSS feeds (including new modules) we will be using

- Develop XSL stylesheets for transformations

Workpackage 10 - HEALTH site visual design and branding

- Commission a new design and brand for the website

- Agree designs with HS&P

- Finalise branding for HEALTH website

- Request all necessary logos from Academy

- Produce CSS to implement HEALTH site branding

Workpackage 11 - Generic web form handler project

- Paul D and Tony's team to do SSADM evaluation of requirements

- Set of generic form content checks defined and implemented

- Generic solution possibly using Python Archetypes developed

- Forms developed using new tools and new DB structures for all content currently managed in MySQL


Tags: Functional specifications

Posted by Paul Hollands pj at 03:12 PM

May 27, 2005

A web crawler written in Python

http://www.newton.cx/~peter/software/crawler.py

Tags: Python

Posted by Paul Hollands pj at 01:20 PM

Example of how to go from Unicode to HTML

Unicode to HTML - tiddly-pom.com

Tags: Python

Posted by Paul Hollands pj at 12:54 PM

Information about the Python urlparse module

The urlparse module ::: The Standard Python Library (2005) ::: www.effbot.org

Tags: Python

Posted by Paul Hollands pj at 12:46 PM

More information about Python HTMLTidy wrappers

XML.com: Wrestling HTML

Tags: HTML to XHTML conversion , Parsing HTML

Posted by Paul Hollands pj at 12:03 PM

A Python based HTML parser which handles tag soup and does tidying automaticamente

Beautiful Soup: We called him Tortoise because he taught us.

Tags: Python

Posted by Paul Hollands pj at 11:59 AM

Python based RSS and Atom feed parser

SourceForge.net: Project Info - Universal Feed Parser

Tags: RSS

Posted by Paul Hollands pj at 11:54 AM

May 26, 2005

Rare urllib2 example for handling response codes

ASPN : Python Cookbook : urllib2 for actions depending on http response codes

Tags: Python

Posted by Paul Hollands pj at 12:11 PM

May 23, 2005

Handling Unicode encoding in XML with Python

XML.com: Unicode Secrets

Tags: Python

Posted by Paul Hollands pj at 10:02 PM

May 12, 2005

XML declaration and CSS support in IE

I found out today that I can set the DOCTYPE for XHTML 1.0 and everything seems to work OK in IE as far as our CSS goes.

If I include the XML declaration at the top of the document thus however:

<?xml version="1.0"?>

Then styles start breaking all over the place in IE 5.0.

 

Posted by Paul Hollands pj at 05:08 PM

April 21, 2005

Testing for the presence of objects in Zope

Here's a ZPT way to check for the presence of a particular folder in Zope:

<tal:block tal:define="
  folders python:context.objectValues('Folder');
" tal:repeat="folder python:folders">
<tal:block tal:define="
  this_id python:folder.getId();
  folder_name python:record['foaf_nick_name'];
" tal:condition="python:this_id == folder_name">
<tal:block tal:condition="python: root.new_site.contact.is_rstx_here(folder=folder,test_id='role_stx') == 1
">
<h3>Role and responsibilities</h3>
<tal:block tal:define="
  rstx python:modules['Products'].PythonScripts.standard.restructured_text;
  content_text python: folder.role_stx;
" tal:replace="structure python:rstx(content_text)"/>
</tal:block>
</tal:block>
</tal:block>

The following Python does the same but checks for rstx docs or DTML methods and is called as is_rstx_here() above:

for item in folder.objectValues('ReStructuredText Document'):
  this_id = item.getId()
  if this_id == str(test_id):
    return 1
for item in folder.objectValues('DTML Method'):
  this_id = item.getId()
  if this_id == str(test_id):
    return 1
return 0

Tags: ZPT

Posted by Paul Hollands pj at 04:31 PM

April 20, 2005

Contingent DIV blocks in ZPT - a design flaw.

I've got a problem with the design of ZPT. If I want a DIV block which starts in one iteration of a tal:repeat block but finishes a number of iterations later, then this can't be done, because the resulting code would give opening and closing tags out of document sequence breaking the template.

The only recourse seems to be to print the extra tagging as a a result of a tal:condition test.. YUUUCK:

<tal:block
tal:define="
global counter python:counter + 1;
global odd_even python:root.new_site.odd_or_even(test_figure=counter);
"
tal:condition="python: odd_even == 'odd'"
tal:replace="structure string:&lt;div class=&quot;row&quot;&gt;"/>

....Then the same for the closing block...

<tal:block tal:condition="python: odd_even == 'even'" tal:replace="structure string:&lt;/div&gt; <!-- End of row div -->"/>

Tags: ZPT

Posted by Paul Hollands pj at 04:13 PM

Changing the content type in page templates

<tal:block tal:define="
dummy python: container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/xml');
" tal:replace="structure string:&lt;?xml version=&quot;1.0&quot;?&gt;"/>

Tags: ZPT

Posted by Paul Hollands pj at 01:03 PM

Testing counters to see if they are odd or even

The following is a simple Python script to test whether a number is odd or even:

test_figure = float(test_figure)
half_of_it = float(test_figure/2)
#print str(half_of_it)
if int(half_of_it) == float(half_of_it):
  return 'even'
else: return 'odd'

It relies on the fact that casting a floating point number to an integer will round it up or down, and that dividing an odd number by two always gives a float, whereas dividing an even number gives an integer.

Tags: Python

Posted by Paul Hollands pj at 11:14 AM

April 18, 2005

Calling one page template inside another

Wow this is so much easier than calling DTML from within ZPT:

(In fact maybe you could do this with DTML too :~)

<tal:block tal:define="
dummy python: container.REQUEST.set('foaf_email', record['foaf_email']);
content_text root/new_site/contact/embedded_foafs;"
tal:replace="structure python: '<!--' + content_text + '-->'"/>

Note that I can pass it params in the REQUEST too..

Tags: ZPT

Posted by Paul Hollands pj at 03:48 PM

How to do RDF with Zope / ZPT

I've been trying to generate FOAF RDF from a Page Template. This has proven quite tricky. Zope 2.7 seems to stop wanting to parse and render the template if you change the content-type to text/xml from text/html.

This is not only a pain but is also intermittent.

The first thing I had to do therefore was re-set the content-type in the response header as follows, leaving the template content-type as text/html so the ZPT engine would parse it:

<tal:block tal:define="
dummy python: container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/xml');" />

Then I had to use tal:replace to put the XML declaration back in:

<tal:block tal:define="dummy python:
container.REQUEST.RESPONSE.setHeader('Content-Type', 'text/xml');"
tal:replace="structure
string:&lt;?xml version=&quot;1.0&quot;?&gt;"/>

Because I wanted to use the same template for single FOAFs and multiples I had to test for a foaf_email parameter in the request. This is doable with has_key.

However, because tal:condition affects both subsequent tal:define statements and the rendering of any child nodes within the block where it is called, and scope of tal:define vars is limited to the current block, I've had to resort to passing variables up into the request namespace. This is due to the lack of a syntactic equivalent of <dtml-if>..<dtml-else>. This gives very obfuscatory code:

<tal:block tal:define="
request python: container.REQUEST;
email python: None;
where_clause string: where 1;
wc python: request.set('where_clause', where_clause);
">
<tal:block tal:condition="python:request.has_key('foaf_email')">
<tal:block tal:define="
email python: request['foaf_email'];
where_clause python:' where foaf_email=\'' + str(email) + '\'';
wc python: request.set('where_clause', where_clause);
"/>
</tal:block>
<rdf:RDF
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#"
xmlns:mofoaf="http://minnesota.ncl.ac.uk/mofoaf/1.0/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:rdfs="http://www.w3.org/"
xmlns:foaf="http://xmlns.com/foaf/0.1/"
xmlns:dc="http://purl.org/dc/elements/1.1"
tal:define="
foaf_recs
python:root.generic_query(query_sql='select * from ltsn01_ng.01_foafs' + request['where_clause']);
work_url string:http://www.ltsn-01.ac.uk;
info_url_stem python: work_url + '/new_site/contact/person_details?foaf_id=';
">
.....RDF stuff here.....
</rdf:RDF>
</tal:block>

You'll see the where clause for the SQL is fished out of the request namespace.

The full template is here:

- 01_foafs.rdf.txt

Hmmm.. Seems if I'd read my own posts I could have done it with a PHP like global statement instead.


Tags: FOAF , ZPT

Posted by Paul Hollands pj at 01:24 PM

April 15, 2005

New 'Back in Business' FOAF specification

FOAF Vocabulary Specification

Tags: Evaluation and peer review

Posted by Paul Hollands pj at 11:24 AM

April 13, 2005

Identifying unique visitors to a website

A list and explanation of the ways Urchin software uses to determine unique visits. The only way to avoid proxy and cache issues is to use their bespoke JavaScript tracking approach:

Urchin Documentation - Visitor Identification Methods

Tags: Website statistics and analytics

Posted by Paul Hollands pj at 08:40 PM

Merging multiple RSS feeds

Suzanne thought it would be a good idea if we could merge multiple news feeds from BIOME, HS&P and HEALTH-01 for our joint portal page.

Whilst unconvinced of the requirement for such a thing I have come up with the following:

- http://www.ltsn-01.ac.uk/static/merge_feeds.php

To get a text/xml view of it in your browser use:

- http://www.ltsn-01.ac.uk/static/merge_feeds.php?debug=1

The script is as follows:

- http://www.ltsn-01.ac.uk/static/merge_feeds.txt

Merging multiple RSS feeds into one involves de-duping based on link URLs in items and interleaving items so that they appear next to items of the same age in the final feed.

The script pulls our news feed and the feed from a blog we're hosting and represents them. In theory it can handle as many feeds as you want.

But why? I hear you ask.. Errm.. still not sure? Suzanne?

As a side effect of all this work, I was determined to get the feed to validate on http://feedvalidator.org.

It doesn't like my image references so those are gone from the feed, then it was a matter of getting the right content-type (application/rss+xml), stripping annoying Windows meta characters from the feed, making sure there are no duplicate URLs, and I've UTF-8 encoded the final output for good measure.

- http://www.ltsn-01.ac.uk/static/strip_ms_chars.txt

Basically all the problems we've had with the LOM XML stuff.

I've done this with the rest of our feeds too and they now validate.

Tags: PHP , RSS

Posted by Paul Hollands pj at 04:58 PM

April 12, 2005

Why 1.0 is best..

XML.com: Why Choose RSS 1.0?

Tags: RSS

Posted by Paul Hollands pj at 08:44 AM

Handling RSS 1.0 in PHP

PHP and XML: Parsing RSS 1.0

Tags: RSS

Posted by Paul Hollands pj at 08:43 AM

April 11, 2005

RSS events to XHTML notes by Libby Miller

RSS, xhtml and XSLT

Tags: Calendaring

Posted by Paul Hollands pj at 03:05 PM

April 09, 2005

Embedding RDF in XHTML the hard way

RDF in HTML: Approaches

Tags: RDF

Posted by Paul Hollands pj at 05:27 PM

April 08, 2005

Meatspace metadata and authentication reminiscences

Super Springtime Dogtag Dignity contest results

Thanks for highlighting my lack of legal training Dr. P..

Tags: FOAF

Posted by Paul Hollands pj at 11:51 PM

A Python RDF parser

rdfxml.py: An RDF/XML Parser in under 10KB of Python

Tags: RDF

Posted by Paul Hollands pj at 04:50 PM

The cult of Tony

We want a Labour party on May 6th. We just aren't inviting Tony:

Backing Blair :: UK General Election 2005

Take part in Operation Henman..

Print out a poster:

Poster - Blair


 

Posted by Paul Hollands pj at 10:58 AM

April 07, 2005

Article about the UK Creative Commons effort

Policy DevCenter: Some Rights Reserved

Tags: Creative Commons

Posted by Paul Hollands pj at 07:50 PM

Doing dynamic reStructuredText in Zope

Suzanne and I have been playing with reStructuredText in Zope as a means of rapidly adding large chunks of copy to our new website. It is HWAYYY better than the old StructuredText.

The policy on the new site is that we are more carefully managing the URLs in page links and for the moment at least storing these as folder properties to be called in ZPT. This means for the navigation we only need to change URLs in one place.

We need to able to do the same in a simple way for links in rstx. This has its own way of handling URLs for links where they need only be defined once in the document to be re-used in lots of places.

We need a way to insert the values of properties into our rstx documents.

Fortunately in ZPT (which is where we are calling our rstx from) you have to define a rstx parser object and then pass text to it. This means that we could pass it the result of a DTML method and have the template still treat that text as rstx.

So instead of creating a reStructuredText document with the following:

.. _contact_us: /contact/contact_us

We create a DTML method with the following:

.. _contact_us: <dtml-with new_site><dtml-var contact_us_url></dtml-with>

So in our page template we now have the following to call the stx engine and the dtml:

<div style="text-align: justify;" id="content" tal:define="stx python:modules['Products'].PythonScripts.standard.restructured_text; content_text python:root.contact.index_html_dtml(root.contact);" tal:content="structure python:stx(content_text)"/>

Where this syntax: python:root.contact.index_html_dtml(root.contact) calls the DTML, passing its context as an argument.

Tags: Zope stuff

Posted by Paul Hollands pj at 11:12 AM

April 04, 2005

Paper detailing how to rig Zope / Plone up with Shibboleth authentication

MAMS - "Shibbolizing" Zope

Tags: Zope stuff

Posted by Paul Hollands pj at 08:56 PM

April 03, 2005

Datamining Apache Logs with PostgreSQL

ONLamp.com: Datamining Apache Logs with PostgreSQL

Datamining Apache Logs with PostgreSQL

Tags: Apache stuff

Posted by Paul Hollands pj at 09:15 PM

March 23, 2005

PHP4 Installer for Mac OS X

Marc Liyanage - Software - Mac OS X Packages - PHP

Tags: PHP

Posted by Paul Hollands pj at 03:38 PM

March 22, 2005

LIP ePortfolios XML parser

I've been working for the past few days on a parser for the ePortfolios LIP XML standard for the ePET project.

The work is based upon my LOM XML parser that forms part of my LOM Harvester:

- http://www.ltsn-01.ac.uk/interoperability/harvesters

The script uses the python libxml2 library to run a set of XPath queries over the LIP XML and extract the values. The XPath map is stored in the ltsn01_harvester.epet_xpath_map table for the testbed.

The parser script is called parse_lip_xml.py and is written as a Zope external method which needs to be passed the contents of the XPath table either as a dictionary or tuple plus the XML.

The following is a DTML web form which passes some test XML (engresume.xml) to a handler script which marshalls the XPath map from an SQL method and hands both off to the parse script external method.

- http://cadmedfac19.ncl.ac.uk/epet_test/parse_test

Because of the way the LIP XML is structured in quite heavily nested blocks, it really requires iterative parsing a la the classification section of the LOM. This is done by a two stage parse run. The first stage grabs sections such as all the <qcl/> nodes (which is repeatable) and serializes these into a python list of XML fragments so that they can be treated as separate documents in a second stage parse run using special XPath queries just for the contents of that node. This has been written into the parser for the name, qcl and affiliation sections.

Those sections which do not require iterative parsing (as defined by having their XPath queries starting at the learnerinformation root node) are parsed in a final single level parse run at the end.

The result is a nested Python dictionary representing the values serialized in the XML which can be passed to handler methods to do the database inserts / updates.

Newsflash: RM just sent me this URL which is his version of my stuff rolled into ePET with the REST put handler on the front:

- http://epet.ncl.ac.uk/ePET/new/epet_test/parse_test_rm

Tags: ePortfolios

Posted by Paul Hollands pj at 02:58 PM

March 18, 2005

Article outlining how to go about setting up a RESTful web service from XML.com

XML.com: Show Me the Code

Tags: REST

Posted by Paul Hollands pj at 05:02 PM

February 21, 2005

Documentation about MT-Blacklist plugin

MT-Blacklist v1.6.5 User Guide

Tags: Blogging

Posted by Paul Hollands pj at 10:42 AM

February 18, 2005

A handy CSS trick for creating paired bulleted lists

A List Apart has published a useful tutorial on creating two columns of bullet points.

Tags: Surface plane / Visual design

Posted by glittrgirl at 02:17 PM

February 17, 2005

Second draft of website workpackages

Workpackage 1 - Joint MDVM / HSP portal demonstrator page at http://www.health.ac.uk

- Determine portal page functional requirements

- Produce a non-styled mock-up to test content combinations

- Produce a wireframe for the page

- Finalise and implement outcomes of navigation WP

- Finalise content and wireframe and produce CSS

- Implement final demonstrator page

Workpackage 2 - New MDVM website - initially of limited scope

- Determine initial page functional requirements

- Produce a non-styled mock-up to test content combinations

- Produce a wireframe for the page

- Finalise and implement outcomes of navigation WP

- Produce a node / site map on paper

- Finalise content and wireframe and produce CSS

- Implement final page

Workpackage 3 - Navigation design

- Develop and model demonstrator navigation elements for portal page

- Develop and model final MDVM site navigation to ensure interim model fits

- Develop and model interim navigational elements for MDVM interim site (referencing old site navigation)

- Implement navigational elements

Workpackage 4 - Visual design and branding

- Finalise branding for MDVM website (probably based on our PPT style)

- Request all necessary logos from Academy

- Produce CSS to implement MDVM site branding

- Do the same for the joint Portal page

Workpackage 5 - RSS and iCalendar feeds

- Finalise events database table structure

- Develop new events RSS feeds using the Event module

- Develop new fund ops RSS feeds using new schema

- Refine iCalendar view of events

- Build movabletype Latest additions consumer pod into MDVM homepage

- Forms for event information entry to include appropriate publishing and editorial controls

- Forms for fund ops information entry to include appropriate publishing and editorial controls

- Include feeds from mini-projects RSS and a number of blogs (to be determined)

- Hack Feed2JS or MagpieRSS tools to handle the new RSS formats

Workpackage 6 - MovableType gubbins

- Investigate the strengths and threats of using MT for classification over and above a home grown DB approach

- Implement a movabletype blog for Latest additions blogging and feed (to double for classification of resources too)

Workpackage 7 - Using Plone for static managing static content from multiple authors

- Investigate the strengths and threats of using Plone as part of our CMS or exclusively as against a home grown approach

- Investigate if resources external to Plone can be rolled into the publishing workflow and controls without having to extend the content model with Archetypes etc.

- Implement Plone for use as a publishing environment for static authoring by naieve users

- Skin Plone with new branding

Workpackage 8 - Portal / MDVM site and resource searching

- Investigate the functional requirements for site searching in all areas

- Implement according to findings of the above

Workpackage 9 - DTML to ZPT and / or Plone porting

- Generic form builder and manager DTML

- Workshop proposals

- Mini-project proposals

- Publication requests

- Workshop publishing

- Workshop bookings

- Contact details administration

- Contact details user checking

- Newsletter publication process

- Uploading of resources for MPs and WSs

- FAQ, Glossary, project reports and websites, special reports

Workpackage 10 - XSLT based RSS to HTML conversion

- Develop Zope / Python based tools for running XSLT transformations on the various flavours of RSS feeds (including new modules) we will be using

- Develop XSL stylesheets for transformations

Tags: Web user experience

Posted by Paul Hollands pj at 01:18 PM

MySql 4.x Database Survival Guide

http://www.akadia.com/services/mysql_survival.html

 

Posted by Paul Hollands pj at 12:54 PM

Article about RESTful reporting

XML.com: REST Reporting

Tags: REST

Posted by Paul Hollands pj at 12:42 PM

Recipe metadata (meatadata?) in RDF? not

XML.com: Eat Drink Feel Good Markup Language

Tags: RDF

Posted by Paul Hollands pj at 12:27 PM

February 16, 2005

First stab at website workpackages

Workpackage 1 - Joint MDVM HSP portal page at http://www.health.ac.uk

Tasks:

- Determine portal page functional requirements

- Decide on HEALTH portal page branding and style including CSS

- Mock up a dummy page for review by MDVM, HSP and BIOME

Workpackage 2 - New MDVM website with limited scope

- Determine the scope of the new website

- Determine which areas will still be served from the old site

- Develop new MDVM branding

- Mock up a style-less barebones HTML page which includes everything that is required structurally to test what content should go where

- Finalise events database structure

- Develop new events RSS feeds using the Event module

- Develop final iCalendar view of events

- Develop forms for event information entry along with appropriate publishing and editorial control workflow

- Develop forms for fund ops information entry along with appropriate publishing and editorial control workflow

- Develop new fund ops RSS feed using fund ops module

- Set-up a movabletype blog for news feed

- Hack Feed2JS or MagpieRSS tools to handle new RSS formats

- Investigate and list the strengths and threats of using movabletype for classification over and above a home made DB approach

- Set up a movabletype blog for Latest additions blogging and feed (this will double for classification of resources too).

- Produce a wireframe for the homepage

- Produce a paper site map based upon the output of 4 above

Workpackage 3 - Do a cost benefit analysis of what Plone offers us over a home grown CMS approach

- List Plone benefits for suitable comparison

- Investigate if resources external to Plone can be rolled into the publishing workflow and controls without having to extend content model with new archetypes etc.

Workpackage 4 - Set-up Plone for use as a publishing environment for static content

Workpackage 5 - Specify the functional requirements for Portal and MDVM site and resource searching and implement

----------------------

Stuff that needs to be done:

- LTSN-01 staff contact details

- NPC listings

- Functional reqs for the joint Portal page

- Investigation of EPOZ vs Silva and Kupu for simple content authoring

- Investigation of best way to catalogue and classify site resources

- Investigating ways of managing non-standard Plone content within Plone vs MySQL

- Plone site skinning

- Porting of current services from old to new site and from DTML to ZPT including:

-- Generic form builder and manager DTML

-- Workshop proposals

-- Mini-project proposals

-- Publication requests

-- Workshop publishing

-- Workshop bookings

-- Contact details administration

-- Contact details user checking

-- Funding opportunities administration

-- Events administration

-- News administration

-- Newsletter publication process

-- Uploading of resources for MPs and WSs

-- search of BIOME database

-- FAQ, Glossary, project reports and websites, special reports

Tags: Web user experience

Posted by Paul Hollands pj at 04:42 PM

Website meeting notes

New portal page

New splash page for www.ltsn-01.ac.uk in new style and pointing off to the old archived site. (MDVM homepage)

MDVM homepage will have time dependent content ported over now using MySQL and ZPT.

We will have a blog for classification which users do not see directly but whose RSS feed populates 'New additions'.

Access will be provided to archives and subject archives.

Links to old site.

Stuff we'd like on the new MDVM homepage:

- Search

- Calendar

- New additions to this site pod

- Link to browse by subject area

- Link(s) to old site

- Events: includes WS, external events, deadlines for fundops and calls

- Funding opportunities coming up

- Link to main portal page and HS&P

- Find teaching materials (including BIOME)

Mock up an MDVM web page with all the possible content on in a long list but split up with DIVs.

New cadmedfac address required from upstairs.

 

Posted by Paul Hollands pj at 01:11 PM

February 15, 2005

Running JavaScript in Python

But why?

python-spidermonkey

Tags: Python

Posted by Paul Hollands pj at 02:43 PM

February 11, 2005

Logging Apache into MySQL

ONLamp.com: Writing Apache's Logs to MySQL

Tags: Apache stuff

Posted by Paul Hollands pj at 10:17 AM

February 10, 2005

CETIS Metadata FAQ Wiki

Metadata for Education - FAQ

 

Posted by Paul Hollands pj at 11:39 AM

February 09, 2005

An iCalendar view of our events database

I've spent today hacking together a PHP script to generate a view of our ltsn01_general.events table.

http://www.ltsn-01.ac.uk/static/ltsn-01_events.ics.php

I've also written a cron job which uses curl to get a snapshot of that output into a static .ics file:

http://www.ltsn-01.ac.uk/static/ltsn-01_events.ics

I've successfully subscribed to this in iCal.

There is also a web view of this calendar here:

http://minnesota.ncl.ac.uk/calendar/

Tags: Calendaring , PHP

Posted by Paul Hollands pj at 04:29 PM

vCalendar and iCalendar in PHP

http://www.phpbuilder.com/columns/chow20021007.php3?print_mode=1

Tags: Calendaring

Posted by Paul Hollands pj at 11:53 AM

PHP WebCalendar Project

SourceForge.net: Project Info - WebCalendar

Tags: Calendaring

Posted by Paul Hollands pj at 10:37 AM

iCalendar and vCalendar Python API

iCalendar and vCalendar API tools in Python:

- Small Python-PDI tutorial

- http://savannah.nongnu.org/projects/python-pdi

Tags: Calendaring

Posted by Paul Hollands pj at 10:16 AM

February 03, 2005

Types of content currently published on the LTSN-01 website

This is a stab at a rough, top-of-the-head, first draft information architecture:

The site contains content describing or arising out of subject centre activities, past and current and also there are a number of resources aimed at our constituency which are published on the site. There is a caveat in that obviously many of our activities also produce resources.

I would like to make a distinction between information describing activities and the resources which we publish.

Further, there is a distinction between internally sourced and externally sourced information. A good example is funding opportunities. These typically cover external sources of funding. However, LTSN-01 also provides funding for or participates in research and developement projects, mini-projects and also workshops.

These inter-relationships between our areas of activity and the role of the website for promoting external opportunities needs to be reflected in the information architecture of the site and in the navigation elements.

Activities:

- funding opportunities (including workshop and mini-project calls)

- workshop promotion and booking

- contact details maintenance

- mini-project information and publication of reports

- news and events service

- publications:

-- newsletter

-- special reports

-- email bulletins

- pulication requests handling

- discussion boards

- research and development projects

- link of the month service

- cataloguing resources into BIOME

Resources:

- service for search of BIOME databases

- FAQ

- Glossary

- Free web courseware

- project reports and websites

- workshop resources

- newsletter

- special reports

Another issue is what to do with out-of-date content that we post. There should be some sort of archive area so that there's a clear delineation between current and older information.

We should maybe seek to archive and publish old email bulletins too?

There are two other issues that need to be decided upon as well, one is the issue of metadata for each page on the site. The other related matter is how each piece of content is classified, i.e. whether we should use MESH, METRO and whether we should be assigning terms from the Academy vocabularies to keep them happy.

Tags: Content requirements , Information architecture , Navigation design

Posted by Paul Hollands pj at 03:29 PM

January 31, 2005

Railroad Respository Software

The following is digital repository software which plugs into Plone or Silva:

Infrae Products: Railroad Repository

Tags: Digital Repositories , Dublin Core , Learning Objects , OAI-PMH

Posted by Paul Hollands pj at 11:05 AM

January 28, 2005

We probably need an intranet section for our site

Rather than have an approach where users and editors visit the same URI and get a different view of have a number of pages to visit for content admin purposes, we should have a distinct URI tree for content management tasks and related interfaces.

Tags: Information architecture , Information design , Navigation design

Posted by Paul Hollands pj at 03:06 PM

upCast and downCast Word 2 XML converters

infinity-loop Home :: Document Conversion Software

Tags: Word to XML conversion

Posted by Paul Hollands pj at 01:18 PM

XML.com article about round tripping Word to XML

XML.com: Word to XML and Back Again

Also, this earlier round-up:

http://www.xml.com/lpt/a/2003/12/31/qa.html

Tags: Word to XML conversion

Posted by Paul Hollands pj at 11:39 AM

January 20, 2005

Multi-step Word to DocBook conversion

[Zope-xml] DocBook processing HowTo (long)

Download PDF copy..

Relies on the following:

http://wvware.sourceforge.net/

Tags: Word to XML conversion

Posted by Paul Hollands pj at 09:45 PM

Yet Another Word Converter

YAWC Pro - Welcome to YAWC Pro

Tags: Word to XML conversion

Posted by Paul Hollands pj at 09:42 PM

Advice from the W3C about URL formatting and persistence

Hypertext Style: Cool URIs don't change.

 

Posted by Paul Hollands pj at 11:15 AM

January 19, 2005

Atom API implementations

isolani - Atom: PHP AtomAPI Implementation

Bitworking - New AtomAPI Implementation Release

Tags: Atom

Posted by Paul Hollands pj at 08:47 PM

January 18, 2005

Plone Atom API plugin

The net.presence of mathie (AKA Graeme Mathieson) - PloneAtom

Tags: Atom

Posted by Paul Hollands pj at 12:27 PM

January 05, 2005

A LOM RDF binding

IEEE Learning Object Metadata RDF Binding

Tags: IEEE LOM

Posted by Paul Hollands pj at 11:41 AM

Article about del.icio.us style co-operative classification

Folksonomies - Cooperative Classification and Communication Through Shared Metadata

Tags: Blogging

Posted by Paul Hollands pj at 11:09 AM

December 22, 2004

A little experiment

Title: Cyberpatient simulator

General description:

A series of interactive patient case simulations.

Education description:

Includes cases based on acute coronary syndrome, acute leg swelling, cardiac life support (including paediatric life support).

Coverage:

  • UK
  • Europe
  • US

Publisher: MDChoice

Keywords:

  • Teaching Materials
  • Computer Simulations
  • Acute Coronary Syndrome
  • Acute Leg Swelling
  • Cardiac Life Support

Technical format: text/html

Technical location: http://www.mdchoice.com/cyberpt/cyber.asp

Learning resource types:

  • Simulation model
  • Case study
  • Collection

Copyright and other restrictions: No

Classification:

  • Pre-clinical medicine

Tags: IEEE LOM

Posted by Paul Hollands pj at 02:16 PM

RDF from my little experiment

http://minnesota.ncl.ac.uk/fuzzybuckets/archives/2004/12/a_little_experi.html

Tags: IEEE LOM

Posted by Paul Hollands pj at 02:16 PM

December 21, 2004

Aah! Character encoding :)

A tutorial on character code issues

 

Posted by Paul Hollands pj at 02:19 PM

The Atom fun just never stops!

XML.com: An Atom-Powered Wiki

Tags: Atom

Posted by Paul Hollands pj at 02:12 PM

Articles about Atom athentication, RDF and Identification

XML.com: Atom Authentication

XML.com: Identifying Atom

http://www.xml.com/pub/a/2003/08/20/dive.html

Tags: Atom

Posted by Paul Hollands pj at 11:29 AM

December 20, 2004

Article about ePortfolios

elearnspace. Eportfolios

 

Posted by Paul Hollands pj at 04:19 PM

Latest draft of the Atom API

Been reading through the following article describing the history of the Atom API and then describing it in full:

http://www.xml.com/lpt/a/2003/10/15/dive.html

The following is related reading:

The AtomAPI

http://bitworking.org/news/AtomAPI_Quick_Reference

http://www.isolani.co.uk/blog/atom/PhpAtomApiImplementation

Tags: Atom

Posted by Paul Hollands pj at 01:20 PM

December 18, 2004

Apache module available for OAI-PMH

mod_oai

Tags: Apache stuff , OAI-PMH

Posted by Paul Hollands pj at 08:13 PM

PubMed records available over OAI-PMH

PMC Open Archives (OAI) Service

Tags: OAI-PMH

Posted by Paul Hollands pj at 08:10 PM

December 15, 2004

Doozers in ZPT

I've been working on converting my DTML generic form builder into ZPT.

It has taken me a couple of days to move the concept of a doozer over. A doozer is a script which performs some business logic functions, such as inserting data into a table but instead of returning any resulting HTML, hands off to another URI using a redirect.

The main trick I was missing was the use of either tal:block or the tal:omit-tag="" attribute to ensure nothing is written to the browser before the redirect. I then discovered that this is actually unecessary as unlike PHP if you call a redirect it seems to send a new header to the browser anyway.

<div tal:define="
  debug python:0;
  table_name request/table_name;
  pk_recs python:here.get_pk_column(table_name=table_name);
  title_column python:str(pk_recs[0]['title_column']);
  pk_column python:str(pk_recs[0]['pk_column']);
  these_items python:request.form;
  title_column_value python:these_items[title_column];
  result python:here.insert_entry_id(table_name=table_name, title_column=title_column, this_value=title_column_value);
  max_id_recs python:here.get_table_max_id(table_name=table_name,pk_column=pk_column);
  entry_id python:max_id_recs[0]['entry_id'];" tal:omit-tag="">
<p tal:condition="python:debug == 1" tal:content="title_column" tal:omit-tag=""></p>
<p tal:condition="python:debug == 1" tal:content="title_column_value" tal:omit-tag=""></p>
<p tal:condition="python:debug == 1" tal:content="entry_id" tal:omit-tag=""></p>
<div tal:repeat="item_key python:these_items.keys()" tal:omit-tag="">

<p tal:define="item_value python:these_items[item_key];" tal:omit-tag="">

<span tal:condition="python:debug == 1" tal:omit-tag="">
<span tal:condition="python:debug == 1" tal:content="item_key" tal:omit-tag=""></span>
<span tal:condition="python:debug == 1" tal:content="item_value | nothing" tal:omit-tag="">Item here<
/span>
</span>

<span tal:condition="python:item_key != 'table_name' and item_key != 'redirect_url'" tal:omit-tag="">
<br
  tal:define="result python:here.update_entry(table_name=table_name,pk_column=pk_column,
this_key=item_key,this_value=item_value,entry_id=entry_id)"
  tal:omit-tag=""/>
</span>
</p>
</div>
<p tal:condition="python:debug == 1" tal:content="these_items" tal:omit-tag=""></p>
<div tal:condition="python:not request.has_key('redirect_url')" tal:omit-tag="">
<br tal:omit-tag="" tal:define="
  redirect_url python:'/generic_form_zpt/show_entry?entry_id=' + str(entry_id) 
+ '&table_name=' + table_name + '&pk_column=' + pk_column 
+ '&title_column=' + title_column;
  redirect python:request.RESPONSE.redirect(redirect_url);
"/>
</div>
<div tal:condition="python:request.has_key('redirect_url')" tal:omit-tag="">
<br tal:omit-tag="" tal:define="
  final_url python:request['redirect_url'] + '?entry_id=' + str(entry_id) 
+ '&table_name=' + table_name + '&pk_column=' + pk_column + '&title_column=' 
+ title_column;
  redirect python:request.RESPONSE.redirect(final_url);
"/>
</div>
</div>

Tags: ZPT

Posted by Paul Hollands pj at 04:01 PM

December 13, 2004

Overriding angle bracket escaping in ZPT

To avoid ZPT turning your HTML angle brackets into entity codes prefix your tal:replace statement with the structure keyword.

<span tal:replace="structure my_value"/>

Tags: ZPT

Posted by Paul Hollands pj at 05:56 PM

December 10, 2004

Article about PEAR, Smarty and MySQL

ONLamp.com: Three-Tier Development with PHP 5

Tags: PHP

Posted by Paul Hollands pj at 01:31 PM

December 08, 2004

More about METS

Metadata Encoding and Transmission Standard

http://www.loc.gov/standards/mets/

Different sections for different types of metadata:

- fileSec

All the files associated with the digital object

- dmdSec

-- Descriptive metadata goes here (can embed DC, MARCXML etc.)

- admSec

-- Administrative metadata

- behaviorSec

- structMap

-- Equivalent of IEEE CP manifest? Lists associated files

Oxford are using MODS (Metadata Object Description Schema)

Tags: METS

Posted by Paul Hollands pj at 02:39 PM

Wilbert Kraan: LTSC content aggregation

Notes from today's Joint CETIS Metadata and EC SIG meeting in Manchester:

Content Aggregation for Managed Learning, Education and Teaching (CAMLET)

METS version 1.1 released June 2002

"Descriptive, administrative and structural Metadata for objects in a digital library."

Tries to merge METS, Content Packaging and MPEG-21 specifications.

 

Posted by Paul Hollands pj at 02:06 PM

Derek Hoy presentation: Topic Maps - d.hoy@gcal.ac.uk

Notes from today's Joint CETIS Metadata and EC SIG meeting in Manchester:

Use a combination of Protege (ontology editor) plus TMTab from the TM4J people.

Protege does not produce XTM from the outset.

Producing a Knowledge Base of Healthcare Associated Infection.

Tags: Topic Maps

Posted by Paul Hollands pj at 12:10 PM

Gnowsys: A topic map tool in Python

Topic Map tool in Python written as as Zope product

Tags: Topic Maps

Posted by Paul Hollands pj at 12:03 PM

Topic Map Tools

Topic Map Tools

Tags: Topic Maps

Posted by Paul Hollands pj at 12:00 PM

December 03, 2004

MT and del.icio.us

MovableBlog: Archives: Integrating del.icio.us with PHP and Magpie

See also:

http://www.benhammersley.com/code/putting_delicious_tags_into_movable_type_entries_using_the_keywords_space.html

Tags: Blogging

Posted by Paul Hollands pj at 09:52 AM

Wish I'd found this a few days ago

Zope.org - DTML2ZPT Conversion examples

Tags: ZPT

Posted by Paul Hollands pj at 08:55 AM

Ooh.. This looks cool.. PurpleWiki

Blue Oxen Associates: PurpleWiki

Tags: Wikis

Posted by Paul Hollands pj at 08:38 AM

New XML.com column about things RESTful

XML.com: How to Create a REST Protocol

See also:

http://udell.roninhouse.com/bytecols/2001-08-15.html

http://rest.blueoxen.net/cgi-bin/wiki.pl?FrontPage

Tags: REST

Posted by Paul Hollands pj at 08:34 AM

December 02, 2004

This is quite sick - ZPT in PHP

circle.ch :: PHPTAL - PHP Template Attribute Language

http://phptal.sourceforge.net/

Tags: PHP , ZPT

Posted by Paul Hollands pj at 09:36 PM

November 26, 2004

Figured out where I was going wrong..

Note to self..

I need to use macros in my ZPT form builder. That's where I was going wrong.

Tags: ZPT

Posted by Paul Hollands pj at 08:38 PM

November 25, 2004

How to call REQUEST.set() from within ZPT

 > How do I call REQUEST.set() ?
Most uses of "REQUEST.set" can be avoided in ZPT because it has
true assignment:

     tal:define="var value;
                 global global_var  value;
		 ...
		"

If you need to communicate with objects outside the ZPT (and you
want to use "REQUEST" for this), you can use

     tal:define="dummy python: request.set(....)"

http://mail.zope.org/pipermail/zpt/2002-January/002763.html

Tags: ZPT

Posted by Paul Hollands pj at 05:09 PM

The Linear Topic Map Notation

Topic map notation format that is more human readable than XTM (the XML standard).

http://www.ontopia.net/download/ltm.html

There's also this Python tool tmproc.

Tags: Topic Maps

Posted by Paul Hollands pj at 03:20 PM

November 24, 2004

FOAF explorer view of my weblog metadata

FoaF Explorer: Paul Hollands

Tags: FOAF

Posted by Paul Hollands pj at 11:02 AM

Photo metadata

I've finished the cataloguing tool for my photo album and formalised how the RDF is represented for the album, each collection, associated events and event attendees and then person depictions in the images themselves.

This is done within the framework of the CC License and Work model to assign a CC license to everything aswell.

I've also set up an RSS feed of the latest catalogued pictures and then hacked Feed2JS so that it pics up the image thumbnails if they are in the feed:

Paul Hollands - Photo Album - RSS

Tags: Dublin Core , FOAF , PHP , RDF , RSS , Syndication

Posted by Paul Hollands pj at 10:14 AM

November 23, 2004

RSS 1.0 module for photos

RDF Site Summary 1.0 Modules: Img

Tags: RSS

Posted by Paul Hollands pj at 01:02 PM

November 22, 2004

A Web Service Interface for Creating Concept Browsing Interfaces

DLib article:

http://www.dlib.org/dlib/november04/sumner/11sumner.html

Tags: Digital Repositories

Posted by Paul Hollands pj at 10:58 AM

November 18, 2004

Instructions for building PHP with Apache 2

Apache 2 and PHP (mod_php) on Linux

Tags: Apache stuff

Posted by Paul Hollands pj at 11:41 AM

Compiling and installing Apache

Compiling and Installing - Apache HTTP Server

See also:

http://httpd.apache.org/docs-2.0/programs/configure.html

Tags: Apache stuff

Posted by Paul Hollands pj at 11:29 AM

November 16, 2004

Photo metadata: the co-depiction experiment

RDFWeb: co-depiction photo metadata

Tags: FOAF

Posted by Paul Hollands pj at 10:14 PM

Script to generate just FOAF

I've added a PHP script that generates just my FOAF, as opposed to the FOAF and blog DC.

http://minnesota.ncl.ac.uk/foaf.rdf.php?email=p.j.hollands@ncl.ac.uk

Tags: FOAF , PHP

Posted by Paul Hollands pj at 05:02 PM

PKN and Social Networks Change Knowledge Management

PKN and Social Networks Change Knowledge Management

Tags: Blogging

Posted by Paul Hollands pj at 11:45 AM

November 15, 2004

Guide to a Linux iTunes Server | Linux Gazette

Guide to a Linux iTunes Server | Linux Gazette

Tags: Linux

Posted by Paul Hollands pj at 11:41 AM

November 13, 2004

Article introducing del.icio.us

XML.com: Introducing del.icio.us

Tags: Blogging

Posted by Paul Hollands pj at 07:44 PM

November 12, 2004

Calendar woes

Sunbird turns out to be quite buggy and I can no longer be doing with it :(

I've had to go back to using version 1.6 of Mozilla with the 1.4 Linux install. This seems to work fine. Any later version of Mozilla and I can't get the installer to work.... Arrrrgh..

Tags: Calendaring

Posted by Paul Hollands pj at 03:49 PM

November 11, 2004

Syndicated bookmarks in Mozilla 1.0

You can now bookmark RSS feeds in Mozilla 1.0, but you need the following tags in the headers of your pages to let it know there are feeds available:


<link rel="alternate" type="application/atom+xml" title="Atom" href="http://minnesota.ncl.ac.uk/fuzzybuckets/atom.xml" />

Tags: RSS

Posted by Paul Hollands pj at 12:44 PM

Changes to my photo album code

I finally installed my PHP photo album on minnesota with the latest version of PHP which has GD rolled into it. When I finally got the JPEG library compiled into it though, I was getting images with only 256 colours.

I amended the code as follows and now have better image quality than I do with the app running on my iBook with a more aged PHP:

#$img_src=imagecreatefromjpeg('yoursource.jpg');
#$img_dst=imagecreatetruecolor(20,20);
#imagecopyresampled($img_dst, $img_src, 0, 0, 0, 0, 20, 20, 20, 20);
#imagejpeg($img_dst, $g_dstfile, 100);
#imagedestroy($img_dst);

$original = imagecreatefromjpeg($url);

$new = imagecreatetruecolor($width, $height);
#$new = imagecreate($width, $height);

imagecopyresampled($new, $original, 0,0,0,0, $width, $height, $size[0], $size[1]);

#imagecopyresized($new, $original, 0,0,0,0, $width, $height, $size[0], $size[1]);

Header("Content-type: image/jpeg");

if(is_null($gamma_off)){ imagegammacorrect($new, 1.0, 1.6); }

imagejpeg($new, '', 100);

#imagejpeg($new, '', 90);

imagedestroy($new);

imagedestroy($original);
< http://minnesota.ncl.ac.uk/photo_collections.php >

I've also added CC license, DC and FOAF metadata to the scripts. See copyright.rdf.

Tags: PHP

Posted by Paul Hollands pj at 11:40 AM

November 10, 2004

Feed2JS - RSS to Javascript code from Maricopa

< http://jade.mcli.dist.maricopa.edu/feed/ >

Tags: RSS

Posted by Paul Hollands pj at 04:41 PM

November 08, 2004

Adding blogrolls to MT

- < http://people.etango.com/~markm/archives.....>

- < http://people.etango.com/~markm/archives....>

Tags: Blogging

Posted by Paul Hollands pj at 09:03 PM

Publishing my iCalendar files as RDF

I've been tinkering with the Python tool by Dan Connolly for converting .ics files into RDF. I've set up a series of cron jobs to grab my .ics files from the Zope server where I store them and convert them and publish them to the web server as RDF:

< http://minnesota.ncl.ac.uk/Work.rdf.xml >

< http://minnesota.ncl.ac.uk/Home.rdf.xml >

The cron jobs update the file every half an hour.

Tags: Calendaring , RDF

Posted by Paul Hollands pj at 03:16 PM

November 04, 2004

iBook blues

Went to try and do a software update again yesterday to install iTunes 4.7, but it just sat there like it had for the past four days. I decided to try and run an update from the command line and that seemed to work OK but it got to 94% complete and it stopped. I killed the process but my Finder immediately froze up. I rebooted but the Finder just hung up again with the beach ball of doom.

All the networking was still up so I ssh'd to the machine and did a top. coreservicesd was hogging 99% of the CPU cycles and each time I rebooted it just came right back up again and took over the machine.

After a night of fruitless searching and tearing out of hair, Tony M suggested I delete the /Library/Caches directory.

That seems to have fixed it. I suspect I was in some sort of Software Update induced behaviour loop :(

Tags: MacOS X

Posted by Paul Hollands pj at 11:37 AM

November 02, 2004

Libby Miller's work to convert iCalendars to RDF

Libby Miller has come up with a two stage protocol for converting iCalendars into RDF:

<http://www.w3.org/2002/12/cal/>

I've got my own iCalendars up on the Web on minnesota now:

<http://minnesota.ncl.ac.uk/calendar/>

Looking to get an RDF view of them too.

Tags: Calendaring

Posted by Paul Hollands pj at 05:03 PM

Presentation about use of blogs and RSS for RLO peer review

This was posted by Phil Barker on the LTSN-Technical list and really set me on a different tack in my thinking about RLO evaluation, hence my current rabid bloggery:

<http://www.mcli.dist.maricopa.edu/show/nmc1003/>

Tags: Blogging , Evaluation and peer review , Learning Objects , RSS , Syndication

Posted by Paul Hollands pj at 03:23 PM

Addition to MT FOAF stuff

Added extra stuff to the MovableType metadata stuff I did yesterday. Thought it'd be nice if I could express my RSS subscriptions as foaf:subscribesTo statements. Wrote a stylesheet to convert NetNewsWire's output format OPML into FOAF RDF and then rolled it into the mt_metatada.rdf.php script I wrote yesterday.

The next step could be to build a web view of your aggregated feeds using the Magpie parser detailed earlier:

<http://minnesota.ncl.ac.uk/fuzzybuckets/archives/2004/10/index.html#000081 >

Tags: FOAF

Posted by Paul Hollands pj at 02:16 PM

What Do Application Profiles Reveal about the Learning Object Metadata Standard?

New Araidne article by Carol Jean Godby from OCLC and posted by Phil Barker on the CETIS-METADATA list:

<http://www.ariadne.ac.uk/issue41/godby/>

Also this summary by Scott Leslie:

<http://www.edtechpost.ca/mt/archive/000595.html>

Tags: IEEE LOM , Learning Objects

Posted by Paul Hollands pj at 10:22 AM

November 01, 2004

Extracting DC and FOAF metadata from the MT table structure

I've just spent the day trying to extract some decent metadata for my blogs from the vanilla MT v3.121 database tables. There's enough information there for a quite a rich Dublin Core description of the blog itself plus a very basic FOAF entry. I've augmented the FOAF entry with a very very hacky new table.

This gives an RDF description of the site with dc:creator tied to the FOAF node to produce a correct graph.

To get the raw RDF see:

<http://minnesota.ncl.ac.uk/mt_metadata.rdf.php?blog_url=http://minnesota.ncl.ac.uk/fuzzybuckets/>

Note that you pass the blog URL to the PHP script as the argument.

To render this up as HTML I then run this through an XSL stylesheet to give this:

<http://minnesota.ncl.ac.uk/render_mt_metadata.php?blog_url=http://minnesota.ncl.ac.uk/fuzzybuckets/>

Tags: Blogging , Dublin Core , FOAF

Posted by Paul Hollands pj at 05:09 PM

October 30, 2004

Blogging iTunes playlists - RSS feeds

Found this posting by Kimbro Staken about a Python script he's written which posts his iTunes playlist to his blog using in-line AppleScript and the MT XML-RPC.

< http://www.xmldatabases.org/movabletype/archives/000159.html >

Should be straight forward to retask it to post 'now playing' titles too?

Tags: MacOS X , Python , RSS

Posted by Paul Hollands pj at 10:58 AM

October 29, 2004

Article about MT and PHP includes

Looking to roll some common PHP into the headers of all my bogs.. This might be useful:

< http://www.elise.com/mt/archives/000484using_php_and_mt_includes.php >

Tags: Blogging , PHP

Posted by Paul Hollands pj at 05:58 PM

Magpie RSS parser for PHP

< http://magpierss.sourceforge.net/ >

Tags: PHP , RSS

Posted by Paul Hollands pj at 03:36 PM