1 |
werner |
36 |
#include <windows.h> |
2 |
|
|
#include <malloc.h> |
3 |
|
|
#include <string.h> |
4 |
|
|
#include <stdio.h> |
5 |
|
|
#include <errno.h> |
6 |
|
|
|
7 |
|
|
#include "w32gpgme.h" |
8 |
|
|
|
9 |
|
|
|
10 |
|
|
|
11 |
|
|
/* Soft line wrapping. */ |
12 |
|
|
static char* |
13 |
|
|
wrap_lines_soft (char *buf, int buflen, int wraplen) |
14 |
|
|
{ |
15 |
|
|
char *curpos, *lastspc, *lastbrk; |
16 |
|
|
|
17 |
|
|
for (curpos = lastspc = lastbrk = buf; *curpos; curpos++) { |
18 |
|
|
if (buflen-- < 1) |
19 |
|
|
break; |
20 |
|
|
if (*curpos == ' ') |
21 |
|
|
lastspc = curpos; |
22 |
|
|
else { |
23 |
|
|
if (*curpos == '\n') { |
24 |
|
|
lastbrk = curpos; |
25 |
|
|
lastspc = lastbrk; |
26 |
|
|
} |
27 |
|
|
} |
28 |
|
|
if ((curpos - lastbrk) >= wraplen) { |
29 |
|
|
*lastspc = '\n'; |
30 |
|
|
lastbrk = lastspc; |
31 |
|
|
} |
32 |
|
|
} |
33 |
|
|
return buf; |
34 |
|
|
} |
35 |
|
|
|
36 |
|
|
|
37 |
|
|
static char* |
38 |
|
|
wrap_lines (char *buf, size_t bufsize, size_t wraplen, size_t *r_len) |
39 |
|
|
{ |
40 |
|
|
char *soft, *buffer; |
41 |
|
|
gpgme_data_t in, out; |
42 |
|
|
int n; |
43 |
|
|
|
44 |
|
|
soft = wrap_lines_soft (buf, bufsize, wraplen); |
45 |
|
|
if (!soft) |
46 |
|
|
return NULL; |
47 |
|
|
buffer = calloc (1, wraplen+4); |
48 |
|
|
gpgme_data_new_from_mem (&in, soft, bufsize, 1); |
49 |
|
|
gpgme_data_new (&out); |
50 |
|
|
|
51 |
|
|
while ((n=gpg_data_readline (in, buffer, wraplen+3)) > 0) { |
52 |
|
|
if (buffer[n-1] == 0 && buffer[n-2] == 0x0a) |
53 |
|
|
n -= 2; |
54 |
|
|
gpgme_data_write (out, buffer, n); |
55 |
|
|
gpgme_data_write (out, "\r\n", 2); |
56 |
|
|
} |
57 |
|
|
gpgme_data_write (out, "", 1); |
58 |
|
|
free (buffer); |
59 |
|
|
gpgme_data_release (in); |
60 |
|
|
return gpgme_data_release_and_get_mem (out, r_len); |
61 |
|
|
} |
62 |
|
|
|
63 |
|
|
|
64 |
|
|
/* Wrap the lines of @r_dh with a line length of @wraplen. |
65 |
|
|
@r_dh will be released and on success it contains the |
66 |
|
|
handle to the wrapped data. |
67 |
|
|
Return value: 0 on success. */ |
68 |
|
|
gpgme_error_t |
69 |
|
|
gpg_data_wrap_lines (gpgme_data_t *r_dh, size_t wraplen) |
70 |
|
|
{ |
71 |
|
|
gpgme_error_t err; |
72 |
|
|
gpgme_data_t mdh; |
73 |
|
|
char *raw = NULL; |
74 |
|
|
char *p = NULL; |
75 |
|
|
size_t nlen; |
76 |
|
|
|
77 |
|
|
err = gpgme_data_new (&mdh); |
78 |
|
|
if (err) |
79 |
|
|
return err; |
80 |
|
|
|
81 |
|
|
raw = gpgme_data_release_and_get_mem (*r_dh, &nlen); |
82 |
|
|
if (!raw) { |
83 |
|
|
gpgme_data_release (mdh); |
84 |
|
|
return gpg_error (GPG_ERR_INV_ARG); |
85 |
|
|
} |
86 |
|
|
if (!memchr (raw, '\n', nlen) && nlen < wraplen) { |
87 |
|
|
/* Restore old data and rewind. */ |
88 |
|
|
gpgme_data_write (mdh, raw, nlen); |
89 |
|
|
gpgme_data_rewind (mdh); |
90 |
|
|
*r_dh = mdh; |
91 |
|
|
gpgme_free (raw); |
92 |
|
|
return 0; |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
p = wrap_lines (raw, nlen, wraplen, &nlen); |
96 |
|
|
if (p) { |
97 |
|
|
gpgme_data_write (mdh, p, nlen); |
98 |
|
|
gpgme_free (p); |
99 |
|
|
} |
100 |
|
|
gpgme_data_rewind (mdh); |
101 |
|
|
*r_dh = mdh; |
102 |
|
|
if (raw) |
103 |
|
|
gpgme_free (raw); |
104 |
|
|
return 0; |
105 |
|
|
} |
106 |
|
|
|
107 |
|
|
|
108 |
|
|
/* Prepend '> ' to each line into @r_dh. On success @r_dh |
109 |
|
|
contains a handle to the quoted data. |
110 |
|
|
Return value: 0 on success. */ |
111 |
|
|
gpgme_error_t |
112 |
|
|
gpg_data_mail_quote (gpgme_data_t *r_dh) |
113 |
|
|
{ |
114 |
|
|
gpgme_data_t dh; |
115 |
|
|
char buf[128]; |
116 |
|
|
|
117 |
|
|
if (!*r_dh) |
118 |
|
|
return gpg_error (GPG_ERR_INV_ARG); |
119 |
|
|
gpgme_data_new (&dh); |
120 |
|
|
while (gpg_data_readline (*r_dh, buf, 127)) { |
121 |
|
|
gpgme_data_write (dh, "> ", 2); |
122 |
|
|
gpgme_data_write (dh, buf, strlen (buf)); |
123 |
|
|
} |
124 |
|
|
gpgme_data_release (*r_dh); |
125 |
|
|
*r_dh = dh; |
126 |
|
|
return 0; |
127 |
|
|
} |
128 |
|
|
|
129 |
|
|
/* Extract the plaintext data from the escaped data object @sig. |
130 |
|
|
The plaintxt is stored in @r_plain. |
131 |
|
|
Return value: 0 on success. */ |
132 |
|
|
gpgme_error_t |
133 |
|
|
gpg_data_extract_plaintext (gpgme_data_t sig, gpgme_data_t *r_plain) |
134 |
|
|
{ |
135 |
|
|
gpgme_data_t plain; |
136 |
|
|
gpgme_error_t err; |
137 |
|
|
char line[128+32]; |
138 |
|
|
int pos = 0; |
139 |
|
|
int sig_begin = 0; |
140 |
|
|
|
141 |
|
|
if (r_plain) |
142 |
|
|
*r_plain = NULL; |
143 |
|
|
err = gpgme_data_new (&plain); |
144 |
|
|
if (err) |
145 |
|
|
return err; |
146 |
|
|
|
147 |
|
|
while (gpg_data_readline (sig, line, 128) > 0) { |
148 |
|
|
if (!strncmp (line, "-----BEGIN PGP SIGNED MESSAGE", 29) || |
149 |
|
|
!strncmp (line, "Version:", 8) || |
150 |
|
|
!strncmp (line, "Comment:", 8) || |
151 |
|
|
!strncmp (line, "Charset:", 8) || |
152 |
|
|
!strncmp (line, "Hash:", 5) || |
153 |
|
|
!strncmp (line, "MessageID", 9)) |
154 |
|
|
continue; |
155 |
|
|
if (strlen (line) <= 2) |
156 |
|
|
break; /* parsed all headers, now we reached the body */ |
157 |
|
|
} |
158 |
|
|
/* XXX handle multi dash escaped sequences */ |
159 |
|
|
while (gpg_data_readline (sig, line, 128) > 0 ) { |
160 |
|
|
if (!strncmp( line, "-----BEGIN PGP SIGNATURE", 24)) |
161 |
|
|
break; /* end of plaintext */ |
162 |
|
|
if (!strncmp (line, "- -", 3)) |
163 |
|
|
pos = 2; |
164 |
|
|
gpgme_data_write (plain, line+pos, strlen (line+pos)); |
165 |
|
|
pos = 0; |
166 |
|
|
} |
167 |
|
|
gpgme_data_write (plain, "", 1); |
168 |
|
|
if (r_plain) |
169 |
|
|
*r_plain = plain; |
170 |
|
|
else |
171 |
|
|
gpgme_data_release (plain); |
172 |
|
|
return err; |
173 |
|
|
} |
174 |
|
|
|
175 |
|
|
|
176 |
|
|
/* Release the data in @dh and store the contents in the file @fname. |
177 |
|
|
Return value: 0 on success. */ |
178 |
|
|
gpgme_error_t |
179 |
|
|
gpg_data_release_and_set_file (gpgme_data_t dh, const char *fname) |
180 |
|
|
{ |
181 |
|
|
char *p = NULL; |
182 |
|
|
FILE *fp; |
183 |
|
|
size_t n; |
184 |
|
|
|
185 |
|
|
fp = fopen (fname, "wb"); |
186 |
|
|
if (fp == NULL) |
187 |
|
|
return gpg_err_code_from_errno (errno); |
188 |
|
|
|
189 |
|
|
p = gpgme_data_release_and_get_mem (dh, &n); |
190 |
|
|
if (p) { |
191 |
|
|
fwrite (p, 1, n, fp); |
192 |
|
|
fflush (fp); |
193 |
|
|
memset (p, 0xFF, n); |
194 |
|
|
gpgme_free (p); |
195 |
|
|
} |
196 |
|
|
fclose (fp); |
197 |
|
|
return 0; |
198 |
|
|
} |
199 |
|
|
|
200 |
|
|
|
201 |
|
|
/* Try to read a line, terminated by \n from the given |
202 |
|
|
gpgme data object @dh into @line. |
203 |
|
|
Return value: numbers of chars read. */ |
204 |
|
|
size_t |
205 |
|
|
gpg_data_readline (gpgme_data_t dh, char *line, size_t nbytes) |
206 |
|
|
{ |
207 |
|
|
char ch = 0; |
208 |
|
|
int nread = 0, pos = 0; |
209 |
|
|
|
210 |
|
|
if (!dh) |
211 |
|
|
return 0; |
212 |
|
|
|
213 |
|
|
memset (line, 0, nbytes); |
214 |
|
|
while ((nread=gpgme_data_read (dh, &ch, 1)) > 0) { |
215 |
|
|
if (!nread) |
216 |
|
|
break; |
217 |
|
|
if (ch == '\n') { |
218 |
|
|
line[pos++] = ch; |
219 |
|
|
line[pos++] = '\0'; |
220 |
|
|
break; |
221 |
|
|
} |
222 |
|
|
line[pos++] = ch; |
223 |
|
|
if (pos > (int)nbytes) { |
224 |
|
|
line[pos++] = '\0'; |
225 |
|
|
break; |
226 |
|
|
} |
227 |
|
|
} |
228 |
|
|
|
229 |
|
|
return pos; |
230 |
|
|
} |