Change priority from extra to optional in debian/control.
[debian/iodine.git] / src / encoding.c
index 4de10c63593b2ac9457c1bc7e5df57f41d85929c..af7620ea5919084b211c6e3db356fe87427b7cd1 100644 (file)
@@ -1,5 +1,6 @@
 /*
 /*
- * Copyright (c) 2006-2007 Bjorn Andersson <flex@kryo.se>, Erik Ekman <yarrick@kryo.se>
+ * Copyright (c) 2006-2014 Erik Ekman <yarrick@kryo.se>,
+ * 2006-2009 Bjorn Andersson <flex@kryo.se>
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  *
  * Permission to use, copy, modify, and distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#include <stdio.h>
-#include <strings.h>
 #include <string.h>
 #include <string.h>
+#include "common.h"
+#include "encoding.h"
 
 
-/* For FreeBSD */
-#ifndef MIN
-#define MIN(a,b) ((a)<(b)?(a):(b))
-#endif
+int
+build_hostname(char *buf, size_t buflen,
+               const char *data, const size_t datalen,
+               const char *topdomain, struct encoder *encoder, int maxlen)
+{
+       size_t space;
+       char *b;
 
 
-#define SPACING 63
-#define ENC_CHUNK 8
-#define RAW_CHUNK 5
+       space = MIN((size_t)maxlen, buflen) - strlen(topdomain) - 8;
+       /* 8 = 5 max header length + 1 dot before topdomain + 2 safety */
 
 
-static const char base32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ98765-";
-static const char padder[] = " 1234";
-static char reverse32[128];
-static int reverse_init = 0;
+       if (!encoder->places_dots())
+               space -= (space / 57); /* space for dots */
 
 
-/* Eat 5 bytes from src, write 8 bytes to dest */
-static void
-encode_chunk(char *dest, const char *src)
-{
-       unsigned char c;
+       memset(buf, 0, buflen);
 
 
-       *dest++ = base32[(*src & 0xF8) >> 3];   /* 1111 1000 first byte */
+       encoder->encode(buf, &space, data, datalen);
 
 
-       c = (*src++ & 0x07) << 2;               /* 0000 0111 first byte */
-       c |=  ((*src & 0xC0) >> 6);             /* 1100 0000 second byte */
-       *dest++ = base32[(int) c];
+       if (!encoder->places_dots())
+               inline_dotify(buf, buflen);
 
 
-       *dest++ = base32[(*src & 0x3E) >> 1];   /* 0011 1110 second byte */
+       b = buf;
+       b += strlen(buf);
 
 
-       c = (*src++ & 0x01) << 4;               /* 0000 0001 second byte */
-       c |=  ((*src & 0xF0) >> 4);             /* 1111 0000 third byte */
-       *dest++ = base32[(int) c];
-       
-       c = (*src++ & 0x0F) << 1;               /* 0000 1111 third byte */
-       c |=  ((*src & 0x80) >> 7);             /* 1000 0000 fourth byte */
-       *dest++ = base32[(int) c];
-       
-       *dest++ = base32[(*src & 0x7C) >> 2];   /* 0111 1100 fourth byte */
+       /* move b back one step to see if the dot is there */
+       b--;
+       if (*b != '.')
+               *++b = '.';
+       b++;
+       /* move b ahead of the string so we can copy to it */
 
 
-       c = (*src++ & 0x03) << 3;               /* 0000 0011 fourth byte */
-       c |=  ((*src & 0xE0) >> 5);             /* 1110 0000 fifth byte */
-       *dest++ = base32[(int) c];
+       strncpy(b, topdomain, strlen(topdomain)+1);
 
 
-       *dest++ = base32[*src++ & 0x1F];        /* 0001 1111 fifth byte */
+       return space;
 }
 
 }
 
-/* Eat 8 bytes from src, write 5 bytes to dest */
-static void
-decode_chunk(char *dest, char *src)
+int
+unpack_data(char *buf, size_t buflen, char *data, size_t datalen, struct encoder *enc)
 {
 {
-       unsigned char c;
-       int i;
-
-       if (!reverse_init) {
-               for (i = 0; i < 32; i++) {
-                       c = base32[i];
-                       reverse32[(int) c] = i;
-               }
-               reverse_init = 1;
-       }
-
-       c = reverse32[(int) *src++] << 3;               /* Take bits 11111 from byte 1 */
-       c |= (reverse32[(int) *src] & 0x1C) >> 2;       /* Take bits 11100 from byte 2 */
-       *dest++ = c;
-       
-       c = (reverse32[(int) *src++] & 0x3) << 6;       /* Take bits 00011 from byte 2 */
-       c |= reverse32[(int) *src++] << 1;              /* Take bits 11111 from byte 3 */
-       c |= (reverse32[(int) *src] & 0x10) >> 4;       /* Take bits 10000 from byte 4 */
-       *dest++ = c;
-       
-       c = (reverse32[(int) *src++] & 0xF) << 4;       /* Take bits 01111 from byte 4 */
-       c |= (reverse32[(int) *src] & 0x1E) >> 1;       /* Take bits 11110 from byte 5 */
-       *dest++ = c;
-       
-       c = reverse32[(int) *src++] << 7;               /* Take bits 00001 from byte 5 */
-       c |= reverse32[(int) *src++] << 2;              /* Take bits 11111 from byte 6 */
-       c |= (reverse32[(int) *src] & 0x18) >> 3;       /* Take bits 11000 from byte 7 */
-       *dest++ = c;
-       
-       c = (reverse32[(int) *src++] & 0x7) << 5;       /* Take bits 00111 from byte 7 */
-       c |= reverse32[(int) *src++];                   /* Take bits 11111 from byte 8 */
-       *dest++ = c;
+       if (!enc->eats_dots())
+               datalen = inline_undotify(data, datalen);
+       return enc->decode(buf, &buflen, data, datalen);
 }
 
 int
 }
 
 int
-encode_data(const char *buf, const size_t len, int space, char *dest)
+inline_dotify(char *buf, size_t buflen)
 {
 {
-       int final;
-       int write;
-       int realwrite;
-       int chunks;
-       int leftovers;
-       int i;
-       char encoded[255];
-       char padding[5];
-       const char *dp;
-       char *pp;
-       char *ep;
-
-       space -= space / SPACING;
-       chunks = (space - 1) / ENC_CHUNK;
-       while ((chunks + 1) * ENC_CHUNK + 1 > space) {
-               chunks--;
-       }
-       write = RAW_CHUNK * chunks;
-       write = MIN(write, len); /* do not use more bytes than is available; */
-       final = (write == len); /* is this the last block? */
-       chunks = write / RAW_CHUNK;
-       leftovers = write % RAW_CHUNK;
-
-       memset(encoded, 0, sizeof(encoded));
-       ep = encoded;
-       dp = buf;
-       for (i = 0; i < chunks; i++) {
-               encode_chunk(ep, dp);
-               ep += ENC_CHUNK;
-               dp += RAW_CHUNK;
-       }
-       realwrite = ENC_CHUNK * chunks;
-       memset(padding, 0, sizeof(padding));
-       pp = padding;
-       if (leftovers) {
-               pp += RAW_CHUNK - leftovers;
-               memcpy(pp, dp, leftovers);
-
-               pp = padding;
-               *ep++ = padder[leftovers];
-               encode_chunk(ep, pp);
-               
-               realwrite += ENC_CHUNK + 1;     /* plus padding character */
+       unsigned dots;
+       unsigned pos;
+       unsigned total;
+       char *reader, *writer;
+
+       total = strlen(buf);
+       dots = total / 57;
+
+       writer = buf;
+       writer += total;
+       writer += dots;
+
+       total += dots;
+       if (strlen(buf) + dots > buflen) {
+               writer = buf;
+               writer += buflen;
+               total = buflen;
        }
        }
-       ep = encoded;
-       if (len > 0) {
-               for (i = 1; i <= realwrite; i++) {
-                       if (i % SPACING == 0) {
-                               *dest++ = '.';
-                       }
-                       *dest++ = *ep++;
+
+       reader = writer - dots;
+       pos = (unsigned) (reader - buf) + 1;
+
+       while (dots) {
+               *writer-- = *reader--;
+               pos--;
+               if (pos % 57 == 0) {
+                       *writer-- = '.';
+                       dots--;
                }
        }
                }
        }
-       
-       return write;
+
+       /* return new length of string */
+       return total;
 }
 
 int
 }
 
 int
-decode_data(char *dest, int size, const char *src, char *srcend)
+inline_undotify(char *buf, size_t len)
 {
 {
-       int len;
-       int i;
-       int chunks;
-       int padded;
-       char encoded[255];
-       char padding[5];
-       int enclen;
-       char *pp;
-       char *ep;
-
-       memset(encoded, 0, sizeof(encoded));
-       memset(dest, 0, size);
-
-       /* First byte is not encoded */
-       *dest++ = *src++;
-       len = 1;
-
-       ep = encoded;
-       enclen = 0;
-       while(enclen < sizeof(encoded) && src < srcend) {
-               if(*src == '.') {
-                       src++;
+       unsigned pos;
+       unsigned dots;
+       char *reader, *writer;
+
+       writer = buf;
+       reader = writer;
+
+       pos = 0;
+       dots = 0;
+
+       while (pos < len) {
+               if (*reader == '.') {
+                       reader++;
+                       pos++;
+                       dots++;
                        continue;
                }
                        continue;
                }
-
-               *ep++ = *src++;
-               enclen++;
-       }
-       chunks = enclen / 8;
-       padded = enclen % 8;
-
-       ep = encoded;
-       for (i = 0; i < chunks-1; i++) {
-               decode_chunk(dest, ep);
-               dest += RAW_CHUNK;
-               ep += ENC_CHUNK;
-               len += RAW_CHUNK;
-       }
-       /* Read last chunk */
-       if (padded) {
-               pp = padding;
-               padded = *ep++ - '0';
-               decode_chunk(pp, ep);
-               pp += RAW_CHUNK - padded;
-               memcpy(dest, pp, padded);
-               len += padded;
-       } else {
-               decode_chunk(dest, ep);
-               len += RAW_CHUNK;
+               *writer++ = *reader++;
+               pos++;
        }
 
        }
 
-       return len;
+       /* return new length of string */
+       return len - dots;
 }
 }
-