Mercurial > libpst
changeset 28:51d826f31329
more cleanup from Arne, document 7c block format
author | carl |
---|---|
date | Sat, 25 Feb 2006 16:03:45 -0800 |
parents | 99e6b70cdfb3 |
children | 311e52c62f06 |
files | configure.in package src/define.h src/libpst.c src/libpst.h src/readpst.c xml/libpst.in |
diffstat | 7 files changed, 251 insertions(+), 127 deletions(-) [+] |
line wrap: on
line diff
--- a/configure.in Sat Feb 25 16:03:45 2006 -0800 +++ b/configure.in Sat Feb 25 16:03:45 2006 -0800 @@ -1,7 +1,7 @@ AC_INIT(configure.in) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(libpst,0.5.3) +AM_INIT_AUTOMAKE(libpst,0.5.4) AC_PATH_PROGS(BASH, bash) AC_LANG_CPLUSPLUS
--- a/package Sat Feb 25 16:03:45 2006 -0800 +++ b/package Sat Feb 25 16:03:45 2006 -0800 @@ -12,14 +12,16 @@ ./configure >/dev/null (cd xml; make; make distclean) cp -a html/*html $web -## make -## pst=/home/ldap/outlook.pst -## rm -f pst2ldif.log my.log -## src/pst2ldif -b 'o=ams-cc.com, c=US' -c 'newPerson' $pst >ams.ldif -## src/readpstlog pst2ldif.log | less >my.log -## hexdump -C -v $pst >pst.dump -## chown --recursive carl:carl * -## exit +if [ "$1" == "test" ]; then + make + pst=/home/ldap/outlook.pst + rm -f pst2ldif.log my.log + src/pst2ldif -b 'o=ams-cc.com, c=US' -c 'newPerson' $pst >ams.ldif + src/readpstlog pst2ldif.log | less >my.log + hexdump -C -v $pst >pst.dump + chown --recursive carl:carl * + exit +fi make distcheck >$distlog 2>&1 if [ $? -eq 0 ]; then
--- a/src/define.h Sat Feb 25 16:03:45 2006 -0800 +++ b/src/define.h Sat Feb 25 16:03:45 2006 -0800 @@ -6,8 +6,8 @@ */ // last one wins +#define DEBUG_ALL #undef DEBUG_ALL -#define DEBUG_ALL #ifndef DEFINEH_H #define DEFINEH_H
--- a/src/libpst.c Sat Feb 25 16:03:45 2006 -0800 +++ b/src/libpst.c Sat Feb 25 16:03:45 2006 -0800 @@ -1027,7 +1027,6 @@ item->attach = attach; x++; } - item->current_attach = item->attach; if (_pst_process(list, item)) { DEBUG_WARN(("ERROR _pst_process() failed with attachments\n")); @@ -1051,7 +1050,6 @@ attach = attach->next; continue; } - item->current_attach = attach; if (_pst_process(list, item)) { DEBUG_WARN(("ERROR _pst_process() failed with an attachment\n")); _pst_free_list(list); @@ -1072,7 +1070,6 @@ attach = attach->next; } } - item->current_attach = item->attach; //reset back to first } _pst_free_id2(id2_head); @@ -1087,7 +1084,7 @@ pst_block_offset block_offset; // pst_index_ll *rec = NULL; u_int32_t size = 0, t_ptr = 0, fr_ptr = 0, to_ptr = 0, ind_ptr = 0, x = 0; - u_int32_t num_recs = 0, count_rec = 0, ind2_ptr = 0, list_start = 0, num_list = 0, cur_list = 0; + u_int32_t num_recs = 0, count_rec = 0, ind2_ptr = 0, ind2_end = 0, list_start = 0, num_list = 0, cur_list = 0; int32_t block_type, rec_size; size_t read_size=0; pst_x_attrib_ll *mapptr; @@ -1164,9 +1161,9 @@ } _pst_getBlockOffset(buf, read_size, ind_ptr, table_rec.value, &block_offset); - list_start = fr_ptr = block_offset.from; - to_ptr = block_offset.to; - num_list = (to_ptr - fr_ptr)/sizeof(table_rec); + list_start = block_offset.from; + to_ptr = block_offset.to; + num_list = (to_ptr - list_start)/sizeof(table_rec); num_recs = 1; // only going to one object in these blocks rec_size = 0; // doesn't matter cause there is only one object } @@ -1204,11 +1201,10 @@ _pst_getBlockOffset(buf, read_size, ind_ptr, seven_c_blk.b_five_offset, &block_offset); fr_ptr = block_offset.from; memcpy(&table_rec, &(buf[fr_ptr]), sizeof(table_rec)); - DEBUG_EMAIL(("before convert %#x\n", table_rec.type)); LE16_CPU(table_rec.type); - DEBUG_EMAIL(("after convert %#x\n", table_rec.type)); LE16_CPU(table_rec.ref_type); LE32_CPU(table_rec.value); + DEBUG_EMAIL(("after convert %#x\n", table_rec.type)); if (table_rec.type != 0x04B5) { // different constant than a type 1 record WARN(("Unknown second block constant - %#X for id %#x\n", table_rec.type, block_id)); @@ -1229,6 +1225,7 @@ _pst_getBlockOffset(buf, read_size, ind_ptr, seven_c_blk.ind2_offset, &block_offset); ind2_ptr = block_offset.from; + ind2_end = block_offset.to; } else { WARN(("ERROR: Unknown block constant - %#X for id %#x\n", block_hdr.type, block_id)); DEBUG_HEXDUMPC(buf, read_size,0x10); @@ -1258,6 +1255,7 @@ memcpy(&table_rec, &(buf[fr_ptr]), sizeof(table_rec)); LE16_CPU(table_rec.type); LE16_CPU(table_rec.ref_type); + //LE32_CPU(table_rec.value); // done later, some may be order invariant fr_ptr += sizeof(table_rec); } else if (block_type == 2) { // we will copy the table2_rec values into a table_rec record so that we can keep the rest of the code @@ -1270,9 +1268,10 @@ // table_rec and table2_rec are arranged differently, so assign the values across table_rec.type = table2_rec.type; table_rec.ref_type = table2_rec.ref_type; - if ((ind2_ptr+table2_rec.ind2_off > 0) && - (ind2_ptr+table2_rec.ind2_off < read_size-sizeof(table_rec.value))) + if (ind2_ptr+table2_rec.ind2_off <= ind2_end) { memcpy(&(table_rec.value), &(buf[ind2_ptr+table2_rec.ind2_off]), sizeof(table_rec.value)); + //LE32_CPU(table_rec.value); // done later, some may be order invariant + } else { DEBUG_WARN (("trying to read more than blocks size. Size=%#x, Req.=%#x," " Req Size=%#x\n", read_size, ind2_ptr+table2_rec.ind2_off, @@ -1473,7 +1472,7 @@ return -1; } - attach = item->current_attach; // a working variable + attach = item->attach; // a working variable while (list) { x = 0;
--- a/src/libpst.h Sat Feb 25 16:03:45 2006 -0800 +++ b/src/libpst.h Sat Feb 25 16:03:45 2006 -0800 @@ -385,7 +385,6 @@ struct _pst_item_folder *folder; // data reffering to folder struct _pst_item_contact *contact; // data reffering to contact struct _pst_item_attach *attach; // linked list of attachments - struct _pst_item_attach *current_attach; // pointer to current attachment struct _pst_item_message_store * message_store; // data referring to the message store struct _pst_item_extra_field *extra_fields; // linked list of extra headers and such struct _pst_item_journal *journal; // data reffering to a journal entry
--- a/src/readpst.c Sat Feb 25 16:03:45 2006 -0800 +++ b/src/readpst.c Sat Feb 25 16:03:45 2006 -0800 @@ -918,8 +918,8 @@ void write_inline_attachment(FILE* f_output, pst_item_attach* current_attach, char boundary[], pst_file* pst) { char *enc; // base64 encoded attachment - DEBUG_MAIN(("write_inline_attachment: Attachment Size is %i\n", item->current_attach->size)); - DEBUG_MAIN(("write_inline_attachment: Attachment Pointer is %p\n", item->current_attach->data)); + DEBUG_MAIN(("write_inline_attachment: Attachment Size is %i\n", current_attach->size)); + DEBUG_MAIN(("write_inline_attachment: Attachment Pointer is %p\n", current_attach->data)); if (current_attach->data != NULL) { if ((enc = base64_encode (current_attach->data, current_attach->size)) == NULL) { DEBUG_MAIN(("write_inline_attachment: ERROR base64_encode returned NULL. Must have failed\n")); @@ -957,6 +957,7 @@ int attach_num, base64_body = 0; time_t em_time; char *c_time; + pst_item_attach* current_attach; // convert the sent date if it exists, or set it to a fixed date if (item->email->sent_date != NULL) { @@ -1154,17 +1155,17 @@ if (item->email->rtf_compressed != NULL) { DEBUG_MAIN(("Adding RTF body as attachment\n")); - item->current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; - item->current_attach->data = lzfu_decompress(item->email->rtf_compressed); - item->current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); - strcpy(item->current_attach->filename2, RTF_ATTACH_NAME); - item->current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); - strcpy(item->current_attach->mimetype, RTF_ATTACH_TYPE); - memcpy(&(item->current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); - LE32_CPU(item->current_attach->size); + current_attach = (pst_item_attach*)xmalloc(sizeof(pst_item_attach)); + memset(current_attach, 0, sizeof(pst_item_attach)); + current_attach->next = item->attach; + item->attach = current_attach; + current_attach->data = lzfu_decompress(item->email->rtf_compressed); + current_attach->filename2 = xmalloc(strlen(RTF_ATTACH_NAME)+2); + strcpy(current_attach->filename2, RTF_ATTACH_NAME); + current_attach->mimetype = xmalloc(strlen(RTF_ATTACH_TYPE)+2); + strcpy(current_attach->mimetype, RTF_ATTACH_TYPE); + memcpy(&(current_attach->size), item->email->rtf_compressed+sizeof(int32_t), sizeof(int32_t)); + LE32_CPU(current_attach->size); // item->email->rtf_compressed = ; // attach_num++; } @@ -1172,42 +1173,42 @@ // if either the body or htmlbody is encrypted, add them as attachments if (item->email->encrypted_body) { DEBUG_MAIN(("Adding Encrypted Body as attachment\n")); - item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; + current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(current_attach, 0, sizeof(pst_item_attach)); + current_attach->next = item->attach; + item->attach = current_attach; - item->current_attach->data = item->email->encrypted_body; - item->current_attach->size = item->email->encrypted_body_size; + current_attach->data = item->email->encrypted_body; + current_attach->size = item->email->encrypted_body_size; item->email->encrypted_body = NULL; } if (item->email->encrypted_htmlbody) { DEBUG_MAIN(("Adding encrypted HTML body as attachment\n")); - item->current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); - memset(item->current_attach, 0, sizeof(pst_item_attach)); - item->current_attach->next = item->attach; - item->attach = item->current_attach; + current_attach = (pst_item_attach*) xmalloc(sizeof(pst_item_attach)); + memset(current_attach, 0, sizeof(pst_item_attach)); + current_attach->next = item->attach; + item->attach = current_attach; - item->current_attach->data = item->email->encrypted_htmlbody; - item->current_attach->size = item->email->encrypted_htmlbody_size; + current_attach->data = item->email->encrypted_htmlbody; + current_attach->size = item->email->encrypted_htmlbody_size; item->email->encrypted_htmlbody = NULL; } write_email_body(f_output, "The body of this email is encrypted. This isn't supported yet, but the body is now an attachment\n"); } // attachments attach_num = 0; - for(item->current_attach = item->attach; - item->current_attach; - item->current_attach = item->current_attach->next) { + for(current_attach = item->attach; + current_attach; + current_attach = current_attach->next) { DEBUG_MAIN(("write_normal_email: Attempting Attachment encoding\n")); - if (item->current_attach->data == NULL) { - DEBUG_MAIN(("write_normal_email: Data of attachment is NULL!. Size is supposed to be %i\n", item->current_attach->size)); + if (current_attach->data == NULL) { + DEBUG_MAIN(("write_normal_email: Data of attachment is NULL!. Size is supposed to be %i\n", current_attach->size)); } attach_num++; if (mode == MODE_SEPERATE && !mode_MH) - write_separate_attachment(f_name, item->current_attach, attach_num, pst); + write_separate_attachment(f_name, current_attach, attach_num, pst); else - write_inline_attachment(f_output, item->current_attach, boundary, pst); + write_inline_attachment(f_output, current_attach, boundary, pst); } if (mode != MODE_SEPERATE) { /* do not add a boundary after the last attachment for mode_MH */ DEBUG_MAIN(("write_normal_email: Writing buffer between emails\n"));
--- a/xml/libpst.in Sat Feb 25 16:03:45 2006 -0800 +++ b/xml/libpst.in Sat Feb 25 16:03:45 2006 -0800 @@ -47,9 +47,9 @@ <refsect1 id='readpst.description.1'> <title>Description</title> - <para><command>readpst</command> is a program that can read an Outlook PST (Personal Folders) file - and convert it into an mbox file, a format suitable for KMail, a recursive mbox - structure, or separate emails. + <para><command>readpst</command> is a program that can read an Outlook + PST (Personal Folders) file and convert it into an mbox file, a format + suitable for KMail, a recursive mbox structure, or separate emails. </para> </refsect1> @@ -65,8 +65,9 @@ <varlistentry> <term>-d <replaceable class="parameter">debug-file</replaceable></term> <listitem><para> - Specify name of debug log file. Defaults to "readpst.log". The log - file is not an ascii file, it is a binary file readable by <command>readpstlog</command>. + Specify name of debug log file. Defaults to "readpst.log". The + log file is not an ascii file, it is a binary file readable + by <command>readpstlog</command>. </para></listitem> </varlistentry> <varlistentry> @@ -110,20 +111,19 @@ <listitem><para> Output messages into separate files. This will create folders as named in the PST file, and will put each email in its own file. These files - will be numbered from 000000000 increasing in intervals of 1 (ie - 000000000, 000000001, 0000000002). Any attachments are saved alongside - each email as 000000000-attach0, or with the name of the attachment if - one is present. + will be numbered from 1 increasing in intervals of 1 (ie 1, 2, 3, ...). + Any attachments are saved alongside each email as XXXXXXXXX-attach1, + XXXXXXXXX-attach2 and so on, or with the name of the attachment if one + is present. </para></listitem> </varlistentry> <varlistentry> <term>-M</term> <listitem><para> Output messages in MH format as separate files. This will create - folders as named in the PST file, and will put each email in its own - file. These files will be numbered from 1 to n with no leading zeros. - Any attachments are saved alongside each email as 000000000-attach0, or - with the name of the attachment if one is present. + folders as named in the PST file, and will put each email together with + any attachments into its own file. These files will be numbered from 1 + to n with no leading zeros. </para></listitem> </varlistentry> <varlistentry> @@ -165,7 +165,7 @@ <title>Copyright</title> <para> Copyright (C) 2002 by David Smith <dave.s@earthcorp.com>. - XML version Copyright (C) 2005 by 510 Software Group <carl@five-ten-sg.com>. + XML version Copyright (C) 2006 by 510 Software Group <carl@five-ten-sg.com>. </para> <para> This program is free software; you can redistribute it and/or modify it @@ -542,27 +542,27 @@ 01f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 signature [4 bytes] 0x4e444221 constant -000a index type [1 byte] 0x0e constant -01cd encryption type [1 byte] 0x01 constant +000a indexType [1 byte] 0x0e constant +01cd encryptionType [1 byte] 0x01 constant 00a8 total file size [4 bytes] 0x270400 in this case -00c0 back-pointer-1 [4 bytes] 0x021eb4 in this case -00c4 offset-index-1 [4 bytes] 0x005400 in this case -00b8 back-pointer-2 [4 bytes] 0x021ebc in this case -00bc offset-index-2 [4 bytes] 0x0c7e00 in this case +00c0 backPointer1 [4 bytes] 0x021eb4 in this case +00c4 offsetIndex1 [4 bytes] 0x005400 in this case +00b8 backPointer2 [4 bytes] 0x021ebc in this case +00bc offsetIndex2 [4 bytes] 0x0c7e00 in this case ]]></literallayout> <para> We only support index type 0x0E and encryption type 0x01. </para> <para> - offset-index-1 is the file offset of the root of the + offsetIndex1 is the file offset of the root of the index1 b-tree, which contains (ID1, offset, size, unknown) tuples - for each item in the file. back-pointer-1 is the value that should + for each item in the file. backPointer1 is the value that should appear in the parent pointer of that root node. </para> <para> - offset-index-2 is the file offset of the root of the + offsetIndex2 is the file offset of the root of the index2 b-tree, which contains (ID2, DESC-ID1, LIST-ID1, PARENT-ID2) - tuples for each item in the file. back-pointer-2 is the value that should + tuples for each item in the file. backPointer2 is the value that should appear in the parent pointer of that root node. </para> </refsect1> @@ -617,21 +617,21 @@ 01ec 00 00 00 00 02 29 0c 02 80 80 b6 4a 01f8 b4 1e 02 00 27 9c cc 56 58 27 03 00 -01f0 item-count [1 byte] 0x02 in this case -01f1 max-item-count [1 byte] 0x29 constant -01f3 node-level [1 byte] 0x02 in this case -01f8 back-pointer [4 bytes] 0x021eb4 in this case +01f0 itemCount [1 byte] 0x02 in this case +01f1 maxItemCount [1 byte] 0x29 constant +01f3 nodeLevel [1 byte] 0x02 in this case +01f8 backPointer [4 bytes] 0x021eb4 in this case ]]></literallayout> <para> - The item-count specifies the number of 12 byte records that - are active. The node-level is non-zero for this style of nodes. - The leaf nodes have a different format. The back-pointer must - match the back-pointer from the triple that pointed to this node. + The itemCount specifies the number of 12 byte records that + are active. The nodeLevel is non-zero for this style of nodes. + The leaf nodes have a different format. The backPointer must + match the backPointer from the triple that pointed to this node. </para> <para> - Each item in this node is a triple of (ID, back-pointer, offset) + Each item in this node is a triple of (ID, backPointer, offset) where the offset points to the next deeper node in the tree, the - back-pointer value must match the back-pointer in that deeper node, + backPointer value must match the backPointer in that deeper node, and ID is the lowest ID value in the subtree. </para> </refsect1> @@ -686,15 +686,15 @@ 01ec 00 00 00 00 1f 29 0c 00 80 80 5b b3 01f8 5a 67 01 00 4f ae 70 a7 92 06 00 00 -01f0 item-count [1 byte] 0x1f in this case -01f1 max-item-count [1 byte] 0x29 constant -01f3 node-level [1 byte] 0x00 in this case -01f8 back-pointer [4 bytes] 0x01675a in this case +01f0 itemCount [1 byte] 0x1f in this case +01f1 maxItemCount [1 byte] 0x29 constant +01f3 nodeLevel [1 byte] 0x00 in this case +01f8 backPointer [4 bytes] 0x01675a in this case ]]></literallayout> <para> - The item-count specifies the number of 12 byte records that - are active. The node-level is zero for these leaf nodes. - The back-pointer must match the back-pointer from the triple + The itemCount specifies the number of 12 byte records that + are active. The nodeLevel is zero for these leaf nodes. + The backPointer must match the backPointer from the triple that pointed to this node. </para> <para> @@ -752,21 +752,21 @@ 01ec 00 00 00 00 02 29 0c 02 81 81 b2 60 01f8 bc 1e 02 00 7e 70 dc e3 21 00 00 00 -01f0 item-count [1 byte] 0x02 in this case -01f1 max-item-count [1 byte] 0x29 constant -01f3 node-level [1 byte] 0x02 in this case -01f8 back-pointer [4 bytes] 0x021ebc in this case +01f0 itemCount [1 byte] 0x02 in this case +01f1 maxItemCount [1 byte] 0x29 constant +01f3 nodeLevel [1 byte] 0x02 in this case +01f8 backPointer [4 bytes] 0x021ebc in this case ]]></literallayout> <para> - The item-count specifies the number of 12 byte records that - are active. The node-level is non-zero for this style of nodes. - The leaf nodes have a different format. The back-pointer must - match the back-pointer from the triple that pointed to this node. + The itemCount specifies the number of 12 byte records that + are active. The nodeLevel is non-zero for this style of nodes. + The leaf nodes have a different format. The backPointer must + match the backPointer from the triple that pointed to this node. </para> <para> - Each item in this node is a triple of (ID2, back-pointer, offset) + Each item in this node is a triple of (ID2, backPointer, offset) where the offset points to the next deeper node in the tree, the - back-pointer value must match the back-pointer in that deeper node, + backPointer value must match the backPointer in that deeper node, and ID2 is the lowest ID2 value in the subtree. </para> </refsect1> @@ -811,15 +811,15 @@ 01F0 10 1f 10 00 81 81 a0 9a ae 1e 02 00 89 44 6a 0f 0200 b8 b1 03 00 -01f0 item-count [1 byte] 0x10 in this case -01f1 max-item-count [1 byte] 0x1f constant -01f3 node-level [1 byte] 0x00 in this case -01f8 back-pointer [4 bytes] 0x021eae in this case +01f0 itemCount [1 byte] 0x10 in this case +01f1 maxItemCount [1 byte] 0x1f constant +01f3 nodeLevel [1 byte] 0x00 in this case +01f8 backPointer [4 bytes] 0x021eae in this case ]]></literallayout> <para> - The item-count specifies the number of 16 byte records that - are active. The node-level is zero for these leaf nodes. - The back-pointer must match the back-pointer from the triple + The itemCount specifies the number of 16 byte records that + are active. The nodeLevel is zero for these leaf nodes. + The backPointer must match the backPointer from the triple that pointed to this node. </para> <para> @@ -848,12 +848,13 @@ </refsect1> <refsect1 id='pst.file.desc.5'> - <title>Associated Descriptor Item</title> + <title>Associated Descriptor Item 0xbcec</title> <para> - Contains information about the item, which may be email, contact, or other outlook types. - In the above leaf node, we have a tuple of (0x21, 0x00e638, 0, 0) - 0x00e638 is the ID1 of the associated descriptor, and we can lookup that ID1 value - in the index1 b-tree to find the (offset,size) of the data in the .pst file. + Contains information about the item, which may be email, contact, or + other outlook types. In the above leaf node, we have a tuple of (0x21, + 0x00e638, 0, 0) 0x00e638 is the ID1 of the associated descriptor, and we + can lookup that ID1 value in the index1 b-tree to find the (offset,size) + of the data in the .pst file. </para> <literallayout class="monospaced"><![CDATA[ 0000 3c 01 ec bc 20 00 00 00 00 00 00 00 b5 02 06 00 @@ -879,23 +880,25 @@ 0140 0c 00 14 00 7c 00 8c 00 93 00 ab 00 c3 00 db 00 0150 f3 00 0b 01 23 01 3b 01 -0000 index-offset [2 bytes] 0x013c in this case +0000 indexOffset [2 bytes] 0x013c in this case 0002 signature [2 bytes] 0xbcec constant 0004 offset [2 bytes] 0x0020 in this case ]]></literallayout> <para> - Note the index-offset of 0x013c - starting at that position in the + Note the signature of 0xbcec. There are other descriptor block + formats with other signatures. + Note the indexOffset of 0x013c - starting at that position in the descriptor block, we have an array of two byte integers. The first - integer (0x000b) is a count of the number of overlapping pairs + integer (0x000b) is a (count-1) of the number of overlapping pairs following the count. The first pair is (0, 0xc), the next pair is (0xc, 0x14) - and the last (11th) pair is (0x10b, 0x123). These pairs are (start,end+1) - offsets of items in this block. So we have count+1 integers following + and the last (12th) pair is (0x123, 0x13b). These pairs are (start,end+1) + offsets of items in this block. So we have count+2 integers following the count value. </para> <para> Note the offset of 0x0020, which needs to be right shifted by 4 bits to become 0x0002, which is then a byte offset to be added to the above - index-offset plus two (to skip the count), so it points to the (0xc, 0x14) + indexOffset plus two (to skip the count), so it points to the (0xc, 0x14) pair. Finally, we have the offset and size of the "b5" block located at offset 0xc with a size of 8 bytes in this descriptor block. The "b5" block has the following format: @@ -908,13 +911,13 @@ <para> Note the "b5" offset of 0x0040, which needs to be right shifted by 4 bits to become 0x0004, which is then a byte offset to be added to the above - index-offset plus two (to skip the count), so it points to the (0x14, 0x7c) + indexOffset plus two (to skip the count), so it points to the (0x14, 0x7c) pair. We now have the offset 0x14 of the descriptor array, composed of 8 byte entries. Each descriptor entry has the following format: </para> <literallayout class="monospaced"><![CDATA[ -0000 item-type [2 bytes] -0002 reference-type [2 bytes] +0000 itemType [2 bytes] +0002 referenceType [2 bytes] 0004 value [4 bytes] ]]></literallayout> <para> @@ -1167,5 +1170,125 @@ ]]></literallayout> </refsect1> + <refsect1 id='pst.file.desc2.5'> + <title>Associated Descriptor Item 0x7cec</title> + <para> + This style of descriptor block is similar to the BCEC format. + </para> + <literallayout class="monospaced"><![CDATA[ +0000 7a 01 ec 7c 40 00 00 00 00 00 00 00 b5 04 02 00 +0010 60 00 00 00 7c 18 60 00 60 00 62 00 65 00 20 00 +0020 00 00 80 00 00 00 00 00 00 00 03 00 20 0e 0c 00 +0030 04 03 1e 00 01 30 2c 00 04 0b 1e 00 03 37 28 00 +0040 04 0a 1e 00 04 37 14 00 04 05 03 00 05 37 10 00 +0050 04 04 1e 00 07 37 24 00 04 09 1e 00 08 37 20 00 +0060 04 08 02 01 0a 37 18 00 04 06 03 00 0b 37 08 00 +0070 04 02 1e 00 0d 37 1c 00 04 07 1e 00 0e 37 40 00 +0080 04 10 02 01 0f 37 30 00 04 0c 1e 00 11 37 34 00 +0090 04 0d 1e 00 12 37 3c 00 04 0f 1e 00 13 37 38 00 +00A0 04 0e 03 00 f2 67 00 00 04 00 03 00 f3 67 04 00 +00B0 04 01 03 00 09 69 44 00 04 11 03 00 fa 7f 5c 00 +00C0 04 15 40 00 fb 7f 4c 00 08 13 40 00 fc 7f 54 00 +00D0 08 14 03 00 fd 7f 48 00 04 12 0b 00 fe 7f 60 00 +00E0 01 16 0b 00 ff 7f 61 00 01 17 45 82 00 00 00 00 +00F0 45 82 00 00 78 3c 00 00 ff ff ff ff 49 1e 00 00 +0100 06 00 00 00 00 00 00 00 a0 00 00 00 00 00 00 00 +0110 00 00 00 00 00 00 00 00 00 00 00 00 c0 00 00 00 +0120 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +0130 00 00 00 00 00 00 00 00 00 00 00 00 00 40 dd a3 +0140 57 45 b3 0c 00 40 dd a3 57 45 b3 0c 02 00 00 00 +0150 00 00 fa 10 3e 2a 86 48 86 f7 14 03 0a 03 02 01 +0160 4a 2e 20 44 61 76 69 64 20 4b 61 72 61 6d 27 73 +0170 20 42 69 72 74 68 64 61 79 00 06 00 00 00 0c 00 +0180 14 00 ea 00 f0 00 55 01 60 01 79 01 + +0000 indexOffset [2 bytes] 0x017a in this case +0002 signature [2 bytes] 0x7cec constant +0004 offset [2 bytes] 0x0040 in this case +]]></literallayout> + <para> + Note the signature of 0x7cec. There are other descriptor block + formats with other signatures. + Note the indexOffset of 0x017a - starting at that position in the + descriptor block, we have an array of two byte integers. The first + integer (0x0006) is a (count-1) of the number of overlapping pairs + following the count. The first pair is (0, 0xc), the next pair is (0xc, 0x14) + and the last (7th) pair is (0x160, 0x179). These pairs are (start,end+1) + offsets of items in this block. So we have count+2 integers following + the count value. + </para> + <para> + Note the offset of 0x0040, which needs to be right shifted by 4 bits + to become 0x0004, which is then a byte offset to be added to the above + indexOffset plus two (to skip the count), so it points to the (0x14, 0xea) + pair. We have the offset and size of the "7c" block located at offset 0x14 + with a size of 214 bytes in this case. The "7c" block starts with + a header with the following format: + </para> + <literallayout class="monospaced"><![CDATA[ +0000 signature [1 bytes] 0x7c constant +0001 itemCount [1 bytes] 0x18 in this case +0002 unknown [2 bytes] 0x0060 in this case +0004 unknown [2 bytes] 0x0060 in this case +0006 unknown [2 bytes] 0x0062 in this case +0008 recordSize [2 bytes] 0x0065 in this case +000a b5Offset [2 bytes] 0x0020 in this case +000c unknown [2 bytes] 0x0000 in this case +000e index2Offset [2 bytes] 0x0080 in this case +0010 unknown [2 bytes] 0x0000 in this case +0012 unknown [2 bytes] 0x0000 in this case +0014 unknown [2 bytes] 0x0000 in this case +]]></literallayout> + <para> + Note the b5Offset of 0x0020, which needs to be right shifted by 4 bits + to become 0x0002, which is then a byte offset to be added to the above + indexOffset plus two (to skip the count), so it points to the (0xc, + 0x14) pair. Finally, we have the offset and size of the "b5" block + located at offset 0xc with a size of 8 bytes in this descriptor block. + The "b5" block has the following format: + </para> + <literallayout class="monospaced"><![CDATA[ +0000 signature [2 bytes] 0x04b5 constant +0002 unknown [2 bytes] 0x0002 in this case +0004 offset [4 bytes] 0x0060 in this case +]]></literallayout> + <para> + Note the "b5" offset of 0x0060, which needs to be right shifted by 4 + bits to become 0x0006, which is then a byte offset to be added to the + above indexOffset plus two (to skip the count), so it points to the + (0xea, 0xf0) pair. That gives us (0xf0 - 0xea)/6 = 1, so we have a + recordCount of one. The actual data between 0xea and 0xf0 is unknown + and unused here. + </para> + <para> + Note the index2Offset above of 0x0080, which needs to be right shifted + by 4 bits to become 0x0008, which is then a byte offset to be added to + the above indexOffset plus two (to skip the count), so it points to the + (0xf0, 0x155) pair. This is an array of tables of four byte integers. + We will call these the IND2 tables. The size of each of these tables is + specified by the recordSize field of the "7c" header. The number of + these tables is the above recordCount value derived from the "b5" block. + </para> + <para> + Now the remaining data in the "7c" block after the header starts at + offset 0x2a. There should be itemCount 8 byte items here, with the + following format: + </para> + <literallayout class="monospaced"><![CDATA[ +0000 referenceType [2 bytes] +0002 itemType [2 bytes] +0004 ind2Offset [2 bytes] +0006 unknown [2 bytes] +]]></literallayout> + <para> + The ind2Offset is a byte offset into the current IND2 table of a four + byte integer value. Once we fetch that, we have the same triple (item + type, reference type, value) as we find in the 0xbcec style descriptor + blocks. These 8 byte descriptors are processed recordCount times, each + time using the next IND2 table. The item and reference types are as + described above for the 0xbcec format descriptor block. + </para> + </refsect1> + </refentry> </reference>