static int WriteMetaDataAttribute( VDIR_OPERATION * op, VDIR_ATTRIBUTE * pAttr, int numAttrMetaData, PATTRIBUTE_META_DATA_NODE pAttrMetaData, BerElement * ber, BOOLEAN * nonTrivialAttrsInReplScope, PSTR* ppszErrorMsg ) { int retVal = LDAP_SUCCESS; VDIR_BERVALUE attrMetaData = { {ATTR_ATTR_META_DATA_LEN, ATTR_ATTR_META_DATA}, 0, 0, NULL }; int i = 0; VDIR_BERVALUE berVal = VDIR_BERVALUE_INIT; char attrMetaDataVal[256 + VMDIR_MAX_ATTR_META_DATA_LEN]; PSTR pszLocalErrorMsg = NULL; *nonTrivialAttrsInReplScope = FALSE; if (ber_printf( ber, "{O[", &(attrMetaData) ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print attribute name ...) failed" ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding attribute type failed."); } for ( ; pAttr != NULL; pAttr = pAttr->next) { // By this time, we have already filtered out attributes that should be send back to replication consumer // in prior WriteAttributes -> IsAttrInReplScope call. They contain proper pAttr->metaData value. if (pAttr->metaData[0] != '\0') { VmDirStringPrintFA( attrMetaDataVal, sizeof(attrMetaDataVal), "%.256s:%s", pAttr->type.lberbv.bv_val, pAttr->metaData); berVal.lberbv.bv_val = attrMetaDataVal; berVal.lberbv.bv_len = VmDirStringLenA( attrMetaDataVal ); if (VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_MODIFYTIMESTAMP, FALSE ) != 0 && VmDirStringCompareA( pAttr->type.lberbv.bv_val, ATTR_USN_CHANGED, FALSE ) != 0) { // To prevent endless replication ping pong, supplier should send result only if there are changes // to attribute other than ATTR_USN_CHANGED and ATTR_MODIFYTIMESTAMP. *nonTrivialAttrsInReplScope = TRUE; } if (ber_printf( ber, "O", &berVal ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print an attribute value ...) failed." ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding an attribute value failed."); } } } // include attrMetaData for the deleted attributes for (i = 0; i<numAttrMetaData; i++) { if (pAttrMetaData[i].metaData[0] != '\0') { BOOLEAN bSendAttrMetaData = TRUE; PVDIR_SCHEMA_AT_DESC pATDesc = NULL; if (op->syncReqCtrl != NULL) // Replication { retVal = IsAttrInReplScope( op, NULL, pAttrMetaData[i].metaData, &bSendAttrMetaData, &pszLocalErrorMsg ); BAIL_ON_VMDIR_ERROR( retVal ); } else { bSendAttrMetaData = TRUE; } if (bSendAttrMetaData) { if ((pATDesc = VmDirSchemaAttrIdToDesc(op->pSchemaCtx, pAttrMetaData[i].attrID)) == NULL) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: VmDirSchemaAttrIdToDesc failed for attribute id: %d.", pAttrMetaData[i].attrID ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "WriteMetaDataAttribute: VmDirSchemaAttrIdToDesc failed."); } VmDirStringPrintFA( attrMetaDataVal, sizeof(attrMetaDataVal), "%.256s:%s", pATDesc->pszName, pAttrMetaData[i].metaData); berVal.lberbv.bv_val = attrMetaDataVal; berVal.lberbv.bv_len = VmDirStringLenA( attrMetaDataVal ); *nonTrivialAttrsInReplScope = TRUE; if (ber_printf( ber, "O", &berVal ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to print an attribute value ...) failed." ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding an attribute value failed."); } } } } if ( ber_printf( ber, "]N}" ) == -1 ) { VMDIR_LOG_VERBOSE( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute: ber_printf (to terminate an attribute's values ...) failed" ); retVal = LDAP_OTHER; BAIL_ON_VMDIR_ERROR_WITH_MSG( retVal, (pszLocalErrorMsg), "Encoding terminating an attribute type failed."); } cleanup: if (ppszErrorMsg) { *ppszErrorMsg = pszLocalErrorMsg; } else { VMDIR_SAFE_FREE_MEMORY(pszLocalErrorMsg); } return( retVal ); error: VMDIR_LOG_ERROR( VMDIR_LOG_MASK_ALL, "WriteMetaDataAttribute failed (%u)(%s)", retVal, VDIR_SAFE_STRING(pszLocalErrorMsg) ); goto cleanup; }
/* DecodeEntry: Decodes an Entry that was stored using EncodeEntry. Create the Entry structure from entry->encodedEntry * string. * */ DWORD VmDirDecodeEntry( PVDIR_SCHEMA_CTX pSchemaCtx, PVDIR_ENTRY pEntry ) { DWORD dwError = 0; int len = 0; int i = 0; int j = 0; int nAttrs = 0; int nVals = 0; VDIR_ATTRIBUTE * pBeginAttr = NULL; VDIR_ATTRIBUTE * pEndAttr = NULL; VDIR_ATTRIBUTE * attr = NULL; unsigned char * strPtr = NULL; VDIR_BERVALUE * bvPtr = NULL; BOOLEAN bKeepAttr = TRUE; if (pEntry == NULL || pSchemaCtx == NULL) { dwError = ERROR_INVALID_PARAMETER; BAIL_ON_VMDIR_ERROR(dwError); } pEntry->pSchemaCtx = VmDirSchemaCtxClone(pSchemaCtx); strPtr = pEntry->encodedEntry; nAttrs = VmDirDecodeShort(&strPtr); nVals = VmDirDecodeShort(&strPtr); dwError = VmDirInitializeEntry( pEntry, ENTRY_STORAGE_FORMAT_PACK, nAttrs, nVals); BAIL_ON_VMDIR_ERROR( dwError ); bvPtr = (VDIR_BERVALUE *)pEntry->bvs; for (i = 0, attr = pEntry->attrs; i < nAttrs; attr = &(pEntry->attrs[++i])) { unsigned short usIdMap = VmDirDecodeShort(&strPtr); bKeepAttr = TRUE; // set pATDesc attr->pATDesc = VmDirSchemaAttrIdToDesc(pEntry->pSchemaCtx, usIdMap); if (attr->pATDesc == NULL) { if ( pEntry->eId == SUB_SCEHMA_SUB_ENTRY_ID && VmDirSchemaCtxIsBootStrap(pSchemaCtx) == TRUE // bootstrap ctx ) { // bootstrap schema case, ignore attributes not defined in // schema/defines.h VDIR_SCHEMA_BOOTSTRP_ATTR_INITIALIZER table // while decoding schema entry during InitializeSchema call. bKeepAttr = FALSE; } else { dwError = VMDIR_ERROR_INVALID_ATTRIBUTETYPES; BAIL_ON_VMDIR_ERROR(dwError); } } if ( bKeepAttr ) { // type.bv_val always uses in-place storage attr->type.lberbv.bv_val = attr->pATDesc->pszName; attr->type.lberbv.bv_len = VmDirStringLenA(attr->type.lberbv.bv_val); } // Keep consuming strPtr even if bKeepAttr is FALSE // Get number of attribute values j = VmDirDecodeShort(&strPtr); attr->numVals = j; attr->vals = bvPtr; // Set vals array while (j) { len = VmDirDecodeShort(&strPtr); bvPtr->lberbv.bv_len = len; bvPtr->lberbv.bv_val = (char *)strPtr; strPtr += len + 1; // Skipping \0 bvPtr++; j--; } // Set the last BerValue in vals array. bvPtr->lberbv.bv_val = NULL; bvPtr->lberbv.bv_len = 0; bvPtr++; if ( bKeepAttr ) { if (VmDirStringCompareA( attr->type.lberbv.bv_val, ATTR_DN, FALSE) == 0) { pEntry->dn = attr->vals[0]; } if ( pBeginAttr == NULL ) { pBeginAttr = attr; pEndAttr = attr; } else { pEndAttr->next = attr; pEndAttr = attr; } } } if ( pBeginAttr == NULL ) { dwError = VMDIR_ERROR_INVALID_ENTRY; BAIL_ON_VMDIR_ERROR(dwError); } // reposition pEntry->attrs to the first kept attr pEntry->attrs = pBeginAttr; pEndAttr->next = NULL; dwError = VmDirNormalizeDN( &(pEntry->dn), pSchemaCtx ); BAIL_ON_VMDIR_ERROR(dwError); cleanup: return dwError; error: VMDIR_LOG_ERROR ( VMDIR_LOG_MASK_ALL, "DecodeEntry failed (%u) DN:(%s)", dwError, pEntry ? VDIR_SAFE_STRING(pEntry->dn.lberbv.bv_val) : "unknown" ); goto cleanup; }