1 /* literal.c - Literal packet filters
2 * Copyright (C) 2002, 2003, 2008, 2009, 2010 Free Software Foundation,
7 * This file is part of OpenCDK.
9 * The OpenCDK library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1 of
12 * the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
36 /* Duplicate the string @s but strip of possible
37 relative folder names of it. */
39 dup_trim_filename (const char *s
)
45 p
= strrchr (s
, '\\');
47 return cdk_strdup (s
);
48 return cdk_strdup (p
+ 1);
53 literal_decode (void *data
, FILE * in
, FILE * out
)
55 literal_filter_t
*pfx
= data
;
64 _cdk_log_debug ("literal filter: decode\n");
66 if (!pfx
|| !in
|| !out
)
69 rc
= _cdk_stream_fpopen (in
, STREAMCTL_READ
, &si
);
74 rc
= cdk_pkt_read (si
, pkt
);
75 if (rc
|| pkt
->pkttype
!= CDK_PKT_LITERAL
)
77 cdk_pkt_release (pkt
);
78 cdk_stream_close (si
);
79 return !rc
? CDK_Inv_Packet
: rc
;
82 rc
= _cdk_stream_fpopen (out
, STREAMCTL_WRITE
, &so
);
85 cdk_pkt_release (pkt
);
86 cdk_stream_close (si
);
90 pt
= pkt
->pkt
.literal
;
93 if (pfx
->filename
&& pt
->namelen
> 0)
95 /* The name in the literal packet is more authorative. */
96 cdk_free (pfx
->filename
);
97 pfx
->filename
= dup_trim_filename (pt
->name
);
99 else if (!pfx
->filename
&& pt
->namelen
> 0)
100 pfx
->filename
= dup_trim_filename (pt
->name
);
101 else if (!pt
->namelen
&& !pfx
->filename
&& pfx
->orig_filename
)
103 /* In this case, we need to derrive the output file name
104 from the original name and cut off the OpenPGP extension.
105 If this is not possible, we return an error. */
106 if (!stristr (pfx
->orig_filename
, ".gpg") &&
107 !stristr (pfx
->orig_filename
, ".pgp") &&
108 !stristr (pfx
->orig_filename
, ".asc"))
110 cdk_pkt_release (pkt
);
111 cdk_stream_close (si
);
112 cdk_stream_close (so
);
114 ("literal filter: no file name and no PGP extension\n");
117 _cdk_log_debug ("literal filter: derrive file name from original\n");
118 pfx
->filename
= dup_trim_filename (pfx
->orig_filename
);
119 pfx
->filename
[strlen (pfx
->filename
) - 4] = '\0';
124 _cdk_log_debug ("literal_decode: part on %d size %lu\n",
125 (int) pfx
->blkmode
.on
, pfx
->blkmode
.size
);
127 bufsize
= pfx
->blkmode
.size
;
129 bufsize
= pt
->len
< DIM (buf
) ? pt
->len
: DIM (buf
);
130 nread
= cdk_stream_read (pt
->buf
, buf
, bufsize
);
136 if (pfx
->md_initialized
)
137 _gnutls_hash (&pfx
->md
, buf
, nread
);
138 cdk_stream_write (so
, buf
, nread
);
142 pfx
->blkmode
.size
= _cdk_pkt_read_len (in
, &pfx
->blkmode
.on
);
143 if ((ssize_t
) pfx
->blkmode
.size
== EOF
)
144 return CDK_Inv_Packet
;
146 if (pt
->len
<= 0 && !pfx
->blkmode
.on
)
150 cdk_stream_close (si
);
151 cdk_stream_close (so
);
152 cdk_pkt_release (pkt
);
158 intmode_to_char (int mode
)
162 case CDK_LITFMT_BINARY
:
164 case CDK_LITFMT_TEXT
:
166 case CDK_LITFMT_UNICODE
:
177 literal_encode (void *data
, FILE * in
, FILE * out
)
179 literal_filter_t
*pfx
= data
;
180 cdk_pkt_literal_t pt
;
186 _cdk_log_debug ("literal filter: encode\n");
188 if (!pfx
|| !in
|| !out
)
189 return CDK_Inv_Value
;
192 pfx
->filename
= cdk_strdup ("_CONSOLE");
194 return CDK_Out_Of_Core
;
197 rc
= _cdk_stream_fpopen (in
, STREAMCTL_READ
, &si
);
201 filelen
= strlen (pfx
->filename
);
203 pt
= pkt
->pkt
.literal
= cdk_calloc (1, sizeof *pt
+ filelen
);
204 pt
->name
= (char *) pt
+ sizeof (*pt
);
207 cdk_pkt_release (pkt
);
208 cdk_stream_close (si
);
209 return CDK_Out_Of_Core
;
211 memcpy (pt
->name
, pfx
->filename
, filelen
);
212 pt
->namelen
= filelen
;
213 pt
->name
[pt
->namelen
] = '\0';
214 pt
->timestamp
= (u32
) time (NULL
);
215 pt
->mode
= intmode_to_char (pfx
->mode
);
216 pt
->len
= cdk_stream_get_length (si
);
219 pkt
->pkttype
= CDK_PKT_LITERAL
;
220 pkt
->pkt
.literal
= pt
;
221 rc
= _cdk_pkt_write_fp (out
, pkt
);
223 cdk_pkt_release (pkt
);
224 cdk_stream_close (si
);
230 _cdk_filter_literal (void *data
, int ctl
, FILE * in
, FILE * out
)
232 if (ctl
== STREAMCTL_READ
)
233 return literal_decode (data
, in
, out
);
234 else if (ctl
== STREAMCTL_WRITE
)
235 return literal_encode (data
, in
, out
);
236 else if (ctl
== STREAMCTL_FREE
)
238 literal_filter_t
*pfx
= data
;
241 _cdk_log_debug ("free literal filter\n");
242 cdk_free (pfx
->filename
);
243 pfx
->filename
= NULL
;
244 cdk_free (pfx
->orig_filename
);
245 pfx
->orig_filename
= NULL
;
254 text_encode (void *data
, FILE * in
, FILE * out
)
260 return CDK_Inv_Value
;
262 /* FIXME: This code does not work for very long lines. */
265 s
= fgets (buf
, DIM (buf
) - 1, in
);
268 _cdk_trim_string (buf
, 1);
269 fwrite (buf
, 1, strlen (buf
), out
);
277 text_decode (void *data
, FILE * in
, FILE * out
)
279 text_filter_t
*tfx
= data
;
283 if (!tfx
|| !in
|| !out
)
284 return CDK_Inv_Value
;
288 s
= fgets (buf
, DIM (buf
) - 1, in
);
291 _cdk_trim_string (buf
, 0);
292 fwrite (buf
, 1, strlen (buf
), out
);
293 fwrite (tfx
->lf
, 1, strlen (tfx
->lf
), out
);
301 _cdk_filter_text (void *data
, int ctl
, FILE * in
, FILE * out
)
303 if (ctl
== STREAMCTL_READ
)
304 return text_encode (data
, in
, out
);
305 else if (ctl
== STREAMCTL_WRITE
)
306 return text_decode (data
, in
, out
);
307 else if (ctl
== STREAMCTL_FREE
)
309 text_filter_t
*tfx
= data
;
312 _cdk_log_debug ("free text filter\n");