1 /* GNU Mailutils -- a suite of utilities for electronic mail
2    Copyright (C) 2005-2021 Free Software Foundation, Inc.
3 
4    GNU Mailutils is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    GNU Mailutils is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <string.h>
24 
25 #include <mailutils/mailutils.h>
26 
27 /* Replace all octal escapes in BUF with the corresponding characters. */
28 static void
decode_octal(char * buf)29 decode_octal (char *buf)
30 {
31   char *p;
32   unsigned i, n;
33 
34   for (p = buf; *p;)
35     {
36       if (*buf == '\\')
37 	{
38 	  buf++;
39 	  switch (*buf)
40 	    {
41 	    case 'a':
42 	      *p++ = '\a';
43 	      buf++;
44 	      break;
45 
46 	    case 'b':
47 	      *p++ = '\b';
48 	      buf++;
49 	      break;
50 
51 	    case 'f':
52 	      *p++ = '\f';
53 	      buf++;
54 	      break;
55 
56 	    case 'n':
57 	      *p++ = '\n';
58 	      buf++;
59 	      break;
60 
61 	    case 'r':
62 	      *p++ = '\r';
63 	      buf++;
64 	      break;
65 
66 	    case 't':
67 	      *p++ = '\t';
68 	      buf++;
69 	      break;
70 
71 	    case '0': case '1': case '2': case '3':
72 	    case '4': case '5': case '6': case '7':
73 	      n = 0;
74 	      for (i = 0; i < 3; i++, buf++)
75 		{
76 		  unsigned x = *(unsigned char*)buf - '0';
77 		  if (x > 7)
78 		    break;
79 		  n <<= 3;
80 		  n += x;
81 		}
82 	      if (i != 3)
83 		{
84 		  buf -= i;
85 		  *p++ = '\\';
86 		}
87 	      else
88 		*p++ = n;
89 	      break;
90 
91 	    default:
92 	      *p++ = '\\';
93 	      *p++ = *buf++;
94 	      break;
95 	    }
96 	}
97       else
98 	*p++ = *buf++;
99     }
100   *p = 0;
101 }
102 
103 int
main(int argc,char * argv[])104 main (int argc, char *argv[])
105 {
106   int rc;
107   char *buf = NULL;
108   size_t size = 0;
109   size_t n;
110   char *charset = "iso-8859-1";
111   char *encoding = "quoted-printable";
112   int octal = 0;
113   struct mu_option options[] = {
114     { "charset", 'c', "NAME", MU_OPTION_DEFAULT,
115       "define input character set", mu_c_string, &charset },
116     { "encoding", 'e', "NAME", MU_OPTION_DEFAULT,
117       "define input encoding", mu_c_string, &encoding },
118     { "octal", 'o', NULL, MU_OPTION_DEFAULT,
119       "decode octal escape notations on input", mu_c_bool, &octal },
120     MU_OPTION_END
121   };
122 
123   mu_set_program_name (argv[0]);
124   mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
125   mu_cli_simple (argc, argv,
126                  MU_CLI_OPTION_OPTIONS, options,
127 		 MU_CLI_OPTION_PROG_DOC, "Test RFC 2047 encoding function",
128 		 MU_CLI_OPTION_EXTRA_INFO, "Defaults are: --charset=iso-8859-1 --encoding=quoted-printable",
129 		 MU_CLI_OPTION_END);
130 
131   while ((rc = mu_stream_getline (mu_strin, &buf, &size, &n)) == 0 && n > 0)
132     {
133       char *p;
134 
135       mu_rtrim_class (buf, MU_CTYPE_ENDLN);
136       if (octal)
137 	decode_octal (buf);
138 
139       rc = mu_rfc2047_encode (charset, encoding, buf, &p);
140       if (rc)
141 	mu_diag_funcall (MU_DIAG_ERROR, "mu_rfc2047_encode", NULL, rc);
142       else if (p)
143 	mu_printf ("%s\n", p);
144       free (p);
145     }
146   if (rc)
147     mu_diag_funcall (MU_DIAG_ERROR, "mu_stream_getline", NULL, rc);
148   return 0;
149 }
150