/*
 * Copyright 2021 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

/*
 * This is a read only BIO filter that can be used to add BIO_tell() and
 * BIO_seek() support to source/sink BIO's (such as a file BIO that uses stdin).
 * It does this by caching ALL data read from the BIO source/sink into a
 * resizable memory buffer.
 */

#include <stdio.h>
#include <errno.h>
#include "bio_local.h"
#include "internal/cryptlib.h"

#define DEFAULT_BUFFER_SIZE     4096

static int readbuffer_write(BIO *h, const char *buf, int num);
static int readbuffer_read(BIO *h, char *buf, int size);
static int readbuffer_puts(BIO *h, const char *str);
static int readbuffer_gets(BIO *h, char *str, int size);
static long readbuffer_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int readbuffer_new(BIO *h);
static int readbuffer_free(BIO *data);
static long readbuffer_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp);

static const BIO_METHOD methods_readbuffer = {
    BIO_TYPE_BUFFER,
    "readbuffer",
    bwrite_conv,
    readbuffer_write,
    bread_conv,
    readbuffer_read,
    readbuffer_puts,
    readbuffer_gets,
    readbuffer_ctrl,
    readbuffer_new,
    readbuffer_free,
    readbuffer_callback_ctrl,
};

const BIO_METHOD *BIO_f_readbuffer(void)
{
    return &methods_readbuffer;
}

static int readbuffer_new(BIO *bi)
{
    BIO_F_BUFFER_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));

    if (ctx == NULL)
        return 0;
    ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
    ctx->ibuf = OPENSSL_zalloc(DEFAULT_BUFFER_SIZE);
    if (ctx->ibuf == NULL) {
        OPENSSL_free(ctx);
        return 0;
    }

    bi->init = 1;
    bi->ptr = (char *)ctx;
    bi->flags = 0;
    return 1;
}

static int readbuffer_free(BIO *a)
{
    BIO_F_BUFFER_CTX *b;

    if (a == NULL)
        return 0;
    b = (BIO_F_BUFFER_CTX *)a->ptr;
    OPENSSL_free(b->ibuf);
    OPENSSL_free(a->ptr);
    a->ptr = NULL;
    a->init = 0;
    a->flags = 0;
    return 1;
}

static int readbuffer_resize(BIO_F_BUFFER_CTX *ctx, int sz)
{
    char *tmp;

    /* Figure out how many blocks are required */
    sz += (ctx->ibuf_off + DEFAULT_BUFFER_SIZE - 1);
    sz = DEFAULT_BUFFER_SIZE * (sz / DEFAULT_BUFFER_SIZE);

    /* Resize if the buffer is not big enough */
    if (sz > ctx->ibuf_size) {
        tmp = OPENSSL_realloc(ctx->ibuf, sz);
        if (tmp == NULL)
            return 0;
        ctx->ibuf = tmp;
        ctx->ibuf_size = sz;
    }
    return 1;
}

static int readbuffer_read(BIO *b, char *out, int outl)
{
    int i, num = 0;
    BIO_F_BUFFER_CTX *ctx;

    if (out == NULL || outl == 0)
        return 0;
    ctx = (BIO_F_BUFFER_CTX *)b->ptr;

    if ((ctx == NULL) || (b->next_bio == NULL))
        return 0;
    BIO_clear_retry_flags(b);

    for (;;) {
        i = ctx->ibuf_len;
        /* If there is something in the buffer just read it. */
        if (i != 0) {
            if (i > outl)
                i = outl;
            memcpy(out, &(ctx->ibuf[ctx->ibuf_off]), i);
            ctx->ibuf_off += i;
            ctx->ibuf_len -= i;
            num += i;
            /* Exit if we have read the bytes required out of the buffer */
            if (outl == i)
                return num;
            outl -= i;
            out += i;
        }

        /* Only gets here if the buffer has been consumed */
        if (!readbuffer_resize(ctx, outl))
            return 0;

        /* Do some buffering by reading from the next bio */
        i = BIO_read(b->next_bio, ctx->ibuf + ctx->ibuf_off, outl);
        if (i <= 0) {
            BIO_copy_next_retry(b);
            if (i < 0)
                return ((num > 0) ? num : i);
            else
                return num; /* i == 0 */
        }
        ctx->ibuf_len = i;
    }
}

static int readbuffer_write(BIO *b, const char *in, int inl)
{
    return 0;
}
static int readbuffer_puts(BIO *b, const char *str)
{
    return 0;
}

static long readbuffer_ctrl(BIO *b, int cmd, long num, void *ptr)
{
    BIO_F_BUFFER_CTX *ctx;
    long ret = 1, sz;

    ctx = (BIO_F_BUFFER_CTX *)b->ptr;

    switch (cmd) {
    case BIO_CTRL_EOF:
        if (ctx->ibuf_len > 0)
            return 0;
        if (b->next_bio == NULL)
            return 1;
        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        break;

    case BIO_C_FILE_SEEK:
    case BIO_CTRL_RESET:
        sz = ctx->ibuf_off + ctx->ibuf_len;
        /* Assume it can only seek backwards */
        if (num < 0 || num > sz)
            return 0;
        ctx->ibuf_off = num;
        ctx->ibuf_len = sz - num;
        break;

    case BIO_C_FILE_TELL:
    case BIO_CTRL_INFO:
        ret = (long)ctx->ibuf_off;
        break;
    case BIO_CTRL_PENDING:
        ret = (long)ctx->ibuf_len;
        if (ret == 0) {
            if (b->next_bio == NULL)
                return 0;
            ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
        }
        break;
    case BIO_CTRL_DUP:
    case BIO_CTRL_FLUSH:
        ret = 1;
        break;
    default:
        ret = 0;
        break;
    }
    return ret;
}

static long readbuffer_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
{
    if (b->next_bio == NULL)
        return 0;
    return BIO_callback_ctrl(b->next_bio, cmd, fp);
}

static int readbuffer_gets(BIO *b, char *buf, int size)
{
    BIO_F_BUFFER_CTX *ctx;
    int num = 0, num_chars, found_newline;
    char *p;
    int i, j;

    if (size == 0)
        return 0;
    --size; /* the passed in size includes the terminator - so remove it here */
    ctx = (BIO_F_BUFFER_CTX *)b->ptr;
    BIO_clear_retry_flags(b);

    /* If data is already buffered then use this first */
    if (ctx->ibuf_len > 0) {
        p = ctx->ibuf + ctx->ibuf_off;
        found_newline = 0;
        for (num_chars = 0;
             (num_chars < ctx->ibuf_len) && (num_chars < size);
             num_chars++) {
            *buf++ = p[num_chars];
            if (p[num_chars] == '\n') {
                found_newline = 1;
                num_chars++;
                break;
            }
        }
        num += num_chars;
        size -= num_chars;
        ctx->ibuf_len -= num_chars;
        ctx->ibuf_off += num_chars;
        if (found_newline || size == 0) {
            *buf = '\0';
            return num;
        }
    }
    /*
     * If there is no buffered data left then read any remaining data from the
     * next bio.
     */

     /* Resize if we have to */
     if (!readbuffer_resize(ctx, 1 + size))
         return 0;
     /*
      * Read more data from the next bio using BIO_read_ex:
      * Note we cannot use BIO_gets() here as it does not work on a
      * binary stream that contains 0x00. (Since strlen() will stop at
      * any 0x00 not at the last read '\n' in a FILE bio).
      * Also note that some applications open and close the file bio
      * multiple times and need to read the next available block when using
      * stdin - so we need to READ one byte at a time!
      */
     p = ctx->ibuf + ctx->ibuf_off;
     for (i = 0; i < size; ++i) {
         j = BIO_read(b->next_bio, p, 1);
         if (j <= 0) {
             BIO_copy_next_retry(b);
             *buf = '\0';
             return num > 0 ? num : j;
         }
         *buf++ = *p;
         num++;
         ctx->ibuf_off++;
         if (*p == '\n')
             break;
         ++p;
     }
     *buf = '\0';
     return num;
}
