4
* Graham Norbury <gnorbury@bondcar.com>
5
* (c) 2002 (GNU GPL - see ../../COPYING)
7
* Functions for decoding TNEF attachments in native PHP
9
* Adapted from original designs by:
10
* Thomas Boll <tb@boll.ch> [tnef.c]
11
* Mark Simpson <damned@world.std.com> [tnef-1.1.1]
15
define("TNEF_SIGNATURE", 0x223e9f78);
16
define("TNEF_LVL_MESSAGE", 0x01);
17
define("TNEF_LVL_ATTACHMENT", 0x02);
19
define("TNEF_STRING", 0x00010000);
20
define("TNEF_TEXT", 0x00020000);
21
define("TNEF_BYTE", 0x00060000);
22
define("TNEF_WORD", 0x00070000);
23
define("TNEF_DWORD", 0x00080000);
25
define("TNEF_ASUBJECT", TNEF_DWORD | 0x8004);
26
define("TNEF_AMCLASS", TNEF_WORD | 0x8008);
27
define("TNEF_BODYTEXT", TNEF_TEXT | 0x800c);
28
define("TNEF_ATTACHDATA", TNEF_BYTE | 0x800f);
29
define("TNEF_AFILENAME", TNEF_STRING | 0x8010);
30
define("TNEF_ARENDDATA", TNEF_BYTE | 0x9002);
31
define("TNEF_AMAPIATTRS", TNEF_BYTE | 0x9005);
32
define("TNEF_AVERSION", TNEF_DWORD | 0x9006);
34
define("TNEF_MAPI_NULL", 0x0001);
35
define("TNEF_MAPI_SHORT", 0x0002);
36
define("TNEF_MAPI_INT", 0x0003);
37
define("TNEF_MAPI_FLOAT", 0x0004);
38
define("TNEF_MAPI_DOUBLE", 0x0005);
39
define("TNEF_MAPI_CURRENCY", 0x0006);
40
define("TNEF_MAPI_APPTIME", 0x0007);
41
define("TNEF_MAPI_ERROR", 0x000a);
42
define("TNEF_MAPI_BOOLEAN", 0x000b);
43
define("TNEF_MAPI_OBJECT", 0x000d);
44
define("TNEF_MAPI_INT8BYTE", 0x0014);
45
define("TNEF_MAPI_STRING", 0x001e);
46
define("TNEF_MAPI_UNICODE_STRING", 0x001f);
47
define("TNEF_MAPI_SYSTIME", 0x0040);
48
define("TNEF_MAPI_CLSID", 0x0048);
49
define("TNEF_MAPI_BINARY", 0x0102);
51
define("TNEF_MAPI_ATTACH_MIME_TAG", 0x370E);
52
define("TNEF_MAPI_ATTACH_LONG_FILENAME", 0x3707);
53
define("TNEF_MAPI_ATTACH_DATA", 0x3701);
55
function tnef_getx($size, &$buf)
58
if (strlen($buf) >= $size)
60
$value = substr($buf, 0, $size);
61
$buf = substr_replace($buf, '', 0, $size);
66
function tnef_geti8(&$buf)
69
if (strlen($buf) >= 1)
71
$value = ord($buf{0});
72
$buf = substr_replace($buf, '', 0, 1);
77
function tnef_geti16(&$buf)
80
if (strlen($buf) >= 2)
82
$value = ord($buf{0}) +
84
$buf = substr_replace($buf, '', 0, 2);
89
function tnef_geti32(&$buf)
92
if (strlen($buf) >= 4)
94
$value = ord($buf{0}) +
96
(ord($buf{2}) << 16) +
98
$buf = substr_replace($buf, '', 0, 4);
103
function tnef_decode_attribute($attribute, &$buf)
105
global $debug, $download;
107
$length = tnef_geti32($buf);
108
$value = tnef_getx($length, $buf); //data
109
tnef_geti16($buf); //checksum
113
printf("ATTRIBUTE[%08x] %d bytes\n", $attribute, $length);
121
printf("<b>Embedded message:</b><pre>%s</pre>",$value);
129
function extract_mapi_attrs($buf, &$attachment_data)
133
tnef_geti32($buf); // number of attributes
134
while(strlen($buf) > 0)
138
$attr_type = tnef_geti16($buf);
139
$attr_name = tnef_geti16($buf);
142
printf("mapi attribute: %04x:%04x\n", $attr_type, $attr_name);
146
case TNEF_MAPI_SHORT:
147
$value = tnef_geti16($buf);
151
case TNEF_MAPI_BOOLEAN:
152
$value = tnef_geti32($buf);
155
case TNEF_MAPI_FLOAT:
156
$value = tnef_getx(4, $buf);
159
case TNEF_MAPI_DOUBLE:
160
case TNEF_MAPI_SYSTIME:
161
$value = tnef_getx(8, $buf);
164
case TNEF_MAPI_STRING:
165
case TNEF_MAPI_UNICODE_STRING:
166
case TNEF_MAPI_BINARY:
167
case TNEF_MAPI_OBJECT:
168
$num_vals = tnef_geti32($buf);
169
for ($i = 0; $i < $num_vals; $i++) // usually just 1
171
$length = tnef_geti32($buf);
172
$buflen = $length + ((4 - ($length % 4)) % 4); // pad to next 4 byte boundary
173
$value = substr(tnef_getx($buflen, $buf), 0, $length); // read and truncate to length
180
echo("Unknown mapi attribute!\n");
184
// store any interesting attributes
187
case TNEF_MAPI_ATTACH_LONG_FILENAME: // used in preference to AFILENAME value
188
$attachment_data[0]['name'] = ereg_replace('.*[\/](.*)$', '\1', $value); // strip path
191
case TNEF_MAPI_ATTACH_MIME_TAG: // Is this ever set, and what is format?
192
$attachment_data[0]['type0'] = ereg_replace('^(.*)/.*', '\1', $value);
193
$attachment_data[0]['type1'] = ereg_replace('.*/(.*)$', '\1', $value);
196
case TNEF_MAPI_ATTACH_DATA:
197
tnef_getx(16, $value); // skip the next 16 bytes (unknown data)
198
array_shift($attachment_data); // eliminate the current (bogus) attachment
199
do_tnef_decode($value, $attachment_data); // recursively process the attached message
207
function tnef_decode_message(&$buf)
216
$attribute = tnef_geti32($buf);
217
tnef_decode_attribute($attribute, $buf);
220
function tnef_decode_attachment(&$buf, &$attachment_data)
229
$attribute = tnef_geti32($buf);
232
case TNEF_ARENDDATA: // marks start of new attachment
233
$length = tnef_geti32($buf);
234
tnef_getx($length, $buf);
235
tnef_geti16($buf); //checksum
238
printf("ARENDDATA[%08x]: %d bytes\n", $attribute, $length);
240
// add a new default data block to hold details of this attachment
241
// reverse order is easier to handle later!
242
array_unshift($attachment_data, array('type0' => 'application',
243
'type1' => 'octet-stream',
248
case TNEF_AFILENAME: // filename
249
$length = tnef_geti32($buf);
250
$attachment_data[0]['name'] = ereg_replace('.*[\/](.*)$',
252
tnef_getx($length, $buf)); // strip path
253
tnef_geti16($buf); //checksum
256
printf("AFILENAME[%08x]: %s\n", $attribute, $attachment_data[0]['name']);
260
case TNEF_ATTACHDATA: // the attachment itself
261
$length = tnef_geti32($buf);
262
$attachment_data[0]['size'] = $length;
263
$attachment_data[0]['stream'] = tnef_getx($length, $buf);
264
tnef_geti16($buf); //checksum
267
printf("ATTACHDATA[%08x]: %d bytes\n", $attribute, $length);
271
case TNEF_AMAPIATTRS:
272
$length = tnef_geti32($buf);
273
$value = tnef_getx($length, $buf);
274
tnef_geti16($buf); //checksum
277
printf("AMAPIATTRS[%08x]: %d bytes\n", $attribute, $length);
279
extract_mapi_attrs($value, $attachment_data);
283
tnef_decode_attribute($attribute, $buf);
287
function do_tnef_decode(&$buf, &$attachment_data)
291
$tnef_signature = tnef_geti32($buf);
292
if ($tnef_signature == TNEF_SIGNATURE)
294
$tnef_key = tnef_geti16($buf);
297
printf("Signature: 0x%08x\nKey: 0x%04x\n", $tnef_signature, $tnef_key);
300
while (strlen($buf) > 0)
302
$lvl_type = tnef_geti8($buf);
305
case TNEF_LVL_MESSAGE:
306
tnef_decode_message($buf);
309
case TNEF_LVL_ATTACHMENT:
310
tnef_decode_attachment($buf, $attachment_data);
316
echo("Invalid file format!");
326
echo("Invalid file format!");
331
function tnef_decode($buf)
335
$attachment_data = array();
342
do_tnef_decode($buf, $attachment_data);
348
return array_reverse($attachment_data);
b'\\ No newline at end of file'