_PUBLIC_ void mapidump_tags(enum MAPITAGS *Tags, uint16_t TagCount, const char *sep) { uint32_t i; const char *proptag; for (i = 0; i < TagCount; i++) { proptag = get_proptag_name(Tags[i]); printf("%s Tag: %s\n", sep?sep:"", proptag); fflush(0); } }
_PUBLIC_ void mapidump_SPropTagArray(struct SPropTagArray *SPropTagArray) { uint32_t count; const char *proptag; if (!SPropTagArray) return; if (!SPropTagArray->cValues) return; for (count = 0; count != SPropTagArray->cValues; count++) { proptag = get_proptag_name(SPropTagArray->aulPropTag[count]); if (proptag) { printf("%s\n", proptag); } else { printf("0x%.8x\n", SPropTagArray->aulPropTag[count]); } } }
_PUBLIC_ void ocpf_dump_property(uint32_t context_id) { struct ocpf_context *ctx; struct ocpf_property *element; const char *proptag; ctx = ocpf_context_search_by_context_id(ocpf->context, context_id); if (!ctx) return; OCPF_DUMP_TITLE(indent, "PROPERTIES", OCPF_DUMP_TOPLEVEL); indent++; for (element = ctx->props; element->next; element = element->next) { INDENT(); proptag = (const char *)get_proptag_name(element->aulPropTag); printf("0x%.8x = %s\n", element->aulPropTag, (char *)(proptag ? proptag : "UNKNOWN")); } indent--; }
static enum MAPISTATUS parse_property_cb (struct SPropValue prop, void *closure) { EMapiFXParserClosure *data = closure; if (data->next_proptag_is_nameid == prop.ulPropTag) { prop.ulPropTag = data->next_nameid_proptag; } data->next_proptag_is_nameid = MAPI_E_RESERVED; data->next_nameid_proptag = MAPI_E_RESERVED; if (!data->current_properties) { if (data->marker) g_debug ("%s: Property received out of order under marker %s", G_STRFUNC, get_proptag_name (data->marker)); return MAPI_E_SUCCESS; } switch (prop.ulPropTag & 0xFFFF) { case PT_BINARY: if (data->current_streamed_properties && data->current_streamed_properties_count && prop.value.bin.cb > 65535) { guint32 index; (*data->current_streamed_properties) = talloc_realloc (data->current_streamed_mem_ctx, (*data->current_streamed_properties), EMapiStreamedProp, (*data->current_streamed_properties_count) + 1); index = (*data->current_streamed_properties_count); (*data->current_streamed_properties_count)++; (*data->current_streamed_properties)[index].proptag = prop.ulPropTag; (*data->current_streamed_properties)[index].cb = prop.value.bin.cb; (*data->current_streamed_properties)[index].lpb = prop.value.bin.lpb; break; } else if (prop.value.bin.cb > 65535) { g_debug ("%s: PT_BINARY property 0x%X larger than 64KB (%d), will be truncated", G_STRFUNC, prop.ulPropTag, prop.value.bin.cb); } case PT_BOOLEAN: case PT_I2: case PT_LONG: case PT_DOUBLE: case PT_I8: case PT_STRING8: case PT_UNICODE: case PT_SYSTIME: case PT_ERROR: case PT_CLSID: case PT_SVREID: case PT_MV_STRING8: case PT_MV_UNICODE: case PT_MV_BINARY: case PT_MV_LONG: data->current_properties->cValues++; data->current_properties->lpProps = talloc_realloc (data->mem_ctx, data->current_properties->lpProps, struct mapi_SPropValue, data->current_properties->cValues + 1); cast_mapi_SPropValue (data->mem_ctx, &data->current_properties->lpProps[data->current_properties->cValues - 1], &prop); data->current_properties->lpProps[data->current_properties->cValues].ulPropTag = 0; break; default: /* skip all of other type */ break; } return MAPI_E_SUCCESS; }
/** \details Check if a fid is an special following [MS-OXOSFLD] Section 2.2.2 rules. \param emsmdbp_ctx pointer to the emsmdb provider context \param fid the folder identifier to check \return true on success, otherwise false \note An error on any call is interpreted as false */ _PUBLIC_ bool oxosfld_is_special_folder(struct emsmdbp_context *emsmdbp_ctx, uint64_t fid) { bool ret = false; struct Binary_r *entry_id; struct BinaryArray_r *entries_ids; struct FolderEntryId folder_entry_id; int i, system_idx; enum MAPISTATUS retval; TALLOC_CTX *local_mem_ctx; const uint32_t identification_properties[] = { PidTagIpmAppointmentEntryId, PidTagIpmContactEntryId, PidTagIpmJournalEntryId, PidTagIpmNoteEntryId, PidTagIpmTaskEntryId, PidTagRemindersOnlineEntryId, PidTagIpmDraftsEntryId }; const uint32_t IDENTIFICATION_PROP_COUNT = sizeof(identification_properties)/sizeof(uint32_t); const uint32_t ADDITIONAL_REN_ENTRY_IDS_COUNT = 5, FREEBUSY_DATA_ENTRYID_IDX = 3; uint64_t inbox_fid, mailbox_fid; /* Sanity checks */ if (!emsmdbp_ctx) return false; /* 1. The fids returned in RopLogon are special folders, as they are set with SystemIdx higher than -1. See emsmdbp_provisioning.c for details */ retval = openchangedb_get_system_idx(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, fid, &system_idx); if (retval == MAPI_E_SUCCESS && system_idx > -1) { OC_DEBUG(5, "Fid 0x%"PRIx64 " is a system special folder whose system_idx is %d", fid, system_idx); return true; } retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, EMSMDBP_MAILBOX_ROOT, &mailbox_fid); if (retval == MAPI_E_SUCCESS && mailbox_fid == fid) { OC_DEBUG(5, "Fid 0x%"PRIx64 " is the mailbox ID", fid); return true; } /* 2. Set of binary properties on the root folder or inbox folder */ /* TODO: work in Delegate mode */ retval = openchangedb_get_SystemFolderID(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, EMSMDBP_INBOX, &inbox_fid); if (retval != MAPI_E_SUCCESS) { return false; } memset(&folder_entry_id, 0, sizeof(struct FolderEntryId)); retval = openchangedb_get_MailboxGuid(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, &folder_entry_id.ProviderUID); if (retval != MAPI_E_SUCCESS) { return false; } retval = openchangedb_get_MailboxReplica(emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, NULL, &folder_entry_id.FolderDatabaseGuid); if (retval != MAPI_E_SUCCESS) { return false; } local_mem_ctx = talloc_new(NULL); if (!local_mem_ctx) return false; for (i = 0; i < IDENTIFICATION_PROP_COUNT; i++) { retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, identification_properties[i], inbox_fid, (void **) &entry_id); if (retval == MAPI_E_SUCCESS && fid_in_entry_id(entry_id, inbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found in %s property", fid, get_proptag_name(identification_properties[i])); ret = true; goto end; } } /* 3. The PidTagAdditionalRenEntryIds contains an array of entry IDs with special folders */ retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, PidTagAdditionalRenEntryIds, inbox_fid, (void **) &entries_ids); if (retval == MAPI_E_SUCCESS && entries_ids && entries_ids->cValues >= ADDITIONAL_REN_ENTRY_IDS_COUNT) { for (i = 0; i < ADDITIONAL_REN_ENTRY_IDS_COUNT; i++) { if (fid_in_entry_id((entries_ids->lpbin + i), inbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found as %d index in PidTagAdditionalRenEntryIds", fid, i); ret = true; goto end; } } } /* 4. The PidTagAdditionalRenEntryIdsEx on the store object */ retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, PidTagAdditionalRenEntryIdsEx, inbox_fid, (void **) &entry_id); if (retval == MAPI_E_SUCCESS) { int j, k; struct PersistDataArray *persist_data_array; persist_data_array = get_PersistDataArray(local_mem_ctx, entry_id); if (persist_data_array && persist_data_array->cValues > 0) { struct Binary_r checked_entry_id; DATA_BLOB checked_folder_entry_id; struct PersistData persist_data; struct PersistElement persist_element; struct PersistElementArray persist_element_array; for (j = 0; j < persist_data_array->cValues; j++) { persist_data = persist_data_array->lpPersistData[j]; if (persist_data.PersistID == PERSIST_SENTINEL) { /* This is the last PersistData */ break; } persist_element_array = persist_data.DataElements; for (k = 0; k < persist_element_array.cValues; k++) { persist_element = persist_element_array.lpPersistElement[k]; if (persist_element.ElementID == PERSIST_SENTINEL) { /* This is the last PersistElement */ break; } if (persist_element.ElementID == RSF_ELID_ENTRYID) { checked_folder_entry_id = persist_element.ElementData.rsf_elid_entryid; checked_entry_id.cb = checked_folder_entry_id.length; checked_entry_id.lpb = checked_folder_entry_id.data; if (fid_in_entry_id(&checked_entry_id, inbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found as %d entry in PidTagAdditionalRenEntryIdsEx", fid, persist_data.PersistID); ret = true; goto end; } } } } } else { OC_DEBUG(5, "Cannot parse PersistDataArray"); } } /* 5. The entry ID indexed by 3 in PidTagFreeBusyEntryIds on the root folder stores the Freebusy data folder */ retval = openchangedb_get_folder_property(local_mem_ctx, emsmdbp_ctx->oc_ctx, emsmdbp_ctx->username, PidTagFreeBusyEntryIds, inbox_fid, (void **) &entries_ids); if (retval == MAPI_E_SUCCESS && entries_ids && entries_ids->cValues >= FREEBUSY_DATA_ENTRYID_IDX && fid_in_entry_id((entries_ids->lpbin + FREEBUSY_DATA_ENTRYID_IDX), mailbox_fid, &folder_entry_id, fid)) { OC_DEBUG(5, "The fid 0x%"PRIx64 " found as Freebusy Data\n", fid); ret = true; goto end; } /* 6. The FID returned by RopGetReceiveFolder */ /* According to [MS-OXOSFLD] Section 2.2.7, we should search for the default Receive folder for the Store object. And according to [MS-OXCSTOR] Section 3.2.5.2, it should be the user's inbox folder and it is already checked above. */ end: talloc_free(local_mem_ctx); return ret; }
/** Output one property tag and value \param lpProp the property to print \param sep a separator / spacer to insert in front of the label */ _PUBLIC_ void mapidump_SPropValue(struct SPropValue lpProp, const char *sep) { const char *proptag; const void *data; TALLOC_CTX *mem_ctx = NULL; const struct StringArray_r *StringArray_r = NULL; const struct StringArrayW_r *StringArrayW_r = NULL; const struct BinaryArray_r *BinaryArray_r = NULL; const struct LongArray_r *LongArray_r = NULL; uint32_t i; proptag = get_proptag_name(lpProp.ulPropTag); if (!proptag) { mem_ctx = talloc_named(NULL, 0, "mapidump_SPropValue"); proptag = talloc_asprintf(mem_ctx, "0x%.8x", lpProp.ulPropTag); } switch(lpProp.ulPropTag & 0xFFFF) { case PT_SHORT: data = get_SPropValue_data(&lpProp); printf("%s%s: 0x%x\n", sep?sep:"", proptag, (*(const uint16_t *)data)); break; case PT_LONG: case PT_OBJECT: data = get_SPropValue_data(&lpProp); printf("%s%s: %u\n", sep?sep:"", proptag, (*(const uint32_t *)data)); break; case PT_DOUBLE: data = get_SPropValue_data(&lpProp); printf("%s%s: %f\n", sep?sep:"", proptag, (*(const double *)data)); break; case PT_BOOLEAN: data = get_SPropValue_data(&lpProp); printf("%s%s: 0x%x\n", sep?sep:"", proptag, (*(const uint8_t *)data)); break; case PT_I8: data = get_SPropValue_data(&lpProp); printf("%s%s: %.16"PRIx64"\n", sep?sep:"", proptag, (*(const uint64_t *)data)); break; case PT_STRING8: case PT_UNICODE: data = get_SPropValue_data(&lpProp); printf("%s%s:", sep?sep:"", proptag); if (data && ((*(const uint16_t *)data) == 0x0000)) { /* its an empty string */ printf("\n"); } else if (data && ((*(enum MAPISTATUS *)data) != MAPI_E_NOT_FOUND)) { /* its a valid string */ printf(" %s\n", (const char *)data); } else { /* its a null or otherwise problematic string */ printf(" (NULL)\n"); } break; case PT_SYSTIME: mapidump_date_SPropValue(lpProp, proptag, sep); break; case PT_ERROR: data = get_SPropValue_data(&lpProp); printf("%s%s_ERROR: 0x%.8x\n", sep?sep:"", proptag, (*(const uint32_t *)data)); break; case PT_CLSID: { const uint8_t *ab = (const uint8_t *) get_SPropValue_data(&lpProp); printf("%s%s: ", sep?sep:"", proptag); for (i = 0; i < 15; ++i) { printf("%02x ", ab[i]); } printf("%x\n", ab[15]); break; } case PT_SVREID: case PT_BINARY: data = get_SPropValue_data(&lpProp); if (data) { printf("%s%s:\n", sep?sep:"", proptag); dump_data(0, ((const struct Binary_r *)data)->lpb, ((const struct Binary_r *)data)->cb); } else { printf("%s%s: (NULL)\n", sep?sep:"", proptag); } break; case PT_MV_LONG: LongArray_r = (const struct LongArray_r *) get_SPropValue_data(&lpProp); printf("%s%s ", sep?sep:"", proptag); for (i = 0; i < LongArray_r->cValues - 1; i++) { printf("0x%.8x, ", LongArray_r->lpl[i]); } printf("0x%.8x\n", LongArray_r->lpl[i]); break; case PT_MV_STRING8: StringArray_r = (const struct StringArray_r *) get_SPropValue_data(&lpProp); printf("%s%s: ", sep?sep:"", proptag); for (i = 0; i < StringArray_r->cValues - 1; i++) { printf("%s, ", StringArray_r->lppszA[i]); } printf("%s\n", StringArray_r->lppszA[i]); break; case PT_MV_UNICODE: StringArrayW_r = (const struct StringArrayW_r *) get_SPropValue_data(&lpProp); printf("%s%s: ", sep?sep:"", proptag); for (i = 0; i < StringArrayW_r->cValues - 1; i++) { printf("%s, ", StringArrayW_r->lppszW[i]); } printf("%s\n", StringArrayW_r->lppszW[i]); break; case PT_MV_BINARY: BinaryArray_r = (const struct BinaryArray_r *) get_SPropValue_data(&lpProp); printf("%s%s: ARRAY(%d)\n", sep?sep:"", proptag, BinaryArray_r->cValues); for (i = 0; i < BinaryArray_r->cValues; i++) { printf("\tPT_MV_BINARY [%d]:\n", i); dump_data(0, BinaryArray_r->lpbin[i].lpb, BinaryArray_r->lpbin[i].cb); } break; default: /* If you hit this assert, you'll need to implement whatever type is missing */ OC_ASSERT(0); break; } if (mem_ctx) { talloc_free(mem_ctx); } }