URI:
       tqp.c - scribo - Email-based phlog generator
  HTML git clone git://git.z3bra.org/scribo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tqp.c (2081B)
       ---
            1 #include <ctype.h>
            2 #include <stdint.h>
            3 #include <stdio.h>
            4 #include <stdlib.h>
            5 #include <string.h>
            6 #include <unistd.h>
            7 #include <limits.h>
            8 
            9 #include "qp.h"
           10 
           11 #define QP_FOLD 76
           12 
           13 static char *
           14 qp_bin2hex(const int in, char *out)
           15 {
           16         char hex[] = "0123456789ABCDEF";
           17 
           18         out[0]  = hex[(unsigned char)in >> 4];
           19         out[1]  = hex[(unsigned char)in & 15];
           20 
           21         return out;
           22 }
           23 
           24 static char
           25 qp_hex2bin(const unsigned char *in)
           26 {
           27         int out;
           28 
           29         if (*in == '=')
           30                 in++;
           31 
           32         if ('A' <= in[0] && in[0] <= 'F') out  = 16 * (in[0] - 'A' + 10);
           33         if ('0' <= in[0] && in[0] <= '9') out  = 16 * (in[0] - '0');
           34 
           35         if ('A' <= in[1] && in[1] <= 'F') out += (in[1] - 'A' + 10);
           36         if ('0' <= in[1] && in[1] <= '9') out += (in[1] - '0');
           37 
           38         return out;
           39 }
           40 
           41 /*
           42  * Encode the given message in qp, allocate memory to store the encoded
           43  * message, and return the size allocated.
           44  */
           45 size_t
           46 qp_encode(char **buf, const unsigned char *msg, size_t len)
           47 {
           48         size_t i, n;
           49         char *p;
           50 
           51         /* maximum size the encoded message can have */
           52         *buf = malloc(len * 3);
           53         if (!*buf)
           54                 return 0;
           55 
           56         p = *buf;
           57         memset(*buf, 0, len * 3);
           58 
           59         for (i = 0; i < len; i++) {
           60                 if (isascii(msg[i]) && msg[i] != '=') {
           61                         *(p++) = msg[i];
           62                         n++;
           63                 } else if (msg[i] == '=') {
           64                         strcpy(p, "==");
           65                         p += 2;
           66                         n += 2;
           67                 } else {
           68                         if (n > 72) {
           69                                 strcpy(p, "=\n");
           70                                 p += 2;
           71                                 n  = 0;
           72                         }
           73                         qp_bin2hex(msg[i], p);
           74                         p += 3;
           75                         n += 3;
           76                 }
           77                 if (n > 74) {
           78                         *(p++) = '=';
           79                         *(p++) = '\n';
           80                         n = 0;
           81                 }
           82         }
           83 
           84         return strnlen(*buf, len * 3);;
           85 }
           86 
           87 /*
           88  * Allocate size to decode a qp message, decode it in the buffer and
           89  * return the allocated size.
           90  */
           91 size_t
           92 qp_decode(char **buf, const unsigned char *msg, size_t len)
           93 {
           94         size_t i;
           95         char *p;
           96 
           97         /* maximum size the encoded message can have */
           98         *buf = malloc(len);
           99         if (!*buf)
          100                 return 0;
          101 
          102         p = *buf;
          103         memset(*buf, 0, len);
          104 
          105         for (i = 0; i < len && msg[i]; i++) {
          106                 if (msg[i] == '=') {
          107                         switch (msg[i+1]) {
          108                         case '\r': i++; /* FALLTHROUGH */
          109                         case '\n': i++; break;
          110                         default:
          111                                 *(p++) = qp_hex2bin(&msg[i]);
          112                                 i += 2;
          113                         }
          114                 } else {
          115                         *(p++) = msg[i];
          116                 }
          117         }
          118 
          119         return strnlen(*buf, len);
          120 }