A Mountain Top
  • Home
  • |
  • Archive
  • |
  • Friends
  • |
  • Portfolio
  • |
  • Resume
  • |
  • Why I Blog
Get an Estimate
Home » Portfolio

Connecting XUL Applications with PHP

Note:This is an article I wrote on 11/18/2003. It was originally published at PHPPatterns. I thank Harry for letting me use his site as a platform. I plan to update this article in the near future with new developments in the world of Ajax and PHP/XUL.

This article is introduces some of the technical aspects of getting XUL
clients hooked up with PHP, based on the authors practical experience
of building XUL user interfaces.

If you don't know what XUL is and need an introduction, the article XUL: Rendering GUI's with PHP may be a good place to start. It gives a good introduction to XUL, its background and its uses.

So, you have looked at XUL and think it's pretty cool stuff. But, you
hate programming with javascript and are stuggling to leverage the
power of your favorite scripting language, PHP. There are ways around
this, but the minefield of the Gecko security model is a little to much
work to figure out. Well, hopefully after reading this, you will be
able to create PHP applictions that can be supplemented by the use of a
XUL interface, or even a standalone XUL application that uses PHP as a
server backend.

To start off with, we need a simple XUL file that contains a form.
This form could consist of anything, but for this example, I will be
using a simple Login form that is familiar in many web applications.
Some of the XUL has been left out to save space. The entire file is
included in the attachment.

The XUL file

The form really doesn't have much to offer in the way of beauty, but it
gets the job done. Notice that the Sign in button references the
loginCmd listed in the <commandset></commandset> section
above. Keeping your javascript commands out of the main XUL body helps
promote readabilty and reuseability.

<!-- Client.xul -->

<window
id="phpServer-Communication-test"
title="PHP Server Communication Test"
orient="horizontal"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">

<script src="js/main.js" type="application/x-javascript"></script>

<script src="js/server.js" type="application/x-javascript"></script>

<commandset>
<command id="loginCmd" oncommand="doLogin()"/>

</commandset>

<vbox flex="1" align="center" pack="center"
style="background-color:#444">

<grid style="background-color:#999; padding:40px;
border-top: 2px solid #bbb;
border-left: 2px solid #bbb; border-bottom: 2px solid #555;
border-right: 2px solid #555">
<columns>
<column/>
<column/>
</columns>

<rows>

<row>
<label value="Username"/>
<textbox id="loginUser" style="width:10em"/>
</row>

<row>
<label value="Password"/>
<textbox id="loginPass" style="width:10em" type="password"/>

</row>
<row>
<spacer/>
<button label="Sign in" command="loginCmd"/>

</row>
</rows>
</grid>
</vbox>
</window>

Not too hard to read - we've all seen HTML that makes less sense.

The PHP Server

Rather than being extraordinarily complicated, our PHP server simply
echos the value's passed to it to the screen as well as some text to
prove it's the real thing (a call to the date function).

<?php
session_name('XULSession'); // Set session name
session_start();

echo "Server Time is: ".date("m/d/Y H:i:s")."\n";
echo "\$_POST = \n";
print_r($_POST);
echo "\$_GET = \n";
print_r($_GET);

// Watch these...
echo "\$_COOKIE = \n";
print_r($_COOKIE);

echo "\$_SESSION = \n";
print_r($_SESSION);

if ( $_GET['username'] == 'root' && $_GET['password'] == 'topsecret' ) {
$_SESSION['username'] = $_GET['username'];
$_SESSION['password'] = $_GET['password'];
}
?>

Note the <pre> tags aren't needed around the print_r's because javasript does not squish whitespace like browsers do.

Pay attention (when running this example yourself) to what's happens to the $_COOKIE and $_SESSION variables above.

The session name (XULSession) turns up in the $_COOKIE array. In other
words the XUL client is doing the same as a browser does between
requests (via the XMLHttpRequest object - see below).

Also if you enter the username as "root" password as "topsecret"
these will show up in the $_SESSION array on the next request (you need
to "login" a two times to see this).

In other words you can use PHP's sessions to lock the remote XUL
client out of your PHP application until a valid username and password
is provided. Users will still have the remote client running (unlike
normal browser clients where's you'd probably send an HTTP redirect to
an HTML login form) but as long as you keep the real Business Logic in
PHP, requiring a valid session to execute it, there should be no real
issues here. The XUL client will simply be "dumb and pretty" unable to
do any harm.

The Javascript File

The real action takes place in the main.js file. Here's an excerpt containing the doLogin function. 

/* main.js */
function doLogin() {
var username = document.getElementById('loginUser').value;
var password = document.getElementById('loginPass').value;

req = new phpRequest();
req.add('action','doLogin');
req.add('username',username);
req.add('password',password);

var response = req.execute();
alert(response);
}

Running the script

Ok, so now that all the files are in place, we are going to run the
script. Starting with the blank form, simply enter in a sample username
and password. 

 

Login to XUL

 

Next, his the 'Sign in' button and witness the response from the server.


Connection Established
 How it works

After the "Sign in" button is clicked, the doLogin method in main.js is
called. In it, the username and password have been pulled from the XUL
form via the Javascript DOM. For more information on the methods
available via DOM, take a look at some of the links in the references
at the end of this article.

After we have pulled in the username and password into scope, a new
'phpRequest' object is instantiated. The phpRequest is a javascript
object that takes care of the nasty details of connecting and talking
to a PHP server. More on that later in the article. The add() function
simply takes a key/value pair that contains data that will be sent to
the php script.

After all key/value pairs have been added to the request, the
execute method is called and the request is actually made to the the
server. The entire HTTP response body is returned by the execute
method. The response is then echoed to the screen to provide feedback
that our method actually worked.

A word about security
Now, before you get to excited about how easy that is, I need to
explain about some of the limitations this has. The javascript security
model limits what can be connected to. That means that if you upload
this XUL file and javascript file to a php server, your server MUST
also be on the same server and the path to the server must be relative.

In other words:

XUL URL: http://some.server/xul/xulform.xul

Server URL: /xul/server/server.php (must be relative)

The second way to connect to a remote server would be to install
your XUL package into your local chrome directory. When you install the
package locally, you can connect to any server via an absolute URL.

More information about the javascript security model can be found on the web.

The phpRequest object
The phpRequest object is where all the magic happens. It provides a
programmer friendly interface to the implementation details of the
XMLHttpRequest object that actually makes the call to the php page.

The Javascript:

const SERVER_URL = "/xul/server.php";

//Start phpRequest Object
function phpRequest() {
//Set some default variables
this.parms = new Array();
this.parmsIndex = 0;

//Set the server url
this.server = SERVER_URL;

//Add two methods
this.execute = phpRequestExecute;
this.add = phpRequestAdd;
}

function phpRequestAdd(name,value) {
//Add a new pair object to the params
this.parms[this.parmsIndex] = new Pair(name,value);
this.parmsIndex++;
}

function phpRequestExecute() {
//Set the server to a local variable
var targetURL = this.server;

//Try to create our XMLHttpRequest Object
try {
var httpRequest = new XMLHttpRequest();
}catch (e){
alert('Error creating the connection!');
return;
}

//Make the connection and send our data
try {
var txt = "?1";
for(var i in this.parms) {
txt = txt+'&'+this.parms[i].name+'='+this.parms[i].value;
}
//Two options here, only uncomment one of these
//GET REQUEST
httpRequest.open("GET", targetURL+txt, false, null, null);

//POST REQUEST EXAMPLE
/*
httpRequest.open("POST", targetURL+txt, false, null, null);
httpRequest.setRequestHeader("Content-Type",
"application/x-www-form-urlencoded");
*/
httpRequest.send('');
}catch (e){
alert('An error has occured calling the external site: '+e);
return false;
}

//Make sure we received a valid response
switch(httpRequest.readyState) {
case 1,2,3:
alert('Bad Ready State: '+httpRequest.status);
return false;
break;
case 4:
if(httpRequest.status !=200) {
alert('The server respond with a bad status code:'
+httpRequest.status);
return false;
} else {
var response = httpRequest.responseText;
}
break;
}

return response;
}

//Utility Pair class
function Pair(name,value) {
this.name = name;
this.value = value;
}

Javascript's object model is a little screwy. Instead of defining a
'class' in php, you create functions and then link them together. That
is what is happening in the phpRequest function. Several variables are
set including the server URL that is defined by a constant variable on
the first line of the program. After the variables are defined, the
literal function names are assigned to local variables. When that is
done, they become callable methods inside the object. There are several
other ways to do this within javascript, please refer to the javascript
core specifiacation for details.

The phpRequest maintains an internal array of Pair objects. Because
javascript does not have the same array support that php does, a
workaround is needed to create a key/value array. The Pair object
performs this task very well.

The method where the action really happens in the phpRequestExecute
method. It contains the code that helps us to connect to a php server
from our javascript. The javascript object that allows us to connect to
another script via HTTP is the XMLHttpRequest object. It is an internal
javascript object that can be used to return XML (or HTML) documents
from an external source. More information about the XMLHttpRequest
object can be found on the XULPlanet website.

After the XMLHttpRequest object has successfully been instantiated, the
url is simply created by looping over the internal array of key/value
pairs. Now, you can use either GET or POST to send data to the server.
I have included code for both methods. The same URL is passed, but
there is one difference. When you send a POST request, you have to set
the content type to be 'application/x-www-form-urlencoded' so the web
server you are sending it to will know that you are sending a POST
request. There are more tricks if you need to send larger amounts of
data, but they are beyond the scope of this article.

After you set the url, you must call the XMLHttpRequests send
method. This is what actually sends the request to the server.
Following the code, after a response from the server is received, it is
stored in the XMLHttpRequest's responseText variable and available for
use. 
Conclusion

This is a good start. We've got the building blocks in place. If there
is enough interest, I can explain in my next article about how to wrap
up data from PHP (such as the results of a database query) in our own
XML dialect and access it from XUL.

Code for this article

More Info

Create Web applets with Mozilla and XML - has some tips on "inlining" XUL in XHTML.
The Mozilla Amazon Browser - if you haven't seen it already, be amazed...
XUL Planet

‹ Portfolio up QDrupal - Drupal module with the Qcodo Framework ›

WHAT WE DO

  • Programming


Navigation

  • blogs
  • books
  • compose tips
  • content
  • Recent posts

‹ Login / Register ›

NEW FROM THE BLOG

Date of Entry
Blog Entry 1

Date of Entry
Blog Entry 2

Date of Entry
Blog Entry 3

Date of Entry
Blog Entry 4

Advertisments

ReputationDefender
Moeller Electric
toner
Cheap Web Hosting

GET AN ESTIMATE

Complete the form below.



© 2006 - 2010 A Mountain Top, LLC, All rights reserved.