Browse Source

fdm: new package added

Signed-off-by: Dmitry V. Zimin <pfzim@mail.ru>
Dmitry V. Zimin 10 years ago
parent
commit
c400fe3b09

+ 10
- 0
mail/fdm/Config.in View File

@@ -0,0 +1,10 @@
1
+menu "Configuration"
2
+	depends on PACKAGE_fdm
3
+
4
+config FDM_WITH_PCRE
5
+	bool
6
+	default y
7
+	select libpcre
8
+	prompt "Enable PCRE support (elsewhere POSIX regex)"
9
+
10
+endmenu

+ 86
- 0
mail/fdm/Makefile View File

@@ -0,0 +1,86 @@
1
+#
2
+# Copyright (C) 2007-2014 OpenWrt.org
3
+#
4
+# This is free software, licensed under the GNU General Public License v2.
5
+# See /LICENSE for more information.
6
+#
7
+
8
+include $(TOPDIR)/rules.mk
9
+
10
+PKG_NAME:=fdm
11
+PKG_VERSION:=1.7
12
+PKG_RELEASE:=1
13
+PKG_LICENSE:=BSD-2-Clause
14
+
15
+PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
16
+PKG_SOURCE_URL:=@SF/fdm
17
+PKG_MD5SUM:=aea0421571e8f3ec8f747a5d72c84348
18
+
19
+PKG_INSTALL:=1
20
+
21
+include $(INCLUDE_DIR)/package.mk
22
+
23
+define Package/fdm
24
+  SECTION:=mail
25
+  CATEGORY:=Mail
26
+  TITLE:=fetch mail and deliver
27
+  URL:=http://fdm.sourceforge.net/
28
+  MAINTAINER:=Dmitry V. Zimin <pfzim@mail.ru>
29
+  MENU:=1
30
+  DEPENDS:=+tdb +zlib +libopenssl +FDM_WITH_PCRE:libpcre
31
+  USERID:=_fdm=99:_fdm=99
32
+endef
33
+
34
+define Package/fdm/description
35
+  fdm is a simple, lightweight replacement for mail fetch, filter
36
+  and delivery programs such as fetchmail and procmail. It can
37
+  fetch using POP3 or IMAP (with SSL) or from stdin, and deliver
38
+  to a pipe, file, maildir, mbox or SMTP server, based on $(if $(CONFIG_FDM_WITH_PCRE),PCRE,POSIX regexp)
39
+endef
40
+
41
+MAKE_FLAGS += \
42
+	PREFIX="/usr"\
43
+	$(if $(CONFIG_FDM_WITH_PCRE),PCRE=1)
44
+
45
+define Build/Prepare
46
+	$(call Build/Prepare/Default)
47
+	$(CP) ./src/compat/* $(PKG_BUILD_DIR)/
48
+endef
49
+
50
+define Package/fdm/config
51
+	source "$(SOURCE)/Config.in
52
+endef
53
+
54
+define Package/fdm/conffiles
55
+/etc/fdm.conf
56
+endef
57
+
58
+define Package/fdm/install
59
+	$(INSTALL_DIR) $(1)/usr/bin
60
+	$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/* $(1)/usr/bin/
61
+	$(INSTALL_DIR) $(1)/etc
62
+	$(INSTALL_DATA) ./files/etc/* $(1)/etc/
63
+	$(INSTALL_DIR) $(1)/opt/fdm
64
+	chmod a+rwx $(1)/opt/fdm
65
+endef
66
+
67
+define Package/fdm/postinst
68
+#!/bin/sh
69
+if [ -z "$${IPKG_INSTROOT}" ]; then
70
+	echo "Creating cron job template for user _fdm..."
71
+	(crontab -l -u _fdm 2>/dev/null; echo "# */13 * * * * fdm -q fetch") | crontab -u _fdm -
72
+	echo "Please, edit file /etc/fdm.conf and enable cron job!"
73
+fi
74
+exit 0
75
+endef
76
+
77
+define Package/fdm/prerm
78
+#!/bin/sh
79
+if [ -z "$${IPKG_INSTROOT}" ]; then
80
+	echo "Don't forget disable cron job!"
81
+	echo "# crontab -r -u _fdm"
82
+fi
83
+exit 0
84
+endef
85
+
86
+$(eval $(call BuildPackage,fdm))

+ 36
- 0
mail/fdm/files/etc/fdm.conf View File

@@ -0,0 +1,36 @@
1
+# /etc/fdm.conf example file
2
+# 1. Edit this file
3
+# 2. Test: fdm -vv fetch
4
+# 3. Enable cron job: crontab -e -u _fdm
5
+
6
+set maximum-size      3M
7
+set delete-oversized
8
+set queue-high        1
9
+set queue-low         0
10
+set purge-after       5
11
+set unmatched-mail    keep
12
+
13
+action "drop" drop
14
+action "keep" keep
15
+
16
+action "wakeup" exec "wol -h 192.168.0.255 -p 9 00:11:22:33:44:55"
17
+action "my-test-action" exec "echo \"OK\" > /tmp/fdm.ok"
18
+
19
+# This action extract *.torrent files from incoming email and put it
20
+# to watch-dir your torrect client application
21
+
22
+action "torrent-add" pipe "munpack -f -q -C /your-path/watch-dir/ ; for i in /your-path/watch-dir/*.torrent ; do chmod a+r \$i ; done"
23
+
24
+account "xbmc" disabled
25
+        pop3s
26
+        server   "pop.yandex.ru"
27
+        port     995
28
+        user     "username-enter-here"
29
+        pass     "password-enter-here"
30
+        new-only
31
+        cache    "/opt/fdm/cache"
32
+
33
+match "^Subject:[ \t]+openwrt:[ \t]*wakeup[ \t]*$" in headers actions { "wakeup" "drop" }
34
+match "^Subject:[ \t]+openwrt:[ \t]*torrent[ \t]+add[ \t]*\$" in headers actions { "torrent-add" "drop" }
35
+match "^Subject:[ \t]+openwrt:[ \t]*test[ \t]*$" in headers actions { "my-test-action" "drop" }
36
+match all action "keep"

+ 14
- 0
mail/fdm/patches/001-base64-fix.patch View File

@@ -0,0 +1,14 @@
1
+--- a/fdm.h	2011-10-10 17:36:29.000000000 +0400
2
++++ b/fdm.h	2014-11-13 12:56:59.217083683 +0300
3
+@@ -719,6 +719,11 @@
4
+ size_t	 	 strlcat(char *, const char *, size_t);
5
+ #endif
6
+ 
7
++int local_b64_ntop(uint8_t const *src, size_t srclength, char *target,
8
++    size_t targsize);
9
++
10
++int local_b64_pton(char const *src, uint8_t *target, size_t targsize);
11
++
12
+ /* shm.c */
13
+ char  		*shm_path(struct shm *);
14
+ void		*shm_create(struct shm *, size_t);

+ 20
- 0
mail/fdm/patches/002-base64-fix.patch View File

@@ -0,0 +1,20 @@
1
+--- a/imap-common.c	2011-12-20 00:19:03.000000000 +0400
2
++++ b/imap-common.c	2014-11-13 12:56:06.930418446 +0300
3
+@@ -206,7 +206,7 @@
4
+ 
5
+ 	size = (strlen(in) * 2) + 1;
6
+ 	out = xcalloc(1, size);
7
+-	if (b64_ntop(in, strlen(in), out, size) < 0) {
8
++	if (local_b64_ntop(in, strlen(in), out, size) < 0) {
9
+ 		xfree(out);
10
+ 		return (NULL);
11
+ 	}
12
+@@ -222,7 +222,7 @@
13
+ 
14
+ 	size = (strlen(in) * 4) + 1;
15
+ 	out = xcalloc(1, size);
16
+-	if (b64_pton(in, out, size) < 0) {
17
++	if (local_b64_pton(in, out, size) < 0) {
18
+ 		xfree(out);
19
+ 		return (NULL);
20
+ 	}

+ 183
- 0
mail/fdm/src/compat/b64_ntop.c View File

@@ -0,0 +1,183 @@
1
+/*
2
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15
+ * SOFTWARE.
16
+ */
17
+
18
+/*
19
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
20
+ *
21
+ * International Business Machines, Inc. (hereinafter called IBM) grants
22
+ * permission under its copyrights to use, copy, modify, and distribute this
23
+ * Software with or without fee, provided that the above copyright notice and
24
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
25
+ * not be used in connection with the marketing of any product incorporating
26
+ * the Software or modifications thereof, without specific, written prior
27
+ * permission.
28
+ *
29
+ * To the extent it has a right to do so, IBM grants an immunity from suit
30
+ * under its patents, if any, for the use, sale or manufacture of products to
31
+ * the extent that such products are used for performing Domain Name System
32
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
33
+ * granted for any product per se or for any other function of any product.
34
+ *
35
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
36
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
38
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
39
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
40
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
41
+ */
42
+//#include <config.h>
43
+
44
+#include <sys/types.h>
45
+#include <sys/param.h>
46
+#include <sys/socket.h>
47
+
48
+#include <netinet/in.h>
49
+#include <arpa/inet.h>
50
+
51
+#include <ctype.h>
52
+#include <stdio.h>
53
+#include <stdlib.h>
54
+#include <string.h>
55
+
56
+#include "fdm.h"
57
+
58
+#define Assert(Cond) if (!(Cond)) abort()
59
+
60
+static const char Base64[] =
61
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
62
+static const char Pad64 = '=';
63
+
64
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
65
+   The following encoding technique is taken from RFC 1521 by Borenstein
66
+   and Freed.  It is reproduced here in a slightly edited form for
67
+   convenience.
68
+
69
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
70
+   represented per printable character. (The extra 65th character, "=",
71
+   is used to signify a special processing function.)
72
+
73
+   The encoding process represents 24-bit groups of input bits as output
74
+   strings of 4 encoded characters. Proceeding from left to right, a
75
+   24-bit input group is formed by concatenating 3 8-bit input groups.
76
+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
77
+   of which is translated into a single digit in the base64 alphabet.
78
+
79
+   Each 6-bit group is used as an index into an array of 64 printable
80
+   characters. The character referenced by the index is placed in the
81
+   output string.
82
+
83
+                         Table 1: The Base64 Alphabet
84
+
85
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
86
+          0 A            17 R            34 i            51 z
87
+          1 B            18 S            35 j            52 0
88
+          2 C            19 T            36 k            53 1
89
+          3 D            20 U            37 l            54 2
90
+          4 E            21 V            38 m            55 3
91
+          5 F            22 W            39 n            56 4
92
+          6 G            23 X            40 o            57 5
93
+          7 H            24 Y            41 p            58 6
94
+          8 I            25 Z            42 q            59 7
95
+          9 J            26 a            43 r            60 8
96
+         10 K            27 b            44 s            61 9
97
+         11 L            28 c            45 t            62 +
98
+         12 M            29 d            46 u            63 /
99
+         13 N            30 e            47 v
100
+         14 O            31 f            48 w         (pad) =
101
+         15 P            32 g            49 x
102
+         16 Q            33 h            50 y
103
+
104
+   Special processing is performed if fewer than 24 bits are available
105
+   at the end of the data being encoded.  A full encoding quantum is
106
+   always completed at the end of a quantity.  When fewer than 24 input
107
+   bits are available in an input group, zero bits are added (on the
108
+   right) to form an integral number of 6-bit groups.  Padding at the
109
+   end of the data is performed using the '=' character.
110
+
111
+   Since all base64 input is an integral number of octets, only the
112
+   following cases can arise:
113
+
114
+       (1) the final quantum of encoding input is an integral
115
+           multiple of 24 bits; here, the final unit of encoded
116
+	   output will be an integral multiple of 4 characters
117
+	   with no "=" padding,
118
+       (2) the final quantum of encoding input is exactly 8 bits;
119
+           here, the final unit of encoded output will be two
120
+	   characters followed by two "=" padding characters, or
121
+       (3) the final quantum of encoding input is exactly 16 bits;
122
+           here, the final unit of encoded output will be three
123
+	   characters followed by one "=" padding character.
124
+   */
125
+
126
+int
127
+local_b64_ntop(uint8_t const *src, size_t srclength, char *target, size_t targsize) {
128
+	size_t datalength = 0;
129
+	uint8_t input[3];
130
+	uint8_t output[4];
131
+	size_t i;
132
+
133
+	while (2 < srclength) {
134
+		input[0] = *src++;
135
+		input[1] = *src++;
136
+		input[2] = *src++;
137
+		srclength -= 3;
138
+
139
+		output[0] = input[0] >> 2;
140
+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
141
+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
142
+		output[3] = input[2] & 0x3f;
143
+		Assert(output[0] < 64);
144
+		Assert(output[1] < 64);
145
+		Assert(output[2] < 64);
146
+		Assert(output[3] < 64);
147
+
148
+		if (datalength + 4 > targsize)
149
+			return (-1);
150
+		target[datalength++] = Base64[output[0]];
151
+		target[datalength++] = Base64[output[1]];
152
+		target[datalength++] = Base64[output[2]];
153
+		target[datalength++] = Base64[output[3]];
154
+	}
155
+
156
+	/* Now we worry about padding. */
157
+	if (0 != srclength) {
158
+		/* Get what's left. */
159
+		input[0] = input[1] = input[2] = '\0';
160
+		for (i = 0; i < srclength; i++)
161
+			input[i] = *src++;
162
+		output[0] = input[0] >> 2;
163
+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
164
+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
165
+		Assert(output[0] < 64);
166
+		Assert(output[1] < 64);
167
+		Assert(output[2] < 64);
168
+
169
+		if (datalength + 4 > targsize)
170
+			return (-1);
171
+		target[datalength++] = Base64[output[0]];
172
+		target[datalength++] = Base64[output[1]];
173
+		if (srclength == 1)
174
+			target[datalength++] = Pad64;
175
+		else
176
+			target[datalength++] = Base64[output[2]];
177
+		target[datalength++] = Pad64;
178
+	}
179
+	if (datalength >= targsize)
180
+		return (-1);
181
+	target[datalength] = '\0'; /* Returned value doesn't count \0. */
182
+	return (datalength);
183
+}

+ 393
- 0
mail/fdm/src/compat/b64_pton.c View File

@@ -0,0 +1,393 @@
1
+/*
2
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
9
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
10
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
11
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
13
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
14
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15
+ * SOFTWARE.
16
+ */
17
+
18
+/*
19
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
20
+ *
21
+ * International Business Machines, Inc. (hereinafter called IBM) grants
22
+ * permission under its copyrights to use, copy, modify, and distribute this
23
+ * Software with or without fee, provided that the above copyright notice and
24
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
25
+ * not be used in connection with the marketing of any product incorporating
26
+ * the Software or modifications thereof, without specific, written prior
27
+ * permission.
28
+ *
29
+ * To the extent it has a right to do so, IBM grants an immunity from suit
30
+ * under its patents, if any, for the use, sale or manufacture of products to
31
+ * the extent that such products are used for performing Domain Name System
32
+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
33
+ * granted for any product per se or for any other function of any product.
34
+ *
35
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
36
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37
+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
38
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
39
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
40
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
41
+ */
42
+//#include <config.h>
43
+
44
+#include <sys/types.h>
45
+#include <sys/param.h>
46
+#include <sys/socket.h>
47
+
48
+#include <netinet/in.h>
49
+#include <arpa/inet.h>
50
+
51
+#include <ctype.h>
52
+#include <stdio.h>
53
+#include <stdlib.h>
54
+#include <string.h>
55
+
56
+#include "fdm.h"
57
+
58
+#define Assert(Cond) if (!(Cond)) abort()
59
+
60
+static const char Base64[] =
61
+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
62
+static const char Pad64 = '=';
63
+
64
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
65
+   The following encoding technique is taken from RFC 1521 by Borenstein
66
+   and Freed.  It is reproduced here in a slightly edited form for
67
+   convenience.
68
+
69
+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
70
+   represented per printable character. (The extra 65th character, "=",
71
+   is used to signify a special processing function.)
72
+
73
+   The encoding process represents 24-bit groups of input bits as output
74
+   strings of 4 encoded characters. Proceeding from left to right, a
75
+   24-bit input group is formed by concatenating 3 8-bit input groups.
76
+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
77
+   of which is translated into a single digit in the base64 alphabet.
78
+
79
+   Each 6-bit group is used as an index into an array of 64 printable
80
+   characters. The character referenced by the index is placed in the
81
+   output string.
82
+
83
+                         Table 1: The Base64 Alphabet
84
+
85
+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
86
+          0 A            17 R            34 i            51 z
87
+          1 B            18 S            35 j            52 0
88
+          2 C            19 T            36 k            53 1
89
+          3 D            20 U            37 l            54 2
90
+          4 E            21 V            38 m            55 3
91
+          5 F            22 W            39 n            56 4
92
+          6 G            23 X            40 o            57 5
93
+          7 H            24 Y            41 p            58 6
94
+          8 I            25 Z            42 q            59 7
95
+          9 J            26 a            43 r            60 8
96
+         10 K            27 b            44 s            61 9
97
+         11 L            28 c            45 t            62 +
98
+         12 M            29 d            46 u            63 /
99
+         13 N            30 e            47 v
100
+         14 O            31 f            48 w         (pad) =
101
+         15 P            32 g            49 x
102
+         16 Q            33 h            50 y
103
+
104
+   Special processing is performed if fewer than 24 bits are available
105
+   at the end of the data being encoded.  A full encoding quantum is
106
+   always completed at the end of a quantity.  When fewer than 24 input
107
+   bits are available in an input group, zero bits are added (on the
108
+   right) to form an integral number of 6-bit groups.  Padding at the
109
+   end of the data is performed using the '=' character.
110
+
111
+   Since all base64 input is an integral number of octets, only the
112
+   following cases can arise:
113
+
114
+       (1) the final quantum of encoding input is an integral
115
+           multiple of 24 bits; here, the final unit of encoded
116
+	   output will be an integral multiple of 4 characters
117
+	   with no "=" padding,
118
+       (2) the final quantum of encoding input is exactly 8 bits;
119
+           here, the final unit of encoded output will be two
120
+	   characters followed by two "=" padding characters, or
121
+       (3) the final quantum of encoding input is exactly 16 bits;
122
+           here, the final unit of encoded output will be three
123
+	   characters followed by one "=" padding character.
124
+   */
125
+
126
+/* skips all whitespace anywhere.
127
+   converts characters, four at a time, starting at (or after)
128
+   src from base - 64 numbers into three 8 bit bytes in the target area.
129
+   it returns the number of data bytes stored at the target, or -1 on error.
130
+ */
131
+
132
+static int b64rmap_initialized = 0;
133
+static uint8_t b64rmap[256];
134
+
135
+static const uint8_t b64rmap_special = 0xf0;
136
+static const uint8_t b64rmap_end = 0xfd;
137
+static const uint8_t b64rmap_space = 0xfe;
138
+static const uint8_t b64rmap_invalid = 0xff;
139
+
140
+/**
141
+ * Initializing the reverse map is not thread safe.
142
+ * Which is fine for NSD. For now...
143
+ **/
144
+static void
145
+b64_initialize_rmap ()
146
+{
147
+	int i;
148
+	char ch;
149
+
150
+	/* Null: end of string, stop parsing */
151
+	b64rmap[0] = b64rmap_end;
152
+
153
+	for (i = 1; i < 256; ++i) {
154
+		ch = (char)i;
155
+		/* Whitespaces */
156
+		if (isspace(ch))
157
+			b64rmap[i] = b64rmap_space;
158
+		/* Padding: stop parsing */
159
+		else if (ch == Pad64)
160
+			b64rmap[i] = b64rmap_end;
161
+		/* Non-base64 char */
162
+		else
163
+			b64rmap[i] = b64rmap_invalid;
164
+	}
165
+
166
+	/* Fill reverse mapping for base64 chars */
167
+	for (i = 0; Base64[i] != '\0'; ++i)
168
+		b64rmap[(uint8_t)Base64[i]] = i;
169
+
170
+	b64rmap_initialized = 1;
171
+}
172
+
173
+static int
174
+b64_pton_do(char const *src, uint8_t *target, size_t targsize)
175
+{
176
+	int tarindex, state, ch;
177
+	uint8_t ofs;
178
+
179
+	state = 0;
180
+	tarindex = 0;
181
+
182
+	while (1)
183
+	{
184
+		ch = *src++;
185
+		ofs = b64rmap[ch];
186
+
187
+		if (ofs >= b64rmap_special) {
188
+			/* Ignore whitespaces */
189
+			if (ofs == b64rmap_space)
190
+				continue;
191
+			/* End of base64 characters */
192
+			if (ofs == b64rmap_end)
193
+				break;
194
+			/* A non-base64 character. */
195
+			return (-1);
196
+		}
197
+
198
+		switch (state) {
199
+		case 0:
200
+			if ((size_t)tarindex >= targsize)
201
+				return (-1);
202
+			target[tarindex] = ofs << 2;
203
+			state = 1;
204
+			break;
205
+		case 1:
206
+			if ((size_t)tarindex + 1 >= targsize)
207
+				return (-1);
208
+			target[tarindex]   |=  ofs >> 4;
209
+			target[tarindex+1]  = (ofs & 0x0f)
210
+						<< 4 ;
211
+			tarindex++;
212
+			state = 2;
213
+			break;
214
+		case 2:
215
+			if ((size_t)tarindex + 1 >= targsize)
216
+				return (-1);
217
+			target[tarindex]   |=  ofs >> 2;
218
+			target[tarindex+1]  = (ofs & 0x03)
219
+						<< 6;
220
+			tarindex++;
221
+			state = 3;
222
+			break;
223
+		case 3:
224
+			if ((size_t)tarindex >= targsize)
225
+				return (-1);
226
+			target[tarindex] |= ofs;
227
+			tarindex++;
228
+			state = 0;
229
+			break;
230
+		default:
231
+			abort();
232
+		}
233
+	}
234
+
235
+	/*
236
+	 * We are done decoding Base-64 chars.  Let's see if we ended
237
+	 * on a byte boundary, and/or with erroneous trailing characters.
238
+	 */
239
+
240
+	if (ch == Pad64) {		/* We got a pad char. */
241
+		ch = *src++;		/* Skip it, get next. */
242
+		switch (state) {
243
+		case 0:		/* Invalid = in first position */
244
+		case 1:		/* Invalid = in second position */
245
+			return (-1);
246
+
247
+		case 2:		/* Valid, means one byte of info */
248
+			/* Skip any number of spaces. */
249
+			for ((void)NULL; ch != '\0'; ch = *src++)
250
+				if (b64rmap[ch] != b64rmap_space)
251
+					break;
252
+			/* Make sure there is another trailing = sign. */
253
+			if (ch != Pad64)
254
+				return (-1);
255
+			ch = *src++;		/* Skip the = */
256
+			/* Fall through to "single trailing =" case. */
257
+			/* FALLTHROUGH */
258
+
259
+		case 3:		/* Valid, means two bytes of info */
260
+			/*
261
+			 * We know this char is an =.  Is there anything but
262
+			 * whitespace after it?
263
+			 */
264
+			for ((void)NULL; ch != '\0'; ch = *src++)
265
+				if (b64rmap[ch] != b64rmap_space)
266
+					return (-1);
267
+
268
+			/*
269
+			 * Now make sure for cases 2 and 3 that the "extra"
270
+			 * bits that slopped past the last full byte were
271
+			 * zeros.  If we don't check them, they become a
272
+			 * subliminal channel.
273
+			 */
274
+			if (target[tarindex] != 0)
275
+				return (-1);
276
+		}
277
+	} else {
278
+		/*
279
+		 * We ended by seeing the end of the string.  Make sure we
280
+		 * have no partial bytes lying around.
281
+		 */
282
+		if (state != 0)
283
+			return (-1);
284
+	}
285
+
286
+	return (tarindex);
287
+}
288
+
289
+
290
+static int
291
+b64_pton_len(char const *src)
292
+{
293
+	int tarindex, state, ch;
294
+	uint8_t ofs;
295
+
296
+	state = 0;
297
+	tarindex = 0;
298
+
299
+	while (1)
300
+	{
301
+		ch = *src++;
302
+		ofs = b64rmap[ch];
303
+
304
+		if (ofs >= b64rmap_special) {
305
+			/* Ignore whitespaces */
306
+			if (ofs == b64rmap_space)
307
+				continue;
308
+			/* End of base64 characters */
309
+			if (ofs == b64rmap_end)
310
+				break;
311
+			/* A non-base64 character. */
312
+			return (-1);
313
+		}
314
+
315
+		switch (state) {
316
+		case 0:
317
+			state = 1;
318
+			break;
319
+		case 1:
320
+			tarindex++;
321
+			state = 2;
322
+			break;
323
+		case 2:
324
+			tarindex++;
325
+			state = 3;
326
+			break;
327
+		case 3:
328
+			tarindex++;
329
+			state = 0;
330
+			break;
331
+		default:
332
+			abort();
333
+		}
334
+	}
335
+
336
+	/*
337
+	 * We are done decoding Base-64 chars.  Let's see if we ended
338
+	 * on a byte boundary, and/or with erroneous trailing characters.
339
+	 */
340
+
341
+	if (ch == Pad64) {		/* We got a pad char. */
342
+		ch = *src++;		/* Skip it, get next. */
343
+		switch (state) {
344
+		case 0:		/* Invalid = in first position */
345
+		case 1:		/* Invalid = in second position */
346
+			return (-1);
347
+
348
+		case 2:		/* Valid, means one byte of info */
349
+			/* Skip any number of spaces. */
350
+			for ((void)NULL; ch != '\0'; ch = *src++)
351
+				if (b64rmap[ch] != b64rmap_space)
352
+					break;
353
+			/* Make sure there is another trailing = sign. */
354
+			if (ch != Pad64)
355
+				return (-1);
356
+			ch = *src++;		/* Skip the = */
357
+			/* Fall through to "single trailing =" case. */
358
+			/* FALLTHROUGH */
359
+
360
+		case 3:		/* Valid, means two bytes of info */
361
+			/*
362
+			 * We know this char is an =.  Is there anything but
363
+			 * whitespace after it?
364
+			 */
365
+			for ((void)NULL; ch != '\0'; ch = *src++)
366
+				if (b64rmap[ch] != b64rmap_space)
367
+					return (-1);
368
+
369
+		}
370
+	} else {
371
+		/*
372
+		 * We ended by seeing the end of the string.  Make sure we
373
+		 * have no partial bytes lying around.
374
+		 */
375
+		if (state != 0)
376
+			return (-1);
377
+	}
378
+
379
+	return (tarindex);
380
+}
381
+
382
+
383
+int
384
+local_b64_pton(char const *src, uint8_t *target, size_t targsize)
385
+{
386
+	if (!b64rmap_initialized)
387
+		b64_initialize_rmap ();
388
+
389
+	if (target)
390
+		return b64_pton_do (src, target, targsize);
391
+	else
392
+		return b64_pton_len (src);
393
+}