// --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package com.netscape.cms.servlet.wizard;
import java.io.IOException;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.util.Vector;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.servlet.VelocityServlet;
import com.netscape.certsrv.apps.CMS;
import com.netscape.cms.servlet.csadmin.Cert;
import com.netscape.cmsutil.crypto.Module;
/**
* wizard?p=[panel number]&op=usage <= usage in xml
* wizard?p=[panel number]&op=display
* wizard?p=[panel number]&op=next&...[additional parameters]...
* wizard?p=[panel number]&op=apply
* wizard?p=[panel number]&op=back
* wizard?op=menu
* return menu options
*/
public class WizardServlet extends VelocityServlet {
/**
*
*/
private static final long serialVersionUID = -4513510177445656799L;
private String name = null;
private Vector mPanels = new Vector();
public void init(ServletConfig config) throws ServletException
{
super.init(config);
/* load sequence map */
name = config.getInitParameter("name");
String panels = config.getInitParameter("panels");
StringTokenizer st = new StringTokenizer(panels, ",");
int pno = 0;
while (st.hasMoreTokens()) {
String p = st.nextToken();
StringTokenizer st1 = new StringTokenizer(p, "=");
String id = st1.nextToken();
String pvalue = st1.nextToken();
try {
IWizardPanel panel = (IWizardPanel)Class.forName(pvalue).newInstance();
panel.init(this, config, pno, id);
CMS.debug("WizardServlet: panel name=" + panel.getName());
mPanels.addElement(panel);
} catch (Exception e) {
CMS.debug("WizardServlet: " + e.toString());
}
pno++;
}
CMS.debug("WizardServlet: done");
}
public void exposePanels(HttpServletRequest request,
HttpServletResponse response,
Context context )
{
Enumeration e = mPanels.elements();
Vector panels = new Vector();
while (e.hasMoreElements()) {
IWizardPanel p = (IWizardPanel)e.nextElement();
panels.addElement(p);
}
context.put("panels", panels);
}
/**
* Cleans up panels from a particular panel.
*/
public void cleanUpFromPanel(int pno) throws IOException
{
/* panel number starts from zero */
int s = mPanels.size();
for (int i = pno; i < s; i++) {
IWizardPanel panel = (IWizardPanel)mPanels.elementAt(i);
panel.cleanUp();
}
}
public IWizardPanel getPanelByNo(int p)
{
IWizardPanel panel = (IWizardPanel)mPanels.elementAt(p);
if (panel.shouldSkip()) {
panel = getPanelByNo(p+1);
}
return panel;
}
public Template displayPanel(HttpServletRequest request,
HttpServletResponse response,
Context context )
{
CMS.debug("WizardServlet: in display");
int p = getPanelNo(request);
if (p == 0) {
CMS.debug("WizardServlet: firstpanel");
context.put("firstpanel", Boolean.TRUE);
}
if (p == (mPanels.size() - 1)) {
CMS.debug("WizardServlet: lastpanel");
context.put("lastpanel", Boolean.TRUE);
}
IWizardPanel panel = getPanelByNo(p);
CMS.debug("WizardServlet: panel=" + panel);
if (panel.showApplyButton() == true)
context.put("showApplyButton", Boolean.TRUE);
else
context.put("showApplyButton", Boolean.FALSE);
panel.display(request, response, context);
context.put("p", Integer.toString(panel.getPanelNo()));
try {
return Velocity.getTemplate("admin/console/config/wizard.vm");
} catch (Exception e) {
}
return null;
}
public String xml_value_flatten(Object v)
{
String ret = "";
if (v instanceof String) {
ret += v;
} else if (v instanceof Integer) {
ret += ((Integer)v).toString();
} else if (v instanceof Vector) {
ret += "";
Vector v1 = (Vector)v;
Enumeration e = v1.elements();
StringBuffer sb = new StringBuffer();
while (e.hasMoreElements()) {
sb.append(xml_value_flatten(e.nextElement()));
}
ret += sb.toString();
ret += "";
} else if (v instanceof Module) { // for hardware token
Module m = (Module)v;
ret += "";
ret += "" + m.getCommonName() + "";
ret += "" + m.getUserFriendlyName() + "";
ret += "" + m.getImagePath() + "";
ret += "";
} else if (v instanceof Cert) {
Cert m = (Cert)v;
ret += "";
ret += "" + m.getNickname() + "";
ret += "" + m.getTokenname() + "";
ret += "" + m.getRequest() + "";
ret += "" + m.getCert() + "";
ret += "" + m.getType() + "";
ret += "" + m.getDN() + "";
ret += "" + m.getCertpp() + "";
ret += "" + m.getKeyOption() + "";
ret += "";
} else if (v instanceof IWizardPanel) {
IWizardPanel m = (IWizardPanel)v;
ret += "";
ret += "" + m.getId() + "";
ret += "" + m.getName() + "";
ret += "";
} else {
CMS.debug("Error: unknown type " + v.getClass().getName());
}
return ret;
}
public String xml_flatten(Context context)
{
StringBuffer ret = new StringBuffer();
Object o[] = context.getKeys();
for (int i = 0; i < o.length; i ++) {
if (o[i] instanceof String) {
String key = (String)o[i];
if (key.startsWith("__")) {
continue;
}
ret.append("<");
ret.append(key);
ret.append(">");
if (key.equals("bindpwd")) {
ret.append("(sensitive)");
} else {
Object v = context.get(key);
ret.append(xml_value_flatten(v));
}
ret.append("");
ret.append(key);
ret.append(">");
}
}
return ret.toString();
}
public int getPanelNo(HttpServletRequest request)
{
int p = 0;
// panel number can be identified by either
// panel no (p parameter) directly, or
// panel name (panelname parameter).
if (request.getParameter("panelname") != null) {
String name = request.getParameter("panelname");
for (int i = 0; i < mPanels.size(); i++) {
IWizardPanel panel = (IWizardPanel)mPanels.elementAt(i);
if (panel.getId().equals(name)) {
return i;
}
}
} else if (request.getParameter("p") != null) {
p = Integer.parseInt(request.getParameter("p"));
}
return p;
}
public String getNameFromPanelNo(int p)
{
IWizardPanel wp = (IWizardPanel)mPanels.elementAt(p);
return wp.getId();
}
public IWizardPanel getPreviousPanel(int p)
{
CMS.debug("getPreviousPanel input p=" + p);
IWizardPanel backpanel = (IWizardPanel)mPanels.elementAt(p-1);
if (backpanel.isSubPanel()) {
backpanel = (IWizardPanel)mPanels.elementAt(p-1-1);
}
while (backpanel.shouldSkip()) {
backpanel = (IWizardPanel)
mPanels.elementAt(backpanel.getPanelNo() - 1);
}
CMS.debug("getPreviousPanel output p=" + backpanel.getPanelNo());
return backpanel;
}
public IWizardPanel getNextPanel(int p)
{
CMS.debug("getNextPanel input p=" + p);
IWizardPanel panel = (IWizardPanel)mPanels.elementAt(p);
if (p == (mPanels.size() - 1)) {
p = p;
} else if(panel.isSubPanel()) {
if (panel.isLoopbackPanel()) {
p = p-1; // Login Panel is a loop back panel
} else {
p = p+1;
}
} else if (panel.hasSubPanel()) {
p = p + 2;
} else {
p = p + 1;
}
IWizardPanel nextpanel = getPanelByNo(p);
CMS.debug("getNextPanel output p=" + p);
return nextpanel;
}
public Template goApply(HttpServletRequest request,
HttpServletResponse response,
Context context)
{
return goNextApply(request, response, context, true);
}
public Template goNext(HttpServletRequest request,
HttpServletResponse response,
Context context )
{
return goNextApply(request, response, context, false);
}
/*
* The parameter "stay" is used to indicate "apply" without
* moving to the next panel
*/
public Template goNextApply(HttpServletRequest request,
HttpServletResponse response,
Context context, boolean stay )
{
int p = getPanelNo(request);
if (stay == true)
CMS.debug("WizardServlet: in reply " + p);
else
CMS.debug("WizardServlet: in next " + p);
IWizardPanel panel = (IWizardPanel)mPanels.elementAt(p);
try {
panel.validate(request, response, context);
try {
panel.update(request, response, context);
if (stay == true) { // "apply"
if (panel.showApplyButton() == true)
context.put("showApplyButton", Boolean.TRUE);
else
context.put("showApplyButton", Boolean.FALSE);
panel.display(request, response, context);
} else { // "next"
IWizardPanel nextpanel = getNextPanel(p);
if (nextpanel.showApplyButton() == true)
context.put("showApplyButton", Boolean.TRUE);
else
context.put("showApplyButton", Boolean.FALSE);
nextpanel.display(request, response, context);
panel = nextpanel;
}
context.put("errorString", "");
} catch (Exception e) {
context.put("errorString", e.getMessage());
panel.displayError(request, response, context);
}
} catch (IOException eee) {
context.put("errorString", eee.getMessage());
panel.displayError(request, response, context);
}
p = panel.getPanelNo();
CMS.debug("panel no=" + p);
CMS.debug("panel name=" + getNameFromPanelNo(p));
CMS.debug("total number of panels="+mPanels.size());
context.put("p", Integer.toString(p));
context.put("panelname", getNameFromPanelNo(p));
if (p == 0) {
CMS.debug("WizardServlet: firstpanel");
context.put("firstpanel", Boolean.TRUE);
}
if (p == (mPanels.size() - 1)) {
CMS.debug("WizardServlet: lastpanel");
context.put("lastpanel", Boolean.TRUE);
}
// this is where we handle the xml request
String xml = request.getParameter("xml");
if (xml != null && xml.equals("true")) {
CMS.debug("WizardServlet: found xml");
response.setContentType("application/xml");
String xmlstr = xml_flatten(context);
context.put("xml", xmlstr);
try {
return Velocity.getTemplate("admin/console/config/xml.vm");
} catch (Exception e) {
CMS.debug("Failing to get template" + e );
}
} else {
try {
return Velocity.getTemplate("admin/console/config/wizard.vm");
} catch (Exception e) {
CMS.debug("Failing to get template" + e );
}
}
return null;
}
public Template goBack(HttpServletRequest request,
HttpServletResponse response,
Context context )
{
int p = getPanelNo(request);
CMS.debug("WizardServlet: in back " + p);
IWizardPanel backpanel = getPreviousPanel(p);
if (backpanel.showApplyButton() == true)
context.put("showApplyButton", Boolean.TRUE);
else
context.put("showApplyButton", Boolean.FALSE);
backpanel.display(request, response, context);
context.put("p", Integer.toString(backpanel.getPanelNo()));
context.put("panelname", getNameFromPanelNo(backpanel.getPanelNo()));
p = backpanel.getPanelNo();
if (p == 0) {
CMS.debug("WizardServlet: firstpanel");
context.put("firstpanel", Boolean.TRUE);
}
if (p == (mPanels.size() - 1)) {
CMS.debug("WizardServlet: lastpanel");
context.put("lastpanel", Boolean.TRUE);
}
try {
return Velocity.getTemplate("admin/console/config/wizard.vm");
} catch (Exception e) {
}
return null;
}
public boolean authenticate(HttpServletRequest request,
HttpServletResponse response,
Context context ) {
String pin = (String)request.getSession().getAttribute("pin");
if (pin == null) {
try {
response.sendRedirect("login");
} catch (IOException e) {
}
return false;
}
return true;
}
public void outputHttpParameters(HttpServletRequest httpReq)
{
CMS.debug("WizardServlet:service() uri = " + httpReq.getRequestURI());
Enumeration paramNames = httpReq.getParameterNames();
while (paramNames.hasMoreElements()) {
String pn = (String)paramNames.nextElement();
// added this facility so that password can be hidden,
// all sensitive parameters should be prefixed with
// __ (double underscores); however, in the event that
// a security parameter slips through, we perform multiple
// additional checks to insure that it is NOT displayed
if( pn.startsWith("__") ||
pn.endsWith("password") ||
pn.endsWith("passwd") ||
pn.endsWith("pwd") ||
pn.equalsIgnoreCase("admin_password_again") ||
pn.equalsIgnoreCase("directoryManagerPwd") ||
pn.equalsIgnoreCase("bindpassword") ||
pn.equalsIgnoreCase("bindpwd") ||
pn.equalsIgnoreCase("passwd") ||
pn.equalsIgnoreCase("password") ||
pn.equalsIgnoreCase("pin") ||
pn.equalsIgnoreCase("pwd") ||
pn.equalsIgnoreCase("pwdagain") ||
pn.equalsIgnoreCase("uPasswd") ) {
CMS.debug("WizardServlet::service() param name='" + pn +
"' value='(sensitive)'" );
} else {
CMS.debug("WizardServlet::service() param name='" + pn +
"' value='" + httpReq.getParameter(pn) + "'" );
}
}
}
public Template handleRequest(HttpServletRequest request,
HttpServletResponse response,
Context context )
{
CMS.debug("WizardServlet: process");
if (CMS.debugOn()) {
outputHttpParameters(request);
}
if (!authenticate(request, response, context)) {
CMS.debug("WizardServlet: authentication failure");
return null;
}
String op = request.getParameter("op"); /* operation */
if (op == null) {
op = "display";
}
CMS.debug("WizardServlet: op=" + op);
CMS.debug("WizardServlet: size=" + mPanels.size());
context.put("name", name);
context.put("size", Integer.toString(mPanels.size()));
exposePanels(request, response, context);
if (op.equals("display")) {
return displayPanel(request, response, context);
} else if (op.equals("next")) {
return goNext(request, response, context);
} else if (op.equals("apply")) {
return goApply(request, response, context);
} else if (op.equals("back")) {
return goBack(request, response, context);
}
return null;
}
}