mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 06:05:37 +00:00
snapshot-20000823
This commit is contained in:
@@ -4147,3 +4147,12 @@ Apologies for any names omitted.
|
||||
that cannot be represented with the off_t type that is used
|
||||
by standard functions such as lseek(2). Problem reported
|
||||
by Blaz Zupan @ amis.net.
|
||||
|
||||
20000823
|
||||
|
||||
Feature: all this discussion about when to reject mail and
|
||||
when not made me decide to implement a TCP-based map type
|
||||
so that it becomes relatively simple to implement dynamic
|
||||
access controls, for example, hold off mail from an unknown
|
||||
client or sender until we have completed some investigation,
|
||||
after which we will either reject or accept.
|
||||
|
@@ -15,7 +15,7 @@
|
||||
* Version of this program.
|
||||
*/
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20000822"
|
||||
#define DEF_MAIL_VERSION "Snapshot-20000823"
|
||||
extern char *var_mail_version;
|
||||
|
||||
/* LICENSE
|
||||
|
1
postfix/util/.indent.pro
vendored
1
postfix/util/.indent.pro
vendored
@@ -32,6 +32,7 @@
|
||||
-TDICT_PCRE
|
||||
-TDICT_REGEXP
|
||||
-TDICT_REGEXP_RULE
|
||||
-TDICT_TCP
|
||||
-TDICT_UNIX
|
||||
-TDNS_FIXED
|
||||
-TDNS_REPLY
|
||||
|
@@ -21,7 +21,8 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
|
||||
write_buf.c write_wait.c dict_unix.c dict_pcre.c stream_listen.c \
|
||||
stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \
|
||||
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
|
||||
sane_link.c unescape.c timed_read.c timed_write.c
|
||||
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
|
||||
hex_quote.c
|
||||
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
|
||||
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
|
||||
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
|
||||
@@ -44,7 +45,8 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
|
||||
write_buf.o write_wait.o dict_unix.o dict_pcre.o stream_listen.o \
|
||||
stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \
|
||||
clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
|
||||
sane_link.o unescape.o timed_read.o timed_write.o
|
||||
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
|
||||
hex_quote.o
|
||||
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
|
||||
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
|
||||
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
|
||||
@@ -59,7 +61,7 @@ HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
|
||||
timed_connect.h timed_wait.h trigger.h username.h valid_hostname.h \
|
||||
vbuf.h vbuf_print.h vstream.h vstring.h vstring_vstream.h \
|
||||
dict_unix.h dict_pcre.h dict_regexp.h mac_expand.h clean_env.h \
|
||||
watchdog.h spawn_command.h sane_fsops.h
|
||||
watchdog.h spawn_command.h sane_fsops.h dict_tcp.h hex_quote.h
|
||||
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
|
||||
stream_test.c dup2_pass_on_exec.c
|
||||
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
|
||||
@@ -75,7 +77,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
|
||||
inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
|
||||
mystrtok sigdelay translit valid_hostname vstream_popen \
|
||||
vstring vstring_vstream doze select_bug stream_test mac_expand \
|
||||
watchdog unescape
|
||||
watchdog unescape hex_quote
|
||||
|
||||
LIB_DIR = ../lib
|
||||
INC_DIR = ../include
|
||||
@@ -249,6 +251,11 @@ unescape: $(LIB)
|
||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||
mv junk $@.o
|
||||
|
||||
hex_quote: $(LIB)
|
||||
mv $@.o junk
|
||||
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||
mv junk $@.o
|
||||
|
||||
depend: $(MAKES)
|
||||
(sed '1,/^# do not edit/!d' Makefile.in; \
|
||||
set -e; for i in [a-z][a-z0-9]*.c; do \
|
||||
@@ -260,7 +267,8 @@ depend: $(MAKES)
|
||||
stream_test: stream_test.c $(LIB)
|
||||
$(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS)
|
||||
|
||||
tests: valid_hostname_test mac_expand_test dict_test unescape_test
|
||||
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
|
||||
hex_quote_test
|
||||
|
||||
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
|
||||
./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
|
||||
@@ -277,6 +285,12 @@ unescape_test: unescape unescape.in unescape.ref
|
||||
diff -b unescape.ref unescape.tmp
|
||||
rm -f unescape.tmp
|
||||
|
||||
hex_quote_test: hex_quote
|
||||
./hex_quote <hex_quote.c | od -cb >hex_quote.tmp
|
||||
od -cb <hex_quote.c >hex_quote.ref
|
||||
cmp hex_quote.ref hex_quote.tmp
|
||||
rm -f hex_quote.ref hex_quote.tmp
|
||||
|
||||
DB_TYPE = `../postconf/postconf -h default_database_type`
|
||||
|
||||
dict_test: dict_open testdb dict_test.in dict_test.ref
|
||||
@@ -416,6 +430,7 @@ dict_open.o: vstream.h
|
||||
dict_open.o: vbuf.h
|
||||
dict_open.o: dict_env.h
|
||||
dict_open.o: dict_unix.h
|
||||
dict_open.o: dict_tcp.h
|
||||
dict_open.o: dict_dbm.h
|
||||
dict_open.o: dict_db.h
|
||||
dict_open.o: dict_nis.h
|
||||
@@ -445,6 +460,20 @@ dict_regexp.o: dict.h
|
||||
dict_regexp.o: argv.h
|
||||
dict_regexp.o: dict_regexp.h
|
||||
dict_regexp.o: mac_parse.h
|
||||
dict_tcp.o: dict_tcp.c
|
||||
dict_tcp.o: sys_defs.h
|
||||
dict_tcp.o: msg.h
|
||||
dict_tcp.o: mymalloc.h
|
||||
dict_tcp.o: vstring.h
|
||||
dict_tcp.o: vbuf.h
|
||||
dict_tcp.o: vstream.h
|
||||
dict_tcp.o: vstring_vstream.h
|
||||
dict_tcp.o: connect.h
|
||||
dict_tcp.o: iostuff.h
|
||||
dict_tcp.o: hex_quote.h
|
||||
dict_tcp.o: dict.h
|
||||
dict_tcp.o: argv.h
|
||||
dict_tcp.o: dict_tcp.h
|
||||
dict_unix.o: dict_unix.c
|
||||
dict_unix.o: sys_defs.h
|
||||
dict_unix.o: msg.h
|
||||
@@ -465,6 +494,7 @@ doze.o: doze.c
|
||||
doze.o: sys_defs.h
|
||||
doze.o: msg.h
|
||||
doze.o: iostuff.h
|
||||
dup2_pass_on_exec.o: dup2_pass_on_exec.c
|
||||
duplex_pipe.o: duplex_pipe.c
|
||||
duplex_pipe.o: sys_defs.h
|
||||
duplex_pipe.o: iostuff.h
|
||||
@@ -526,6 +556,12 @@ get_hostname.o: mymalloc.h
|
||||
get_hostname.o: msg.h
|
||||
get_hostname.o: valid_hostname.h
|
||||
get_hostname.o: get_hostname.h
|
||||
hex_quote.o: hex_quote.c
|
||||
hex_quote.o: sys_defs.h
|
||||
hex_quote.o: msg.h
|
||||
hex_quote.o: vstring.h
|
||||
hex_quote.o: vbuf.h
|
||||
hex_quote.o: hex_quote.h
|
||||
htable.o: htable.c
|
||||
htable.o: sys_defs.h
|
||||
htable.o: mymalloc.h
|
||||
@@ -948,6 +984,7 @@ vstring_vstream.o: vstream.h
|
||||
vstring_vstream.o: vstring_vstream.h
|
||||
watchdog.o: watchdog.c
|
||||
watchdog.o: sys_defs.h
|
||||
watchdog.o: posix_signals.h
|
||||
watchdog.o: msg.h
|
||||
watchdog.o: mymalloc.h
|
||||
watchdog.o: watchdog.h
|
||||
|
@@ -156,6 +156,7 @@
|
||||
#include <dict.h>
|
||||
#include <dict_env.h>
|
||||
#include <dict_unix.h>
|
||||
#include <dict_tcp.h>
|
||||
#include <dict_dbm.h>
|
||||
#include <dict_db.h>
|
||||
#include <dict_nis.h>
|
||||
@@ -180,6 +181,7 @@ typedef struct {
|
||||
static DICT_OPEN_INFO dict_open_info[] = {
|
||||
"environ", dict_env_open,
|
||||
"unix", dict_unix_open,
|
||||
"tcp", dict_tcp_open,
|
||||
#ifdef HAS_DBM
|
||||
"dbm", dict_dbm_open,
|
||||
#endif
|
||||
@@ -318,6 +320,7 @@ ARGV *dict_mapnames()
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
@@ -343,6 +346,8 @@ main(int argc, char **argv)
|
||||
const char *value;
|
||||
int ch;
|
||||
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
msg_vstream_init(argv[0], VSTREAM_ERR);
|
||||
while ((ch = GETOPT(argc, argv, "v")) > 0) {
|
||||
switch (ch) {
|
||||
@@ -380,7 +385,9 @@ main(int argc, char **argv)
|
||||
vstream_printf("%s: deleted\n", key);
|
||||
} else if (strcmp(cmd, "get") == 0 && key && !value) {
|
||||
if ((value = dict_get(dict, key)) == 0) {
|
||||
vstream_printf("%s: not found\n", key);
|
||||
vstream_printf("%s: %s\n", key,
|
||||
dict_errno == DICT_ERR_RETRY ?
|
||||
"soft error" : "not found");
|
||||
} else {
|
||||
vstream_printf("%s=%s\n", key, value);
|
||||
}
|
||||
@@ -388,7 +395,7 @@ main(int argc, char **argv)
|
||||
dict_put(dict, key, value);
|
||||
vstream_printf("%s=%s\n", key, value);
|
||||
} else {
|
||||
vstream_printf("usage: del key|get key|put key=value");
|
||||
vstream_printf("usage: del key|get key|put key=value\n");
|
||||
}
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
}
|
||||
|
191
postfix/util/dict_tcp.c
Normal file
191
postfix/util/dict_tcp.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_tcp 3
|
||||
/* SUMMARY
|
||||
/* dictionary manager interface to tcp-based lookup tables
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_tcp.h>
|
||||
/*
|
||||
/* DICT *dict_tcp_open(map, dummy, dict_flags)
|
||||
/* const char *map;
|
||||
/* int dummy;
|
||||
/* int dict_flags;
|
||||
/* DESCRIPTION
|
||||
/* dict_tcp_open() makes a TCP server accessible via the generic
|
||||
/* dictionary operations described in dict_open(3).
|
||||
/* The \fIdummy\fR argument is not used. Server access is read-only
|
||||
/* (i.e., only lookups are implemented).
|
||||
/*
|
||||
/* Map names have the form host:port.
|
||||
/*
|
||||
/* The map implements a very simple protocol: the query is sent as
|
||||
/* one line of text, and the reply is sent back in the same format.
|
||||
/* Data is sent as a newline-terminated string. % and non-printable
|
||||
/* characters are replaced by %xx, xx being the corresponding
|
||||
/* hexadecimal value.
|
||||
/* SEE ALSO
|
||||
/* dict(3) generic dictionary manager
|
||||
/* DIAGNOSTICS
|
||||
/* Fatal errors: out of memory, unknown host or service name,
|
||||
/* attempt to update map.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include "sys_defs.h"
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include "msg.h"
|
||||
#include "mymalloc.h"
|
||||
#include "vstring.h"
|
||||
#include "vstream.h"
|
||||
#include "vstring_vstream.h"
|
||||
#include "connect.h"
|
||||
#include "hex_quote.h"
|
||||
#include "dict.h"
|
||||
#include "dict_tcp.h"
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
typedef struct {
|
||||
DICT dict; /* generic members */
|
||||
char *map; /* server host:port */
|
||||
VSTRING *raw_buf; /* raw buffer */
|
||||
VSTRING *hex_buf; /* hexified buffer */
|
||||
VSTREAM *fp; /* I/O stream */
|
||||
} DICT_TCP;
|
||||
|
||||
#define DICT_TCP_MAXTRY 10
|
||||
#define DICT_TCP_TMOUT 100
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
/* dict_tcp_lookup - query TCP server */
|
||||
|
||||
static const char *dict_tcp_lookup(DICT *dict, const char *key)
|
||||
{
|
||||
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
dict_errno = 0;
|
||||
|
||||
for (i = 0; /* see below */ ; i++) {
|
||||
|
||||
/*
|
||||
* Try to connect a few times before giving up.
|
||||
*/
|
||||
if (i >= DICT_TCP_MAXTRY) {
|
||||
dict_errno = DICT_ERR_RETRY;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sleep between connection attempts.
|
||||
*/
|
||||
if (i > 0)
|
||||
sleep(1);
|
||||
|
||||
/*
|
||||
* Try to connect to the server.
|
||||
*/
|
||||
if (dict_tcp->fp == 0) {
|
||||
if ((fd = inet_connect(dict_tcp->map, BLOCKING, 0)) < 0) {
|
||||
msg_warn("connect to TCP map %s: %m", dict_tcp->map);
|
||||
continue;
|
||||
}
|
||||
dict_tcp->fp = vstream_fdopen(fd, O_RDWR);
|
||||
vstream_control(dict_tcp->fp,
|
||||
VSTREAM_CTL_TIMEOUT, DICT_TCP_TMOUT,
|
||||
VSTREAM_CTL_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate per-map buffers on the fly.
|
||||
*/
|
||||
if (dict_tcp->raw_buf == 0) {
|
||||
dict_tcp->raw_buf = vstring_alloc(10);
|
||||
dict_tcp->hex_buf = vstring_alloc(10);
|
||||
}
|
||||
|
||||
/*
|
||||
* Send query and receive response. Both are %XX quoted and both are
|
||||
* terminated by newline.
|
||||
*/
|
||||
hex_quote(dict_tcp->hex_buf, key);
|
||||
vstream_fprintf(dict_tcp->fp, "%s\n", STR(dict_tcp->hex_buf));
|
||||
errno = 0;
|
||||
if (vstring_get_nonl(dict_tcp->hex_buf, dict_tcp->fp) == VSTREAM_EOF) {
|
||||
msg_warn("read TCP map reply from %s: %m", dict_tcp->map);
|
||||
} else if (!hex_unquote(dict_tcp->raw_buf, STR(dict_tcp->hex_buf))) {
|
||||
msg_warn("read TCP map reply from %s: malformed reply %.100s",
|
||||
dict_tcp->map, STR(dict_tcp->hex_buf));
|
||||
} else {
|
||||
return (STR(dict_tcp->raw_buf));
|
||||
}
|
||||
|
||||
/*
|
||||
* That did not work. Clean up and try again.
|
||||
*/
|
||||
(void) vstream_fclose(dict_tcp->fp);
|
||||
dict_tcp->fp = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* dict_tcp_update - add or update table entry */
|
||||
|
||||
static void dict_tcp_update(DICT *dict, const char *unused_name, const char *unused_value)
|
||||
{
|
||||
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
|
||||
|
||||
msg_fatal("dict_tcp_update: attempt to update map %s", dict_tcp->map);
|
||||
}
|
||||
|
||||
/* dict_tcp_close - close TCP map */
|
||||
|
||||
static void dict_tcp_close(DICT *dict)
|
||||
{
|
||||
DICT_TCP *dict_tcp = (DICT_TCP *) dict;
|
||||
|
||||
if (dict_tcp->fp)
|
||||
(void) vstream_fclose(dict_tcp->fp);
|
||||
if (dict_tcp->raw_buf)
|
||||
vstring_free(dict_tcp->raw_buf);
|
||||
if (dict_tcp->hex_buf)
|
||||
vstring_free(dict_tcp->hex_buf);
|
||||
myfree(dict_tcp->map);
|
||||
myfree((char *) dict_tcp);
|
||||
}
|
||||
|
||||
/* dict_tcp_open - open TCP map */
|
||||
|
||||
DICT *dict_tcp_open(const char *map, int unused_flags, int dict_flags)
|
||||
{
|
||||
DICT_TCP *dict_tcp;
|
||||
|
||||
dict_errno = 0;
|
||||
|
||||
dict_tcp = (DICT_TCP *) mymalloc(sizeof(*dict_tcp));
|
||||
dict_tcp->fp = 0;
|
||||
dict_tcp->raw_buf = dict_tcp->hex_buf = 0;
|
||||
dict_tcp->dict.lookup = dict_tcp_lookup;
|
||||
dict_tcp->dict.update = dict_tcp_update;
|
||||
dict_tcp->dict.close = dict_tcp_close;
|
||||
dict_tcp->dict.fd = -1;
|
||||
dict_tcp->map = mystrdup(map);
|
||||
dict_tcp->dict.flags = dict_flags | DICT_FLAG_FIXED;
|
||||
return (&dict_tcp->dict);
|
||||
}
|
35
postfix/util/dict_tcp.h
Normal file
35
postfix/util/dict_tcp.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef _DICT_TCP_H_INCLUDED_
|
||||
#define _DICT_TCP_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* dict_tcp 3h
|
||||
/* SUMMARY
|
||||
/* dictionary manager interface to tcp-based lookup tables
|
||||
/* SYNOPSIS
|
||||
/* #include <dict_tcp.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <dict.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern DICT *dict_tcp_open(const char *, int, int);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
#endif
|
148
postfix/util/hex_quote.c
Normal file
148
postfix/util/hex_quote.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/*++
|
||||
/* NAME
|
||||
/* hex_quote 3
|
||||
/* SUMMARY
|
||||
/* quote/unquote text, HTTP style.
|
||||
/* SYNOPSIS
|
||||
/* #include <hex_quote.h>
|
||||
/*
|
||||
/* VSTRING *hex_quote(hex, raw)
|
||||
/* VSTRING *hex;
|
||||
/* const char *raw;
|
||||
/*
|
||||
/* VSTRING *hex_unquote(raw, hex)
|
||||
/* VSTRING *raw;
|
||||
/* const char *hex;
|
||||
/* DESCRIPTION
|
||||
/* hex_quote() takes a null-terminated string and replaces non-printable
|
||||
/* characters and % by %XX, XX being the two-digit hexadecimal equivalent.
|
||||
/* The hexadecimal codes are produced as upper-case characters. The result
|
||||
/* value is the hex argument.
|
||||
/*
|
||||
/* hex_unquote() performs the opposite transformation. This function
|
||||
/* understands lowercase and uppercase %XX sequences. The result
|
||||
/* value is the raw argument in case of success, a null pointer otherwise.
|
||||
/* BUGS
|
||||
/* Cannot process null characters.
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
/* System library. */
|
||||
|
||||
#include "sys_defs.h"
|
||||
#include <ctype.h>
|
||||
|
||||
/* Utility library. */
|
||||
|
||||
#include "msg.h"
|
||||
#include "vstring.h"
|
||||
#include "hex_quote.h"
|
||||
|
||||
/* Application-specific. */
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
#define LEN(x) VSTRING_LEN(x)
|
||||
|
||||
/* hex_quote - raw data to quoted */
|
||||
|
||||
VSTRING *hex_quote(VSTRING *hex, const char *raw)
|
||||
{
|
||||
const char *cp;
|
||||
int ch;
|
||||
|
||||
VSTRING_RESET(hex);
|
||||
for (cp = raw; (ch = *(unsigned const char *) cp) != 0; cp++) {
|
||||
if (ch != '%' && ISPRINT(ch)) {
|
||||
VSTRING_ADDCH(hex, ch);
|
||||
} else {
|
||||
vstring_sprintf_append(hex, "%%%02X", ch);
|
||||
}
|
||||
}
|
||||
VSTRING_TERMINATE(hex);
|
||||
return (hex);
|
||||
}
|
||||
|
||||
/* hex_unquote - quoted data to raw */
|
||||
|
||||
VSTRING *hex_unquote(VSTRING *raw, const char *hex)
|
||||
{
|
||||
const char *cp;
|
||||
int ch;
|
||||
|
||||
VSTRING_RESET(raw);
|
||||
for (cp = hex; (ch = *cp) != 0; cp++) {
|
||||
if (ch == '%') {
|
||||
if (ISDIGIT(cp[1]))
|
||||
ch = (cp[1] - '0') << 4;
|
||||
else if (cp[1] >= 'a' && cp[1] <= 'f')
|
||||
ch = (cp[1] - 'a' + 10) << 4;
|
||||
else if (cp[1] >= 'A' && cp[1] <= 'F')
|
||||
ch = (cp[1] - 'A' + 10) << 4;
|
||||
else
|
||||
return (0);
|
||||
if (ISDIGIT(cp[2]))
|
||||
ch |= (cp[2] - '0');
|
||||
else if (cp[2] >= 'a' && cp[2] <= 'f')
|
||||
ch |= (cp[2] - 'a' + 10);
|
||||
else if (cp[2] >= 'A' && cp[2] <= 'F')
|
||||
ch |= (cp[2] - 'A' + 10);
|
||||
else
|
||||
return (0);
|
||||
cp += 2;
|
||||
}
|
||||
VSTRING_ADDCH(raw, ch);
|
||||
}
|
||||
VSTRING_TERMINATE(raw);
|
||||
return (raw);
|
||||
}
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/*
|
||||
* Proof-of-concept test program: convert to hex and back.
|
||||
*/
|
||||
#include <vstream.h>
|
||||
|
||||
#define BUFLEN 1024
|
||||
|
||||
static int read_buf(VSTREAM *fp, VSTRING *buf)
|
||||
{
|
||||
int len;
|
||||
|
||||
VSTRING_RESET(buf);
|
||||
len = vstream_fread(fp, STR(buf), vstring_avail(buf));
|
||||
VSTRING_AT_OFFSET(buf, len); /* XXX */
|
||||
VSTRING_TERMINATE(buf);
|
||||
return (len);
|
||||
}
|
||||
|
||||
main(int unused_argc, char **unused_argv)
|
||||
{
|
||||
VSTRING *raw = vstring_alloc(BUFLEN);
|
||||
VSTRING *hex = vstring_alloc(100);
|
||||
int len;
|
||||
|
||||
while ((len = read_buf(VSTREAM_IN, raw)) > 0) {
|
||||
hex_quote(hex, STR(raw));
|
||||
if (hex_unquote(raw, STR(hex)) == 0)
|
||||
msg_fatal("bad input: %.100s", STR(hex));
|
||||
if (LEN(raw) != len)
|
||||
msg_fatal("len %d != raw len %d", len, LEN(raw));
|
||||
if (vstream_fwrite(VSTREAM_OUT, STR(raw), LEN(raw)) != LEN(raw))
|
||||
msg_fatal("write error: %m");
|
||||
}
|
||||
vstream_fflush(VSTREAM_OUT);
|
||||
vstring_free(raw);
|
||||
vstring_free(hex);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
36
postfix/util/hex_quote.h
Normal file
36
postfix/util/hex_quote.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _HEX_QUOTE_H_INCLUDED_
|
||||
#define _HEX_QUOTE_H_INCLUDED_
|
||||
|
||||
/*++
|
||||
/* NAME
|
||||
/* hex_quote 3h
|
||||
/* SUMMARY
|
||||
/* quote/unquote text, HTTP style.
|
||||
/* SYNOPSIS
|
||||
/* #include <hex_quote.h>
|
||||
/* DESCRIPTION
|
||||
/* .nf
|
||||
|
||||
/*
|
||||
* Utility library.
|
||||
*/
|
||||
#include <vstring.h>
|
||||
|
||||
/*
|
||||
* External interface.
|
||||
*/
|
||||
extern VSTRING *hex_quote(VSTRING *, const char *);
|
||||
extern VSTRING *hex_unquote(VSTRING *, const char *);
|
||||
|
||||
/* LICENSE
|
||||
/* .ad
|
||||
/* .fi
|
||||
/* The Secure Mailer license must be distributed with this software.
|
||||
/* AUTHOR(S)
|
||||
/* Wietse Venema
|
||||
/* IBM T.J. Watson Research
|
||||
/* P.O. Box 704
|
||||
/* Yorktown Heights, NY 10598, USA
|
||||
/*--*/
|
||||
|
||||
#endif
|
@@ -825,7 +825,7 @@ typedef int pid_t;
|
||||
#if __GNUC__ == 2 && __GNUC_MINOR__ >= 7
|
||||
#define PRINTFLIKE(x,y) __attribute__ ((format (printf, (x), (y))))
|
||||
#else
|
||||
#define PRINTFLIKE
|
||||
#define PRINTFLIKE(x,y)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user