Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pax/pax-tnef.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1987-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Glenn Fowler <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
22
/*
23
* pax tnef format
24
*/
25
26
#include "format.h"
27
28
#include <tm.h>
29
30
#define TNEF_MAGIC 0x223e9f78
31
32
typedef struct Tnef_s
33
{
34
char* format;
35
off_t offset;
36
} Tnef_t;
37
38
static int
39
tnef_getprologue(Pax_t* pax, Format_t* fp, register Archive_t* ap, File_t* f, unsigned char* buf, size_t size)
40
{
41
Tnef_t* tnef;
42
uint32_t magic;
43
44
if (size < 6)
45
return 0;
46
magic = TNEF_MAGIC;
47
if ((ap->swap = swapop(&magic, buf, 4)) < 0 || paxread(pax, ap, NiL, (off_t)6, (off_t)6, 0) != 6)
48
return 0;
49
if (!(tnef = newof(0, Tnef_t, 1, 0)))
50
nospace();
51
ap->data = (void*)tnef;
52
ap->swap = 3;
53
return 1;
54
}
55
56
static int
57
tnef_getheader(Pax_t* pax, Archive_t* ap, register File_t* f)
58
{
59
Tnef_t* tnef = (Tnef_t*)ap->data;
60
char* s;
61
char* e;
62
unsigned char* x;
63
size_t n;
64
size_t m;
65
size_t z;
66
unsigned int level;
67
unsigned int type;
68
unsigned int name;
69
unsigned int checksum;
70
size_t size;
71
size_t part;
72
Tm_t tm;
73
74
*(f->name = paxstash(pax, &ap->stash.head, NiL, PATH_MAX)) = 0;
75
f->st->st_dev = 0;
76
f->st->st_ino = 0;
77
f->st->st_mode = X_IFREG|X_IRUSR|X_IWUSR|X_IRGRP|X_IROTH;
78
f->st->st_uid = state.uid;
79
f->st->st_gid = state.gid;
80
f->st->st_nlink = 1;
81
IDEVICE(f->st, 0);
82
f->st->st_mtime = f->st->st_ctime = f->st->st_atime = NOW;
83
f->st->st_size = 0;
84
while (paxread(pax, ap, s = state.tmp.buffer, (off_t)0, (off_t)9, 0) > 0)
85
{
86
level = swapget(ap->swap, s + 0, 1);
87
n = swapget(ap->swap, s + 1, 4);
88
type = n >> 16;
89
name = n & ((1<<16)-1);
90
n = 0;
91
size = swapget(ap->swap, s + 5, 4);
92
part = ap->io->buffersize;
93
if (size > part)
94
{
95
if (level == 2)
96
{
97
level = 0;
98
if (name == 0x800f)
99
{
100
f->st->st_size = size;
101
tnef->offset = paxseek(pax, ap, (off_t)0, SEEK_CUR, 0);
102
}
103
else
104
error(1, "%s: %s format 0x%04x attribute ignored", ap->name, ap->format->name, name);
105
}
106
while (size > part)
107
{
108
size -= part;
109
if (!(s = paxget(pax, ap, part, NiL)))
110
error(3, "%s: %s format 0x%04x attribute data truncated -- %d expected", ap->name, ap->format->name, name, part);
111
x = (unsigned char*)s;
112
e = s + part;
113
while (x < (unsigned char*)e)
114
n += *x++;
115
}
116
}
117
if (!(s = paxget(pax, ap, size + 2, NiL)))
118
error(3, "%s: %s format 0x%04x attribute data truncated -- %d expected", ap->name, ap->format->name, name, size);
119
checksum = swapget(ap->swap, s + size, 2);
120
x = (unsigned char*)s;
121
e = s + size;
122
while (x < (unsigned char*)e)
123
n += *x++;
124
n &= ((1<<16)-1);
125
if (checksum != n)
126
error(3, "%s: %s format attribute data checksum error", ap->name, ap->format->name);
127
if (level == 2)
128
switch (name)
129
{
130
case 0x800f: /* data */
131
f->st->st_size = size;
132
tnef->offset = paxseek(pax, ap, (off_t)0, SEEK_CUR, 0) - size - 2;
133
break;
134
case 0x8010: /* title */
135
if (!f->name)
136
f->name = paxstash(pax, &ap->stash.head, s, size);
137
break;
138
case 0x8013: /* date */
139
if (type == 0x0003 && size >= 12)
140
{
141
tm.tm_year = swapget(ap->swap, s + 0, 2) - 1900;
142
tm.tm_mon = swapget(ap->swap, s + 2, 2) - 1;
143
tm.tm_mday = swapget(ap->swap, s + 4, 2);
144
tm.tm_hour = swapget(ap->swap, s + 6, 2);
145
tm.tm_min = swapget(ap->swap, s + 8, 2);
146
tm.tm_sec = swapget(ap->swap, s + 10, 2);
147
f->st->st_mtime = tmtime(&tm, TM_LOCALZONE);
148
}
149
break;
150
case 0x9005: /* attachment */
151
if (size >= 4)
152
{
153
e = s + size - 4;
154
n = swapget(ap->swap, s, 4); s += 4;
155
while (n-- && s < e)
156
{
157
type = swapget(ap->swap, s, 2); s += 2;
158
name = swapget(ap->swap, s, 2); s += 2;
159
switch (type)
160
{
161
case 0x0002:
162
case 0x000b:
163
s += 2;
164
break;
165
case 0x0003:
166
case 0x0004:
167
case 0x0007:
168
case 0x000a:
169
case 0x000d:
170
case 0x0048:
171
s += 4;
172
break;
173
case 0x0005:
174
case 0x0006:
175
case 0x0014:
176
case 0x0040:
177
s += 8;
178
break;
179
case 0x001e:
180
case 0x001f:
181
case 0x0102:
182
m = swapget(ap->swap, s, 4); s += 4;
183
while (m--)
184
{
185
z = swapget(ap->swap, s, 4); s += 4;
186
z = roundof(z, 4);
187
if (name == 0x3707)
188
f->name = paxstash(pax, &ap->stash.head, s, z);
189
s += z;
190
}
191
break;
192
}
193
}
194
}
195
n = tnef->offset;
196
tnef->offset = paxseek(pax, ap, (off_t)0, SEEK_CUR, 0);
197
if (paxseek(pax, ap, n, SEEK_SET, 1) != n)
198
error(3, "%s: %s input must be seekable", ap->name, ap->format->name);
199
if (!*f->name)
200
{
201
if (s = strrchr(ap->name, '/'))
202
s++;
203
else
204
s = ap->name;
205
if (!(e = strrchr(s, '.')) || isdigit(*(e + 1)))
206
e = s + strlen(s);
207
z = sfsprintf(state.tmp.buffer, state.tmp.buffersize, "%-.*s.%03u", e - s, s, ap->entry);
208
f->name = paxstash(pax, &ap->stash.head, state.tmp.buffer, z);
209
}
210
return 1;
211
}
212
}
213
if (ap->io->eof && ap->entry == 1)
214
error(1, "%s: no members in %s file", ap->name, ap->format->name);
215
return 0;
216
}
217
218
static int
219
tnef_done(Pax_t* pax, register Archive_t* ap)
220
{
221
if (ap->data)
222
{
223
free(ap->data);
224
ap->data = 0;
225
}
226
return 0;
227
}
228
229
static int
230
tnef_gettrailer(Pax_t* pax, Archive_t* ap, File_t* f)
231
{
232
register Tnef_t* tnef = (Tnef_t*)ap->data;
233
234
if (paxseek(pax, ap, tnef->offset, SEEK_SET, 1) != tnef->offset)
235
error(3, "%s: %s format seek error", ap->name, ap->format->name);
236
return 1;
237
}
238
239
Format_t pax_tnef_format =
240
{
241
"tnef",
242
0,
243
"MS outlook transport neutral encapsulation format",
244
0,
245
ARCHIVE|DOS|NOHARDLINKS|IN,
246
DEFBUFFER,
247
DEFBLOCKS,
248
0,
249
PAXNEXT(tnef),
250
0,
251
tnef_done,
252
tnef_getprologue,
253
tnef_getheader,
254
0,
255
tnef_gettrailer,
256
};
257
258
PAXLIB(tnef)
259
260