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