SSIProcessorpublic class SSIProcessor extends Object The entry point to SSI processing. This class does the actual parsing,
delegating to the SSIMediator, SSICommand, and SSIExternalResolver as
necessary[ |
Fields Summary |
---|
protected static final String | COMMAND_STARTThe start pattern | protected static final String | COMMAND_ENDThe end pattern | protected static final int | BUFFER_SIZE | protected SSIExternalResolver | ssiExternalResolver | protected HashMap | commands | protected int | debug |
Constructors Summary |
---|
public SSIProcessor(SSIExternalResolver ssiExternalResolver, int debug)
this.ssiExternalResolver = ssiExternalResolver;
this.debug = debug;
addBuiltinCommands();
|
Methods Summary |
---|
protected void | addBuiltinCommands()
addCommand("config", new SSIConfig());
addCommand("echo", new SSIEcho());
addCommand("exec", new SSIExec());
addCommand("include", new SSIInclude());
addCommand("flastmod", new SSIFlastmod());
addCommand("fsize", new SSIFsize());
addCommand("printenv", new SSIPrintenv());
addCommand("set", new SSISet());
SSIConditional ssiConditional = new SSIConditional();
addCommand("if", ssiConditional);
addCommand("elif", ssiConditional);
addCommand("endif", ssiConditional);
addCommand("else", ssiConditional);
| public void | addCommand(java.lang.String name, SSICommand command)
commands.put(name, command);
| protected boolean | charCmp(java.lang.String buf, int index, java.lang.String command)
return buf.regionMatches(index, command, 0, command.length());
| protected boolean | isQuote(char c)
return c == '\'" || c == '\"" || c == '`";
| protected boolean | isSpace(char c)
return c == ' " || c == '\n" || c == '\t" || c == '\r";
| private java.lang.String | parseCmd(java.lang.StringBuffer cmd)Parse a StringBuffer and take out the command token. Called from
requestHandler
int firstLetter = -1;
int lastLetter = -1;
for (int i = 0; i < cmd.length(); i++) {
char c = cmd.charAt(i);
if (Character.isLetter(c)) {
if (firstLetter == -1) {
firstLetter = i;
}
lastLetter = i;
} else if (isSpace(c)) {
if (lastLetter > -1) {
break;
}
} else {
break;
}
}
String command = null;
if (firstLetter != -1) {
command = cmd.substring(firstLetter, lastLetter + 1);
}
return command;
| protected java.lang.String[] | parseParamNames(java.lang.StringBuffer cmd, int start)Parse a StringBuffer and take out the param type token. Called from
requestHandler
int bIdx = start;
int i = 0;
int quotes = 0;
boolean inside = false;
StringBuffer retBuf = new StringBuffer();
while (bIdx < cmd.length()) {
if (!inside) {
while (bIdx < cmd.length() && isSpace(cmd.charAt(bIdx)))
bIdx++;
if (bIdx >= cmd.length()) break;
inside = !inside;
} else {
while (bIdx < cmd.length() && cmd.charAt(bIdx) != '=") {
retBuf.append(cmd.charAt(bIdx));
bIdx++;
}
retBuf.append('=");
inside = !inside;
quotes = 0;
boolean escaped = false;
for (; bIdx < cmd.length() && quotes != 2; bIdx++) {
char c = cmd.charAt(bIdx);
// Need to skip escaped characters
if (c == '\\" && !escaped) {
escaped = true;
bIdx++;
continue;
}
escaped = false;
if (c == '"") quotes++;
}
}
}
StringTokenizer str = new StringTokenizer(retBuf.toString(), "=");
String[] retString = new String[str.countTokens()];
while (str.hasMoreTokens()) {
retString[i++] = str.nextToken().trim();
}
return retString;
| protected java.lang.String[] | parseParamValues(java.lang.StringBuffer cmd, int start, int count)Parse a StringBuffer and take out the param token. Called from
requestHandler
int valIndex = 0;
boolean inside = false;
String[] vals = new String[count];
StringBuffer sb = new StringBuffer();
char endQuote = 0;
for (int bIdx = start; bIdx < cmd.length(); bIdx++) {
if (!inside) {
while (bIdx < cmd.length() && !isQuote(cmd.charAt(bIdx)))
bIdx++;
if (bIdx >= cmd.length()) break;
inside = !inside;
endQuote = cmd.charAt(bIdx);
} else {
boolean escaped = false;
for (; bIdx < cmd.length(); bIdx++) {
char c = cmd.charAt(bIdx);
// Check for escapes
if (c == '\\" && !escaped) {
escaped = true;
continue;
}
// If we reach the other " then stop
if (c == endQuote && !escaped) break;
// Since parsing of attributes and var
// substitution is done in separate places,
// we need to leave escape in the string
if (c == '$" && escaped) sb.append('\\");
escaped = false;
sb.append(c);
}
// If we hit the end without seeing a quote
// the signal an error
if (bIdx == cmd.length()) return null;
vals[valIndex++] = sb.toString();
sb.delete(0, sb.length()); // clear the buffer
inside = !inside;
}
}
return vals;
| public long | process(java.io.Reader reader, long lastModifiedDate, java.io.PrintWriter writer)Process a file with server-side commands, reading from reader and
writing the processed version to writer. NOTE: We really should be doing
this in a streaming way rather than converting it to an array first.
SSIMediator ssiMediator = new SSIMediator(ssiExternalResolver,
lastModifiedDate, debug);
StringWriter stringWriter = new StringWriter();
IOTools.flow(reader, stringWriter);
String fileContents = stringWriter.toString();
stringWriter = null;
int index = 0;
boolean inside = false;
StringBuffer command = new StringBuffer();
try {
while (index < fileContents.length()) {
char c = fileContents.charAt(index);
if (!inside) {
if (c == COMMAND_START.charAt(0)
&& charCmp(fileContents, index, COMMAND_START)) {
inside = true;
index += COMMAND_START.length();
command.setLength(0); //clear the command string
} else {
if (!ssiMediator.getConditionalState().processConditionalCommandsOnly) {
writer.write(c);
}
index++;
}
} else {
if (c == COMMAND_END.charAt(0)
&& charCmp(fileContents, index, COMMAND_END)) {
inside = false;
index += COMMAND_END.length();
String strCmd = parseCmd(command);
if (debug > 0) {
ssiExternalResolver.log(
"SSIProcessor.process -- processing command: "
+ strCmd, null);
}
String[] paramNames = parseParamNames(command, strCmd
.length());
String[] paramValues = parseParamValues(command,
strCmd.length(), paramNames.length);
//We need to fetch this value each time, since it may
// change
// during the loop
String configErrMsg = ssiMediator.getConfigErrMsg();
SSICommand ssiCommand = (SSICommand)commands
.get(strCmd.toLowerCase());
String errorMessage = null;
if (ssiCommand == null) {
errorMessage = "Unknown command: " + strCmd;
} else if (paramValues == null) {
errorMessage = "Error parsing directive parameters.";
} else if (paramNames.length != paramValues.length) {
errorMessage = "Parameter names count does not match parameter values count on command: "
+ strCmd;
} else {
// don't process the command if we are processing
// conditional
// commands only and the
// command is not conditional
if (!ssiMediator.getConditionalState().processConditionalCommandsOnly
|| ssiCommand instanceof SSIConditional) {
long lmd = ssiCommand.process(ssiMediator, strCmd,
paramNames, paramValues, writer);
if (lmd > lastModifiedDate) {
lastModifiedDate = lmd;
}
}
}
if (errorMessage != null) {
ssiExternalResolver.log(errorMessage, null);
writer.write(configErrMsg);
}
} else {
command.append(c);
index++;
}
}
}
} catch (SSIStopProcessingException e) {
//If we are here, then we have already stopped processing, so all
// is good
}
return lastModifiedDate;
|
|