Click here to request your free 14-day trial of Cisco Umbrella through NetCraftsmen today!

3/1
2010
William Bell

Pushing Backgrounds to a Cisco IP Phone Using XML

Problem Restated

So you have a few hundred or a few thousand phones floating around in the environment.  You have an image that you just created using a procedure similar to this one.  You have uploaded the .png files to the TFTP server, created the List.xml file, and tested this on one of your phones.  Everything is great so far.  Then you go about the process of working on a plan to push this new image out to all of your phones.  Ahhhh.  Now here’s the rub.  How does one go about doing this?

Options

As this blog unfolds, you will find that there are essentially three options that I have come across:

  1. Using API on phone to do a “batch keypress” job.  This is near useless as you will see.
  2. Using API on phone to do a “setBackground” job.  Way easier than #1 but still requires you to write up some code/script/app.
  3. Using a third party application to do the same thing that #2 is accomplishing.

This blog is going to focus on item #2.  We will provide some background on how I got to this solution and provide a sample script that you can test on your own.  A third party option is provided at the end of this blog.

Cisco Phone Designer

This is likely one of the first places you land when doing research on this topic.  This tool is something Cisco developed and made freely available to customers.  The tool allows a user to open up an image file (like a picture of their kids or their Harley) and “push” it to the phone from their desktop.  Man! That does sound like the type of tool an admin could use to push an image to a ton of phones.  Unfortunately, this is a user tool and not an admin tool.  It can push an image to a phone associated to a user.  I suppose one could try and go the route of associating different phones to a user account and then have a process of changing phone associations, reloading the Phone Designer, push image, repeat.  But that is not anywhere near what I would call efficient.  So, Phone Designer is not useful as an admin tool.

However, the methods used by the phone designer to do it’s job are useful.  We’ll touch on them as we continue on our journey.

Using the Cisco Phone XML API to Batch Key Press

Maybe, if you dug deep enough you came across the idea of using the ability to remotely press keys on an IP phone to your advantage.  Yes, this is possible.  You can use HTTP/XML and push key presses to an IP phone.  Essentially, telling the phone to:

  1. Press “Settings”
  2. Press “1” (to go to User Preferences)
  3. Press “2” (to go to Background Images)
  4. Press “2” (or some other number, to select the image you want on the phone)
  5. Press “Softkey 1” to “select” the image
  6. Press “Softkey 2” to “save” the image
  7. Press “Softkey 3” to “exit”
  8. Repeat #7 to go back to the phone display

Sounds ugly?  Well it is and using this method has a very high probability of failure.  Mainly because timing is key.  It isn’t like an Expect script where you can scrape the output and interpret where you are in the process.  Even if that was possible, the ping-pong nature of this approach is just prone to error.   Once you throw in the added variable of different phone models having different images and lists of images, you might as well not bother.  At least, that is my opinion.

When I first researched this topic, this is about where I stopped.  I knew I could program the key press batch process but I also knew it wasn’t worth the time it would take me to get something working.  Like my dad says, “Son, you gotta use the right tool for the job”.  Of course this is the same guy that demonstrates an affinity for 4-letter words when hanging a ceiling fan, but that is a whole other matter.

Using the setBackground XML Object

OK, so where do we go next?  The last stop on this voyage is a hidden XML object.  Well, hidden from documentation but not from those who know how to call it up.  Yes, we still need to write a tool/script/program.  Yes, we still need to use the API on the phone to accomplish this task.

I came across the “setBackground” object after I decided to revisit the overall problem.  I wondered how the Phone Designer accomplished its job.  So, I setup a sniffer trace on a machine running Phone Designer and saw that Phone Designer uses HTTPs and communicates to the CUCM cluster exclusively.  Hmmm. I don’t see the phone talking to the Phone Designer which isn’t a surprise.  Since I want to see the conversation with the phone I decided that the next place to look would be to capture a trace for the conversation between the IP phone and the CUCM.  I used the method described here to gather a protocol trace.  While looking at the protocol trace I discovered a few things:

  1. Phone Designer is uploading the thumbnail and full size version of the background image to the CUCM cluster
  2. The images are stored in the “ccmcip” virtual directory of the CUCM web server
  3. The CUCM uses an XML command “setBackground” to tell the phone where to download the desktop images

This last point was interesting.  I went to the Cisco IP Phone SDK to find out about “setBackground” and there was nada.  I then went to the Cisco developer community and searched for “setBackground”.  I found out that other folks have stumbled across this XML object and that it isn’t really documented in any API release notes.  I also received confirmation that the XML structure is basically the same as what I saw in my sniffer trace.

So,  now we know what the problem is.  We have identified some options and common research results and we found a viable candidate solution.  Now, if you want to do this without investing money in a 3rd party application then you will have to solve your own problem.  I touch on one 3rd party option at the end of this blog.  The following sections go into the “viable candidate solution” of leveraging the “setBackground” XML object.

XML Structure

The setBackground object is pretty simple:

<setBackground>
 <background>
<image>

http://mywebserver/imagename.png</image>
<icon>http://mywebserver/imagethumbnail.png</icon>
 </background>
</setBackground>

Basically, the above XML object is telling the phone to pull the images from a web server. The image child node is the image that will actually become the background image and the icon child node is the “thumbnail” version of the background image.

Methodology: The Image Files

You still need image files and those image files are formatted using the same pixel resolution and file format (.png) as TFTP background images.  The only difference is that “setBackground” is using HTTP to download the images.  I have not found a way to use either TFTP or FTP URLs to get the phone to download the files.  So, from my testing you will need to upload your background images and thumbnails to a web server to leverage the “setBackground” capability.

So, to use the example provided in this blog, you will need to post the background .png file and the thumbnail .png file to a web server that doesn’t require authentication from clients (i.e. IP Phones) accessing the web server.

Methodology: CUCM Provisioning

Since we are using the “setBackground” XML method and are basically emulating the same process used by Cisco Phone Designer, you will need to configure CUCM in the same way you would using Phone Designer.  As an overview:

  1. Create a Common Phone Profile that enables “Phone Personalization” (or modify the system defaults)
  2. Assign profile to the phones you wish to modify
  3. Associate a user object to the phones/devices that you would like to modify

The CUCM cluster does not allow use of the “setBackground” XML object unless phone personalization is enabled.  In addition, when you try to use this API method the phone will authenticate the request which is why you need to associate the target devices to the user.

Methodology: Executing API Call

As with all API calls to a Cisco IP phone you have to use the POST method to upload the “setBackground” XML you want the phone to parse and act on.  You also have to have a user ID that has a device association to the phone.  This is a security measure enforced by the phone and CUCM.

A Sample Script

The following is a sample script that you can use to test the methodology discussed in this blog.  This is a demonstration/concept example and is not intended to be used for any production deployment.  This example is written in Microsoft JavaScript and is intended to be used with Windows Scripting Host (WSH) loaded on W2K, W2k3, XP, etc.

NOTE: Original Sample Has Been Updated

/* =================================
NAME: testbackgroundpush.js
AUTHOR: wjb@netcraftsmen.net
DATE : 2/15/2010
COMMENT: Just a demo.
================================== */
//BEGIN: modify the following
var myuserid="bbell";//this is the user object associated to the phone(s)
var mypassword="C1$co12345";//this is the user password

//modify the myphonelistr to include a list of phones you want updated
//a string value of one IP address is perfectly acceptable
var myphoneliststr = "10.3.199.32"; //"10.3.199.32,10.3.199.33" is another example

var thumbnailurl = "http://10.3.2.252/netcraftsmen-tn.png"; //the thumbnail image
var backgroundurl = "http://10.3.2.252/netcraftsmen.png"; //this is the actual background

//END: modify

var myphonearr = myphoneliststr.split(","); //create an array to walk through
var myauth = text2base64(myuserid + ":" + mypassword);//Create HTML basic auth string
var xmlhttp = new ActiveXObject("Msxml2.ServerXMLHTTP.6.0"); //Object used for client connection

// Loop through the phone list
for (var i=0;i<myphonearr.length;i++)
{
 WScript.Echo("Processing phone record: " + myphonearr[i]);
 var myxml = "XML=<setBackground> <background><image>

"
           + backgroundurl + "</image> <icon>" + thumbnailurl
           + "</icon></background></setBackground>";
 var WebServer = "http://" + myphonearr[i] + "/CGI/Execute";
 xmlhttp.open("POST", WebServer, false);
 with (xmlhttp){
  setRequestHeader("Man", "POST " + WebServer + " HTTP/1.1");
  setRequestHeader("MessageType", "CALL");
  setRequestHeader("Content-Type", "text/xml");
  setRequestHeader("Host", myphonearr[i] + ":80");
  setRequestHeader("Authorization", "Basic " + myauth);
  setRequestHeader("Content-length", myxml.length);
 }
 xmlhttp.send(myxml);
 WScript.Echo(xmlhttp.responseText);
}

/******************************************************
function text2base64() Used to create hashed string
******************************************************/
function text2base64(text) {
  var j = 0;
  var i = 0;
  var base64 = new Array();
  var base64string = "";
  var base64key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  var text0, text1, text2;

////////////////////////////////////////////////////////////////////////////////////////////////////
//  Step thru the input text string 3 characters per loop, creating 4 output characters per loop  //
////////////////////////////////////////////////////////////////////////////////////////////////////

  for (i=0; i < text.length;  )
  {
    text0 = text.charCodeAt(i);
    text1 = text.charCodeAt(i+1);
    text2 = text.charCodeAt(i+2);

    base64[j] = base64key.charCodeAt((text0 & 252) >> 2);
    if ((i+1)<text.length)      // i+1 is still part of string
    {
      base64[j+1] = base64key.charCodeAt(((text0 & 3) << 4)|((text1 & 240) >> 4));
      if ((i+2)<text.length)  // i+2 is still part of string
      {
        base64[j+2] = base64key.charCodeAt(((text1 & 15) << 2) | ((text2 & 192) >> 6));
        base64[j+3] = base64key.charCodeAt((text2 & 63));
      }
      else
      {
        base64[j+2] = base64key.charCodeAt(((text1 & 15) << 2));
        base64[j+3] = 61;
      }
    }
    else
    {
      base64[j+1] = base64key.charCodeAt(((text0 & 3) << 4));
      base64[j+2] = 61;
      base64[j+3] = 61;
    }
    i=i+3;
    j=j+4;
  }
 
  ////////////////////////////////////////////
  //  Create output string from byte array  //
  ////////////////////////////////////////////

  for (i=0; i<base64.length; i++)
  {
    base64string += String.fromCharCode(base64[i]);
  }

  return base64string;
}

So, the above script is fairly simplistic.  It assumes you have a network path from the machine you use to run the script and the IP phone.  It also assumes that the phone’s web server is configured to accept HTTP requests and that the network allows this type of conversation from your desktop to the phone.  You will need to make sure you have the end user and device association configured correctly.  You also need to ensure that phone personalization is configured.  The function text2base64() is necessary because we are using HTTP Basic Authentication method.  The text2base64() will take a user name/password and create the hashed string used by HTTP Basic Auth.

Again, this uses Windows Scripting Host (WSH) and has been tested on WSH version 5.6 and CUCM version 7.1(3b)SU1.

Disclaimer

It should be common sense but I will include a disclaimer anyway.  The above script is a concept sample only and not intended or tested for production use.  The script is provided “as is” and you use this script at your own risk.  It is assumed that the person using the above script is simply testing the moving parts.

Other Options and Future Cisco Features

There is another option I have found but have not tested.  Apparently I have seen that some folks found an application that can do this at a nominal software cost.  Again, I haven’t tested this out but it sounds promising:

http://www.voipintegration.com/software.html

Oh, and one more thing.  There is a feature request in the ol’ CUCM pipeline that is being tracked by this defect id: CSCsi49844.  However, you will find that is one of those internal Cisco Bug IDs.

William Bell

William Bell

Architect, Infrastructure Practice Lead

William’s background spans an array of technical disciplines including application development, network infrastructure, protocol analysis, virtualization, and Unified Communications. Bill is certified as a CCIE Voice (CCIE #38914) and possesses a deep understanding of Cisco’s UC and Collaboration portfolio. He leads the Infrastructure Engineering team and also works with customers on architecting solutions that align with core business drivers. Bill is a regular contributor on the Cisco Support Community, a 3 time Cisco Designated VIP, and blogs on the NetCraftsmen and UC Guerrilla sites.

View more Posts

 

Virgilio “BONG” dela Cruz Jr.

CCDP, CCNA V, CCNP, Cisco IPS Express Security for AM/EE
Field Solutions Architect, Tech Data

Virgilio “Bong” has sixteen years of professional experience in IT industry from academe, technical and customer support, pre-sales, post sales, project management, training and enablement. He has worked in Cisco Technical Assistance Center (TAC) as a member of the WAN and LAN Switching team. Bong now works for Tech Data as the Field Solutions Architect with a focus on Cisco Security and holds a few Cisco certifications including Fire Jumper Elite.

 

John Cavanaugh

CCIE #1066, CCDE #20070002, CCAr
Chief Technology Officer, Practice Lead Security Services, NetCraftsmen

John is our CTO and the practice lead for a talented team of consultants focused on designing and delivering scalable and secure infrastructure solutions to customers across multiple industry verticals and technologies. Previously he has held several positions including Executive Director/Chief Architect for Global Network Services at JPMorgan Chase. In that capacity, he led a team managing network architecture and services.  Prior to his role at JPMorgan Chase, John was a Distinguished Engineer at Cisco working across a number of verticals including Higher Education, Finance, Retail, Government, and Health Care.

He is an expert in working with groups to identify business needs, and align technology strategies to enable business strategies, building in agility and scalability to allow for future changes. John is experienced in the architecture and design of highly available, secure, network infrastructure and data centers, and has worked on projects worldwide. He has worked in both the business and regulatory environments for the design and deployment of complex IT infrastructures.