Add `gnutls/dtls.h' to the distribution.
[gnutls.git] / lib / opencdk / literal.c
blob4c8f966124ad9a18eeed2feff5511ce8aa1f9ee0
1 /* literal.c - Literal packet filters
2 * Copyright (C) 2002, 2003, 2008, 2009, 2010 Free Software Foundation,
3 * Inc.
5 * Author: Timo Schulz
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,
22 * USA
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 #include <stdio.h>
29 #include <time.h>
31 #include "opencdk.h"
32 #include "main.h"
33 #include "filters.h"
36 /* Duplicate the string @s but strip of possible
37 relative folder names of it. */
38 static char *
39 dup_trim_filename (const char *s)
41 char *p = NULL;
43 p = strrchr (s, '/');
44 if (!p)
45 p = strrchr (s, '\\');
46 if (!p)
47 return cdk_strdup (s);
48 return cdk_strdup (p + 1);
52 static cdk_error_t
53 literal_decode (void *data, FILE * in, FILE * out)
55 literal_filter_t *pfx = data;
56 cdk_stream_t si, so;
57 cdk_packet_t pkt;
58 cdk_pkt_literal_t pt;
59 byte buf[BUFSIZE];
60 ssize_t nread;
61 int bufsize;
62 cdk_error_t rc;
64 _cdk_log_debug ("literal filter: decode\n");
66 if (!pfx || !in || !out)
67 return CDK_Inv_Value;
69 rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si);
70 if (rc)
71 return rc;
73 cdk_pkt_new (&pkt);
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);
83 if (rc)
85 cdk_pkt_release (pkt);
86 cdk_stream_close (si);
87 return rc;
90 pt = pkt->pkt.literal;
91 pfx->mode = pt->mode;
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);
113 _cdk_log_debug
114 ("literal filter: no file name and no PGP extension\n");
115 return CDK_Inv_Mode;
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';
122 while (!feof (in))
124 _cdk_log_debug ("literal_decode: part on %d size %lu\n",
125 (int) pfx->blkmode.on, pfx->blkmode.size);
126 if (pfx->blkmode.on)
127 bufsize = pfx->blkmode.size;
128 else
129 bufsize = pt->len < DIM (buf) ? pt->len : DIM (buf);
130 nread = cdk_stream_read (pt->buf, buf, bufsize);
131 if (nread == EOF)
133 rc = CDK_File_Error;
134 break;
136 if (pfx->md_initialized)
137 _gnutls_hash (&pfx->md, buf, nread);
138 cdk_stream_write (so, buf, nread);
139 pt->len -= nread;
140 if (pfx->blkmode.on)
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)
147 break;
150 cdk_stream_close (si);
151 cdk_stream_close (so);
152 cdk_pkt_release (pkt);
153 return rc;
157 static char
158 intmode_to_char (int mode)
160 switch (mode)
162 case CDK_LITFMT_BINARY:
163 return 'b';
164 case CDK_LITFMT_TEXT:
165 return 't';
166 case CDK_LITFMT_UNICODE:
167 return 'u';
168 default:
169 return 'b';
172 return 'b';
176 static cdk_error_t
177 literal_encode (void *data, FILE * in, FILE * out)
179 literal_filter_t *pfx = data;
180 cdk_pkt_literal_t pt;
181 cdk_stream_t si;
182 cdk_packet_t pkt;
183 size_t filelen;
184 cdk_error_t rc;
186 _cdk_log_debug ("literal filter: encode\n");
188 if (!pfx || !in || !out)
189 return CDK_Inv_Value;
190 if (!pfx->filename)
192 pfx->filename = cdk_strdup ("_CONSOLE");
193 if (!pfx->filename)
194 return CDK_Out_Of_Core;
197 rc = _cdk_stream_fpopen (in, STREAMCTL_READ, &si);
198 if (rc)
199 return rc;
201 filelen = strlen (pfx->filename);
202 cdk_pkt_new (&pkt);
203 pt = pkt->pkt.literal = cdk_calloc (1, sizeof *pt + filelen);
204 pt->name = (char *) pt + sizeof (*pt);
205 if (!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);
217 pt->buf = si;
218 pkt->old_ctb = 1;
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);
225 return rc;
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;
239 if (pfx)
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;
246 return 0;
249 return CDK_Inv_Mode;
253 static int
254 text_encode (void *data, FILE * in, FILE * out)
256 const char *s;
257 char buf[2048];
259 if (!in || !out)
260 return CDK_Inv_Value;
262 /* FIXME: This code does not work for very long lines. */
263 while (!feof (in))
265 s = fgets (buf, DIM (buf) - 1, in);
266 if (!s)
267 break;
268 _cdk_trim_string (buf, 1);
269 fwrite (buf, 1, strlen (buf), out);
272 return 0;
276 static int
277 text_decode (void *data, FILE * in, FILE * out)
279 text_filter_t *tfx = data;
280 const char *s;
281 char buf[2048];
283 if (!tfx || !in || !out)
284 return CDK_Inv_Value;
286 while (!feof (in))
288 s = fgets (buf, DIM (buf) - 1, in);
289 if (!s)
290 break;
291 _cdk_trim_string (buf, 0);
292 fwrite (buf, 1, strlen (buf), out);
293 fwrite (tfx->lf, 1, strlen (tfx->lf), out);
296 return 0;
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;
310 if (tfx)
312 _cdk_log_debug ("free text filter\n");
313 tfx->lf = NULL;
316 return CDK_Inv_Mode;