#!/usr/local/bin/python
#-
# Copyright (c) 2010 UPLEX, Nils Goroll
# All rights reserved.
#
# Author: Nils Goroll <slink@uplex.de>
#
# 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.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 AUTHOR OR 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.
#
# Generate glue code for Varnish 2.0.4
#
# $Id$

import sys
srcroot = "../../.."
buildroot = "../../.."
if len(sys.argv) == 3:
        srcroot = sys.argv[1]
        buildroot = sys.argv[2]

digest_types = [
	'DEFAULT',
	'CRC32',
	'SHA256',
	'PLAIN',
	'RS',
	'MD5'
]

# BK variants are "binkey" variants: the key is binary in hex-encoded form
hmac_types = [
	'HMAC_SHA256',
	'HMAC_SHA256BK',
	'HMAC_MD5',
	'HMAC_MD5BK'
]

encoding_types = [
	'BASE64',
	'HEX',
	'HEXLC'
]

h = open("vmod_digest.h", "w")

vrt_f = srcroot + "/include/vrt_digest.h"
vrt = open(vrt_f, "w")

c = open("vmod_digest_if.c", "w")

vtc = open("vtc_snippet","w")

h.write("/* THIS FILE IS AUTO-GENERATED. don't edit */\n")

vrt.write("/* THIS FILE IS AUTO-GENERATED. don't edit */\n")

c.write("/* THIS FILE IS AUTO-GENERATED. don't edit */\n")
c.write("#include \"config.h\"\n")
c.write("#include \"vmod_digest.h\"\n")
c.write("#include \"" + vrt_f + "\"\n")

vtc.write("# THIS FILE IS AUTO-GENERATED. don't edit\n")
vtc.write("# use this code snippet for the vtc test\n")

h.write("""

#include <stdarg.h>
#include "../cache.h"
""")

vrt.write("""

#include <stdarg.h>
""")

h.write("enum digest_type {\n\t" +
	",\n\t".join(digest_types) +
	"\n};\n")
h.write("enum hmac_type {\n\t" +
	",\n\t".join(hmac_types) +
	"\n};\n")
h.write("enum encoding_type {\n\t" +
	",\n\t".join(encoding_types) +
	"\n};\n")
h.write("\n")
h.write("""
char *digest_string(const enum digest_type type, const enum encoding_type enc,
	      struct sess *sp, const char *s, va_list ap);
char *encode_string(const enum encoding_type enc,
	      struct sess *sp, const char *s, va_list ap);
char *hmac_string(const enum hmac_type type, const enum encoding_type enc,
	struct sess *sp, const char *key, const char *s, va_list ap);

""")
h.write("\n")

# output wrappers for "digest&encode" functions
#
# Function STRING digest_encoder(STRING_LIST)
# const char *VRT_digest_encoder_(sp ...)

for d in digest_types:
	for e in encoding_types:
		vrt.write("const char *" + 
"VRT_digest_" + d.lower() + "_" + e.lower() + "(struct sess *sp, const char *s, ...);\n")
		c.write("""
const char *
VRT_digest_""" + d.lower() + "_" + e.lower() + """(struct sess *sp, const char *s, ...)
{
	const char *p;
	va_list ap;

	va_start(ap, s);
	p = digest_string(""" + ", ".join([d, e, "sp", "s", "ap"]) + """);
	va_end(ap);
        return (p);
}
""")
		vtc.write("\t\tset resp.http." +
			  d.lower() + "-" + e.lower() +
			  " = digest." +
			  d.lower() + "_" + e.lower() + 
			  """("123" + "456");"""+ "\n")

# output wrappers for "hmac & encode" functions
#
# Function STRING hmac_encoder(STRING, STRING_LIST)
# const char *vmod_hmac_encoder_(sp ...)

for d in hmac_types:
	for e in encoding_types:
		vrt.write("const char *" + 
"VRT_digest_" + d.lower() + "_" + e.lower() + "(struct sess *sp, const char *key, const char *s, ...);\n")
		c.write("""
const char *
VRT_digest_""" + d.lower() + "_" + e.lower() + """(struct sess *sp, const char *key, const char *s, ...)
{
	const char *p;
	va_list ap;

	va_start(ap, s);
	p = hmac_string(""" + ", ".join([d, e, "sp", "key", "s", "ap"]) + """);
	va_end(ap);
        return (p);
}
""")
		vtc.write("\t\tset resp.http." +
			  d.lower() + "-" + e.lower() +
			  " = digest." +
			  d.lower() + "_" + e.lower() + 
			  """("key", "123" + "456");"""+ "\n")

# PULL-IN HACK of vmod_urlcode
vrt.write("""
const char *VRT_urlencode(struct sess *sp, const char *str, ...);
const char *VRT_urldecode(struct sess *sp, const char *str, ...);
""")

# output wrappers for "encode" functions
#
# Function STRING digest_encoder(STRING_LIST)
# const char *VRT_digest_encoder_(sp ...)

vtc.write("\n#\t\tencodings (no digest)\n")

for e in encoding_types:
	vrt.write("const char *" +
		"VRT_digest_encode_" + e.lower() + "(struct sess *sp, const char *s, ...);\n")
	c.write("""
const char *
VRT_digest_encode_""" + e.lower() + """(struct sess *sp, const char *s, ...)
{
	const char *p;
	va_list ap;

	va_start(ap, s);
	p = encode_string(""" + ", ".join([e, "sp", "s", "ap"]) + """);
	va_end(ap);
        return (p);
}
""")
	vtc.write("\t\tset resp.http." +
		  e.lower() +
		  " = digest.encode_" +
		  e.lower() + 
		  """("123" + "456");"""+ "\n")

h.close
c.close
vtc.close
