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 OperatorsTags: 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
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,
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
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">»</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">»</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 ServletTags: 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 minutesFiles: 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
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
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
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

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
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
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 ") . }
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
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
<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
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
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
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
Posted by Paul Hollands pj at 05:52 PM | Comments (0)
XML_FOAF PEAR Package
http://pear.php.net/package/XML_FOAF
Posted by Paul Hollands pj at 04:33 PM | Comments (0)
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
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
Posted by Paul Hollands pj at 04:51 PM | Comments (0)
Prototype-based 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
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
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
Tags: AJAX
Posted by Paul Hollands pj at 04:28 PM | Comments (0)
XML schema for site maps
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
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
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>
Posted by Paul Hollands pj at 09:02 PM | Comments (0)
XSL for formatting a 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.
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
Posted by Paul Hollands pj at 08:31 AM | Comments (0)
May 26, 2009
MySource Matrix 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)
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
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.
- Primary and foreign key columns should be set as
int(10)
and listed at the top. - All columns apart from the primary key should be set as
null
by default. - Date columns are set as
int(20)
and dates should be inserted as unix timestamps. - Varchar columns are always set as
varchar(255)
. - Enumerations shouldn't be used with the framework.
- 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 theexpired_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
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.
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
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.phpFramework 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
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>
Posted by Paul Hollands pj at 10:01 PM | Comments (0)
March 14, 2009
phpPGAdmin
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
Posted by Paul Hollands pj at 10:19 AM | Comments (0)
What the hell are webhooks?
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
Posted by Paul Hollands pj at 08:15 PM | Comments (0)
February 25, 2009
FOP Apache XSL-FO processor
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
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
Posted by Paul Hollands pj at 11:02 PM | Comments (0)
February 09, 2009
Planet Feed Aggregator
Tags: RSS
Posted by Paul Hollands pj at 11:53 AM | Comments (0)
February 05, 2009
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
Tags: Tomcat
Posted by Paul Hollands pj at 02:54 PM | Comments (0)
January 28, 2009
Emptees
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
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

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
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
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
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
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
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
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
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
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
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
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
Tags: Atom
Posted by Paul Hollands pj at 04:06 PM | Comments (0)
July 16, 2008
The RDF API for PHP
Also and more usefully:
http://www4.wiwiss.fu-berlin.de/bizer/rdfapi/tests.html
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:
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
Posted by Paul Hollands pj at 01:40 PM | Comments (0)
iCal creator class in PHP
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
Posted by Paul Hollands pj at 11:21 PM | Comments (0)
RDFLib Python Libraries
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
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
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
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
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
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[] = ' '.$row[$lcol]; }} try{ return implode("\n", $opts); } catch(Exception $e){ return $opts[0]; } } function update_table_extra($table, $r, $where, $pk){ global $user_id; if(!$where){ $where = '1'; } $sql = "desc `".$table."`"; $reply = just_sql($sql); $exclusions = array('insert_by','update_by','insert_date','update_date'); $pk_col = NULL; $fields = array(); $text_fields = array(); foreach($reply['rows'] as $row){ if($row['Key'] == "PRI"){ $pk_col = $row['Field']; } else{ if(!in_array($row['Field'], $exclusions)){ $fields[] = $row['Field']; } if(strstr($row['Type'], 'text')){ $text_fields[] = $row['Field']; } if(strstr($row['Type'], 'varchar')){ $text_fields[] = $row['Field']; } } } $sets = array(); if(in_array($key, $fields)){ if(in_array($key, $text_fields)){ if((strtolower($value) != 'nulled') && (strtolower($value) != 'null')){ $value = "'".quote_me($value)."'"; } } if(strtolower($value) == 'nulled'){ $sets[] = " ".$key." = NULL"; } elseif(has_value($value)){ $sets[] = " ".$key." = ".$value; } } $sql = "update `".$table."` set ".implode(',',$sets).", update_by = ".$user_id.", update_date = unix_timestamp() where ".$where." and ".$pk_col." = ".$pk; $reply = just_sql($sql); return $reply; } function update_table($table, $r, $pk){ global $user_id; $sql = "desc `".$table."`"; $reply = just_sql($sql); $exclusions = array('insert_by','update_by','insert_date','update_date'); $pk_col = NULL; $fields = array(); $text_fields = array(); foreach($reply['rows'] as $row){ if($row['Key'] == "PRI"){ $pk_col = $row['Field']; } else{ if(!in_array($row['Field'], $exclusions)){ $fields[] = $row['Field']; } if(strstr($row['Type'], 'text')){ $text_fields[] = $row['Field']; } if(strstr($row['Type'], 'varchar')){ $text_fields[] = $row['Field']; } } } $sets = array(); foreach($r as $key => $value){ if(in_array($key, $fields)){ if(in_array($key, $text_fields)){ if((strtolower($value) != 'nulled') && (strtolower($value) != 'null')){ $value = "'".quote_me($value)."'"; } } if(strtolower($value) == 'nulled'){ $sets[] = " ".$key." = NULL"; } elseif(has_value($value)){ $sets[] = " ".$key." = ".$value; } } } $sql = "update `".$table."` set ".implode(',',$sets).", update_by = ".$user_id.", update_date = unix_timestamp() where ".$pk_col." = ".$pk; $reply = just_sql($sql); return $reply; } function add_new_row($table){ global $r; global $user_id; $sql = "insert into `".$table."`(insert_by, insert_date) values(".$user_id.", unix_timestamp())"; $reply = just_sql($sql); return $reply['insert_id']; }
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
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
Posted by Paul Hollands pj at 12:28 PM | Comments (0)
December 15, 2007
PHP SVN bindings
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?
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
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 ManagerTags: 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:
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
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
Posted by Paul Hollands pj at 12:51 PM | Comments (0)
Printing to PDF from HTML using gecko
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:
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.
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.
Tags: Music
Posted by Paul Hollands pj at 10:42 AM | Comments (0)
July 23, 2007
Subversion pre-commit script in Python
Tags: Pre-commit Hooks , Subversion
Posted by Paul Hollands pj at 04:35 PM | Comments (0)
July 05, 2007
Transparent PNG Generator
Posted by Paul Hollands pj at 11:58 AM | Comments (0)
July 04, 2007
Color Wheel
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
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
Tags: Calendaring
Posted by Paul Hollands pj at 05:25 PM | Comments (0)
May 18, 2007
AJAX HTML slideshow
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
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
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:
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
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
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
Tags: Syndication
Posted by Paul Hollands pj at 03:46 PM
September 24, 2006
Web site analysis in PHP
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
Tags: Python
Posted by Paul Hollands pj at 10:06 AM | Comments (0)
Python interpreter embedded in PHP
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
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
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
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
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
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
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
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
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
Posted by Paul Hollands pj at 02:41 PM | Comments (0)
May 24, 2006
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
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
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:
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
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
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
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
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
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
Tags: Linux
Posted by Paul Hollands pj at 04:18 PM
March 30, 2006
Handling cookies in JavaScript
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
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
Tags: JSP
Posted by Paul Hollands pj at 05:04 PM
February 13, 2006
Woz
Posted by Paul Hollands pj at 08:16 PM
February 11, 2006
Best of current trends 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
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:
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
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
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
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
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..
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:
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
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:
Tags: RDF
Posted by Paul Hollands pj at 03:03 PM
Eclipse and Jython
Apparently there are Jython plug-ins for Eclipse too:
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:
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!
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:
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
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:
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
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
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:<div class="row">"/>
....Then the same for the closing block...
<tal:block tal:condition="python: odd_even == 'even'" tal:replace="structure string:</div> <!-- 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:<?xml version="1.0"?>"/>
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:<?xml version="1.0"?>"/>
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:
Hmmm.. Seems if I'd read my own posts I could have done it with a PHP like global
statement instead.
Posted by Paul Hollands pj at 01:24 PM
April 15, 2005
New 'Back in Business' FOAF 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.
Posted by Paul Hollands pj at 04:58 PM
April 12, 2005
Why 1.0 is best..
Tags: RSS
Posted by Paul Hollands pj at 08:44 AM
Handling RSS 1.0 in PHP
Tags: RSS
Posted by Paul Hollands pj at 08:43 AM
April 11, 2005
RSS events to XHTML notes by Libby Miller
Tags: Calendaring
Posted by Paul Hollands pj at 03:05 PM
April 09, 2005
Embedding RDF in XHTML the hard way
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:
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
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
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
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?
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
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:
- 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)
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!
Tags: Atom
Posted by Paul Hollands pj at 02:12 PM
Articles about Atom athentication, RDF and Identification
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
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:
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
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
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:
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/
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
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
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?
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 >
Posted by Paul Hollands pj at 05:58 PM
Magpie RSS parser for PHP
< http://magpierss.sourceforge.net/ >
Posted by Paul Hollands pj at 03:36 PM