<commit_before>/******************************************************************************/
/*          pfixtools: a collection of postfix related tools                  */
/*          ~~~~~~~~~                                                         */
/*  ________________________________________________________________________  */
/*                                                                            */
/*  Redistribution and use in source and binary forms, with or without        */
/*  modification, are permitted provided that the following conditions        */
/*  are met:                                                                  */
/*                                                                            */
/*  1. Redistributions of source code must retain the above copyright         */
/*     notice, this list of conditions and the following disclaimer.          */
/*  2. Redistributions in binary form must reproduce the above copyright      */
/*     notice, this list of conditions and the following disclaimer in the    */
/*     documentation and/or other materials provided with the distribution.   */
/*  3. The names of its contributors may not be used to endorse or promote    */
/*     products derived from this software without specific prior written     */
/*     permission.                                                            */
/*                                                                            */
/*  THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS   */
/*  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED         */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE    */
/*  DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY         */
/*  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        */
/*  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS   */
/*  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)     */
/*  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       */
/*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  */
/*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           */
/*  POSSIBILITY OF SUCH DAMAGE.                                               */
/*                                                                            */
/*   Copyright (c) 2006-2009 the Authors                                      */
/*   see AUTHORS and source files for details                                 */
/******************************************************************************/

/*
 * Copyright © 2005-2007 <NAME>
 * Copyright © 2008 <NAME>
 */

#include "common.h"

#include <srs2.h>

#include "mem.h"
#include "buffer.h"
#include "server.h"

#define DAEMON_NAME             "pfix-srsd"
#define DAEMON_VERSION          PFIXTOOLS_VERSION
#define DEFAULT_ENCODER_PORT    10001
#define DEFAULT_DECODER_PORT    10002
#define RUNAS_USER              "nobody"
#define RUNAS_GROUP             "nogroup"

DECLARE_MAIN

typedef struct srs_config_t {
    srs_t* srs;
    const char* domain;
    int domainlen;
    unsigned ignore_ext : 1;
    char separator;
} srs_config_t;


/* Server {{{1
 */

static listener_t *decoder_ptr = NULL;
static listener_t *encoder_ptr = NULL;

static void *srsd_starter(listener_t *server)
{
    return server;
}


/* Processing {{{1
 */

char *urldecode(char *s, char *end)
{
    char *p = s;

    while (*p) {
        if (*p == '%' && end - p >= 3) {
            int h = (hexval(p[1]) << 4) | hexval(p[2]);

            if (h >= 0) {
                *s++ = h;
                p += 3;
                continue;
            }
        }

        *s++ = *p++;
    }
    *s = '\0';
    return s;
}

int process_srs(client_t *srsd, void* vconfig)
{
    srs_config_t* config = vconfig;
    buffer_t *ibuf = client_input_buffer(srsd);
    buffer_t *obuf = client_output_buffer(srsd);
    bool decoder = (client_data(srsd) == decoder_ptr);
    int res = client_read(srsd);

    if ((res < 0 && errno != EINTR && errno != EAGAIN) || res == 0)
        return -1;

    while (ibuf->len > 4) {
        char buf[BUFSIZ], *p, *q, *nl;
        int err;

        nl = strchr(ibuf->data + 4, '\n');
        if (!nl) {
            if (ibuf->len > BUFSIZ) {
                err("unreasonnable amount of data without a \\n");
                return -1;
            }
            if (obuf->len) {
                client_io_rw(srsd);
            }
            return 0;
        }

        if (strncmp("get ", ibuf->data, 4)) {
            err("bad request, not starting with \"get \"");
            return -1;
        }

        for (p = ibuf->data + 4; p < nl && isspace(*p); p++);
        for (q = nl++; q >= p && isspace(*q); *q-- = '\0');

        if (p == q) {
            buffer_addstr(obuf, "400 empty request ???\n");
            warn("empty request");
            goto skip;
        }

        q = urldecode(p, q);

        if (decoder) {
            if (config->ignore_ext) {
                int dlen = config->domainlen;

                if (q - p <= dlen || q[-1 - dlen] != '@' ||
                    memcmp(q - dlen, config->domain, dlen))
                {
                    buffer_addstr(obuf, "200 ");
                    buffer_add(obuf, p, q - p);
                    buffer_addch(obuf, '\n');
                    goto skip;
                }
            }
            err = srs_reverse(config->srs, buf, ssizeof(buf), p);
        } else {
            err = srs_forward(config->srs, buf, ssizeof(buf), p, config->domain);
        }

        if (err == SRS_SUCCESS) {
            buffer_addstr(obuf, "200 ");
            buffer_addstr(obuf, buf);
        } else {
            switch (SRS_ERROR_TYPE(err)) {
              case SRS_ERRTYPE_CONFIG:
                buffer_addstr(obuf, "400 ");
                break;
              default:
                buffer_addstr(obuf, "500 ");
                break;
            }
            buffer_addstr(obuf, srs_strerror(err));
        }
        buffer_addch(obuf, '\n');

      skip:
        buffer_consume(ibuf, nl - ibuf->data);
    }
    if (obuf->len) {
        client_io_rw(srsd);
    }
    return 0;
}


/* config {{{1
 */

static srs_config_t config = {
    .srs = NULL,
    .domain = NULL,
    .domainlen = 0,
    .ignore_ext = false,
    .reject_err = false,
    .separator = '\0'
};

/** overload srs_free since the lib is not properly maintained.
 */
inline void srs_free(srs_t* srs)
{
    int  i;
    for (i = 0; i < srs->numsecrets; i++) {
        memset(srs->secrets[i], 0, strlen(srs->secrets[i]));
        free(srs->secrets[i]);
        srs->secrets[i] = '\0';
    }
    if (srs->secrets) {
        free(srs->secrets);
    }
    free(srs);<commit_msg>Should compile before commit.<commit_after>/******************************************************************************/
/*          pfixtools: a collection of postfix related tools                  */
/*          ~~~~~~~~~                                                         */
/*  ________________________________________________________________________  */
/*                                                                            */
/*  Redistribution and use in source and binary forms, with or without        */
/*  modification, are permitted provided that the following conditions        */
/*  are met:                                                                  */
/*                                                                            */
/*  1. Redistributions of source code must retain the above copyright         */
/*     notice, this list of conditions and the following disclaimer.          */
/*  2. Redistributions in binary form must reproduce the above copyright      */
/*     notice, this list of conditions and the following disclaimer in the    */
/*     documentation and/or other materials provided with the distribution.   */
/*  3. The names of its contributors may not be used to endorse or promote    */
/*     products derived from this software without specific prior written     */
/*     permission.                                                            */
/*                                                                            */
/*  THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS   */
/*  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED         */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE    */
/*  DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY         */
/*  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL        */
/*  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS   */
/*  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)     */
/*  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,       */
/*  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  */
/*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE           */
/*  POSSIBILITY OF SUCH DAMAGE.                                               */
/*                                                                            */
/*   Copyright (c) 2006-2009 the Authors                                      */
/*   see AUTHORS and source files for details                                 */
/******************************************************************************/

/*
 * Copyright © 2005-2007 <NAME>
 * Copyright © 2008 <NAME>
 */

#include "common.h"

#include <srs2.h>

#include "mem.h"
#include "buffer.h"
#include "server.h"

#define DAEMON_NAME             "pfix-srsd"
#define DAEMON_VERSION          PFIXTOOLS_VERSION
#define DEFAULT_ENCODER_PORT    10001
#define DEFAULT_DECODER_PORT    10002
#define RUNAS_USER              "nobody"
#define RUNAS_GROUP             "nogroup"

DECLARE_MAIN

typedef struct srs_config_t {
    srs_t* srs;
    const char* domain;
    int domainlen;
    unsigned ignore_ext : 1;
    char separator;
} srs_config_t;


/* Server {{{1
 */

static listener_t *decoder_ptr = NULL;
static listener_t *encoder_ptr = NULL;

static void *srsd_starter(listener_t *server)
{
    return server;
}


/* Processing {{{1
 */

char *urldecode(char *s, char *end)
{
    char *p = s;

    while (*p) {
        if (*p == '%' && end - p >= 3) {
            int h = (hexval(p[1]) << 4) | hexval(p[2]);

            if (h >= 0) {
                *s++ = h;
                p += 3;
                continue;
            }
        }

        *s++ = *p++;
    }
    *s = '\0';
    return s;
}

int process_srs(client_t *srsd, void* vconfig)
{
    srs_config_t* config = vconfig;
    buffer_t *ibuf = client_input_buffer(srsd);
    buffer_t *obuf = client_output_buffer(srsd);
    bool decoder = (client_data(srsd) == decoder_ptr);
    int res = client_read(srsd);

    if ((res < 0 && errno != EINTR && errno != EAGAIN) || res == 0)
        return -1;

    while (ibuf->len > 4) {
        char buf[BUFSIZ], *p, *q, *nl;
        int err;

        nl = strchr(ibuf->data + 4, '\n');
        if (!nl) {
            if (ibuf->len > BUFSIZ) {
                err("unreasonnable amount of data without a \\n");
                return -1;
            }
            if (obuf->len) {
                client_io_rw(srsd);
            }
            return 0;
        }

        if (strncmp("get ", ibuf->data, 4)) {
            err("bad request, not starting with \"get \"");
            return -1;
        }

        for (p = ibuf->data + 4; p < nl && isspace(*p); p++);
        for (q = nl++; q >= p && isspace(*q); *q-- = '\0');

        if (p == q) {
            buffer_addstr(obuf, "400 empty request ???\n");
            warn("empty request");
            goto skip;
        }

        q = urldecode(p, q);

        if (decoder) {
            if (config->ignore_ext) {
                int dlen = config->domainlen;

                if (q - p <= dlen || q[-1 - dlen] != '@' ||
                    memcmp(q - dlen, config->domain, dlen))
                {
                    buffer_addstr(obuf, "200 ");
                    buffer_add(obuf, p, q - p);
                    buffer_addch(obuf, '\n');
                    goto skip;
                }
            }
            err = srs_reverse(config->srs, buf, ssizeof(buf), p);
        } else {
            err = srs_forward(config->srs, buf, ssizeof(buf), p, config->domain);
        }

        if (err == SRS_SUCCESS) {
            buffer_addstr(obuf, "200 ");
            buffer_addstr(obuf, buf);
        } else {
            switch (SRS_ERROR_TYPE(err)) {
              case SRS_ERRTYPE_CONFIG:
                buffer_addstr(obuf, "400 ");
                break;
              default:
                buffer_addstr(obuf, "500 ");
                break;
            }
            buffer_addstr(obuf, srs_strerror(err));
        }
        buffer_addch(obuf, '\n');

      skip:
        buffer_consume(ibuf, nl - ibuf->data);
    }
    if (obuf->len) {
        client_io_rw(srsd);
    }
    return 0;
}


/* config {{{1
 */

static srs_config_t config = {
    .srs = NULL,
    .domain = NULL,
    .domainlen = 0,
    .ignore_ext = false,
    .separator = '\0'
};

/** overload srs_free since the lib is not properly maintained.
 */
inline void srs_free(srs_t* srs)
{
    int  i;
    for (i = 0; i < srs->numsecrets; i++) {
        memset(srs->secrets[i], 0, strlen(srs->secrets[i]));
        free(srs->secrets[i]);
        srs->secrets[i] = '\0';
    }
    if (srs->secrets) {
        free(srs->secrets);
    }
    free(srs);
{'fraction_non_alphanumeric': 0.139963436928702, 'fraction_numerical': 0.011407678244972578, 'mean_word_length': 1.4833847830034501, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 42, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2603395', 'n_tokens_mistral': 4081, 'n_tokens_neox': 3760, 'n_words': 1110}