hash-format.c revision c971768955f826fb965d8ffbb13dac93c9bbead8
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2010-2014 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "base64.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hex-binary.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hash-method.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "hash-format.h"
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenenum hash_encoding {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen HASH_ENCODING_HEX,
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen HASH_ENCODING_HEX_SHORT,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen HASH_ENCODING_BASE64
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen};
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainenstruct hash_format_list {
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen struct hash_format_list *next;
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen
7d7b5c98f086ffa8ac9c90f21db17748ca607202Timo Sirainen const struct hash_method *method;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen void *context;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen unsigned int bits;
e627cdc5ef30d87959f9510832427e33a2f1d84aTimo Sirainen enum hash_encoding encoding;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen};
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenstruct hash_format {
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen pool_t pool;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen const char *str;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen struct hash_format_list *list, **pos;
0d70a702dec63d22535684fec6a7247c5f153208Timo Sirainen unsigned char *digest;
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen};
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenhash_format_parse(const char *str, unsigned int *idxp,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const struct hash_method **method_r,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen unsigned int *bits_r, const char **error_r)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen{
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen const char *name, *end, *bitsp;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen unsigned int bits, i = *idxp;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen /* we should have "hash_name}" or "hash_name:bits}" */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen end = strchr(str+i, '}');
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (end == NULL) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen *error_r = "Missing '}'";
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen *idxp = end - str;
03739a8eaad2d8b34b9d87dbbe5b13c5d5dfa11aTimo Sirainen name = t_strdup_until(str+i, end);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen bitsp = strchr(name, ':');
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if (bitsp != NULL)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen name = t_strdup_until(name, bitsp++);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen
ff7257145f317d6ca44a9402427bb74c34b999a9Timo Sirainen *method_r = hash_method_lookup(name);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*method_r == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strconcat("Unknown hash method: ", name, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen bits = (*method_r)->digest_size * 8;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen if (bitsp != NULL) {
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen if (str_to_uint(bitsp, &bits) < 0 ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bits == 0 || bits > (*method_r)->digest_size*8) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strconcat("Invalid :bits number: ",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bitsp, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((bits % 8) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strconcat(
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Currently :bits must be divisible by 8: ",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bitsp, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *bits_r = bits;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenhash_format_string_analyze(struct hash_format *format, const char *str,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **error_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen struct hash_format_list *list;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen unsigned int i;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen for (i = 0; str[i] != '\0'; i++) {
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen if (str[i] != '%')
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen continue;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen i++;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen list = p_new(format->pool, struct hash_format_list, 1);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen list->encoding = HASH_ENCODING_HEX;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen *format->pos = list;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen format->pos = &list->next;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (str[i] == 'B') {
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen list->encoding = HASH_ENCODING_BASE64;
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen i++;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen } else if (str[i] == 'X') {
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen list->encoding = HASH_ENCODING_HEX_SHORT;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen i++;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (str[i++] != '{') {
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen *error_r = "No '{' after '%'";
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen return -1;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (hash_format_parse(str, &i, &list->method,
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen &list->bits, error_r) < 0)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return -1;
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen list->context = p_malloc(format->pool,
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen list->method->context_size);
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen list->method->init(list->context);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen return 0;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen}
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainenint hash_format_init(const char *format_string, struct hash_format **format_r,
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen const char **error_r)
4c8b1c4aa0582c6ca43a4d1cbd210741e7fff952Timo Sirainen{
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen struct hash_format *format;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen pool_t pool;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen int ret;
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen pool = pool_alloconly_create("hash format", 1024);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen format = p_new(pool, struct hash_format, 1);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen format->pool = pool;
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen format->str = p_strdup(pool, format_string);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen format->pos = &format->list;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen T_BEGIN {
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen ret = hash_format_string_analyze(format, format_string,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen error_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (ret < 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen *error_r = p_strdup(format->pool, *error_r);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen } T_END;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (ret < 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strdup(*error_r);
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen pool_unref(&pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *format_r = format;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenvoid hash_format_loop(struct hash_format *format,
24ec3e51a1bd7aaf09c92a7ff7498e225796d7e0Timo Sirainen const void *data, size_t size)
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen{
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen struct hash_format_list *list;
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen for (list = format->list; list != NULL; list = list->next)
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen list->method->loop(list->context, data, size);
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen}
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenvoid hash_format_reset(struct hash_format *format)
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct hash_format_list *list;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
3b80595fcf2001cf7b2fcc6290823e38f4a142fcTimo Sirainen for (list = format->list; list != NULL; list = list->next) {
06fb99af33bd380b382d2d4f2994cf9a5bf0bbaeTimo Sirainen memset(list->context, 0, list->method->context_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen list->method->init(list->context);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen}
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenhash_format_digest(string_t *dest, const struct hash_format_list *list,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const unsigned char *digest)
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int i, orig_len, size = list->bits / 8;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen i_assert(list->bits % 8 == 0);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen switch (list->encoding) {
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen case HASH_ENCODING_HEX:
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen binary_to_hex_append(dest, digest, size);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen break;
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen case HASH_ENCODING_HEX_SHORT:
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen orig_len = str_len(dest);
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen binary_to_hex_append(dest, digest, size);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen /* drop leading zeros, except if it's the only one */
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen for (i = orig_len; i < str_len(dest); i++) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (str_data(dest)[i] != '0')
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen break;
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen }
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen if (i == str_len(dest)) i--;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen str_delete(dest, orig_len, i-orig_len);
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen break;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen case HASH_ENCODING_BASE64:
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen orig_len = str_len(dest);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen base64_encode(digest, size, dest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* drop trailing '=' chars */
024815ea2ffdda9ea79919f18e865663977f73eaTimo Sirainen while (str_len(dest) > orig_len &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_data(dest)[str_len(dest)-1] == '=')
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen str_truncate(dest, str_len(dest)-1);
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen break;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen }
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen}
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenvoid hash_format_write(struct hash_format *format, string_t *dest)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen struct hash_format_list *list;
8afec4d1a32b78f540257a27769b372aad753384Timo Sirainen const char *p;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen unsigned int i, max_digest_size = 0;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen for (list = format->list; list != NULL; list = list->next) {
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen if (max_digest_size < list->method->digest_size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen max_digest_size = list->method->digest_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (format->digest == NULL)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen format->digest = p_malloc(format->pool, max_digest_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen list = format->list;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; format->str[i] != '\0'; i++) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen if (format->str[i] != '%') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str_append_c(dest, format->str[i]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
6d25922a089626f5535d51358e33d3337783a410Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* we already verified that the string is ok */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(list != NULL);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen list->method->result(list->context, format->digest);
6d25922a089626f5535d51358e33d3337783a410Timo Sirainen hash_format_digest(dest, list, format->digest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen list = list->next;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen p = strchr(format->str+i, '}');
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen i_assert(p != NULL);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i = p - format->str;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
6d25922a089626f5535d51358e33d3337783a410Timo Sirainen
5ba25fa97ceebd32d8c58a2d38b0b3f7fc5e67ccTimo Sirainenvoid hash_format_deinit(struct hash_format **_format, string_t *dest)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct hash_format *format = *_format;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *_format = NULL;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen hash_format_write(format, dest);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen pool_unref(&format->pool);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenvoid hash_format_deinit_free(struct hash_format **_format)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct hash_format *format = *_format;
3776ed607821b502468bdfd5a4533af3002125d1Timo Sirainen
62950eeff28f00989a17b20eeade3af7e200c6bcTimo Sirainen *_format = NULL;
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen pool_unref(&format->pool);
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen