Sie sind auf Seite 1von 45

The CPAINT Handbook

Paul Sullivan
Dominique Stender

First Draft
Acknowledgements

• all the users who have contributed code, ideas, defect reports, and made the CPAINT project a success

• Paul would like to thank his loving wife Michelle for all the support she’s given throughout the
development of CPAINT and this book
Table of Contents
AJAX Fundamentals ...................................................................................................................................................................... 2
What is AJAX? ....................................................................................................................................................................... 2
Is AJAX a new concept? ....................................................................................................................................................... 3
Who’s using AJAX? .............................................................................................................................................................. 3
Is AJAX cross-browser compliant? ..................................................................................................................................... 3
The Beginning (a good place to start) ................................................................................................................................. 4
What about POST? ................................................................................................................................................................ 5
Callbacks and Asynchronicity ............................................................................................................................................. 6
Calling the Backend .............................................................................................................................................................. 8
Finally, Some Data ................................................................................................................................................................ 9
Backend Implementation ..................................................................................................................................................... 9
Backend Security ................................................................................................................................................................. 10
Getting Frontend Data ........................................................................................................................................................ 10
Function Execution ............................................................................................................................................................. 11
Usability Considerations .................................................................................................................................................... 11
Further Reading .................................................................................................................................................................. 12
Introduction to CPAINT ............................................................................................................................................................. 13
What is CPAINT? ................................................................................................................................................................ 13
CPAINT Classes and Utilities............................................................................................................................................ 14
Frontend Classes ............................................................................................................................................................. 14
Backend Classes .............................................................................................................................................................. 14
Proxy Utility .................................................................................................................................................................... 15
Debugging Utility ........................................................................................................................................................... 15
Obtaining CPAINT and Other Information .................................................................................................................... 15
Frontend Implementation ........................................................................................................................................................... 16
Import and Setup ................................................................................................................................................................ 16
Object Properties ................................................................................................................................................................. 17
set_debug ......................................................................................................................................................................... 17
set_proxy_url................................................................................................................................................................... 18
set_transfer_mode .......................................................................................................................................................... 18
set_async .......................................................................................................................................................................... 18
set_use_cpaint_api .......................................................................................................................................................... 18
set_persistent_connection .............................................................................................................................................. 19
set_response_type ........................................................................................................................................................... 19
set_auth_user................................................................................................................................................................... 20
set_auth_pass .................................................................................................................................................................. 20
Creating a Callback Function ............................................................................................................................................ 21
Gathering Data .................................................................................................................................................................... 21
Calling Backend Functionality .......................................................................................................................................... 22
Accessing Non-CPAINT Data Sources............................................................................................................................. 23
Traditional Web Scripts ................................................................................................................................................. 24
XML Based Scripts .......................................................................................................................................................... 24
Working With Data in the Callback .................................................................................................................................. 25
Working with CPAINT Result Objects............................................................................................................................. 26
Using the Proxy Utility ....................................................................................................................................................... 28
Backend Implementation ............................................................................................................................................................ 29
Including the Backend ........................................................................................................................................................ 29
Stubbing the Backend Functions ....................................................................................................................................... 29
Registering Functions ......................................................................................................................................................... 30
Executing the Code ............................................................................................................................................................. 30
Accepting Data .................................................................................................................................................................... 31
Building Simple Responses................................................................................................................................................ 31
Building Complex Responses ............................................................................................................................................ 32
cpaint_node Methods ......................................................................................................................................................... 32
add_node ......................................................................................................................................................................... 33
set_data ............................................................................................................................................................................ 33
get_data ............................................................................................................................................................................ 34
set_attribute ..................................................................................................................................................................... 34
get_attribute .................................................................................................................................................................... 34
set_name .......................................................................................................................................................................... 34
get_name .......................................................................................................................................................................... 35
Complex Response Example ............................................................................................................................................. 35
Appendix ...................................................................................................................................................................................... 37
Arbitrary Character Sets..................................................................................................................................................... 37
Frontend........................................................................................................................................................................... 37
Backend ............................................................................................................................................................................ 37
Backend Framework Encodings ................................................................................................................................... 38
CPAINT Backend Protocol ................................................................................................................................................ 38
api_query ......................................................................................................................................................................... 38
cpaint_function ............................................................................................................................................................... 39
cpaint_response_type ..................................................................................................................................................... 39
cpaint_argument[] .......................................................................................................................................................... 39
API Reference ...................................................................................................................................................................... 40
The CPAINT Handbook

AJAX Fundamentals

As this book is titled The CPAINT Handbook, we will only cover the fundamentals of AJAX for newcomers to the
technology in this section. This section is not intended to be a complete reference or implementation guide on AJAX.
There are wealth of books available that go into much greater detail.

What is AJAX?

AJAX, in terms of web development, is an acronym for Asynchronous JavaScript and XML. It is a development
technique that allows more responsive web applications by updating only parts of a web page. Unlike traditional
web forms, where a complete round-trip to the server is required to update a page (including sending all of its data),
AJAX allows developers to break a page into multiple sections and can ‘react’ to changes in data (based on user-
driven or predefined timed events) and update the page without requiring a complete round-trip and page refresh.

In this diagram, we see a traditional web application. The user enters data into one or more form fields and the
browser submits the form (typically based on a user-driven ‘submit’ event). All of the data on the form is sent to the
server. If the data needs to remain on the page, typically the server will have to send that data back the browser
(unless some other method is used, such as saving form data in a cookie before the form is submitted).

2
The CPAINT Handbook

In this diagram, we see an AJAX-based web application. In this case, as the user works with the data on the page,
only the applicable data is sent to the server and the page is updated. Because the page never refreshes, any new (or
unchanged) data remains on the page throughout the multiple server transactions.

Typically, AJAX applications are based on a Browser Push model (the browser pushes data to the server). However,
a new concept called ‘Reverse AJAX’ is being utilized in some very specialized applications where the model is
reversed – Server Push (the server pushes data to the browser). This model is appropriate for situations where pages
need to be updated in response to something on the server-side, not something that is happening on the browser
side.

Is AJAX a new concept?

While most newcomers to the ‘AJAX revolution’ say that this is a new concept – it is a heated debate. Our own
research shows that the concepts of AJAX were being utilized long before 2005. Microsoft’s Outlook Web Client,
released with Microsoft Exchange Server 97, had the capability of updating the mail folder view and some properties
of the mail view window automatically. However, this capability was only available if the user was utilizing Internet
Explorer 4.0. Later that year, Microsoft released the Remote Scripting Toolkit to the public, but again, it only
supported IE and the ASP scripting language.

In addition, in August 2000, Brent Ashley released his JavaScript Remote Scripting toolkit which supported IE and
Netscape and ran entirely client side. We believe it is a combination of ideas from Ashley and Microsoft that gave
rise to the AJAX we all know and love today.

Who’s using AJAX?

If you’ve ever used Google Maps, Flickr, Netflix, or Wordpress – you’ve used AJAX and didn’t even know it (that’s
actually part of the idea). There are literally thousands of websites and applications that utilize AJAX to give its users
an interactive experience on the web. In fact, Tim O’Reilly (love him or hate him) coined the term ‘Web2.0’ to
describe these highly interactive websites (although the term also applies to today’s ‘social networking’ sites such as
MySpace, although they make sparse, if any, use of AJAX concepts).

Is AJAX cross-browser compliant?

Any web browser released since 2005 is ‘AJAX compliant’. Prior to that date, alternative methods must be utilized
(such as hidden IFRAMEs) to make the retrieval of backend data transparent to the user. However, we have found

3
The CPAINT Handbook

other problems in older browsers (such as incompatible JavaScript and DOM implementations) that make the need
for including alternate access methods in AJAX applications a colossal waste of time.

Since Internet Explorer 4.0 (actually MS-XML 1.0 library), an object called ‘XMLHTTP’ has been available to create
the transparent connection to the server. However, it wasn’t until the developers behind Firefox, Opera, and Safari
each built their own 100% compatible version of the object (called XMLHTTPRequest) until things got cooking.

The Beginning (a good place to start)

The fundamentals of AJAX are actually quite simple when broken down. Here we’ll go through a simple
implementation on the frontend side of things. Later, we’ll go through the backend.

To start, we need a reference to our connection object.

var A;
try {
A = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
A = new ActiveXObject('Microsoft.XMLHTTP');
} catch (oc) {
A = null;
}
}
if (!A && typeof XMLHttpRequest != 'undefined')
A = new XMLHttpRequest();
if (!A) alert('Could not create connection object');

As stated earlier, IE calls the connection object ‘XMLHTTP’ and the other browsers call it ‘XMLHTTPRequest’. This
code simply tests for the presence of those objects and assigns a reference to it.

Next, we need to get the data we are going to pass to the backend. For example, I want to pass an email address back
to the server to see if it’s already in a database. In my HTML code, I have an input box with the ID attribute set to
‘email_address’. On the server side, my script (checkemail.php) expects this information to be in a form variable of
the same name (‘email_address’) and it expects a GET request.

So, I’m going to create a few local JavaScript variables containing this information.

var emailAddress = document.getElementById(‘email_address’).value;


var serverURL = ‘checkemail.php’;
var formMethod = ‘GET’;
var queryString = ‘?email_address=’ + emailAddress;

Did you notice the ‘queryString’ variable? Yes, I’m building a querystring just like I would pass it manually in the
browser’s address bar. In fact, those connection objects an be seen as HTTP socket – it can be used to send and

4
The CPAINT Handbook

retrieve data over the web, but we have to set its properties and actions programmatically. And since I’m performing
a ‘GET’ request, I have to include the ‘?’ in order for it to be properly formed.

But, did you notice something missing? If it’s a ‘GET’ request, the querystring must be appended to the URL. So,
one more temporary JavaScript variable:

var URLtoCall = serverURL + queryString;

Yes, I could have built the entire URL in one fatal swoop, but I wanted to show you all the pieces you need for the
request:

1. The URL of the script to call;


2. A properly formed querystring;
3. and, the actual data to pass to the script.
[edit: I don’t get the difference between 2. and 3. – GET vs. POST?]

Now, unlike images which can come across different servers, this is a script and JavaScript security doesn’t allow you
to import (run) scripts across domains (unless your script is signed with a trusted certificate). The same applies to
the XMLHTTP (Request) object – you can’t call a backend script from a different server.

If this script was served up by a page from the www.cpaint.net server, you’ll only be able to access backend scripts
on the www.cpaint.net server (and not any other server, even if it’s on the same domain – for example,
dev.cpaint.net). (However, if you use CPAINT and the backend proxy, you can access scripts across multiple servers
and domains – the data is passed to the local proxy script which in turn makes another request to the remote server
and passes the data back up to the browser.)

Note: Because the values of the URL and querystring are passed by value (and not reference) to the object, if either
piece of data changes, you’re going to run all this code again. That’s why it’s best to put all the ‘setup’ code in one (or
more) functions.

[edit: I find it a little irritating that the sending of the GET request and the response is missing here. Either integrating
it or a reference to the corresponding chapter would be good.]

What about POST?

If you’re script or page is expected a POST request, as opposed to a GET request (or you want to do both), you’re
going to need to do a bit more work. Normally, when you submit a form via the web browser, it handles setting the
HTTP request headers for you. Because the connection objects are more generic, you’re going to have to set the

5
The CPAINT Handbook

headers yourself. It helps to be familiar with the HTTP protocol specification and MIME content-types when it
comes to this, but in most cases, you only need to add these two lines to your JavaScript code:

A.setRequestHeader("Method",
"POST " + URLtoCall + " HTTP/1.1");
A.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");

And yes, I did say above you can do both a GET and a POST at the same time, if your script has the ability to parse
the querystring and the formdata. Most web scripting languages will support both, although you might have to call
two different methods or data structures to get the data you want.

You’ll notice that there’s no place for the POST in the above example. However, similar to the GET querystring, the
POST formdata must be in a URL-encoded string. However, unlike GET, we don’t need to append a question mark
(‘?’) to the beginning of that string. For example:

var postData = ‘email_address=’ + emailAddress


+ ‘&name=’ + username;

Callbacks and Asynchronicity

If you’re familiar with ActiveX components, you already know that they are event driven, not procedural. The same
is true for the XMLHTTP(Request) connection objects. You do not simply call the object and get data back from it.
Inside these objects, after creating a connection to the server, they wait until data is received back from the server.
When that happens, an event is fired where the state of the connection can be checked and we can retrieve our data.

Event are natively supported in many JavaScript objects, among them the XMLHTTPRequest object that AJAX is
built on. For this object it can call JavaScript code when there is a change to its connection state. This JavaScript code
is most commonly referred to as a ‘callback’ function (because it exists outside of the context of the object’s memory
space, thus ‘called back’ from the connection object).

The ‘A’ in AJAX stands for ‘asynchronous’, meaning that these transparent connections to the server can occur while
the user is performing other operations on the same web page (and these connections can occur simultaneously
without interfering with each other, if multiple instances of the object are created).

Note: It is entirely possible to have SJAX (Synchronous JavaScript and XML) where the user is blocked from using
the page until the call to the server is completed. CPAINT is the only toolkit that natively supports ‘SJAX’, although
it is rarely utilized, nor suggested.
The user will experience a “hangup” of the browser until the response has been retrieved

6
The CPAINT Handbook

So, our callback function can be called multiple times as the connection object is performing the request – and the
user is interacting with the page. Because of this, callback functions have to check the connection state of the
XMLHTTP (Request) object each time it is fired. This is achieved by calling the readyState property of the object.
Possible states include:

1: Loading – object has been created, but it has not made a call to the server
2: Loaded – object sent request to the server, no response or data
3: Interactive – object is receiving data from the server
4: Completed – object has received data from the server and ready for retrieval

Unless you need a status of the object, the only state you are really going to care about is ‘4 – Completed’. This
means the object got something back from the server. That doesn’t necessarily mean that you’ve got the correct data.
For example, if you pointed the object to a script that didn’t exist, your data might probably contain the HTML for a
‘404 Page Not Found’ page sent from the server.

So, in addition to the callback function checking the state of the object, it’s a good idea to check the HTTP connection
status (e.g., 200, 401, 404, et cetera). This data is available in the status property of the object. If you get back 404,
which means your server couldn’t find the script you wanted to call. If you get 401, the server expects some user
credentials. But, if you get back 200, you’ve got data – and hopefully, it’s what you wanted! The data will be in two
places (simultaneously) – responseText and responseXML).

responseText is the raw, unparsed data that you can use if you’re using to retrieve a simple value from a backend
function or plain-text. However, if you’re retrieving HTML or XML and want to continue to work with it in
JavaScript as a DOMDocument, use responseXML. The choice is yours to make, the data is identical. Keep in mind
that if you do use responseXML, it must be proper markup otherwise you’ll get errors when trying to work with it.

As I said above, the connection object will call the JavaScript callback function for you. But, you need to write it first.
Here is a simple function you can use.

var data;

A.onreadystatechange = function() {
if (A.readyState != 4)
return;
if (A.status == 200) {
data = A.responseText;
}
}

In addition, you can assign the onreadystatechange property to point to another function that you’ve written
somewhere else (whereas this example is more of an ‘inline’ function). Your callback function can also call any other
JavaScript function. However, it’s best to do it once the the readyState is 4 and the status is 200, otherwise that
function might be hit many times when you don’t necessarily want it to. It’s also highly advisable to pass any data

7
The CPAINT Handbook

received from the object directly to the other function and not in a global variable, as it might be overwritten on your
next call to the server.

Calling the Backend

Once you’ve got your object created, strings properly formatted, and callback function ready – it’s time to make the
call to the server.

The first thing you’ll want to do is open the object and pass a few basic parameters. Those parameters are:

1: Method – whether this is a GET or a POST call


2: URL – what page or script are we going to retrieve
3: Asynchronous – if you’re using AJAX, set this to true and your callback will be utilized. If you’re using
SJAX, set this to false. The object will block further execution of the page until the data is returned from the
server. (Note: for the XMLHTTPRequest object, this parameter is optional and defaults to true. However,
we recommend setting it to ‘true’ in all instances for compatibility.)
4: HTTP Username (optional) – if your script utilizes HTTP basic authentication, set the username here
5: HTTP Password (optional) – if your script utilizes HTTP basic authentication, set the password here

Here’s an example, in all its glory:

A.open(‘GET’, URLtoCall, true);

But, there’s one more thing missing. Remember earlier when I said you could do a HTTP POST, but we didn’t set the
data just yet. Regardless whether or not you are using HTTP GET or POST, you have to make a call to the send
method of the object. If you’re doing a POST request, you will pass it your formdata as the only parameter.
However, on a GET request, anything you put here will be ignored, but we recommend you just pass NULL for
compatibility.

// HTTP POST
A.send(formData);

// HTTP GET
A.send(null);

The data has now been sent to the server and the object will await a response.

8
The CPAINT Handbook

Finally, Some Data

Once you’ve made the call to the server, it’s time to see what you’ve got. Depending on what format the server
returned the data in, as we mentioned above, there’s two ways to get it out of the object and work with it in
JavaScript.

If the data is properly formatted markup, such as HTML or XML and you want to work with it as a DOMDocument
(so you can traverse it, pulling out tag names, attributes, and tag data), you would use responseXML. However, if
it’s in any other format or you don’t need to traverse it (say, you’re just going to display it to the user), use
responseText to get the data. See the sample callback function which uses responseText to assign it to a global
variable. (You could also say, use responseXML for complex data or responseText for simple data.)

What you do with the data once you’ve got it is up to you and your imagination. Simple AJAX applications simply
return HTML from the frontend and replace the contents of an HTML DIV with the results. See
http://cpaint.net/examples.html for a few simple (and complex) examples of what you can do (read about the
CPAINT API later on – the source code to the examples is distributed with CPAINT).

Backend Implementation

Now that you know how to get data from the backend, it’s time to take a closer look at generating that data. Just like
the frontend code, the backend can be as simple or as complex as you make it (but generally, the backend is easier to
implement than the frontend, since you won’t have to deal with cross-browser issues).

Simple backend implementations simply generate HTML data which is retrieved by the frontend and replaces parts
of an existing web page. This can be achieved in PHP by simply using print statements intermingled with HTML
code. You can simply pass parameters into your script like you would a normal form, either on the querystring (for
GET requests) or in the form data (for POST requests).

However, we feel that AJAX is best utilized when performing shared tasks on the backend. This is done by setting
up a simple API that allows the frontend to pass data to backend functions (or class methods). Using this approach
not only lets you share functions across both the frontend and backend, but allows for easier management by having
multiple functions in a single file. (Of course, you can also use include files to break up functionality into multiple
files if you have a large number of them.) And there’s no rule that says that backend functions for the frontend have
to be different.
[edit: not clear what’s the message here]

9
The CPAINT Handbook

Backend Security
In fact, there are a few principles that you need to keep in mind when developing backend functions and an API to
access them:

1. Since a single file (or URL) could expose multiple functions, within your API, you need to include a
parameter to specify the backend function you want to execute.
2. You also need to provide some way in your API for passing multiple parameters to your backend functions,
like an array.
3. While your frontend JavaScript might validate the data, it’s very easy for an advanced user to completely
bypass any sanity checking on the frontend, so you need to perform another level of sanity checking on the
backend (in fact, it’s a good idea to follow this even when using standard HTML forms in a non-AJAX
application).
4. On that note, you need to make sure that your script will only access the functions that you want exposed
AND that any data passed in isn’t directly evaluated or executed.
5. Finally, you’ll want a way to pass errors up to the frontend, in the event the data was invalid or the
operation couldn’t be completed.

Getting Frontend Data

So, based on the principles mentioned earlier, we can start building our API. The first thing we need to do is put the
data we get from the frontend into some local variables (while optional, I’ve found it easier to work with in the long
run, should the API change, I don’t have to change the code in multiple places).

$functionToExecute = $_REQUEST[‘function’];
$parameters = $_REQUEST[‘color’];

I thought we agreed that we would pass in multiple parameters to the backend? Yes, the code above is correct,
provided it was passed in properly. In PHP, multiple parameters can be passed from an HTML form (or in the GET
querystring or POST formdata) by appending an opening and closing bracket to the form variable’s name. For
example:

<input name=”color[]” type=”checkbox” value=”green”>


<input name=”color[]” type=”checkbox” value=”red”>

If this was a normal HTML form, when it was submitted (and if both checkboxes were checked), PHP would create
$_REQUEST[‘color’] as an array containing two members, green and red.

10
The CPAINT Handbook

However, since you’re not using an HTML form, you have to set up the querystring/formdata string yourself. You
may have the desire to pass both values as a single parameter, separating them with commas, but you would end up
with a string reading ‘green,red’. Again, use brackets to specify repeating value names. For example:

color[]=green&color[]=red

Note: Other languages may not use brackets to build the array on the backend – you’ll have to adapt your script to
use whatever conventions it needs.

Function Execution

As mentioned above, you want to limit what can be executed on the backend. In PHP, this is relatively simple to do.
One way is to use simple if statements and check the function name that was passed in. You could also manually
write an array of functions that are allowed to execute and check against that list.

Once you’ve verified the function name, you can now execute the function and pass it the data received from the
frontend. In PHP this is actually very simple, as you’ll see below. However, for other languages, this may be much
more complex (as you need to make sure no arbitrary code was passed in that might get executed server-side).

if ($functionToExecute == ‘check_user’) {
$result = check_user($_REQUEST[‘name’],
$_REQUEST[‘password’]);
print($result);
}

Of course, depending on what the frontend is expecting, your function can return HTML, XML, plain-text, or some
other formatted text (even binary data for the brave). This is also not the only way to call your backend functions.
The CPAINT backend API actually sends all the parameters from the frontend in one string, parses it back out on the
backend, and passes it to user functions in an array using call_user_func_array.

Usability Considerations

Because AJAX changes the way that users interact with the web page, there are a few important usability
considerations to take into account.

1. Users typically expect the entire page to refresh when performing an action. Based on your target audience,
it may be beneficial to use some sort of effect to show that the content has been updated.
2. Users will also know that the browser is retrieving data from the server based on a progress bar or spinning
icon (depending on the browser). When using AJAX, the user won’t know what’s going on, so it might be a

11
The CPAINT Handbook

good idea to display a ‘loading’ message or progress bar while new data is being retrieved from the
backend. Alternatively, change the appearance of the mouse cursor while a request is underway.
3. Typically the user will expect that clicking the browser’s back button will return them to a previous state.
However, the browser button only works for different pages – not new or different parts of the same page.
For this reason, it’s not advisable to use AJAX to update the entire contents of the page unless you can build
your own ‘back’ functionality (you could use cookies to store previous states of the dynamic content).
4. In the event that the user is using an older browser or a non AJAX capable browser, it might be wise to
provide an alternate set of pages and forms for core functionality.

For additional considerations, see Michael Mahemoff’s AjaxPatterns website at http://www.ajaxpatterns.org/ or the
infamous “Ajax Mistakes” article by Alex Bosworth at
http://sourcelabs.com/ajb/archives/2005/05/ajax_mistakes.html

Further Reading

Because the previous section was only intended as an introduction to AJAX fundamentals, it may be beneficial to
refer to other books if you’re going to implement your own frontend and backend.

See http://www.ajaxpatterns.org/Books for some excellent books on AJAX (many of which list CPAINT in the
appendix).

12
The CPAINT Handbook

Introduction to CPAINT
If you just finished reading the first section or you already have some knowledge of or experience with AJAX, this
section will introduce you to CPAINT (the Cross-Platform Asynchronous Interface Toolkit), the open-source toolkit that
is the focus of this book.

What is CPAINT?

CPAINT (Cross-Platform Asynchronous Interface Toolkit) is an open-source project started by Paul Sullivan (the author
of this book) in May 2005 after his disappointment with early AJAX toolkits. His work originally started when he
ported another AJAX toolkit from PHP to ASP. He was disappointed with the inefficiencies and inflexibility of that
toolkit and wrote CPAINT from the ground up.

One month later, Dominique Stender joined the project, bringing time and ideas to the project, including the OOP
design and improved documentation layout. Currently, Paul and Dominique are the lead developers and co-leaders
of the project.

Most AJAX toolkits available on the market, both open-source and commercial, have a strong focus on sexy widgets.
This approach attracts many novice developers who want to build copy-cat web apps and don’t care about flexibility,
compatibility, and creativity.

CPAINT focuses primarily on communications and the ability to access remote data, which is what makes or breaks
AJAX applications. Thanks in part to our OOP design, it is extremely flexible and easy to implement in new and
existing web applications and can interface with any other frontend or backend toolkits or libraries.

CPAINT has separated frontend JavaScript code from server-side code (only PHP is actively supported on the
backend), which allows the CPAINT frontend to access any other AJAX toolkit or server (including SOAP and other
XML servers or those just serving HTML or plain text). In addition, via a server-side proxy script, data can be sent to
remote servers, including those in the backoffice which may not be available for public access.

Additionally, we have one or more independent security teams audit CPAINT during our exhaustive testing and
release process. Coupled with our unmatched flexibility, it has risen to become the toolkit of choice for enterprises
that need solid, secure code that runs efficiently both client- and server-side for high volume web applications.
[edit: sorry to say this but is this going to be a handbook or a marketing-speech? ;)]

13
The CPAINT Handbook

• The frontend and backend classes are licensed under the terms of the LGPL v2; the proxy script and
debugger are licensed under the terms of the GPL v2; and the documentation are licensed under the terms
of the Creative Commons Attribution 1.0 license.
• Project started in late May 2005 and still going
• First AJAX toolkit with 100% OOP approach
• First toolkit that doesn’t focus on GUI components but building a flexible, enterprise-strength AJAX toolkit
• Only toolkit that can communicate with other toolkits, web services, and backoffice/cross-domain servers
(via a server-side proxy)
• First toolkit to generate XML on the server side and interpret XML on the client side.
• First toolkit to support E4X
• Only toolkit to support multi-byte characters
• First toolkit to natively support JSON (JavaScript Object Notation)
• Only toolkit to with the ability to reuse the connection object, therefore keeping browser memory usage to a
minimum
• Only toolkit to support SJAX (Synchronous JavaScript and XML)
• Low churn with a common API across major releases
• Referenced in multiple books on AJAX
• Quick reference “cheat sheet” provided for convenience
[edit: you’re claiming many “firsts” and “onlys” here. I hope they’re verified. I wouldn’t like to unleash the
wrath of all other AJAX toolkit developers here… really baaaaad reputation ;) ]

CPAINT Classes and Utilities

Frontend Classes

The frontend classes are cross-browser compliant JavaScript classes that setup and manage the XMLHTTP (Request)
component for communications, provide translation functions for converting data to and from the backend,
debugging code execution and data responses, and accessing data returned from the backend.

Backend Classes

The backend classes complement the frontend classes and are responsible for code execution, data conversion, and
data return. Currently, CPAINT only supports PHP on the backend.
If you’re developing in a backend language other than PHP and would like to port the CPAINT backend to that
language, let us know!

14
The CPAINT Handbook

Proxy Utility

Since the XMLHTTP (Request) component can only access data on the same server for unsigned JavaScript code, this
script acts as a HTTP proxy to access data across multiple servers and domains. Currently, the proxy is only
supported in PHP.

Debugging Utility

This is an experimental script that can be dropped into any backend code that implements CPAINT. It facilitates the
debugging of backend code without the need for a complete frontend implementation.

Obtaining CPAINT and Other Information

All releases of CPAINT are available via SourceForge at http://sourceforge.net/projects/cpaint

Complete API documentation is included with the source archive and consistently updated at http://cpaint.net/doc
with each new release.

Examples and other information can be obtained at http://cpaint.net

See the latest CPAINT documentation at http://cpaint.net/doc for support options and submitting defect reports.

15
The CPAINT Handbook

Frontend Implementation
Import and Setup

The CPAINT frontend classes are available in two different files – a standard JavaScript file (complete with code
comments) – and a compressed version (which has comments and whitespace removed). Both versions are identical
in operation, as we provided the compressed version to save our users some bandwidth when serving their users.

If for any reason you modify the non-compressed code and want to recompress the code, we used an OSS utility
called jsmin by Douglas Crockford, available at http://crockford.com/javascript/jsmin.html

Importing the CPAINT frontend classes into your code is as simple as one line of code to every page you want to use
it on:

<script type=”text/javascript” src=”cpaint2.inc.js”>

(substitute cpaint2.inc.compressed.js for the compressed version)

Why ‘cpaint2’ and not just ‘cpaint’? We appended the ‘2’ to all the CPAINT filenames because there was such a
difference in the code base between CPAINT v1.x and v2.x. As new versions of CPAINT are developed, this postfix
may change if warranted.

Note: When importing the script, make sure to use type=”text/javascript” in the <script> tag and not
language=”javascript”. This will prevent older browsers (that don’t understand JavaScript classes) from
loading the files.
When using E4X as response type, you have to use type=”text/javascript; e4x=1”> for your javascript
libraries including CPAINT!

After importing the frontend classes, you’ll also want to add another <script> section where you’ll work with the
classes. Like above, make sure to use the type=”text/javascript” attribute to prevent older browsers from
loading the code.

In most cases, you’ll only need to create one instance of the cpaint object, even if you are updating multiple parts of
the page simultaneously. If you need make a request to the backend and the object properties need to change, you
can create multiple instances of cpaint and run them simultaneously (or you can destroy one instance and create a
new instance with the same name and change the object’s properties).

16
The CPAINT Handbook

Since the need for multiple instances of the cpaint object is rare, in this example, I’m going to show the creation of one
instance:

<script type=”text/javascript” src=”cpaint2.inc.js”>


<script type=”text/javascript”>
var objCpaint = new cpaint();
</script>

Object Properties

The frontend cpaint object exposes a number of properties that are used to control how the frontend and backend
operate.

[edit: that’s not true!]

Note: The CPAINT properties are accessible through setter methods.


Within the frontend code, we have implemented a stack handler which manages the creation and use of multiple
XMLHTTP (Request) objects, which give CPAINT the ability to handle multiple simultaneous requests. Because the
number of objects can vary at any given moment, using JavaScript properties in the traditional style will make this
next to impossible. So we use methods to set the properties of a primary cpaint object and pass those properties to
the newly created objects.

Since there are no real destructors in JavaScript, the cpaint object instance can be destroyed by setting it to null, for
example objCpaint = null;

set_debug

This sets the debugging level of the object. Debug messages are returned to the browser in the form of JavaScript
alert boxes. This is useful during the development process, however we don’t recommend setting any debug options
on production applications, as there is currently no way to capture and handle errors.

Possible values for set_debug include:


-1 : no debug or errors (this is the default)
0 or false : no debug messages returned, only errors
1 or true : debugging of commonly used information, such as object creation and connection status
2 : full debugging, adding information about the stack handler and server responses. Use with care.

Example:
objCpaint.set_debug(2);

17
The CPAINT Handbook

set_proxy_url

This sets the URL for the proxy utility in the event you are accessing from a different server or domain. Since the
proxy must be on the same server as what the frontend code was served from, there is no need to include the method
and server name in this property. A valid absolute or relative (to the page that is calling the proxy utility) must be
given in order for the call to succeed.

By default, this value is set to an empty string. If it is not set and you attempt a call to a remote server, an error will
occur.

Example:
objCpaint.set_proxy_url(‘/cpaint2.proxy.php’);

set_transfer_mode

This sets the transfer mode for the backend call. Currently, only GET (the default) and POST are supported.

If you are sending a large amount of data, it is recommended that you use POST, as there are limitations on the
amount of data that can be passed in a GET request. This limit ranges from 2000 to 8192 characters and varies from
browser to browser.

Example:
objCpaint.set_transfer_mode(‘POST’);

set_async

The ‘A’ in AJAX stands for ‘asynchronous’, meaning that the user can continue to work with the web page as
CPAINT interacts with the backend server. However, in some occasions, it may be necessary to receive the data from
the backend server before continuing. In this case, set this property to false which will make the page wait until
data is received from the server to continue. Obviously, the default is for this property is true.

Example:
objCpaint.set_async(false);

Note that with synchronous calls users will experience a temporary “hangup” of their browser!

set_use_cpaint_api

It is entirely possible to use the cpaint frontend object to call both local and remote scripts which don’t implement
CPAINT on the backend. When this applies, you need to set this property to false to let the cpaint object know that
it doesn’t need to worry about building the GET querystring or POST formdata string, as you will have to supply it.
The default for this property is true.

18
The CPAINT Handbook

Example:
objCpaint.set_use_cpaint_api(false);

[edit: reference to an example maybe]

set_persistent_connection

Normally, when the cpaint request object goes to retrieve data from the backend, it will use the stack handler to
control the creation of new and reuse of existing connection objects. This is what gives CPAINT the ability to handle
multiple simultaneous requests.

However, if requests are being made infrequently, it is possible to save memory on the frontend by reusing the same
connection object across multiple requests - a la connection persistence. However, this doesn’t mean the connection
to the server remains open or the backend URL needs to remain the same. Only the connection object is kept alive.

The default for this property is false.

Example:
objCpaint.set_persistent_connection(true);

set_response_type

If you don’t pay attention to any other property, you’ll need to pay attention to this one. This tells not only the cpaint
frontend, but the cpaint backend, in what format the data will be in and helps control how it is generated (in the case
of the backend) and how it is interpreted (on the frontend).

There are five possible values for this property:

• OBJECT (default)
The frontend will expect the results to be in XML (or any SGML-based markup language) and use its
internal methods to convert the data into a native JavaScript object structure.

• TEXT
The frontend will not perform any conversion on the data that is received for the backend. If you are
returning simple values from the backend that you will use in JavaScript, you are returning HTML to
replace part of a web page, or you want to parse the data yourself – use this value.

• JSON
The frontend will expect a properly formatted JSON string. JSON gives developers the ability to pass object
structures between the frontend and backend. The cpaint frontend object will automatically parse the JSON
string and return a JavaScript object structure to the frontend application.

19
The CPAINT Handbook

More information on JSON can be found at http://www.json.org/

• XML
The frontend will expect properly generated XML (or other SGML-based markup) and the connection object
converts the returned data into a DOMDocument object that can be traversed as a native JavaScript object.

• E4X (ECMAScript for XML)


This is almost identical to the ‘XML’ property value, as it returns an object that can be traversed as a native
JavaScript object. However, currently it is only supported by Mozilla Firefox 1.5 and above.
[we need a better explanation here, maybe with some small example – I’ll think of something]

More information on E4X can be found at http://www.ecma-international.org/publications/standards/Ecma-


357.htm

Example:
objCpaint.set_response_type(‘XML’);

set_auth_user

If the backend script (or the proxy utility) you are accessing is protected with HTTP Basic Authentication, use this
property to set the user name to use for authentication.

Note: This information is not passed to remote scripts via the proxy utility – see information about the proxy utility
to learn how to set the remote username.

Example:
objCpaint.set_auth_user(‘username’);

set_auth_pass

This is a companion function for set_auth_user to set the password for HTTP Basic Authentication.

20
The CPAINT Handbook

Creating a Callback Function

As with other AJAX implementations, you will need to write a JavaScript callback function which will receive the
data when it comes back from the backend script. This is true even when using synchronous requests.

Your JavaScript function needs to include at least one input parameter, which can named anything you would like.
Depending on what response type you previously selected, this parameter could contain textual data or an object of
some sort.

Note: The cpaint object will return two parameters to the callback function. The first parameter will be the
‘interpreted’ object (if the response type is anything other than ‘TEXT’) and the second (optional) parameter will
contain the same data, but in plain-text format.

At minimum, it is a good idea to prototype your callback function before making the actual call to the backend. You
may use the same callback function for multiple backend functions (although you may need to return some sort of
identifier if the data is to be handled differently).

Gathering Data

Of course, you’re going to need to gather data to be sent before you can make the backend call. The easiest way to do
this is to use id attributes in your HTML code for easily retrieving values from <input> elements. Here is a very
simple example:

<input type=”text” name=”username” id=”username” />

Retrieve in JavaScript with:


var uName = document.getElementById(‘username’).value;

However, if you need to pass multiple elements of the same name, for example, a group of checkboxes or a multiple
selection box, getting the data and preparing it for the backend requires a bit more code.

If you aren’t using CPAINT on the backend, it all depends on how that implementation is used to handling arrays.
Keep reading to learn how to handle this special situation.

However, if you are using CPAINT on the backend, you simply need to get all the values into a JavaScript array. The
cpaint frontend object class will handle converting this into something the backend can understand (JSON, to be
exact).

21
The CPAINT Handbook

For example, this code simply loops through a multiple select box and puts the selected values into an array:

var selectedArray = new Array();


var selObj = document.getElementById(‘multiSelect’);
var i, count;
for (i=0; i<selObj.options.length; i++) {
if (selObj.options[i].selected) {
selectedArray[count] = selObj.options[i].value;
count++;
}
}

While this example concentrates on rather simple data being sent to the backend, CPAINT allows you to create your
own anonymous objects and object structures in JavaScript and send them to the backend.
[edit: I’ll think of an example here]

Calling Backend Functionality

Once you have either prepared or found the appropriate data and at the very least written a stub for your JavaScript
callback function, it’s now time to send it to the backend using the call method of the cpaint frontend object.

The call method takes a variable length of arguments:

1. URL of backend script (string)


If the backend function is on the same server as the serving page, this can be an absolute or relative
reference to the script you want to access.

However, if the data or script is on a different server or domain (and you set a correct path to the local proxy
utility), supply the full URL path in this argument. We’ll talk about special considerations for remote data
in another section.

If the backend resides on the same server or domain, but uses an alternate port, you can provide a full URI
path – for example:

http://cpaint.net:8080/scripts/ajax.php

2. Backend method name (string)


If the backend method you’re going to call isn’t using CPAINT, you can simply set this to NULL or an
empty string. Otherwise, provide the name of the method (which is case-sensitive) here.

3. Callback function (object)

22
The CPAINT Handbook

This should be set to the JavaScript callback function that will be handling the data that is returned by the
backend.
Be careful not to pass the JavaScipt callback function as string. CPAINT expects the parameter value to be an
object!

4. Arguments (mixed)
The cpaint object does not have a hard limit on the amount of data (or number of parameters) you can send
to the backend. However, if you are using the HTTP GET method, there is a soft limit of around 1000 bytes
(it varies wildly between multiple browsers, but this seems to be the floor).

The backend method will receive arguments in the same order that you specify here and there is no need to
create name-value pairs if the backend script is using CPAINT. If the backend script doesn’t use CPAINT,
read the next section to setup the arguments.

This short example shows us calling a local script named ‘ajax-functions.php’, calling the remote function
‘check_user’, passing a user name from an HTML input tag with the id ‘username’, and using a callback function
named ‘check_user_result’:

cpaintObj.call(‘ajax-functions’, ‘check_user’, check_user_result,


document.getElementById(‘username’).value);

Accessing Non-CPAINT Data Sources

Accessing data from non-CPAINT data sources requires only a small amount of more work, depending exactly what
they expect.

If you are using a non-CPAINT data source, make sure you set the set_use_cpaint_api property to false.

If you’re not sure if the backend script was implemented with CPAINT, there’s one easy way to tell. Simply the call
the script in a web browser with ‘?api_query’ appended. Example:

http://cpaint.net/examples/ping/ping.php?api_query

If the backend uses CPAINT it will reply with a message, for example:

CPAINT v2.0.3/PHP v5.1.2

See the API reference in the appendix for the format of this string.

23
The CPAINT Handbook

CPAINT was built with an API that is compatible with the same major revision number. [edit: meaning?] In other
words, if the backend is v2.0.2 and the frontend is v2.0.1, or vice versa, you won’t have any problems. It is possible to
use a v2.x frontend with the v1.x backend, but not the other way around.

Traditional Web Scripts

This group of scripts encompasses all scripts that take input from some source, for example an HTML form. To
utilize these scripts, you simply need to create name-value pairs and pass each pair as a separate argument to the
cpaint call method. You do not need to worry about separating them with ampersands (‘&’) or encoding the data,
as the cpaint object will take care of that for you.

In addition, you do not need to specify the backend method name as it will be ignored. However, if the backend
script provides multiple methods, you may need to refer to its API definition.

Example:
objCpaint.call(“non-cpaint.php”, ‘’, callback_func,
‘user=’ + strUser, ‘pass=’ + strPass);

Note: If the backend script will be accessed via a GET request, do not put the name-value pairs in the script URL
argument. If you do so, the cpaint object will not be aware of that data, which means the data will not be encoded
nor will any additional parameters you pass to call be properly passed to the backend.
[edit: I had to read it twice to know what you mean. Maybe an example makes things clearer here.]

The frontend will not parse a JavaScript array for use with a non-CPAINT data source at this time. Instead, you will
need to parse the data and build independent name-value pairs on your own.

For PHP-based scripts, you will need to append each name with brackets. For example, if the array had three
members (“red”, “yellow”, & “green”) and you wanted to pass them in as the name “colors”, your parameters to
call would be:

“colors[]=red”, “colors[]=yellow”, “colors[]=green”

XML Based Scripts

This group includes any script which expects XML as its input, including SOAP-based Webservice scripts and
applications. While CPAINT can call the script, you will need to build the XML yourself on the frontend.
CPAINT improvements regarding the XML-creation problem are planned already bot no release date is set as of
now.

In the likely event that the script needs XML in the POST body of the request and additional parameters in the GET
querystring, you may add those parameters to the script URL when invoking the call method. However, the cpaint

24
The CPAINT Handbook

object will not be aware of those parameters, so you will need to ensure the strings are properly encoded (using the
JavaScript encodeURIComponent method).

Once you generate the XML, pass it as a single argument to the call method. You also want to make sure that your
transfer mode is set properly (usually the set_transfer_mode should be ‘POST’).

Example:
var XMLRequest = ‘<request><action>getUser</action>
<parameter>paul</parameter></request>’;

objCpaint.set_transfer_mode(‘POST’);
objCpaint.set_use_cpaint_api(false);

objCpaint.call(‘xmlserver.php’, ‘’, return_handler, XMLRequest);

Working With Data in the Callback

If the backend call completed successfully, the data will be available to your JavaScript callback function. As
previously stated, your callback function needs to take at least one parameter.

The contents of the first parameter will depend on what the response type was set to before you made the backend
call. Unless you set the response type to ‘TEXT’, this will be an object of some sort that you can traverse in a tree-like
manner to retrieve the data.

The second, optional parameter for your callback will always be plain-text, regardless of the response type. In the
case of ‘TEXT’, the contents will be identical. Otherwise, this will be the raw contents that were parsed to generate
the object you received via the first parameter. If the response data is ‘TEXT’, you can start working with the data
directly in your callback script, such as updating the webpage, form values, or use it in other parts of the script.

Keep in mind that the data received by the callback is not global or persistent. Once the function completes
execution, the local data will be lost if you don’t copy it to a global variable. Also keep in mind that if you make
multiple, simultaneous calls to the backend using the same callback function, that you may have multiple instances
of that function executing (“threading”), which (depending on what it does) could overwrite the result of another
instance of the callback.

While CPAINT handles the threading of multiple simultaneous calls to the backend, it is up to you to handle
threading in the frontend applications.
For all other response types other than ‘OBJECT’, you can find many books and references for accessing data in the
object.

25
The CPAINT Handbook

Here is a simple example:

function callback (resultData, resultText) {


alert(‘I received ‘ + resultText);
}

Working with CPAINT Result Objects

If you specified ‘OBJECT’ as the return type, the cpaint frontend will interpret the data and return a
cpaint_result_object object. While this is most commonly used with backend code that has been implemented
with CPAINT, it could be used for any data source that returns XML.

The cpaint_result_object is similar to the DOMDocument object class, as it contains both the data and a few
simple methods to access the data. However, each XML tag is a new named instance of the class, making it easier to
access. Because XML is in a tree-like hierarchy, you get to the data by accessing the data from working your way
down from the top.

Here is a sample response sent from the backend:

<encoding>
<charset id="alphanumeric">
This is a test
</charset>
</encoding>

Assuming our object is named ‘result’, you would access the first level of data (everything that encompasses the
<encoding> tag) simply by referencing it directly, by name:

result.encoding

If there were multiple <encoding> tags in the response, you can access them like you would an object, using a
counter. This example shows a loop where each tag can be accessed:

for (var i = 0; i< result.encoding.length; i++) {


// access the data with result.encoding[i]
}

You should not be using the syntax for (var i in result.encoding) when using CPAINT – the JSON
implementation it is shipped with tends to cause some problems if data is not properly checked via typeof
statements.

If there were multiple tags, each with a unique id attribute, the object provides a quick method for getting a
reference on the data that it contains without having to traverse the entire tree.

26
The CPAINT Handbook

Using the find_item_by_type method takes two parameters, the tag name (using the above example, it would be
‘charset’) and the value of the id attribute (in this example, ‘alphanumeric’). For example, this would get us closer to
the data:

result.find_item_by_type(‘charset’,’alphanumeric’)

In addition, if you are traversing the tree and want to get the value of an attribute, simply use the get_attribute
method:

result.encoding[0].get_attribute(‘id’)

If for any reason you want to dynamically change the value of an attribute (perhaps to ‘mark’ it as being read), you
can use set_attribute in the same manner:

result.encoding[0].set_attribute(‘id’,’1’)

Of course, you can also create and set a new attribute this way.

Finally, to get the actual data within tags, use the data property. For example, a reference to the data in the above
example would be:

result.encoding[0].charset[0].data

Here is a more complex result with references:

<encoding>
// result.encoding[0]
<charset id=”test”>
// result.encoding[0].charset[0]
this is the first test
// result.encoding[0].charset[0].data
</charset>
<charset id=”another_test”>
// result.encoding[0].charset[1]
this is the second test
// result.encoding[0].charset[1].data
</charset>
</encoding>
<encoding>
// result.encoding[1]
<charset id=”test3”>
// result.encoding[1].charset[0]
this is the final test
// result.encoding[1].charset[0].data
</charset>
</encoding>

27
The CPAINT Handbook

Using the Proxy Utility

The backend proxy is a separate entity from the frontend and can be utilized transparently by the frontend. If the
set_proxy_url is not empty, the frontend will attempt to send the backend request via this script that we have
provided for your use.

The proxy utility must have a proper URL in order for the request to work properly, including port number and user
authentication credentials, if necessary. The proper format for URLs is as follows:

http://[userid:password@]server.domain.tld[:port]
/path/filename.ext

You will specify this URL as the first parameter in calls to the cpaint frontend call method. Example:

objCpaint.call(‘http://paul:mypassword@w3.cpaint.net:8080/scripts/ajax.php’, ‘auth_user’,
authHandler, username, ‘password’);

[edit: its quite irritating not to have a CPAINT call here – took me a while to realize that]
Because the proxy utility should only be utilized by your users and not become a gateway for the entire world, we
have implemented a whitelist for the proxy. Simply edit the cpaint2.config.php file that is included with the
CPAINT distribution to set the servers, paths, or scripts that the proxy is allowed to access.

In addition, you can set a few other options (such as error reporting and timeouts) for the proxy utility in the
cpaint2.config.php file.
[edit: a small run-through on the config file itself is missing in the book]

28
The CPAINT Handbook

Backend Implementation
Including the Backend

Like the CPAINT frontend code, the backend implementation is self-contained in a single file. Only external helpers
like the PHP implementation of JSON and the proxy utility reside in their own files. Unlike other AJAX toolkits, we
implemented the backend with the philosophy of separating display from logic, meaning that while it is entirely
possible to include backend functionality within the same source file as the frontend, the CPAINT backend must be
included before any data is sent to the browser (including print statements or even blank lines, as they are sent to the
browser before any code executes).

The CPAINT backend can be included with one simple statement:

include_once(‘cpaint2.inc.php’);

Just as the frontend was implemented using an object-oriented approach, the CPAINT backend includes an object
called cpaint that controls the execution of the backend code. However, there is no reason to create multiple
instances of the cpaint object, otherwise your backend code will be executed twice every single time the script is
called.

Creation of the CPAINT backend object is simple:

$cp = new cpaint();

Stubbing the Backend Functions

If you haven’t already written your backend functions, now is a good time to at the very minimum write stubs for
them, as you will need to at least know what they are called. A little later, we’ll show you how to make your new (or
existing) function work with the CPAINT backend.

Your backend functions don’t need to be standalone. You can implement them as methods within a class. However
at this time, the CPAINT backend can only execute one method for every call to the backend, so the object that
contains the method must be created before it can be used by CPAINT. Class methods that are called statically by the
CPAINT backend do not have this dependency.

In addition, if your functions are implemented across multiple files, as long as they are included in your page where
the cpaint object was created, the backend object will be able to execute those functions.

29
The CPAINT Handbook

Registering Functions

Obviously, you don’t want to expose all of your backend functionality to the world for “free use”, either for security
purposes or the fact that not all of them have been adapted for use by CPAINT. For those reasons, we have
implemented function registration.

You can register a static function or a class method, but you cannot register a built-in function of the scripting
language (if you wanted to do so, you will need to build a wrapper). Because it is possible that functions can be
reused throughout your code, you can have the option of defining an alias name that is used for AJAX calls.

Use the register method of the cpaint backend object to specify which functions can be utilized by the frontend.
At this time, you must specify each function on a separate line.

$cp->register(‘authenticate_user’);

// same function, with an alias


$cp->register(‘authenticate_user’, ‘r2d2);

If you are registering a class method, you must use an array to pass the class name (or the instance name) and the
method name

// this assumes the class has already been instantiated


$cp->register(array(&$new_object, ‘object_method’));
// or for a static method with an alias
$cp->register(array(‘user_class’, ‘authenticate’),
‘authuser’)

Executing the Code

To tell the cpaint frontend object to parse the incoming data and hand it off to the appropriate function, simply call
the start method.

$cp->start();

[edit: notifications for users that need to use charsets other than UTF-8 should be here]
The cpaint backend object will execute the function and store its returned data in memory. At this point, no data has
been sent back to the frontend. To complete execution, simply call the return_data method.

$cp->return_data();

30
The CPAINT Handbook

The script does not stop executing at this point. This is to give you the ability to perform any cleanup, shutdown,
logging, or any other tasks your script may need to perform. You could send further data to the frontend at this
point using print statements (or anything outside the code block), but this really isn’t advised for a proper response.
Note: Custom HTTP headers must be sent before $cp->return_data() is called.

Accepting Data

In order for the cpaint backend object to properly pass the data back to the frontend, you will need to make simple
changes to your function.

For starters, the function will need to have access to the cpaint object. This is achieved by adding the global keyword
and the object’s name to the first line of your function.

function validate_user($username, $password) {


// import the cpaint object
global $cp;
}

At this point, you can write your function like you normally would. The data from the frontend is passed is available
to your function as local variables (based on this example). You can also use your function to accept variable length
arguments, either using defaults or argc/argv[] calls.

Note: If you are using the CPAINT frontend and have passed an array or multibyte character data, the CPAINT
backend will automatically convert the data into the proper format for your function. There is nothing else you need
to do.

Note: It is extremely wise to sanitize your data when you receive it, especially if you’re inserting data into a
database. Since every application is different, CPAINT does not manipulate the data beyond converting it into the
proper format for your function.

Building Simple Responses

Normally, you would be able to return data from a function with a simple return call. However, since your
function could be used outside of the scope of CPAINT, we have implemented methods that can be used to return
both simple and complex (such as XML or JSON) data to the frontend with ease.

To return a simple response, such as plain-text, pre-formatted HTML, or even binary data to the frontend, you simply
need to replace your return call with a call to the set_data method of the cpaint object.

31
The CPAINT Handbook

function validate_user($username, $password) {


// import the cpaint object
global $cp;
// validation code here
$validated = ‘good’;
$cp->set_data($validated);
// optional, if returning to another function
return($validated);
}

We meant it when we said simple! Once this function sets the data and completes, the data (in this case, the string
‘good’) is returned to the frontend and execution stops.

In the majority of cases, this is all you really need to do. But, if you’re going to be returning multiple pieces of data,
rather than coming up with your own scheme and separating the data back out on the frontend, you can use a more
complex method that will adapt to what the frontend has requested.

Building Complex Responses

Simple is good in most cases. But when it comes to returning multiple values to the frontend, it could be difficult.
The cpaint backend object implements another object on the backend called cpaint_node. Instances of this object
can be used to build more complex results.

The major advantage to using the cpaint_node object over building your own string, whether it is a simple string,
XML, or JSON, is the fact that when the cpaint return_data method is called, this object is automatically converted
into the format the frontend has requested (either plain-text, XML, or JSON). By default, the cpaint backend object
creates a single instance of the cpaint_node object, called the basenode. Essentially, the basenode is a top-level tag
(in the case of XML responses) or the object name (in the case of JSON responses). The basenode can be accessed
directly through the object instance.
[edit: the paragraph above is not very clear in some way, I can’t exactly name it]

The basenode is also used when the frontend requests plain-text, however no node names or attributes are sent to the
frontend.

Note: If you don’t change the name of the basenode, it will be called ‘ajaxResponse’.

cpaint_node Methods

The cpaint_node object method implements a number of methods for easily building complex results.

32
The CPAINT Handbook

add_node

This method is used to add a subnode to an existing node, including the basenode. The name of the basenode is
required as the first parameter and an optional parameter for setting an id attribute. Nodenames can repeat, with or
without specifying the id attribute.

Note: If using PHP4, make sure when you perform the assignment to the existing node that you do so by reference,
otherwise the new node instance will be ‘disconnected’ from it’s parent node.

Example:

$new_node = &$cp->add_node(‘new’);

/* the XML now looks like:


<ajaxResponse>
<new>
</new>
</ajaxResponse>
*/

$new_node2 = &$cp->add_node(‘new’);

/* the XML now looks like:


<ajaxResponse>
<new>
</new>
<new>
</new>
</ajaxResponse>
*/

$new_child = &$new_node->add_node(‘child’, 1);

/*
<ajaxResponse>
<new>
<child id=”1”>
</child>
</new>
<new>
</new>
</ajaxResponse>
*/

set_data

This method sets the character data contained within the node.

Example:

$cp->set_data(“hello”);

/* XML:
<ajaxResponse>
hello
</ajaxResponse>
*/

33
The CPAINT Handbook

get_data

Returns the character data contained within a node.

Example:

$cp->set_data(“hello”);
// prints “hello”
print($cp->get_data());

set_attribute

This sets an attribute of a node. The first parameter specifies the attribute’s name and the second parameter specifies
the attribute’s value.
When using JSON as response type, you’ll be creating an object property.

Example:

$cp->set_attribute(“language”, “en-US”);

/* XML:
<ajaxResponse language=”en-US”>
</ajaxResponse>
*/

get_attribute

This will return the value of the specified attribute.

Example:

$cp->set_attribute(“language”, “en-US”);

// prints “en-US”
print($cp->get_attribute(“language”));

set_name

This will set the name of the node. (Not utilized in return data when the response type is JSON.)

Example:

$cp->set_name(“response-data”);

/* XML:
<response-data>
</response-data>
*/

34
The CPAINT Handbook

get_name

This will return the name of the node.

Example:

$cp->set_name(“response-data”);

// prints “response-data”
print($cp->get_name());

Complex Response Example

This example shows how to build a complex result, using multiple nodes.

function search_users($searchCriteria) {
// import the cpaint object
global $cp;

// change the basenode name


$cp->set_name(“users”);

// sanitize the data

// perform a database query

// loop through the results


for ($i = 0; $i < $resultCount; $i++) {
$newUserResult[$i] =
&$cp->add_node(“user”, $i+1);
$newUserResult[$i]->set_data($username);
}

return;
}

/* Sample XML data for the above code:

<users>
<user id=”1”>
Paul
</user>
<user id=”2”>
Dominique
</user>
<user id=”3”>
Michelle
</user>
<user id=”4”>
Britta
</user>
</users>
*/

35
The CPAINT Handbook

36
The CPAINT Handbook

Appendix
Arbitrary Character Sets

CPAINT is fully UTF-8 compliant. Whether you use ISO-8859-1 or more complex character sets like hebrew, arabic,
russian or japanese, CPAINT will support them. This means you don't have to worry about character conversion.
However, you should make sure that the page uses the correct Content-type meta tag in order for characters to
appear properly.

Frontend

The frontend works in UTF-8 data wherever possible and will obey the Content-type everywhere else. This means
that:

• data sent to the CPAINT backend will be submitted as UTF-8.


• data from the CPAINT backend will be converted into UTF-8.

Backend

The CPAINT backend works slightly different in every implementation due to language specifics.

For PHP this means that:

• By default it assumes the character set to be UTF-8.


• If another character set is used CPAINT must be told so in the start method.
• CPAINT will make use of the iconv library to convert backend data to UTF-8 before sending it to the
frontend wherever possible.

If iconv is not installed:


• If the character set is ISO-8859-1, utf8_encode() will be utilized.
• If neither is the case, data will be sent as-is.
• The same logic is applied to incoming frontend data (iconv, utf8_decode(), as-is).
• In any case the correct Content-type will be sent.

37
The CPAINT Handbook

All backend implementations convert non-printable characters 0x00 - 0x20 as well as XML-sensitive characters & < >
to representations safe for transmission as XML or plaintext and processing by the XMLHTTP (Request) connection
object.

In the CPAINT frontend these representations are converted back to their original characters before the data is
handed to the frontend application.

Backend Framework Encodings

It is your responsibility as developer to determine the correct character encoding used by your backend applications
and databases and feed that information to the CPAINT backend. Faulty encodings will in most cases lead to
incorrect incoming / outgoing data, even to crashes of the XMLHTTP object in MSIE sometimes the reasons to which
are both quite hard to debug and eliminate.

CPAINT Backend Protocol

All v2.x releases of CPAINT implement a simple, common backend protocol. We are documenting it here if you
want to access backend scripts that utilize CPAINT with a non-CPAINT frontend. All API parameters can be passed
in via HTTP GET or POST.

api_query

This is a special parameter that takes no additional data and must be called independently of all other API
parameters. It simply returns a formatted string that specifies the version of CPAINT being utilized on the backend,
which backend scripting language is being utilized and its version number.

Example:

http://cpaint.net/examples/ping/ping.php?api_query

Returns: CPAINT v2.0.3/PHP v5.1.2

Format of the string and meanings:

CPAINT v[major].[minor].[revision]/[language] v[version]

• major = the major version number (ie: 2)


• minor = the minor version number (ie: 0)
• revision = the revision or release number (ie: 0)
• language = the scripting language used (ie: ASP-VBscript)

38
The CPAINT Handbook

• version = the version information of the language in use

cpaint_function

This parameter specifies which function or method to execute on the backend. There can only be one function
specified per request at this time. The function must be ‘registered’ with the backend otherwise the request will be
ignored (see the section on backend implementation for details). The function name is case-sensitive.

Example:

/ping/ping.php?cpaint_function=ping

cpaint_response_type

This parameter tells the backend the format of the response. Only one response type can be sent per request.
Possible values are:

• TEXT
The backend will send a plain-text response. Used best for returning HTML, non-complex values, or other
data formats not natively supported by CPAINT.

• JSON
The backend will return a JSON formatted string that will be evaluated to create a native JavaScript object
within the CPAINT frontend.

• OBJECT, E4X, XML


All of these values will return identical XML from the backend. If you aren’t using the CPAINT frontend, it
will not matter which one of these you use at this time – the data and format is identical.

Example:

/ping/ping.php?cpaint_response_type=XML

cpaint_argument[]

This parameter can be used multiple times to pass data to the backend function. Although brackets appended to a
variable name are typically only used by PHP scripts, all scripts implemented with the CPAINT backend expect them
(and the brackets will be handled appropriately). The values passed in must be in the same order that the backend
function expects.

Example:

39
The CPAINT Handbook

/ping/ping.php?cpaint_argument[]=param1
&cpaint_argument[]=param2

In the above example the backend function will receive the data ‘param1’ in the first parameter and ‘param2’ in the
second parameter.

There is no hard limit on the number of arguments that can be passed in at one time, however there are theoretical
limits that vary depending on the backend scripting language and what method is used to call the backend script
(GET vs. POST).

API Reference

The latest copy of the CPAINT API reference for both frontend and backend objects can be found at
http://cpaint.net/doc/.

40