Contents


Create an adaptable phone book and contact list for your phones with XML and PHP

Use XML to feed a consistent contact list to your phones

Comments

You need to keep in touch with contacts, even when you're on the road. When desk-bound, you call with your desktop VoIP phone; when travelling, you use your smart phone. But each device requires that its phone list be in a particular format, each with its own distinctly formatted contact list or phone book. You could, if required, enter all your contacts twice—once for each contact list—and then, each time you have a change, make the change in both lists. Of course, you might prefer to have both phones get their data from the same back-end source, where you can edit names and numbers in only one place. This is not a problem: You are Internet or intranet connected with access to technology. In this article, learn how data from a single MySQL database can provide contact information to two quite different devices: a VoIP phone represented by the snom 300 family of devices and a smart phone in the shape of the Nokia E71 device (see Related topics for links).

Desktop device: the snom 300 family

The snom 300 family offers good, solid VoIP phones with a wide range of functions relevant in an office context, such as hold, transfer, and conference. Although the phone does have native support for data fed from an LDAP server, it also has a minibrowser (see Related topics) that can read HTML. It can even display text on the phone's screen in a format that can trigger a phone call.

Listing 1 provides an example of the XML format that the snom minibrowser requires, specifically in a phone book context.

Listing 1. Example of the snom XML minibrowser
<?xml version="1.0" encoding="UTF-8"?>
<SnomIPPhoneDirectory>
  <Title>PhoneList - Snom</Title>
  <DirectoryEntry>
    <Name>Friend, First</Name>
    <Telephone>555-456-7890</Telephone>
  </DirectoryEntry>
  <DirectoryEntry>
    <Name>Person, Second</Name>
    <Telephone>555-654-0987</Telephone>
  </DirectoryEntry>
  <SoftKeyItem>
    <Name>F1</Name>
    <Label>Dial</Label>
    <SoftKey>F_ENTER</SoftKey>
  </SoftKeyItem>
</SnomIPPhoneDirectory>

In this code, the root element SnomIPPhoneDirectory has three different children: Title, DirectoryEntry, and SoftKeyItem. The title appears at the top of the phone display and remains in place during scrolling. The directory entries follow—one per line—and can scroll. The soft key items relate to four buttons just below the display. These buttons can perform such functions as initiating a call to the currently highlighted directory entry. The data in this example consist of two phone number entries: a display name and the number used for dialing. It activates only one button: Press the F1 button and the phone begins to dial.

Traveling device: The Nokia E71 smart phone

The Nokia E71 device is a good example of a modern smart phone. It can connect with wireless LAN or cell service, has a Session Initiation Protocol (SIP) client, can browse the Internet with its own native browser, and manages voice communications on the go.

The E71 device is capable of Wireless Application Protocol (WAP) version 2.0 (WAP2—see Related topics)—not to be confused with the Wi-Fi Protected Access II (WPA2) functions. This means that it can read XML-formatted files that communicate internally in the phone with its various specialist abilities, such as opening a window to initiate a call.

Listing 2 provides an example of what the smart phone requires in WAP2/XML format. This example uses the same two fictional entries as in Listing 1.

Listing 2. Example of WAP2 XML
<?xml version="1.0"?>
<!DOCTYPE wml PUBLIC "-//WAPFORUM//DTD WML 1.1//EN"
   "http://www.wapforum.org/DTD/wml_1.1.xml" >
<wml>
  <card id="main" title="PhoneList - Nokia">
    Tel (WTAI): <a href="wtai://wp/mc;%2B555-456-7890">Friend, First</a><br />
    Tel (WTAI): <a href="wtai://wp/mc;%2B555-654-0987">Person, Second</a>
  </card>
</wml>

WAP2 requires that you present the data in the form of decks of cards. The root element <wml> has one child <card> (or page), with two lines separated by a break. The title of the page is listed in an attribute of the root element. The telephone numbers are indicated in anchor, or <a>, elements, with an <href> attribute that uses Wireless Telephony Applications Interface (WTAI—see Related topics). When you open the page in the phone's browser and click a phone link, a window pops up and asks if you want to call the number, at which point the phone finds a route to place the call—whether over a wireless LAN or using another phone subscription.

Because the smart phone has no native ability to deal with LDAP and the desktop phone does not handle WAP2, there seems to be little common ground. Scripting, however, provides a solution using the adaptability of XML. You might find a way to synchronize your contacts with the LDAP server through the smart phone, but it might not be as clean as direct dynamic access to information. Fortunately, although the format of the XML might change in the two schemas, the data remains fundamentally the same.

The approach

With ubiquitous access to the Internet from both devices, one solution to a common phone book is to keep all the data in a database, then use a scripting engine to generate an XML file for delivery to a browser on whichever device you find most convenient. As long as you know which device is using the script, the correct output can be delivered. In addition, the script can control access and filter information for delivery, as required.

The database

The data can be stored in a wide variety of formats and extracted as required. Alternatives include PostgreSQL, XML, plain text, IBM® DB2®, and many others. Listing 3 shows a sample schema for MySQL.

Listing 3. Example database schema
CREATE TABLE IF NOT EXISTS 'mycontacts' (
  'id' int(11) NOT NULL auto_increment,
  'firstName' varchar(30) default NULL,
  'lastName' varchar(30) default NULL,
  'number' varchar(20) default NULL,
  PRIMARY KEY  ('id')
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

The table contains just four fields—an ID for convenience, the first name and last name, and the phone number—and one index. This schema presents the bare essentials of information required. Further fields and indices can be added, as required. You can edit the data content with LibreOffice Base or phpMyEdit (see Related topics) the editor of your choice.

The PHP generator

Listing 4 shows a bare-bones script that gets the data from the back end and presents the output in plain-text format. At this point, you are just testing the script to make sure that it returns sensible data.

Listing 4. Basic database generator
<?php
    $dev = "";
    $db_host = "your.database.server";
    $db_user = "your_user";
    $db_pass = "your_password";
    $db_name = "your_database";
    $mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);
    if (mysqli_connect_errno()) show_err($dev,"Could not connect to database");
    $query = "SELECT * FROM mycontacts order by lastName asc";
    $result = $mysqli->query($query);
    $num = $result->num_rows;
    $i = 0;
    while ($row = $result->fetch_array()) {   
        $myarr[$i]['first']=$row["firstName"];
        $myarr[$i]['last']=$row["lastName"];
        $myarr[$i]['phone']=$row["number"];
        $i++;
    }
    $mysqli->close();
    switch ($dev) {
      case 'snom':
        echo mysnom($myarr);
      break;
      case 'noki':
        echo mynoki($myarr);
      break;
      default:
        echo mytest($myarr);
      break;
    }
function mytest($myarr) {
  $cont = "Header\n";
  foreach ($myarr as $a) {
    $cont .= " ".$a['first']." ".$a['last']." ".$a['phone']."\n";
  }
  $cont .= "Footer\n";
  return $cont;
}
function show_err($dev,$msg) {
  die($msg);
}
?>

This code begins by defining the variables used to access the database, opens a connection, and returns a result set or a message if it cannot connect to the database. A while loop then iterates through the dataset, storing the information in a convenient array for later display. Because the device variable $dev is initialized to a zero-length string, when the switch executes, it goes to the default and calls the mytest() function. This function displays a simple header, writes out the content of the array, and then prints a footer—all in plain text.

This script deals with only one possible error: a failure to connect to the database. Plan to deal other conditions, such as successfully connecting to the database but finding an empty table. You can trap and deal with these conditions using similar calls to the show_err() function.

Most of the pieces are in place to generalize this script to deal with other types of devices. The switch has cases for the two phones, but their functions do not yet exist. The challenge now is to make the output relevant for the other destination devices, adding detail as required in XML format.

Desktop minibrowser

Referring to the example in Listing 1, you can see that the functions in Listing 5 add necessary pieces to deal with the desktop VoIP phone.

Listing 5. Function to handle desktop minibrowser
function mysnom($myarr) {
    $cont = "<?xml version=\"1.0\"?>
<SnomIPPhoneDirectory>
  <Title>MySQL Directory</Title>";
  foreach ($myarr as $a) {
    $cont .= "
  <DirectoryEntry>
    <Name>".$a['first']." ".$a['last']."</Name>
    <Telephone>".$a['phone']."</Telephone>
  </DirectoryEntry>\n";
  }
  $cont .= "</SnomIPPhoneDirectory>\n";
  return $cont;
}
function show_err($dev,$msg) {
  switch ($dev) {
    case 'snom':
      echo "<?xml version=\"1.0\"?>
<SnomIPPhoneText>
  <Text>
$msg
  </Text>
</SnomIPPhoneText>
";
    break;
    default:
      echo $msg;
    break;
  }
  die();
}

Comparing Listing 5 with Listing 4, instead of echoing the plain text, these new functions echo data wrapped in the elements that the minibrowser is expecting. The mysnom() function is an addition to the script, and the show_err() function is a replacement. The minibrowser is not capable of presenting plain text: It just does nothing. So XML output is required for both normal and exceptional output. Because you are using the phone, that is where the error messages must appear. In the case of failure to connect to the database, the script reports the error to the phone. In the case of success, before the while loop begins, the script announces the root element. As the loop progresses, each record is wrapped in its own directory entry tags; after the loop is complete, the setup for the buttons begins. With only four buttons, it is questionable whether this needs to be encoded in the database, as well. Finally, the code closes the root element.

The above functions behave correctly if the variable $dev is set correctly at the beginning of the code, as follows:

$dev = "snom";

Smart phone WAP2

In the case of the Nokia phone, you add the output details that provide the XML for the smart phone in WAP2 format with WTAI references. Listing 6 shows the code.

Listing 6. Function to handle smart phone WAP2
function mynoki($myarr) {
  $cont = "<?xml version=\"1.0\"?>
<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"
   \"http://www.wapforum.org/DTD/wml_1.1.xml\" >
<wml>\n
  <card id=\"main\" title=\"PhoneList - Nokia\">\n";
  foreach ($myarr as $a) {
    $cont .= "\nTel (WTAI): <a href=\"wtai://wp/mc;%2B".$a['phone']."\">
      ".$a['last']." ".$a['first']."</a><br />";
  }
  $cont .= "</card></wml>\n";
  return $cont;
}

Again, this code provides the required XML for the Nokia phone. The text output in the case of an error making the connection to the database is not wrapped in any kind of markup because simple output displays correctly on the phone without the markup. When phone book entries are displayed, before the loop begins, the script sends the XML and DOCTYPE information, followed by the opening of the root <wml> element and <card> element. Then, the loop begins, presenting each row enclosed in WTAI information. Finally, the code closes the card and the root <wml> elements.

The above functions behave correctly if the variable $dev is set correctly at the beginning of the code, as follows:

$dev = "noki";

Note that this suggestion for an approach to contacts on the Nokia E71 phone is not intended as a complete replacement for the native contacts application, which clearly has some advantages as part of the phone system and therefore enjoys close internal hooks with other applications. The native contacts list, however, can be generated from the same MySQL database using the same process but generating intermediate output in vCard (VCF) file format (see Related topics) for import into the phone.

Detecting the device

The final piece in the puzzle is to let the script know at run time which device output is required. You can do this in a number of ways, one of which is to send GET information in the HTTP request query string. Imagine that you send the following request, which explicitly states a device and a user:

http://www.myserver.tld/phonebook/myscript.php?device=snom&user=jim

Then, the complete script in Listing 7 parses the query string and inserts the information into the script at run time.

Listing 7. Detecting the device
<?php
    if ($_GET['user'] != 'jim') show_err($dev,'Unauthorised access');
    $dev = $_GET['device'];
    $db_host = "your.database.server";
    $db_user = "your_user";
    $db_pass = "your_password";
    $db_name = "your_database";
    $mysqli = new mysqli($db_host, $db_user, $db_pass, $db_name);
    if (mysqli_connect_errno()) show_err($dev,"Could not connect to database");
    $query = "SELECT * FROM mycontacts order by lastName asc";
    $result = $mysqli->query($query);
    $num = $result->num_rows;
    $i = 0;
    while ($row = $result->fetch_array()) {   
        $myarr[$i]['first']=$row["firstName"];
        $myarr[$i]['last']=$row["lastName"];
        $myarr[$i]['phone']=$row["number"];
        $i++;
    }
    $mysqli->close();
    switch ($dev) {
      case 'snom':
        echo mysnom($myarr);
      break;
      case 'noki':
        echo mynoki($myarr);
      break;
      default:
        echo mytest($myarr);
      break;
    }
function mytest($myarr) {
  $cont = "Header\n";
  foreach ($myarr as $a) {
    $cont .= " ".$a['first']." ".$a['last']." ".$a['phone']."\n";
  }
  $cont .= "Footer\n";
  return $cont;
}
function mynoki($myarr) {
  $cont = "<?xml version=\"1.0\"?>
<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"
   \"http://www.wapforum.org/DTD/wml_1.1.xml\" >
<wml>\n
  <card id=\"main\" title=\"PhoneList - Nokia\">\n";
  foreach ($myarr as $a) {
    $cont .= "\nTel (WTAI): <a href=\"wtai://wp/mc;%2B".$a['phone']."\">
      ".$a['last']." ".$a['first']."</a><br />";
  }
    $cont .= "</card></wml>\n";
  return $cont;
}
function mysnom($myarr) {
    $cont = "<?xml version=\"1.0\"?>
<SnomIPPhoneDirectory>
  <Title>MySQL Directory</Title>";
  foreach ($myarr as $a) {
    $cont .= "
  <DirectoryEntry>
    <Name>".$a['first']." ".$a['last']."</Name>
    <Telephone>".$a['phone']."</Telephone>
  </DirectoryEntry>\n";
  }
  $cont .= "</SnomIPPhoneDirectory>\n";
  return $cont;
}
function show_err($dev,$msg) {
  switch ($dev) {
    case 'snom':
      echo "<?xml version=\"1.0\"?>
<SnomIPPhoneText>
  <Text>
$msg
  </Text>
</SnomIPPhoneText>
";
    break;
    default:
      echo $msg;
    break;
  }
  die();
}
?>

This code, which is basically a repeat of Listing 4 with the functions from Listing 5 and Listing 6 added, begins with a trivial check to see who the user is and stops under controlled conditions if the wrong user attempts to access the information. It then gets the device from the query string and completes the output according to the instructions.

With each phone presenting its own request and query string to the database, output is quickly and easily received in a format that the device can display.

Conclusion

You can use the contact list from a common source on other platforms by modifying the XML output. The function for the Nokia should work on any phone that conforms to WAP 2.0. Adapting the snom function to other phones might be more difficult, but if XML is respected, then all you need is the right schema. You can easily maintain and expand the script as required, using whichever scripting language is most convenient.


Downloadable resources


Related topics

  • The snom minibrowser: Read about the XML objects that are supported by firmware V7 on the snom370, snom360, snom320, snom300, and V8 on snom820 and snom870.
  • Nokia E71 smart phone: Check out this phone with a QWERTY keyboard.
  • Wireless Application Protocol (Wikipedia): Read a good entry about the commonly used web browser for small mobile devices such as cell phones.
  • 12.1.17. CREATE TABLE Syntax: Learn how to create and modify tables in MySQL.
  • Scripting in PHP: Learn more about this general-purpose scripting language that is especially suited for web development and can be embedded into HTML.
  • VCF and vCard file format: Learn more about the vCard file format standard for electronic business cards.
  • More articles by this author (Colin Beckingham, developerWorks, March 2009-current): Read articles about XML, voice recognition, XHTML, PHP, SMIL, and other technologies.
  • LibreOffice: Learn more about this Open Source personal productivity suite for Windows, Macintosh and Linux. Try the six apps for document production and data processing needs: Writer, Calc, Impress, Draw, Math and Base.
  • phpMyEdit: With this utility, write a simple calling program that generates PHP code to display or edit MySQL tables in HTML.
  • IBM certification: Find out how you can become an IBM-Certified Developer.
  • XML technical library: See the developerWorks XML Zone library for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks. Also, read more XML tips.
  • IBM product evaluation versions: Get your hands on application development tools and middleware products.

Comments

Sign in or register to add and subscribe to comments.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Open source
ArticleID=643262
ArticleTitle=Create an adaptable phone book and contact list for your phones with XML and PHP
publish-date=03292011