All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.fortuna.ical4j.model.ParameterCodec Maven / Gradle / Ivy

package net.fortuna.ical4j.model;

import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.EncoderException;
import org.apache.commons.codec.StringDecoder;
import org.apache.commons.codec.StringEncoder;

import java.util.regex.Pattern;

/**
 * Support for encoding/decoding property values that include quotes, newlines, and escape characters.
 */
public class ParameterCodec implements StringEncoder, StringDecoder {

    public static final ParameterCodec INSTANCE = new ParameterCodec();

    private static final String ENCODED_CARET = "^^";

    private static final String ENCODED_NEWLINE = "^n";

    private static final String ENCODED_QUOTE = "^'";


    // matches an unencoded caret character..
    private static final Pattern CARET_EX = Pattern.compile("\\^");

    // matches an unencoded newline character..
    private static final Pattern NEWLINE_EX = Pattern.compile("\n");

    // matches an unencoded quote character..
    private static final Pattern QUOTE_EX = Pattern.compile("\"");

    // matches an encoded caret character..
    private static final Pattern ENCODED_CARET_EX = Pattern.compile(
            ENCODED_CARET.replaceAll("\\^", "\\\\^"));

    // matches an encoded newline character..
    private static final Pattern ENCODED_NEWLINE_EX = Pattern.compile(
            ENCODED_NEWLINE.replaceAll("\\^", "\\\\^"));

    // matches an encoded quote character..
    private static final Pattern ENCODED_QUOTE_EX = Pattern.compile(
            ENCODED_QUOTE.replaceAll("\\^", "\\\\^"));

    // matches one or more characters that require a quoted value..
    public static final Pattern QUOTABLE_VALUE_EX = Pattern.compile("[:;,]|[^\\p{ASCII}]");

    // matches a quoted string..
    public static final Pattern QUOTED_EX = Pattern.compile("^\"[^\"]*\"$");


    @Override
    public String decode(String source) throws DecoderException {
        if (source != null) {
            var decoded = ENCODED_CARET_EX.matcher(
                    ENCODED_NEWLINE_EX.matcher(
                            ENCODED_QUOTE_EX.matcher(source).replaceAll("\"")
                    ).replaceAll("\n")
            ).replaceAll("^");

            // remove extraneous quotes..
            if (QUOTED_EX.matcher(decoded).matches()) {
                return decoded.substring(1, decoded.length() - 1);
            } else {
                return decoded;
            }
        } else {
            throw new DecoderException("Input cannot be null");
        }
    }

    @Override
    public Object decode(Object source) throws DecoderException {
        if (source != null) {
            return decode(source.toString());
        } else {
            throw new DecoderException("Input cannot be null");
        }
    }

    @Override
    public String encode(String source) throws EncoderException {
        if (source != null) {
            // order is significant here as we don't want to double-encode carets..
            var encoded = QUOTE_EX.matcher(
                    NEWLINE_EX.matcher(
                            CARET_EX.matcher(source).replaceAll(ENCODED_CARET)
                    ).replaceAll(ENCODED_NEWLINE)
            ).replaceAll(ENCODED_QUOTE);

            // apply quotes if value includes special characters..
            if (QUOTABLE_VALUE_EX.matcher(encoded).find()) {
                return "\"" + encoded + "\"";
            } else {
                return encoded;
            }
        } else {
            throw new EncoderException("Input cannot be null");
        }
    }

    @Override
    public Object encode(Object source) throws EncoderException {
        if (source != null) {
            return encode(source.toString());
        } else {
            throw new EncoderException("Input cannot be null");
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy