NginxConfigParser icon indicating copy to clipboard operation
NginxConfigParser copied to clipboard

[Major] A semicolon enclosed in quotes is treated as the end of a line.

Open Flithor opened this issue 10 months ago • 3 comments

Original:

    add_header X-Xss-Protection "1;mode=block";

Saves:

    add_header X-Xss-Protection "1;

Flithor avatar Feb 25 '25 04:02 Flithor

@jxnkwlp here I fixed for: https://github.com/jxnkwlp/NginxConfigParser/blob/56a7e6c292818d27000095a77a123c911573da18/NginxConfigParser/Parser.cs#L49

private void ParseLine(string text, int lineIndex)
{
    if (text.Length == 0)
    {
        return;
    }
    // comment row
    if (text[0] == '#')
    {
        var commentToken = new CommentToken(text.Trim().TrimStart('#').Trim());
        AddToken(commentToken);
        return;
    }
    // group ending
    if (text[0] == '}')
    {
        _currentGroupToken = _currentGroupToken?.Parent;

        _currentToken = null;

        return;
    }

    var key = string.Empty;
    var value = string.Empty;
    var comment = string.Empty;
    int keyEndSymbol = -1, groupStartSymbol = -1, commendSymbol = -1, endSymbol = -1;
    bool matchKey = false,
         matchValue = false,
         matchEnd = false,
         isBetweenSingleQuote = false,
         isBetweenDoubleQuote = false;
    for (var i = 0; i < text.Length; i++)
    {
        switch (text[i])
        {
            // match single quote
            case '\'':
                isBetweenSingleQuote = !isBetweenSingleQuote;
                break;
            // continue if in single quote
            case not '\'' when isBetweenSingleQuote:
                break;
            // match double quote
            case '"':
                isBetweenDoubleQuote = !isBetweenDoubleQuote;
                break;
            // continue if in double quote
            case not '"' when isBetweenDoubleQuote:
                break;
            // match the token ending
            case ';':
                endSymbol = i;
                value = text.Substring(keyEndSymbol + 1, endSymbol - keyEndSymbol - 1).Trim();
                matchEnd = true;
                matchValue = true;
                break;
            // match the group beginning
            case '{':
                groupStartSymbol = i;
                value = text.Substring(keyEndSymbol + 1, groupStartSymbol - keyEndSymbol - 1).Trim();
                matchValue = true;
                break;
            // won't match group ending here
            // match comment beginning
            case '#':
                commendSymbol = i;
                comment = text.Substring(commendSymbol).Trim().TrimStart('#').Trim();
                goto CommentBreakCheck;
            // match the first space to match token key
            case ' ' when !matchKey:
                keyEndSymbol = i;
                matchKey = true;
                key = text.Substring(0, keyEndSymbol).Trim();
                break;
        }
    }

    CommentBreakCheck:
    // WARNING: Here you need to consider whether to support cross-line quote mark pairs
    if (isBetweenSingleQuote || isBetweenDoubleQuote)
        throw new Exception($"Unpaired quote detected at line {lineIndex+1}!");
    if (groupStartSymbol > -1)
    {
        var groupToken = new GroupToken(_currentGroupToken, key, value, comment);
        AddToken(groupToken);
        _currentGroupToken = groupToken;
        return;
    }

    if (groupStartSymbol == -1 && endSymbol == -1)
    {
        _currentToken = new ValueToken(_currentGroupToken, key, value, comment);
        return;
    }

    if (endSymbol > -1)
    {
        AddToken(new ValueToken(_currentGroupToken, key, value?.Trim(), comment));
        return;
    }

    throw new Exception("Some thing wrong");
}

Flithor avatar Feb 26 '25 00:02 Flithor

Thanks. Can you create an pull request ?

jxnkwlp avatar Feb 26 '25 03:02 jxnkwlp

@jxnkwlp No, I don't have time to write a full test case.

Flithor avatar Feb 26 '25 11:02 Flithor