Exemple #1
0
static const char *ReferenceEnd(const char *str, size_t len)
{
    assert(len > 1);
    assert(str[0] == '$');
    assert(str[1] == '{' || str[1] == '(');

#define MAX_VARIABLE_REFERENCE_LEVELS 10
    char stack[MAX_VARIABLE_REFERENCE_LEVELS] = { 0, str[1], 0 };
    int level = 1;

    for (size_t i = 2; i < len; i++)
    {
        switch (str[i])
        {
        case '{':
        case '(':
            if (level < MAX_VARIABLE_REFERENCE_LEVELS - 1)
            {
                level++;
                stack[level] = str[i];
            }
            else
            {
                Log(LOG_LEVEL_ERR, "Stack overflow in variable reference parsing. More than %d levels", MAX_VARIABLE_REFERENCE_LEVELS);
                return NULL;
            }
            break;

        case '}':
            if (stack[level] != '{')
            {
                Writer *w = StringWriter();
                WriterWriteLen(w, str, len);
                Log(LOG_LEVEL_ERR, "Variable reference bracket mismatch '%s'", StringWriterData(w));
                WriterClose(w);
                return NULL;
            }
            level--;
            break;
        case ')':
            if (stack[level] != '(')
            {
                Writer *w = StringWriter();
                WriterWriteLen(w, str, len);
                Log(LOG_LEVEL_ERR, "Variable reference bracket mismatch '%s'", StringWriterData(w));
                WriterClose(w);
                return NULL;
            }
            level--;
            break;
        }

        if (level == 0)
        {
            return str + i;
        }
    }

    return NULL;
}
Exemple #2
0
bool ExtractScalarReference(Buffer *out, const char *str, size_t len, bool extract_inner)
{
    if (len <= 1)
    {
        return false;
    }

    const char *dollar_point = memchr(str, '$', len);
    if (!dollar_point || (dollar_point - str) == len)
    {
        return false;
    }
    else
    {
        const char *close_point = NULL;
        {
            size_t remaining = len - (dollar_point - str);
            if (*(dollar_point + 1) == '{' || *(dollar_point + 1) == '(')
            {
                close_point = ReferenceEnd(dollar_point, remaining);
            }
            else
            {
                return ExtractScalarReference(out, dollar_point + 1, remaining - 1, extract_inner);
            }
        }

        if (!close_point)
        {
            Writer *w = StringWriter();
            WriterWriteLen(w, str, len);
            Log(LOG_LEVEL_ERR, "Variable reference close mismatch '%s'", StringWriterData(w));
            WriterClose(w);
            return false;
        }

        size_t outer_len = close_point - dollar_point + 1;
        if (outer_len <= 3)
        {
            Writer *w = StringWriter();
            WriterWriteLen(w, str, len);
            Log(LOG_LEVEL_ERR, "Empty variable reference close mismatch '%s'", StringWriterData(w));
            WriterClose(w);
            return false;
        }

        if (extract_inner)
        {
            BufferAppend(out, dollar_point + 2, outer_len - 3);
        }
        else
        {
            BufferAppend(out, dollar_point, outer_len);
        }
        return true;
    }
}
Exemple #3
0
char *SearchAndReplace(const char *source, const char *search, const char *replace)
{
    const char *source_ptr = source;

    if ((source == NULL) || (search == NULL) || (replace == NULL))
    {
        ProgrammingError("Programming error: NULL argument is passed to SearchAndReplace");
    }

    if (strcmp(search, "") == 0)
    {
        return xstrdup(source);
    }

    Writer *w = StringWriter();

    for (;;)
    {
        const char *found_ptr = strstr(source_ptr, search);

        if (found_ptr == NULL)
        {
            WriterWrite(w, source_ptr);
            return StringWriterClose(w);
        }

        WriterWriteLen(w, source_ptr, found_ptr - source_ptr);
        WriterWrite(w, replace);

        source_ptr += found_ptr - source_ptr + strlen(search);
    }
}
Exemple #4
0
Writer *FileReadFromFd(int fd, size_t max_size, bool *truncated)
{
    if (truncated)
    {
        *truncated = false;
    }

    Writer *w = StringWriter();
    for (;;)
    {
        char buf[READ_BUFSIZE];
        /* Reading more data than needed is deliberate. It is a truncation detection. */
        ssize_t read_ = read(fd, buf, READ_BUFSIZE);

        if (read_ == 0)
        {
            /* Done. */
            return w;
        }
        else if (read_ < 0)
        {
            if (errno != EINTR)
            {
                /* Something went wrong. */
                WriterClose(w);
                return NULL;
            }
            /* Else: interrupted - try again. */
        }
        else if (read_ + StringWriterLength(w) > max_size)
        {
            WriterWriteLen(w, buf, max_size - StringWriterLength(w));
            /* Reached limit - stop. */
            if (truncated)
            {
                *truncated = true;
            }
            return w;
        }
        else /* Filled buffer; copy and ask for more. */
        {
            WriterWriteLen(w, buf, read_);
        }
    }
}
Exemple #5
0
Writer *FileRead(const char *filename, size_t max_size, bool *truncated)
{
    int fd = open(filename, O_RDONLY);
    if (fd == -1)
        return NULL;

    Writer *w = StringWriter();
    for (;;)
    {
        char buf[READ_BUFSIZE];
        /* Reading more data than needed is deliberate. It is a truncation detection. */
        ssize_t read_ = read(fd, buf, READ_BUFSIZE);
        if (read_ == 0)
        {
            if (truncated)
                *truncated = false;
            close(fd);
            return w;
        }
        if (read_ < 0)
        {
            if (errno == EINTR)
                continue;
            WriterClose(w);
            close(fd);
            return NULL;
        }
        if (read_ + StringWriterLength(w) > max_size)
        {
            WriterWriteLen(w, buf, max_size - StringWriterLength(w));
            if (truncated)
                *truncated = true;
            close(fd);
            return w;
        }
        WriterWriteLen(w, buf, read_);
    }
}
Exemple #6
0
static void RenderContent(Writer *out, const char *content, size_t len, bool html, bool skip_content)
{
    if (skip_content)
    {
        return;
    }

    if (html)
    {
        RenderHTMLContent(out, content, len);
    }
    else
    {
        WriterWriteLen(out, content, len);
    }
}
Exemple #7
0
size_t WriterWrite(Writer *writer, const char *str)
{
    return WriterWriteLen(writer, str, INT_MAX);
}