/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.ssi;


import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Locale;
import java.util.StringTokenizer;

import org.apache.catalina.util.IOTools;
/**
 * The entry point to SSI processing. This class does the actual parsing,
 * delegating to the SSIMediator, SSICommand, and SSIExternalResolver as
 * necessary[
 *
 * @author Dan Sandberg
 * @author David Becker
 */
public class SSIProcessor {
    /** The start pattern */
    protected static final String COMMAND_START = "<!--#";
    /** The end pattern */
    protected static final String COMMAND_END = "-->";
    protected final SSIExternalResolver ssiExternalResolver;
    protected final HashMap<String,SSICommand> commands = new HashMap<>();
    protected final int debug;
    protected final boolean allowExec;


    public SSIProcessor(SSIExternalResolver ssiExternalResolver, int debug,
            boolean allowExec) {
        this.ssiExternalResolver = ssiExternalResolver;
        this.debug = debug;
        this.allowExec = allowExec;
        addBuiltinCommands();
    }


    protected void addBuiltinCommands() {
        addCommand("config", new SSIConfig());
        addCommand("echo", new SSIEcho());
        if (allowExec) {
            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(String name, SSICommand command) {
        commands.put(name, command);
    }


    /**
     * 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.
     *
     * @param reader
     *            the reader to read the file containing SSIs from
     * @param writer
     *            the writer to write the file with the SSIs processed.
     * @return the most current modified date resulting from any SSI commands
     * @throws IOException
     *             when things go horribly awry. Should be unlikely since the
     *             SSICommand usually catches 'normal' IOExceptions.
     */
    public long process(Reader reader, long lastModifiedDate,
            PrintWriter writer) throws IOException {
        SSIMediator ssiMediator = new SSIMediator(ssiExternalResolver,
                lastModifiedDate);
        StringWriter stringWriter = new StringWriter();
        IOTools.flow(reader, stringWriter);
        String fileContents = stringWriter.toString();
        stringWriter = null;
        int index = 0;
        boolean inside = false;
        StringBuilder command = new StringBuilder();
        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 =
                            commands.get(strCmd.toLowerCase(Locale.ENGLISH));
                        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;
    }


    /**
     * Parse a StringBuilder and take out the param type token. Called from
     * <code>requestHandler</code>
     *
     * @param cmd
     *            a value of type 'StringBuilder'
     * @return a value of type 'String[]'
     */
    protected String[] parseParamNames(StringBuilder cmd, int start) {
        int bIdx = start;
        int i = 0;
        int quotes = 0;
        boolean inside = false;
        StringBuilder retBuf = new StringBuilder();
        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;
                        continue;
                    }
                    if (c == '"' && !escaped) quotes++;
                    escaped = false;
                }
            }
        }
        StringTokenizer str = new StringTokenizer(retBuf.toString(), "=");
        String[] retString = new String[str.countTokens()];
        while (str.hasMoreTokens()) {
            retString[i++] = str.nextToken().trim();
        }
        return retString;
    }


    /**
     * Parse a StringBuilder and take out the param token. Called from
     * <code>requestHandler</code>
     *
     * @param cmd
     *            a value of type 'StringBuilder'
     * @return a value of type 'String[]'
     */
    protected String[] parseParamValues(StringBuilder cmd, int start, int count) {
        int valIndex = 0;
        boolean inside = false;
        String[] vals = new String[count];
        StringBuilder sb = new StringBuilder();
        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;
    }


    /**
     * Parse a StringBuilder and take out the command token. Called from
     * <code>requestHandler</code>
     *
     * @param cmd
     *            a value of type 'StringBuilder'
     * @return a value of type 'String', or null if there is none
     */
    private String parseCmd(StringBuilder cmd) {
        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;
            }
        }
        if (firstLetter == -1) {
            return "";
        } else {
            return cmd.substring(firstLetter, lastLetter + 1);
        }
    }


    protected boolean charCmp(String buf, int index, String command) {
        return buf.regionMatches(index, command, 0, command.length());
    }


    protected boolean isSpace(char c) {
        return c == ' ' || c == '\n' || c == '\t' || c == '\r';
    }

    protected boolean isQuote(char c) {
        return c == '\'' || c == '\"' || c == '`';
    }
}