1 11 package org.apache.catalina.ssi; 12 13 14 import java.io.IOException ; 15 import java.io.PrintWriter ; 16 import java.io.Reader ; 17 import java.io.StringWriter ; 18 import java.util.HashMap ; 19 import java.util.StringTokenizer ; 20 import org.apache.catalina.util.IOTools; 21 30 public class SSIProcessor { 31 32 protected final static String COMMAND_START = "<!--#"; 33 34 protected final static String COMMAND_END = "-->"; 35 protected final static int BUFFER_SIZE = 4096; 36 protected SSIExternalResolver ssiExternalResolver; 37 protected HashMap commands = new HashMap (); 38 protected int debug; 39 40 41 public SSIProcessor(SSIExternalResolver ssiExternalResolver, int debug) { 42 this.ssiExternalResolver = ssiExternalResolver; 43 this.debug = debug; 44 addBuiltinCommands(); 45 } 46 47 48 protected void addBuiltinCommands() { 49 addCommand("config", new SSIConfig()); 50 addCommand("echo", new SSIEcho()); 51 addCommand("exec", new SSIExec()); 52 addCommand("include", new SSIInclude()); 53 addCommand("flastmod", new SSIFlastmod()); 54 addCommand("fsize", new SSIFsize()); 55 addCommand("printenv", new SSIPrintenv()); 56 addCommand("set", new SSISet()); 57 SSIConditional ssiConditional = new SSIConditional(); 58 addCommand("if", ssiConditional); 59 addCommand("elif", ssiConditional); 60 addCommand("endif", ssiConditional); 61 addCommand("else", ssiConditional); 62 } 63 64 65 public void addCommand(String name, SSICommand command) { 66 commands.put(name, command); 67 } 68 69 70 84 public long process(Reader reader, long lastModifiedDate, 85 PrintWriter writer) throws IOException { 86 SSIMediator ssiMediator = new SSIMediator(ssiExternalResolver, 87 lastModifiedDate, debug); 88 StringWriter stringWriter = new StringWriter (); 89 IOTools.flow(reader, stringWriter); 90 String fileContents = stringWriter.toString(); 91 stringWriter = null; 92 int index = 0; 93 boolean inside = false; 94 StringBuffer command = new StringBuffer (); 95 try { 96 while (index < fileContents.length()) { 97 char c = fileContents.charAt(index); 98 if (!inside) { 99 if (c == COMMAND_START.charAt(0) 100 && charCmp(fileContents, index, COMMAND_START)) { 101 inside = true; 102 index += COMMAND_START.length(); 103 command.setLength(0); } else { 105 if (!ssiMediator.getConditionalState().processConditionalCommandsOnly) { 106 writer.write(c); 107 } 108 index++; 109 } 110 } else { 111 if (c == COMMAND_END.charAt(0) 112 && charCmp(fileContents, index, COMMAND_END)) { 113 inside = false; 114 index += COMMAND_END.length(); 115 String strCmd = parseCmd(command); 116 if (debug > 0) { 117 ssiExternalResolver.log( 118 "SSIProcessor.process -- processing command: " 119 + strCmd, null); 120 } 121 String [] paramNames = parseParamNames(command, strCmd 122 .length()); 123 String [] paramValues = parseParamValues(command, 124 strCmd.length(), paramNames.length); 125 String configErrMsg = ssiMediator.getConfigErrMsg(); 129 SSICommand ssiCommand = (SSICommand)commands 130 .get(strCmd.toLowerCase()); 131 String errorMessage = null; 132 if (ssiCommand == null) { 133 errorMessage = "Unknown command: " + strCmd; 134 } else if (paramValues == null) { 135 errorMessage = "Error parsing directive parameters."; 136 } else if (paramNames.length != paramValues.length) { 137 errorMessage = "Parameter names count does not match parameter values count on command: " 138 + strCmd; 139 } else { 140 if (!ssiMediator.getConditionalState().processConditionalCommandsOnly 145 || ssiCommand instanceof SSIConditional) { 146 long lmd = ssiCommand.process(ssiMediator, strCmd, 147 paramNames, paramValues, writer); 148 if (lmd > lastModifiedDate) { 149 lastModifiedDate = lmd; 150 } 151 } 152 } 153 if (errorMessage != null) { 154 ssiExternalResolver.log(errorMessage, null); 155 writer.write(configErrMsg); 156 } 157 } else { 158 command.append(c); 159 index++; 160 } 161 } 162 } 163 } catch (SSIStopProcessingException e) { 164 } 167 return lastModifiedDate; 168 } 169 170 171 179 protected String [] parseParamNames(StringBuffer cmd, int start) { 180 int bIdx = start; 181 int i = 0; 182 int quotes = 0; 183 boolean inside = false; 184 StringBuffer retBuf = new StringBuffer (); 185 while (bIdx < cmd.length()) { 186 if (!inside) { 187 while (bIdx < cmd.length() && isSpace(cmd.charAt(bIdx))) 188 bIdx++; 189 if (bIdx >= cmd.length()) break; 190 inside = !inside; 191 } else { 192 while (bIdx < cmd.length() && cmd.charAt(bIdx) != '=') { 193 retBuf.append(cmd.charAt(bIdx)); 194 bIdx++; 195 } 196 retBuf.append('='); 197 inside = !inside; 198 quotes = 0; 199 boolean escaped = false; 200 for (; bIdx < cmd.length() && quotes != 2; bIdx++) { 201 char c = cmd.charAt(bIdx); 202 if (c == '\\' && !escaped) { 204 escaped = true; 205 bIdx++; 206 continue; 207 } 208 escaped = false; 209 if (c == '"') quotes++; 210 } 211 } 212 } 213 StringTokenizer str = new StringTokenizer (retBuf.toString(), "="); 214 String [] retString = new String [str.countTokens()]; 215 while (str.hasMoreTokens()) { 216 retString[i++] = str.nextToken().trim(); 217 } 218 return retString; 219 } 220 221 222 230 protected String [] parseParamValues(StringBuffer cmd, int start, int count) { 231 int valIndex = 0; 232 boolean inside = false; 233 String [] vals = new String [count]; 234 StringBuffer sb = new StringBuffer (); 235 char endQuote = 0; 236 for (int bIdx = start; bIdx < cmd.length(); bIdx++) { 237 if (!inside) { 238 while (bIdx < cmd.length() && !isQuote(cmd.charAt(bIdx))) 239 bIdx++; 240 if (bIdx >= cmd.length()) break; 241 inside = !inside; 242 endQuote = cmd.charAt(bIdx); 243 } else { 244 boolean escaped = false; 245 for (; bIdx < cmd.length(); bIdx++) { 246 char c = cmd.charAt(bIdx); 247 if (c == '\\' && !escaped) { 249 escaped = true; 250 continue; 251 } 252 if (c == endQuote && !escaped) break; 254 if (c == '$' && escaped) sb.append('\\'); 258 escaped = false; 259 sb.append(c); 260 } 261 if (bIdx == cmd.length()) return null; 264 vals[valIndex++] = sb.toString(); 265 sb.delete(0, sb.length()); inside = !inside; 267 } 268 } 269 return vals; 270 } 271 272 273 281 private String parseCmd(StringBuffer cmd) { 282 int firstLetter = -1; 283 int lastLetter = -1; 284 for (int i = 0; i < cmd.length(); i++) { 285 char c = cmd.charAt(i); 286 if (Character.isLetter(c)) { 287 if (firstLetter == -1) { 288 firstLetter = i; 289 } 290 lastLetter = i; 291 } else if (isSpace(c)) { 292 if (lastLetter > -1) { 293 break; 294 } 295 } else { 296 break; 297 } 298 } 299 String command = null; 300 if (firstLetter != -1) { 301 command = cmd.substring(firstLetter, lastLetter + 1); 302 } 303 return command; 304 } 305 306 307 protected boolean charCmp(String buf, int index, String command) { 308 return buf.regionMatches(index, command, 0, command.length()); 309 } 310 311 312 protected boolean isSpace(char c) { 313 return c == ' ' || c == '\n' || c == '\t' || c == '\r'; 314 } 315 316 protected boolean isQuote(char c) { 317 return c == '\'' || c == '\"' || c == '`'; 318 } 319 } | Popular Tags |