public Object [] processStringEscapes(JavNag javNag, Totals totals, Calendar rightNow, Problem problem, boolean haveNotifiedProblems, String cmd, boolean recurse)
	{
		long now = System.currentTimeMillis() / 1000;
		String pars = null;
		String [] parts = cmd.split("\\^");
		cmd = parts[0];
		if (parts.length > 1)
			pars = parts[1];

		if ((cmd.equals("EQUAL") || cmd.equals("LESS") || cmd.equals("LESSOREQUAL") || cmd.equals("BIGGER") || cmd.equals("BIGGEROREQUAL")) && recurse == true) {
			double aValue = convertField(parts[1], javNag, totals, rightNow, problem, haveNotifiedProblems, cmd);
			double bValue = convertField(parts[2], javNag, totals, rightNow, problem, haveNotifiedProblems, cmd);
			boolean result = false;
			if (cmd.equals("LESS"))
				result = aValue < bValue;
			else if (cmd.equals("LESSOREQUAL"))
				result = aValue <= bValue;
			else if (cmd.equals("BIGGER"))
				result = aValue > bValue;
			else if (cmd.equals("BIGGEROREQUAL"))
				result = aValue >= bValue;
			else if (cmd.equals("EQUAL"))
				result = aValue == bValue;
			else
				return new Object [] { cmd + " is not understood", true };

			if (!result)
				return new Object [] { "", false };

			String out = parts[3];
			return processStringWithEscapes(out, javNag, rightNow, problem, haveNotifiedProblems, false);
		}

		if (cmd.equals("STATE") && recurse == true)
		{
			if (haveNotifiedProblems)
				return processStringWithEscapes(config.getStateProblemsText(), javNag, rightNow, problem, haveNotifiedProblems, false);

			return processStringWithEscapes(config.getNoProblemsText(), javNag, rightNow, problem, haveNotifiedProblems, false);
		}

		if (cmd.equals("EXEC") && pars != null)
			return new Object [] { execWithPars(problem, pars), false };

		if (cmd.equals("PERCENT"))
			return new Object [] { "%", false };

		if (cmd.equals("AT"))
			return new Object [] { "@", false };

		if (cmd.equals("FIELD") && pars != null) {
			String [] fields = pars.split("|");
			// field|service|host
			// field|host
			// field
			if (fields.length == 1) { // field
				if (problem.getService() != null)
					return new Object [] { problem.getService().getParameter(fields[0]), false };
				else if (problem.getHost() != null)
					return new Object [] { problem.getHost().getParameter(fields[0]), false };
			}
			else if (fields.length == 2) { // field|host
				javNag.getField(fields[1], fields[0]);
			}
			else if (fields.length == 3) { // field|service|host
				javNag.getField(fields[2], fields[1], fields[0]);
			}
		}

		if (cmd.equals("FIELDHOST") && pars != null && pars.length() > 0)
		{
			String data = problem.getHost().getParameter(pars);
			if (data != null)
				return new Object [] { data, false };
		}

		if (cmd.equals("FIELDSERVICE") && pars != null && pars.length() > 0)
		{
			String data = problem.getService().getParameter(pars);
			if (data != null)
				return new Object [] { data, false };
		}

		if (cmd.equals("FIELDBOOLEANHOST") && pars != null && pars.length() > 0)
		{
			String data = problem.getHost().getParameter(pars);
			if (data != null)
				return new Object [] { data.equals("1") ? "yes" : "no", false };
		}

		if (cmd.equals("FIELDBOOLEANSERVICE") && pars != null && pars.length() > 0)
		{
			String data = problem.getService().getParameter(pars);
			if (data != null)
				return new Object [] { data.equals("1") ? "yes" : "no", false };
		}

		if (cmd.equals("FIELDDATEHOST") && pars != null && pars.length() > 0)
		{
			String data = problem.getHost().getParameter(pars);
			if (data != null)
				return new Object [] { stringTsToDate(data), false };
		}

		if (cmd.equals("FIELDDATESERVICE") && pars != null && pars.length() > 0)
		{
			String data = problem.getService().getParameter(pars);
			if (data != null)
				return new Object [] { stringTsToDate(data), false };
		}

		if (cmd.equals("CRITICAL"))
			return new Object [] { "" + totals.getNCritical(), false };
		if (cmd.equals("WARNING"))
			return new Object [] { "" + totals.getNWarning(), false };
		if (cmd.equals("OK"))
			return new Object [] { "" + totals.getNOk(), false };

		if (cmd.equals("NACKED"))
			return new Object [] { "" + totals.getNAcked(), false };
		if (cmd.equals("NFLAPPING"))
			return new Object [] { "" + totals.getNFlapping(), false };

		if (cmd.equals("UP"))
			return new Object [] { "" + totals.getNUp(), false };
		if (cmd.equals("DOWN"))
			return new Object [] { "" + totals.getNDown(), false };
		if (cmd.equals("UNREACHABLE"))
			return new Object [] { "" + totals.getNUnreachable(), false };
		if (cmd.equals("PENDING"))
			return new Object [] { "" + totals.getNPending(), false };

		if (cmd.equals("TOTALISSUES"))
			return new Object [] { "" + (totals.getNCritical() + totals.getNWarning() + totals.getNDown() + totals.getNUnreachable()), false };

		if (predictor != null && cmd.equals("PREDICT"))
		{
			Double count = predictProblemCount(rightNow);
			if (count == null)
				return new Object [] { "?", false };
			String countStr = "" + count;
			int dot = countStr.indexOf(".");
			if (dot != -1)
				countStr = countStr.substring(0, dot + 2);
			return new Object [] { countStr, false };
		}

		if (cmd.equals("CHECKLATENCY"))
		{
			Double latency = javNag.getAvgCheckLatency();
			if (latency != null)
				return new Object [] { "" + String.format("%.3f", latency), false };
		}

		if (cmd.equals("HISTORICAL"))
			return new Object [] { "" + predictor.getHistorical(rightNow), false };

		if (cmd.equals("H"))
			return new Object [] { make2Digit("" + rightNow.get(Calendar.HOUR_OF_DAY)), false };
		if (cmd.equals("M"))
			return new Object [] { make2Digit("" + rightNow.get(Calendar.MINUTE)), false };

		if (cmd.equals("HOSTNAME") && problem != null && problem.getHost() != null)
			return new Object [] { problem.getHost().getHostName(), false };

		if (cmd.equals("SERVICENAME") && problem != null && problem.getService() != null)
			return new Object [] { problem.getService().getServiceName(), false };

		if (cmd.equals("SERVERNAME"))
			return new Object [] { problem.getHost().getNagiosSource(), false };

		if (cmd.equals("HOSTSTATE") && problem != null && problem.getHost() != null)
			return new Object [] { hostState(problem.getHost().getParameter("current_state")), false };

		if (cmd.equals("SERVICESTATE") && problem != null && problem.getService() != null)
			return new Object [] { serviceState(problem.getService().getParameter("current_state")), false };

		if (cmd.equals("HOSTDURATION"))
			return new Object [] { "" + durationToString(System.currentTimeMillis() / 1000 - Long.valueOf(problem.getHost().getParameter("last_state_change"))), false };
		if (cmd.equals("SERVICEDURATION"))
			return new Object [] { "" + durationToString(System.currentTimeMillis() / 1000 - Long.valueOf(problem.getService().getParameter("last_state_change"))), false };

		if (cmd.equals("HOSTSINCE") && problem != null && problem.getHost() != null)
			return new Object [] { stringTsToDate(problem.getHost().getParameter("last_state_change")), false };

		if (cmd.equals("HOSTSINCETS") && problem != null && problem.getHost() != null) {
			Host current = problem.getHost();
			String current_state = current.getParameter("current_state");
			String field = null;
			if (current_state.equals("0"))
				field = "last_time_up";
			else if (current_state.equals("1"))
				field = "last_time_down";
			else if (current_state.equals("2"))
				field = "last_time_unreachable";
			// System.out.println("======== " + field + " " + current.getParameter(field));
			if (field != null)
				return new Object [] { "" + (now - Long.valueOf(current.getParameter(field))), false };
		}

		if (cmd.equals("SERVICESINCE") && problem != null && problem.getService() != null)
			return new Object [] { stringTsToDate(problem.getService().getParameter("last_state_change")), false };

		if (cmd.equals("SERVICESINCETS") && problem != null && problem.getService() != null)
			return new Object [] { "" + (now - Long.valueOf(problem.getService().getParameter("last_state_change"))), false };

		if (cmd.equals("HOSTFLAPPING") && problem != null && problem.getHost() != null)
			return new Object [] { problem.getHost().getParameter("is_flapping").equals("1") ? "FLAPPING" : "", false };

		if (cmd.equals("SERVICEFLAPPING") && problem != null && problem.getService() != null)
			return new Object [] { problem.getService().getParameter("is_flapping").equals("1") ? "FLAPPING" : "", false };

		if (cmd.equals("OUTPUT") && problem != null)
		{
			String output;
			if (problem.getService() != null)
				output = problem.getService().getParameter("plugin_output");
			else
				output = problem.getHost().getParameter("plugin_output");
			if (output != null)
				return new Object [] { output, false };
			return new Object [] { "?", false };
		}

		if (cmd.equals("FLASH"))
			return new Object [] { "", true };

		return new Object [] { "?" + cmd + "?", false };
	}