]> git.llucax.com Git - software/mutt-debian.git/blob - pgppacket.c
fix index weirdness if mailbox is emptied while inside the pager (Closes: 375530)
[software/mutt-debian.git] / pgppacket.c
1 /*
2  * Copyright (C) 2001-2,2007 Thomas Roessler <roessler@does-not-exist.org>
3  * 
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public
15  * License along with this program; if not, write to the Free
16  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
17  * MA  02110-1301, USA.
18  */
19
20 #if HAVE_CONFIG_H
21 # include "config.h"
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <time.h>
29
30
31
32 /* yuck, we were including this one somewhere below. */
33 #include "mutt.h"
34
35 #include "lib.h"
36 #include "pgppacket.h"
37
38 #define CHUNKSIZE 1024
39
40 static unsigned char *pbuf = NULL;
41 static size_t plen = 0;
42
43 static int read_material (size_t material, size_t * used, FILE * fp)
44 {
45   if (*used + material >= plen)
46   {
47     unsigned char *p;
48     size_t nplen;
49
50     nplen = *used + material + CHUNKSIZE;
51
52     if (!(p = realloc (pbuf, nplen)))   /* __MEM_CHECKED__ */
53     {
54       perror ("realloc");
55       return -1;
56     }
57     plen = nplen;
58     pbuf = p;
59   }
60
61   if (fread (pbuf + *used, 1, material, fp) < material)
62   {
63     perror ("fread");
64     return -1;
65   }
66
67   *used += material;
68   return 0;
69 }
70
71 unsigned char *pgp_read_packet (FILE * fp, size_t * len)
72 {
73   size_t used = 0;
74   LOFF_T startpos;
75   unsigned char ctb;
76   unsigned char b;
77   size_t material;
78
79   startpos = ftello (fp);
80
81   if (!plen)
82   {
83     plen = CHUNKSIZE;
84     pbuf = safe_malloc (plen);
85   }
86
87   if (fread (&ctb, 1, 1, fp) < 1)
88   {
89     if (!feof (fp))
90       perror ("fread");
91     goto bail;
92   }
93
94   if (!(ctb & 0x80))
95   {
96     goto bail;
97   }
98
99   if (ctb & 0x40)               /* handle PGP 5.0 packets. */
100   {
101     int partial = 0;
102     pbuf[0] = ctb;
103     used++;
104
105     do
106     {
107       if (fread (&b, 1, 1, fp) < 1)
108       {
109         perror ("fread");
110         goto bail;
111       }
112
113       if (b < 192)
114       {
115         material = b;
116         partial = 0;
117         /* material -= 1; */
118       }
119       else if (192 <= b && b <= 223)
120       {
121         material = (b - 192) * 256;
122         if (fread (&b, 1, 1, fp) < 1)
123         {
124           perror ("fread");
125           goto bail;
126         }
127         material += b + 192;
128         partial = 0;
129         /* material -= 2; */
130       }
131       else if (b < 255)
132       {
133         material = 1 << (b & 0x1f);
134         partial = 1;
135         /* material -= 1; */
136       }
137       else
138         /* b == 255 */
139       {
140         unsigned char buf[4];
141         if (fread (buf, 4, 1, fp) < 1)
142         {
143           perror ("fread");
144           goto bail;
145         }
146         /*assert( sizeof(material) >= 4 ); */
147         material = buf[0] << 24;
148         material |= buf[1] << 16;
149         material |= buf[2] << 8;
150         material |= buf[3];
151         partial = 0;
152         /* material -= 5; */
153       }
154
155       if (read_material (material, &used, fp) == -1)
156         goto bail;
157
158     }
159     while (partial);
160   }
161   else
162     /* Old-Style PGP */
163   {
164     int bytes = 0;
165     pbuf[0] = 0x80 | ((ctb >> 2) & 0x0f);
166     used++;
167
168     switch (ctb & 0x03)
169     {
170       case 0:
171       {
172         if (fread (&b, 1, 1, fp) < 1)
173         {
174           perror ("fread");
175           goto bail;
176         }
177
178         material = b;
179         break;
180       }
181
182       case 1:
183       bytes = 2;
184
185       case 2:
186       {
187         int i;
188
189         if (!bytes)
190           bytes = 4;
191
192         material = 0;
193
194         for (i = 0; i < bytes; i++)
195         {
196           if (fread (&b, 1, 1, fp) < 1)
197           {
198             perror ("fread");
199             goto bail;
200           }
201
202           material = (material << 8) + b;
203         }
204         break;
205       }
206
207       default:
208       goto bail;
209     }
210
211     if (read_material (material, &used, fp) == -1)
212       goto bail;
213   }
214
215   if (len)
216     *len = used;
217
218   return pbuf;
219
220 bail:
221
222   fseeko (fp, startpos, SEEK_SET);
223   return NULL;
224 }
225
226 void pgp_release_packet (void)
227 {
228   plen = 0;
229   FREE (&pbuf);
230 }
231