<%@ page language="java" import="com.cisco.ipphone.sdk.*, java.util.*, java.net.URLEncoder, java.net.InetAddress" %>

<%
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Title:  		SpeedDials
// Author: 		kstearns
// Source File(s):  	speeddials.jsp
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Description:
//
// SpeedDials allows users to configure their personal SpeedDials (not FastDials) directly
// from their phone (via a phone service). Personal SpeedDials are normally only accessible
// thru the CallManager user pages.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
//  Requirements and Caveats:
//
// -  Client: Cisco IP Phone XSI Browser
//
// - The SpeedDials.jsp script MUST be supplied with the device name of the phone. So when the
//   Phone Service is defined in CallManager, include the #DEVICENAME# tag as a querystring parameter
//   when defining the URL:
//
//          http://yourserver:8080/speeddials/speeddials.jsp?name=#DEVICENAME#
//
// - The SpeedDials app is Extension Mobility aware. If a user is logged into the phone via EM,
//   the speed dials of the user's default Device Profile are used instead of the speed
//   dials of the phone itself.
//   NOTE: This can cause unexpected behavior if the user is logged
//   into the phone using a Device Profile other than their default.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////

//
//  Edit the following Strings for your environment.
//  This is for sample purposes only - placing passwords and other
//  sensitive information in an open text file is obviously NOT recommended !!!
//

String callManager = "10.0.0.1";
String callManagerUserId = "administrator";
String callManagerPassword = "cisco";

String extMobUserId = "sdkapps";
String extMobPassword = "sdkapps";

String ldapServer = "10.0.0.1";
String ldapRoot = "o=cisco.com";
String ldapUserId = "cn=Directory Manager, o=cisco.com";
String ldapPassword = "cisco";
int ldapPort = 8404;


//  This application uses querystring parameters to pass session information between pages.
//  Grab that session information and load it into variables ...

int index = -1;
if (request.getParameter("index") != null)
  index = Integer.parseInt(request.getParameter("index"));

String deviceName = request.getParameter("name");
String dirn = request.getParameter("dirn");
String label = request.getParameter("label");
if (dirn == null) dirn = "";
if (label == null) label = "";

Integer position = new Integer(0);
if (request.getParameter("position") != null) {
  position = Integer.valueOf(request.getParameter("position"));
}

//  Create strings for referencing the URL of this page

String thisServer = InetAddress.getLocalHost().getHostAddress();
String thisPath = request.getRequestURI();
String thisPort = String.valueOf(request.getServerPort());
String thisPage = "http://" + thisServer + ":" + thisPort + thisPath + "?name=" + deviceName;

String action = request.getParameter("action");
if (action == null) action = "main";

AXLProvider axlProvider = new AXLProvider(callManager, callManagerUserId, callManagerPassword);
EMProvider emProvider = new EMProvider(callManager, callManagerUserId, callManagerPassword, extMobUserId, extMobPassword);
LDAPProvider lp = new LDAPProvider(ldapServer, ldapUserId, ldapPassword, ldapPort, ldapRoot);

Vector speedDials = new Vector();

Phone thePhone = Phone.getPhone(deviceName);

// Notice that whether this Phone is a 'hard' phone or an 'virtual' EM Device Profile,
// the Phone.loadAttributes method still works

thePhone.loadAttributes(axlProvider);
SpeedDial[] sdArray = thePhone.getSpeedDials();
speedDials.setSize(sdArray.length);
for (int i=0; i < sdArray.length; i++) {
  speedDials.set(i, sdArray[i]);
}

response.setContentType("text/xml");

//////////////////////////////////////////////////////
//  Main
//////////////////////////////////////////////////////

if (action.equals("main")) {
  // The main page lists of the currently configured speeddials for this phone

  out.print("<CiscoIPPhoneMenu><Title>Current Speed Dials</Title>");

  //  Step thru each speeddial and build an CiscoIPPhoneMenu object to return to the phone

  for (int i = 0; i < speedDials.size(); i++) {
    SpeedDial sd = (SpeedDial)speedDials.get(i);
    if (sd != null) {
      out.print("<MenuItem><Name>");
      out.println("Speeddial Position: " + sd.getPosition());
      out.print(XmlEncoder.encode(sd.getLabel() + "   " + sd.getNumber()));
      out.print("</Name><URL>QueryStringParam:index=" + i + "&amp;dirn=" + URLEncoder.encode(sd.getNumber(), "UTF-8") + "&amp;label=" + URLEncoder.encode(sd.getLabel(), "UTF-8") + "&amp;position=" + sd.getPosition() + "</URL></MenuItem>\r\n");
    }
  }

  %>
  <SoftKeyItem><Name>Edit</Name><URL><%=thisPage%>&amp;action=edit</URL><Position>1</Position></SoftKeyItem>
  <SoftKeyItem><Name>Add</Name><URL><%=thisPage%>&amp;action=add</URL><Position>2</Position></SoftKeyItem>
  <SoftKeyItem><Name>Delete</Name><URL><%=thisPage%>&amp;action=delete</URL><Position>3</Position></SoftKeyItem>
  <SoftKeyItem><Name>Done</Name><URL><%=thisPage%>&amp;action=done</URL><Position>4</Position></SoftKeyItem>
  </CiscoIPPhoneMenu>
  <%
}

//////////////////////////////////////////////////////
//  Edit
//////////////////////////////////////////////////////

if (action.equals("edit")) {
  //  Input the Label name and directory number for the current edited speeddials
  //  The default values are the currently configured values which are passed by querystring parameters

  response.addHeader("Expires", "-1");
  %>
  <CiscoIPPhoneInput>
  <Title>Edit SpeedDial (<%=position%>)</Title>
  <URL><%=thisPage%>&amp;action=update&amp;index=<%=index%>&amp;position=<%=position%></URL>
  <InputItem>
    <DisplayName>Label</DisplayName>
    <QueryStringParam>label</QueryStringParam>
    <DefaultValue><%=label%></DefaultValue>
    <InputFlags>A</InputFlags>
  </InputItem>
  <InputItem>
    <DisplayName>Number</DisplayName>
    <QueryStringParam>dirn</QueryStringParam>
    <DefaultValue><%=dirn%></DefaultValue>
    <InputFlags>T</InputFlags>
  </InputItem>
  </CiscoIPPhoneInput>
  <%
}

//////////////////////////////////////////////////////
//  Update
//////////////////////////////////////////////////////

if (action.equals("update"))  {

  // This update routine does the actually updating of the CallManager database via the AXL API.
  // If either the label or the number is null (blank), then the speeddial entry is deleted from CallManager

  response.addHeader("Refresh", "1;URL=" + thisPage);
  response.addHeader("Expires", "-1");

  String updateXML = "";

  // First update the speeddial vectors in memory with the requested change

  String operation = "";

  if (index == -1) {    // Index==-1 means that we're adding a speeddial
    for (int i=0; i < speedDials.size(); i++) {
      if (((SpeedDial)speedDials.get(i)).getPosition() == position.intValue()) {
        response.setContentType("text/html");
        out.println("ERROR: SpeedDial already exists in position "+position);
        return;
      }
    }
    speedDials.add(new SpeedDial(label, dirn, position.intValue()));
    operation = "Added";
  }
  else {               // Index!=-1 means we're updating an existing speeddial
    if (dirn.equals("") | label.equals("") | position.intValue() == 0)  {
      speedDials.set(index, null);
      operation = "Deleted";
    }
    else {
      speedDials.set(index, new SpeedDial(label, dirn, position.intValue()));
      operation = "Updated";
    }
  }

  // Now step thru those speeddials and build an XML <speeddial> object to send to the AXL updatePhone method

  for (int i = 0; i < speedDials.size(); i++) {
    SpeedDial sd = (SpeedDial)speedDials.get(i);
    if (sd != null) {
      updateXML += "<speeddial index=\"" + sd.getPosition() + "\"><dirn>" + XmlEncoder.encode(sd.getNumber()) + "</dirn><label>" + XmlEncoder.encode(sd.getLabel()) + "</label></speeddial>";
    }
  }

  updateXML += "</speeddials>";

  // Check to see if someone is currently logged into this phone via Extension Mobility, so
  // that we know whether the supplied device name is a phone or a device profile.
  // This must be known so that the correct AXL update method is used.

  User emUser = thePhone.getCurrentExtMobUser(emProvider);
  if (emUser == null) {
    System.out.println(axlProvider.sendRequest("updatePhone", "<name>" + deviceName + "</name><speeddials>" + updateXML));
  }
  else {
    String dp = emUser.getDefaultDeviceProfile(lp);
    if (dp == null) {
      String[] dps = emUser.getDeviceProfiles(lp);
      if (dps.length != 0) {
        dp = dps[0];
      }
    }
    if (dp != null) {
      axlProvider.sendRequest("updateDeviceProfile", "<name>" + dp + "</name><speeddials>" + updateXML);
    }
  }

  //  Send an updated/deleted confirmation back to the phone and then have the phone refresh back to the main
  //  page after 3 seconds.


  %>
  <CiscoIPPhoneText>
  <Title>Speeddials</Title>
  <Text>Speed Dial successfully <%=operation%>.</Text>
  </CiscoIPPhoneText>
  <%

}

//////////////////////////////////////////////////////
//  Add
//////////////////////////////////////////////////////

if (action.equals("add")) {
  response.addHeader("Expires", "-1");
  %>
  <CiscoIPPhoneInput>
  <Title>Add Speed Dial</Title>
  <URL><%=thisPage%>&amp;action=update</URL>
  <InputItem>
    <DisplayName>Position</DisplayName>
    <QueryStringParam>position</QueryStringParam>
    <DefaultValue></DefaultValue>
    <InputFlags>N</InputFlags>
  </InputItem>
  <InputItem>
    <DisplayName>Label</DisplayName>
    <QueryStringParam>label</QueryStringParam>
    <DefaultValue></DefaultValue>
    <InputFlags>A</InputFlags>
  </InputItem>
  <InputItem>
    <DisplayName>Number</DisplayName>
    <QueryStringParam>dirn</QueryStringParam>
    <DefaultValue></DefaultValue>
    <InputFlags>T</InputFlags>
  </InputItem>
  </CiscoIPPhoneInput>
  <%
}

//////////////////////////////////////////////////////
//  Delete
//////////////////////////////////////////////////////

if (action.equals("delete")) {
  // Redirect to Update page with only the index - this will cause it to be deleted
  response.sendRedirect(thisPage+"&action=update&index="+index);
}

//////////////////////////////////////////////////////
//  Done
//////////////////////////////////////////////////////

if (action.equals("done")) {
  User emUser = thePhone.getCurrentExtMobUser(emProvider);
  if (emUser == null) {
    //  Before exiting, perform a "soft" device reset on this phone so that the speeddial changes take effect
    axlProvider.sendRequest("doDeviceReset", "<deviceName>" + deviceName + "</deviceName><isHardReset>false</isHardReset>");
  }
  else {
    // If the device profile was updated, the user must be logged out and back in for the
    // changes to take affect
    thePhone.logout(emProvider);
    thePhone.login(emProvider, emUser);
  }
}


//  THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND BY CISCO,
//  EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
//  FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE
//  OF DEALING, LAW, USAGE, OR TRADE PRACTICE.  CISCO TAKES NO RESPONSIBILITY REGARDING ITS USAGE IN AN
//  APPLICATION., THE APPLICATION IS PROVIDED AS AN EXAMPLE ONLY, THEREFORE CISCO DOES NOT MAKE ANY
//  REPRESENTATIONS REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION.  IN NO EVENT DOES CISCO
//  WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE TO OPERATE THE SOFTWARE WITHOUT
//  PROBLEMS OR INTERRUPTIONS.  NOR DOES CISCO WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE
//  SOFTWARE IS USED WILL BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK.  THIS SAMPLE APPLICATION IS
//  NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY ARISING FROM THE USE OF THE
//  APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR
//  CONSEQUENTIAL DAMAGES, LOST PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
//  SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.

%>



