From EUTC Wiki
Revision as of 12:03, 27 February 2009 by Xander (talk | contribs) (Migrating content to opentheatre.org.uk)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

XTS has a home!

Because XTS might be useful to other theatres and is taking code contributions from multiple people, XTS now has it's own website at http://www.opentheatre.org.uk. The content on this page is being migrated to the new site, where it should be better updated and made more comprehensive.

eXtensible Ticketing System

XTS is the Bedlam Theatre's new ticketing system. It's key feature is extensibility, meaning that if it doesn't do something you want it to do, you (or a suitably inclined geek) should easily be able to add it. Read on for more key features and read further for technical information that will help you maintain and make changes to the system if that is your want.

If you are just looking for help using the software to sell tickets, try Using XTS.

What I planned to write about

  • History / Motivation
  • Things you should know before you start
    • Key Concepts and Terminology
      • "Reserved" vs. "Booked".
      • "Holding" tickets.
      • "Ticket Prototypes"
      • Verifying bookings
      • "Snewts"
      • How XTS handles times between 0AM and 3AM.
    • Principles
      • Portability (OS Transparency)
      • Accessibility (Network Transparency)
      • Extensibility
      • Readability
      • Simplicity (Minimum Complexity in the Layers that Matter)
      • High-Level Scripting
  • Technologies in use
    • HTTP
    • XML
    • HTML
    • CSS
    • Python
    • Java
    • Crypto - Rjindael (AES)
  • Parts of the system
    • DONE Database
      • DONE Scheduled Database Backup
    • DONE Ticket Server
      • DONE Web.py
      • DONE API
    • DONE Print Server
      • DONE API
      • DONE Making new ticket layouts
      • DONE Changing the ticket logo
    • Static Server
      • Apache 2.2
    • Administration Server
    • Javascript Client
      • Ami
      • Snewts
      • Prism
    • Reporting
      • XSLT
    • HTTPProxy
      • Protecting the ticketing server from the proxy
    • Startup - Windows Services
      • JSWrapper
  • Directory Structure (C:\XTS\)
  • Installing XTS
  • Making Improvements - A HOWTO
    • Known Issues / Things you might like to work on
      • Sniffing attacks
      • No test suite, no TDD
      • Transactions (there aren't any)
      • Printing - it's pretty crap
      • Reports - XSLT, but not as it should be
    • Familiarisation
      • Grokking the Source
    • Tools You Must Use
      • Firebug
      • IPython
    • Things You Must Do
      • DONE Setting up your own dev version from trunk
      • Keeping the documentation up-to-date
    • Safe and Unsafe
      • Where is the money?
    • Versioning
    • Fun Ideas For Improvements or Otherwise
      • Booking from portable devices for producers ("Would you like to come? I'll book you a ticket now.")
      • XTS-controlled DMX for Box Office Lighting Fun Times
      • Heads-up displays for show times and sold out info a-la every cinema you've ever been to


Parts of the System


XTS uses a MySQL database. It should be very easy to port XTS to other databases, most access is abstracted through #web.py's db module but there may be some report-generating SQL queries that are specific to MySQL in the XTS source. See #data.py for more info.

The schema is called "xts".

Scheduled Database Backups

As of 2008-07-18, Maude is configured to take nightly backups of the XTS database to C:\XTS\Backups. These backups should be scaled back to weeklies or slower at the end of Fringe 2008 or they will eventually consume all available disk space on the machine. Furthermore the database should occasionally be backed up "off-site" in case of hard disk failure.

Ticket Server

The ticket server does the hard work of allocating, booking and selling tickets of various types for various performances of various shows. The ticket server is written in #Python. It is implemented on top of a web server (web.py]), allowing clients to interact with the server via #HTTP using #XML for data exchange.

The ticket server is accessible via HTTP on port 8080.


API stands for Application Programming Interface. It tells you how you can write programs that talk to the ticket server in order to do useful things (like get show information, or sell tickets online).

The #Javascript Client uses the XTS API to make a nice box office interface for selling tickets to customers.

If you know a little XML you can write programs that interact with the API yourself. You can write your programs in Java, PHP, Python, Ruby -- whatever. So long as you can make an HTTP connection and deal with a little XML, you're good to go.

See XTS API for further information and full documentation.


The ticket server uses host and password authentication to decide who can do what using the API. Full details are in the API documentation.

XTS also has a built-in secure proxy (security.py, part of #XWF), based on AES with a preshared key. It allows trusted remote hosts privileged access to the ticketing server over an encrypted connection.

Applications that want to use the secure method of connecting to the server use a special URL (/v1/secure/v1/connect) and then "trade secrets" with the ticketing server in order to prove it's trustworthiness and verify the trustworthiness of the server. It's all very ingenious and you really shouldn't try doing it yourself until you've taken Computer Security (a really good course) or are Bruce Schneier.

To be honest, it's quite voodoo - but it's also crucial when doing anything regarding ticket sales over the internet. So, really, don't mess with it until you quite know what you're doing.

Error Handling

When the server encounters an error (for instance, a ticket that you are selling has already been sold), internally it throws a SnewtsError exception.

SnewtsErrors are caught by the request dispatcher (snewtsUrlInvocation in server.py) and turned into an XML-formatted error that is sent back to the client.

SnewtsErrors consist of an error number (useful to computers) and an error message (useful to people). Errors are grouped into types. For instance, all errors that start with the number 404 represent a requested thing not being there ("Not Found"). However, 404.1 specifically means that it was a ticket that wasn't found. 404.2 means a performance wasn't found and so on.

This is important when writing software that talk to the ticket server via the #API. When reading responses from the server the client software can have a default way of handling 404 errors but additionally can have a specific way of handling 404.5 errors.

Where possible, error numbers correspond to the HTTP status code definitions. This is mostly because I'm perverse and think it's funny that when something isn't there you get a 404 error. However, it can be useful when writing your client software in that a 4xx error indicates that the client probably did something wrong whereas 5xx errors indicate that something went wrong on the server (which is potentially much more serious).


XWF is a python module of useful bits of code for writing web applications. The thinking is that only XTS code should be in the XTS module. So if there's some code which does something more generic - like writing log files or providing security - this code should be written in a different module where it doesn't clutter up the code that actually matters.

At time of writing, XWF includes xml.py, which is a lightweight set of functions for very quickly writing XML documents, and security.py, which provides a security layer for remote hosts that need trust and secrecy when talking to the Ticket Server (see #Security).




Contains various useful constants used in the rest of the XTS source. This makes the code more readable. In the database, the number 2 represents a ticket that is booked. However, instead of using the number 2 to refer to such tickets in the source code, we use the expression ticketstates['BOOKED']. This makes the code (a lot) more readable.

Funnily enough, it's generally a bad idea to change the constants. However, you should add to them where appropriate, for instance, if you intend to record new kinds of events in the log.

There is nothing technically constant about the variables in constants.py - they could easily be modified at runtime. If you know how to define constants that are actually constant, or just of a better general approach, then this might be an area of the server that you could improve. --Xander 17:21, 18 July 2008 (BST)


data.py provides an interface to the database. Wherever XTS needs to get information from the database, it does it by calling a function in data.py. data.py then takes care of turning the information request into SQL, and if necessary, post-processing the response into a useful form for the caller.

You should be able to port XTS to another datastore simply by replacing data.py and stats.py.


exceptions.py defines the SnewtsError exception type. For more information, see #Error_Handling.


helpers.py contains various functions that help to solve common and recurring problems in the Snewts application (for instance, turning datetime objects into human-readable date strings). This unclutters #logic.py, which should just contain the business logic of how to sell tickets properly. Functions in helpers.py should ideally be moved into #XWF, but who really cares?


logic.py sits between the client request and the database. When the client asks to sell a ticket, logic.py makes sure that the show actually exists, the ticket is valid for the performance, there are enough tickets left and anything else that needs making sure of. If any one bit of XTS is going to get something critically wrong, it's going to be in logic.py.

logic.py never talks to the database directly. To get data from the database and make changes to the database it must call functions in #data.py.


printer.py is an abstraction layer with one synchronous public function, printTicket(). It takes care of sending the ticket to the #Print Server and making sure that the printer got the ticket. If the print can't be confirmed it throws a SnewtsError.


reflection.py is a silly bit of code with some functions for counting lines in code. It's used to provide some of the statistics you get when you look at the XTS "about" page, such as how many TODO comments are still left in the code.

reflection.py should be refactored into the XWF module - none of the code is specific to XTS itself, so it shouldn't be cluttering up the snewts module.


report.py contains all of the code that formats statistics gathered from the database into XML reports. It also does a little math. See #Reporting.


snewts.py does the job of recognising requests from clients, checking that the clients are authorised to make the requests, and sending back responses. Simple requests (ie. getPerformances) are fulfilled by getting data from #data.py directly. More complicated requests are fulfilled by calling business logic in #logic.py or getting #report.py to generate reports.


stats.py contains code for calculating various metrics and statistics with regards to the XTS database (such as "how many tickets have been sold?" and "of all of the seats that have been available for all of the shows ever, what percentage of them did we actually sell?"). stats.py accesses the database directly, because otherwise all of the code in stats.py would have to be in data.py, and that would make data.py even bigger than it already is.


status.py contains definitions of all of the errors that XTS may reply with when something goes wrong. If you're writing client software, you need to anticipate these coming back at you.

Print Server

The print server is a separate entity from the ticketing server that handles ticket printing. It listens on the network for messages instructing it to print tickets.

It is written in pure Java for the convenience of Java's layout and printing library. It uses the effective users' default printer for printing (so this printer needs to be set to the ticket printer).


The print server listens for tickets to print on port . Tickets are sent to the printer as UDP messages on port 8301. The UDP message format consists of six strings terminated by the NULL character. It does not support UTF8 encoding. It is very fail. The strings are, in order:

  • Show Name
  • Date (expected format: ddd YYYY-MM-DD)
  • Time (expected format: HH:MM)
  • Booking name (can be an empty string)
  • Ticket serial
  • Ticket type (ie. "Student")

When the print server receives your ticket and succeeds in dispatching it to the printer it will reply with a UDP packet containing the ticket serial you specified.

Making new ticket layouts

You need to know Java to write new ticket layouts.

Make a pair of new classes implementing uk.org.opentheatre.xts.Ticket and uk.org.opentheatre.xts.TicketFactory. The former must lay out the ticket, the latter must create instances of the ticket. Look at existing ticket classes for examples on how to do this.

Then, modify the uk.co.bedlamtheatre.BedlamTicketPrintServer to use your new TicketFactory class. You're now done. You can run your modified BedlamTicketPrintServer straight from your IDE and use the taskbar icon that appears to print test tickets and receive tickets from the XTS Ticket Server (if the print service isn't running - see #Startup - Windows Services). When you're happy with your new layout, replace the classes in C:\XTS\PrinterInterface\bin and either restart the Windows Service or just reboot.

This is much easier than making a new layout. Just replace C:\Xander\ticketlogo.bmp with your new logo. It should have the same dimensions and should probably be just black and white.