summaryrefslogtreecommitdiffstats
path: root/crypto/bio
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2019-11-27 16:02:33 +0100
committerRichard Levitte <levitte@openssl.org>2019-12-18 19:42:44 +0100
commit319cee9e2fc6fcf6ad865564eccdac4c55e92c0a (patch)
treeca3093a9ec029fc743fad64821e402904f0576f6 /crypto/bio
parenta0848daee50b30f441813ecc90042c6af14c62aa (diff)
BIO: Add BIO_f_prefix(), a text line prefixing filter
Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10531)
Diffstat (limited to 'crypto/bio')
-rw-r--r--crypto/bio/bf_prefix.c207
-rw-r--r--crypto/bio/build.info2
2 files changed, 208 insertions, 1 deletions
diff --git a/crypto/bio/bf_prefix.c b/crypto/bio/bf_prefix.c
new file mode 100644
index 0000000000..5727c14950
--- /dev/null
+++ b/crypto/bio/bf_prefix.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2018-2019 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
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "bio_local.h"
+
+static int prefix_write(BIO *b, const char *out, size_t outl,
+ size_t *numwritten);
+static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread);
+static int prefix_puts(BIO *b, const char *str);
+static int prefix_gets(BIO *b, char *str, int size);
+static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2);
+static int prefix_create(BIO *b);
+static int prefix_destroy(BIO *b);
+static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
+
+static const BIO_METHOD prefix_meth = {
+ BIO_TYPE_BUFFER,
+ "prefix",
+ prefix_write,
+ NULL,
+ prefix_read,
+ NULL,
+ prefix_puts,
+ prefix_gets,
+ prefix_ctrl,
+ prefix_create,
+ prefix_destroy,
+ prefix_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_f_prefix(void)
+{
+ return &prefix_meth;
+}
+
+typedef struct prefix_ctx_st {
+ char *prefix; /* Text prefix, given by user */
+ unsigned int indent; /* Indentation amount, given by user */
+
+ int linestart; /* flag to indicate we're at the line start */
+} PREFIX_CTX;
+
+static int prefix_create(BIO *b)
+{
+ PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
+
+ if (ctx == NULL)
+ return 0;
+
+ ctx->prefix = NULL;
+ ctx->indent = 0;
+ ctx->linestart = 1;
+ BIO_set_data(b, ctx);
+ BIO_set_init(b, 1);
+ return 1;
+}
+
+static int prefix_destroy(BIO *b)
+{
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ OPENSSL_free(ctx->prefix);
+ OPENSSL_free(ctx);
+ return 1;
+}
+
+static int prefix_read(BIO *b, char *in, size_t size, size_t *numread)
+{
+ return BIO_read_ex(BIO_next(b), in, size, numread);
+}
+
+static int prefix_write(BIO *b, const char *out, size_t outl,
+ size_t *numwritten)
+{
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ if (ctx == NULL)
+ return 0;
+
+ /*
+ * If no prefix is set or if it's empty, and no indentation amount is set,
+ * we've got nothing to do here
+ */
+ if ((ctx->prefix == NULL || *ctx->prefix == '\0')
+ && ctx->indent == 0) {
+ /*
+ * We do note if what comes next will be a new line, though, so we're
+ * prepared to handle prefix and indentation the next time around.
+ */
+ if (outl > 0)
+ ctx->linestart = (out[outl-1] == '\n');
+ return BIO_write_ex(BIO_next(b), out, outl, numwritten);
+ }
+
+ *numwritten = 0;
+
+ while (outl > 0) {
+ size_t i;
+ char c;
+
+ /*
+ * If we know that we're at the start of the line, output prefix and
+ * indentation.
+ */
+ if (ctx->linestart) {
+ size_t dontcare;
+
+ if (ctx->prefix != NULL
+ && !BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix),
+ &dontcare))
+ return 0;
+ BIO_printf(BIO_next(b), "%*s", ctx->indent, "");
+ ctx->linestart = 0;
+ }
+
+ /* Now, go look for the next LF, or the end of the string */
+ for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++)
+ continue;
+ if (c == '\n')
+ i++;
+
+ /* Output what we found so far */
+ while (i > 0) {
+ size_t num = 0;
+
+ if (!BIO_write_ex(BIO_next(b), out, i, &num))
+ return 0;
+ out += num;
+ outl -= num;
+ *numwritten += num;
+ i -= num;
+ }
+
+ /* If we found a LF, what follows is a new line, so take note */
+ if (c == '\n')
+ ctx->linestart = 1;
+ }
+
+ return 1;
+}
+
+static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr)
+{
+ long ret = 0;
+ PREFIX_CTX *ctx = BIO_get_data(b);
+
+ if (ctx == NULL)
+ return -1;
+
+ switch (cmd) {
+ case BIO_CTRL_SET_PREFIX:
+ OPENSSL_free(ctx->prefix);
+ if (ptr == NULL) {
+ ctx->prefix = NULL;
+ ret = 1;
+ } else {
+ ctx->prefix = OPENSSL_strdup((const char *)ptr);
+ ret = ctx->prefix != NULL;
+ }
+ break;
+ case BIO_CTRL_SET_INDENT:
+ if (num >= 0) {
+ ctx->indent = (unsigned int)num;
+ ret = 1;
+ }
+ break;
+ case BIO_CTRL_GET_INDENT:
+ ret = (long)ctx->indent;
+ break;
+ default:
+ /* Commands that we intercept before passing them along */
+ switch (cmd) {
+ case BIO_C_FILE_SEEK:
+ case BIO_CTRL_RESET:
+ ctx->linestart = 1;
+ break;
+ }
+ if (BIO_next(b) != NULL)
+ ret = BIO_ctrl(BIO_next(b), cmd, num, ptr);
+ break;
+ }
+ return ret;
+}
+
+static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
+{
+ return BIO_callback_ctrl(BIO_next(b), cmd, fp);
+}
+
+static int prefix_gets(BIO *b, char *buf, int size)
+{
+ return BIO_gets(BIO_next(b), buf, size);
+}
+
+static int prefix_puts(BIO *b, const char *str)
+{
+ return BIO_write(b, str, strlen(str));
+}
diff --git a/crypto/bio/build.info b/crypto/bio/build.info
index 3f84bb824c..8e3f530f88 100644
--- a/crypto/bio/build.info
+++ b/crypto/bio/build.info
@@ -15,4 +15,4 @@ SOURCE[../../libcrypto]=\
# Filters
SOURCE[../../libcrypto]=\
- bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c
+ bf_null.c bf_buff.c bf_lbuf.c bf_nbio.c bf_prefix.c