comparison src/libpst.c @ 191:4b498fd68464

add pst_attach_to_mem() back into the shared library interface. improve developer documentation. fix memory leak caught by valgrind.
author Carl Byington <carl@five-ten-sg.com>
date Wed, 15 Apr 2009 18:39:42 -0700
parents e3a63888cdd4
children cf3df962f1e5
comparison
equal deleted inserted replaced
190:e3a63888cdd4 191:4b498fd68464
14 #pragma pack(push, 1) 14 #pragma pack(push, 1)
15 #endif 15 #endif
16 #if defined(__GNUC__) || defined (__SUNPRO_C) || defined(__SUNPRO_CC) 16 #if defined(__GNUC__) || defined (__SUNPRO_C) || defined(__SUNPRO_CC)
17 #pragma pack(1) 17 #pragma pack(1)
18 #endif 18 #endif
19
20 19
21 #define ASSERT(x) { if(!(x)) raise( SIGSEGV ); } 20 #define ASSERT(x) { if(!(x)) raise( SIGSEGV ); }
22 21
23 #define INDEX_TYPE32 0x0E 22 #define INDEX_TYPE32 0x0E
24 #define INDEX_TYPE32A 0x0F // unknown, but assumed to be similar for now 23 #define INDEX_TYPE32A 0x0F // unknown, but assumed to be similar for now
446 //DEBUG_INDEX(("Null parent\n")); 445 //DEBUG_INDEX(("Null parent\n"));
447 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); 446 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail);
448 } 447 }
449 else if (node->parent_d_id == node->d_id) { 448 else if (node->parent_d_id == node->d_id) {
450 // add top level node to the descriptor tree 449 // add top level node to the descriptor tree
451 DEBUG_INDEX(("%#"PRIx64" is its own parent. What is this world coming to?\n")); 450 DEBUG_INDEX(("%#"PRIx64" is its own parent. What is this world coming to?\n", node->d_id));
452 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail); 451 add_descriptor_to_list(node, &pf->d_head, &pf->d_tail);
453 } else { 452 } else {
454 //DEBUG_INDEX(("Searching for parent %#"PRIx64" of %#"PRIx64"\n", node->parent_d_id, node->d_id)); 453 //DEBUG_INDEX(("Searching for parent %#"PRIx64" of %#"PRIx64"\n", node->parent_d_id, node->d_id));
455 pst_desc_tree *parent = pst_getDptr(pf, node->parent_d_id); 454 pst_desc_tree *parent = pst_getDptr(pf, node->parent_d_id);
456 if (parent) { 455 if (parent) {
518 DEBUG_RET(); 517 DEBUG_RET();
519 return topnode; 518 return topnode;
520 } 519 }
521 520
522 521
522 size_t pst_attach_to_mem(pst_file *pf, pst_item_attach *attach, char **b) {
523 pst_index_ll *ptr;
524 pst_holder h = {b, NULL, 0};
525 size_t size = 0;
526 DEBUG_ENT("pst_attach_to_mem");
527 if (attach->i_id != (uint64_t)-1) {
528 ptr = pst_getID(pf, attach->i_id);
529 if (ptr) {
530 size = pst_ff_getID2data(pf, ptr, &h);
531 } else {
532 DEBUG_WARN(("Couldn't find ID pointer. Cannot handle attachment\n"));
533 }
534 attach->data.size = size;
535 } else {
536 size = attach->data.size;
537 *b = attach->data.data;
538 }
539 DEBUG_RET();
540 return size;
541 }
542
543
523 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) { 544 size_t pst_attach_to_file(pst_file *pf, pst_item_attach *attach, FILE* fp) {
524 pst_index_ll *ptr; 545 pst_index_ll *ptr;
525 pst_holder h = {NULL, fp, 0}; 546 pst_holder h = {NULL, fp, 0};
526 size_t size = 0; 547 size_t size = 0;
527 DEBUG_ENT("pst_attach_to_file"); 548 DEBUG_ENT("pst_attach_to_file");
556 DEBUG_WARN(("Couldn't find ID pointer. Cannot save attachment to Base64\n")); 577 DEBUG_WARN(("Couldn't find ID pointer. Cannot save attachment to Base64\n"));
557 } 578 }
558 attach->data.size = size; 579 attach->data.size = size;
559 } else { 580 } else {
560 // encode the attachment to the file 581 // encode the attachment to the file
561 char *c = pst_base64_encode(attach->data.data, attach->data.size); 582 size = attach->data.size;
583 char *c = pst_base64_encode(attach->data.data, size);
562 if (c) { 584 if (c) {
563 (void)pst_fwrite(c, (size_t)1, strlen(c), fp); 585 (void)pst_fwrite(c, (size_t)1, strlen(c), fp);
564 free(c); // caught by valgrind 586 free(c); // caught by valgrind
565 } 587 }
566 size = attach->data.size;
567 } 588 }
568 DEBUG_RET(); 589 DEBUG_RET();
569 return size; 590 return size;
570 } 591 }
571 592
684 xattrib.extended= PST_LE_GET_UINT32(buffer+bptr), bptr += 4; 705 xattrib.extended= PST_LE_GET_UINT32(buffer+bptr), bptr += 4;
685 xattrib.type = PST_LE_GET_UINT16(buffer+bptr), bptr += 2; 706 xattrib.type = PST_LE_GET_UINT16(buffer+bptr), bptr += 2;
686 xattrib.map = PST_LE_GET_UINT16(buffer+bptr), bptr += 2; 707 xattrib.map = PST_LE_GET_UINT16(buffer+bptr), bptr += 2;
687 ptr = (pst_x_attrib_ll*) pst_malloc(sizeof(*ptr)); 708 ptr = (pst_x_attrib_ll*) pst_malloc(sizeof(*ptr));
688 memset(ptr, 0, sizeof(*ptr)); 709 memset(ptr, 0, sizeof(*ptr));
689 ptr->type = xattrib.type;
690 ptr->map = xattrib.map+0x8000; 710 ptr->map = xattrib.map+0x8000;
691 ptr->next = NULL; 711 ptr->next = NULL;
692 DEBUG_INDEX(("xattrib: ext = %#"PRIx32", type = %#"PRIx16", map = %#"PRIx16"\n", 712 DEBUG_INDEX(("xattrib: ext = %#"PRIx32", type = %#"PRIx16", map = %#"PRIx16"\n",
693 xattrib.extended, xattrib.type, xattrib.map)); 713 xattrib.extended, xattrib.type, xattrib.map));
694 if (xattrib.type & 0x0001) { // if the Bit 1 is set 714 if (xattrib.type & 0x0001) { // if the Bit 1 is set
1260 return NULL; 1280 return NULL;
1261 } 1281 }
1262 pst_free_list(list); 1282 pst_free_list(list);
1263 1283
1264 // now we will have initial information of each attachment stored in item->attach... 1284 // now we will have initial information of each attachment stored in item->attach...
1265 // we must now read the secondary record for each based on the id2 val associated with 1285 // we must now read the secondary record for each based on the id2_val associated with
1266 // each attachment 1286 // each attachment
1267 attach = item->attach; 1287 for (attach = item->attach; attach; attach = attach->next) {
1268 while (attach) {
1269 DEBUG_WARN(("initial attachment id2 %#"PRIx64"\n", attach->id2_val)); 1288 DEBUG_WARN(("initial attachment id2 %#"PRIx64"\n", attach->id2_val));
1270 if ((id2_ptr = pst_getID2(id2_head, attach->id2_val))) { 1289 if ((id2_ptr = pst_getID2(id2_head, attach->id2_val))) {
1271 DEBUG_WARN(("initial attachment id2 found id %#"PRIx64"\n", id2_ptr->id->i_id)); 1290 DEBUG_WARN(("initial attachment id2 found id %#"PRIx64"\n", id2_ptr->id->i_id));
1272 // id_ptr is a record describing the attachment 1291 // id2_ptr is a record describing the attachment
1273 // we pass NULL instead of id2_head cause we don't want it to 1292 // we pass NULL instead of id2_head cause we don't want it to
1274 // load all the extra stuff here. 1293 // load all the extra stuff here.
1275 list = pst_parse_block(pf, id2_ptr->id->i_id, NULL); 1294 list = pst_parse_block(pf, id2_ptr->id->i_id, NULL);
1276 if (!list) { 1295 if (!list) {
1277 DEBUG_WARN(("ERROR error processing an attachment record\n")); 1296 DEBUG_WARN(("ERROR error processing an attachment record\n"));
1278 attach = attach->next;
1279 continue; 1297 continue;
1280 } 1298 }
1281 if (list->count_objects > 1) { 1299 if (list->count_objects > 1) {
1282 DEBUG_WARN(("ERROR probably fatal, list count array will overrun attach structure.\n")); 1300 DEBUG_WARN(("ERROR probably fatal, list count array will overrun attach structure.\n"));
1283 } 1301 }
1284 if (pst_process(list, item, attach)) { 1302 if (pst_process(list, item, attach)) {
1285 DEBUG_WARN(("ERROR pst_process() failed with an attachment\n")); 1303 DEBUG_WARN(("ERROR pst_process() failed with an attachment\n"));
1286 pst_free_list(list); 1304 pst_free_list(list);
1287 attach = attach->next;
1288 continue; 1305 continue;
1289 } 1306 }
1290 pst_free_list(list); 1307 pst_free_list(list);
1291 id2_ptr = pst_getID2(id2_head, attach->id2_val); 1308 id2_ptr = pst_getID2(id2_head, attach->id2_val);
1292 if (id2_ptr) { 1309 if (id2_ptr) {
1300 } 1317 }
1301 } else { 1318 } else {
1302 DEBUG_WARN(("ERROR cannot locate id2 value %#"PRIx64"\n", attach->id2_val)); 1319 DEBUG_WARN(("ERROR cannot locate id2 value %#"PRIx64"\n", attach->id2_val));
1303 attach->id2_val = 0; // suppress this missing attachment 1320 attach->id2_val = 0; // suppress this missing attachment
1304 } 1321 }
1305 attach = attach->next;
1306 } 1322 }
1307 } 1323 }
1308 1324
1309 if (!m_head) pst_free_id2(id2_head); 1325 if (!m_head) pst_free_id2(id2_head);
1310 DEBUG_RET(); 1326 DEBUG_RET();
2078 switch (list->elements[x]->mapi_id) { 2094 switch (list->elements[x]->mapi_id) {
2079 case PST_ATTRIB_HEADER: // CUSTOM attribute for saying the Extra Headers 2095 case PST_ATTRIB_HEADER: // CUSTOM attribute for saying the Extra Headers
2080 if (list->elements[x]->extra) { 2096 if (list->elements[x]->extra) {
2081 pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field)); 2097 pst_item_extra_field *ef = (pst_item_extra_field*) pst_malloc(sizeof(pst_item_extra_field));
2082 memset(ef, 0, sizeof(pst_item_extra_field)); 2098 memset(ef, 0, sizeof(pst_item_extra_field));
2083 ef->field_name = strdup(list->elements[x]->extra);
2084 LIST_COPY_CSTR(ef->value); 2099 LIST_COPY_CSTR(ef->value);
2085 if (ef->value) { 2100 if (ef->value) {
2086 ef->next = item->extra_fields; 2101 ef->field_name = strdup(list->elements[x]->extra);
2102 ef->next = item->extra_fields;
2087 item->extra_fields = ef; 2103 item->extra_fields = ef;
2088 DEBUG_EMAIL(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value)); 2104 DEBUG_EMAIL(("Extra Field - \"%s\" = \"%s\"\n", ef->field_name, ef->value));
2089 if (strcmp(ef->field_name, "content-type") == 0) { 2105 if (strcmp(ef->field_name, "content-type") == 0) {
2090 char *p = strstr(ef->value, "charset=\""); 2106 char *p = strstr(ef->value, "charset=\"");
2091 if (p) { 2107 if (p) {
2104 } 2120 }
2105 } 2121 }
2106 else { 2122 else {
2107 DEBUG_EMAIL(("What does this mean? Internet header %s value\n", list->elements[x]->extra)); 2123 DEBUG_EMAIL(("What does this mean? Internet header %s value\n", list->elements[x]->extra));
2108 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size); 2124 DEBUG_HEXDUMP(list->elements[x]->data, list->elements[x]->size);
2125 free(ef); // caught by valgrind
2109 } 2126 }
2110 } 2127 }
2111 break; 2128 break;
2112 case 0x0002: // PR_ALTERNATE_RECIPIENT_ALLOWED 2129 case 0x0002: // PR_ALTERNATE_RECIPIENT_ALLOWED
2113 if (list->elements[x]->type == 0x0b) { 2130 if (list->elements[x]->type == 0x0b) {
3806 return rc; 3823 return rc;
3807 } 3824 }
3808 3825
3809 3826
3810 /** 3827 /**
3811 * Get an ID block from file using _pst_ff_getIDblock and decrypt if necessary 3828 * Get an ID block from file using pst_ff_getIDblock() and decrypt if necessary
3812 *
3813 * @param pf PST file structure 3829 * @param pf PST file structure
3814 * @param i_id ID of block to retrieve 3830 * @param i_id ID of block to retrieve
3815 * @param buf reference to pointer to buffer that will contain the data block. 3831 * @param buf reference to pointer to buffer that will contain the data block.
3816 * If this pointer is non-NULL, it will first be free()d. 3832 * If this pointer is non-NULL, it will first be free()d.
3817 * @return Size of block read into memory 3833 * @return Size of block read into memory
4083 static char* buf = NULL; 4099 static char* buf = NULL;
4084 static size_t buflen = 0; 4100 static size_t buflen = 0;
4085 char *ret, *a, *b; 4101 char *ret, *a, *b;
4086 size_t x = 0; 4102 size_t x = 0;
4087 int y, z; 4103 int y, z;
4104 if (!str) return NULL;
4088 DEBUG_ENT("rfc2426_escape"); 4105 DEBUG_ENT("rfc2426_escape");
4089 if (!str) 4106 // calculate space required to escape all the following characters
4107 y = pst_chr_count(str, ',')
4108 + pst_chr_count(str, '\\')
4109 + pst_chr_count(str, ';')
4110 + pst_chr_count(str, '\n');
4111 z = pst_chr_count(str, '\r');
4112 if (y == 0 && z == 0)
4113 // there isn't any extra space required
4090 ret = str; 4114 ret = str;
4091 else { 4115 else {
4092 4116 x = strlen(str) + y - z + 1; // don't forget room for the NUL
4093 // calculate space required to escape all the following characters 4117 if (x > buflen) {
4094 y = pst_chr_count(str, ',') 4118 buf = (char*) realloc(buf, x);
4095 + pst_chr_count(str, '\\') 4119 buflen = x;
4096 + pst_chr_count(str, ';') 4120 }
4097 + pst_chr_count(str, '\n'); 4121 a = str;
4098 z = pst_chr_count(str, '\r'); 4122 b = buf;
4099 if (y == 0 && z == 0) 4123 while (*a != '\0') {
4100 // there isn't any extra space required 4124 switch (*a) {
4101 ret = str; 4125 case ',' :
4102 else { 4126 case '\\':
4103 x = strlen(str) + y - z + 1; // don't forget room for the NUL 4127 case ';' :
4104 if (x > buflen) { 4128 *(b++) = '\\';
4105 buf = (char*) realloc(buf, x); 4129 *b = *a;
4106 buflen = x; 4130 break;
4131 case '\n': // newlines are encoded as "\n"
4132 *(b++) = '\\';
4133 *b = 'n';
4134 break;
4135 case '\r': // skip cr
4136 b--;
4137 break;
4138 default:
4139 *b=*a;
4107 } 4140 }
4108 a = str; 4141 b++;
4109 b = buf; 4142 a++;
4110 while (*a != '\0') { 4143 }
4111 switch (*a) { 4144 *b = '\0'; // NUL-terminate the string (buf)
4112 case ',' : 4145 ret = buf;
4113 case '\\':
4114 case ';' :
4115 *(b++) = '\\';
4116 *b = *a;
4117 break;
4118 case '\n': // newlines are encoded as "\n"
4119 *(b++) = '\\';
4120 *b = 'n';
4121 break;
4122 case '\r': // skip cr
4123 b--;
4124 break;
4125 default:
4126 *b=*a;
4127 }
4128 b++;
4129 a++;
4130 }
4131 *b = '\0'; // NUL-terminate the string (buf)
4132 ret = buf;
4133 }
4134 } 4146 }
4135 DEBUG_RET(); 4147 DEBUG_RET();
4136 return ret; 4148 return ret;
4137 } 4149 }
4138 4150