+/* Retrieve an Entry that was stored using entry_encode above.
+ * We malloc a single block with the size stored above for the Entry
+ * and all if its Attributes. We also must lookup the stored
+ * attribute names to get AttributeDescriptions. To detect if the
+ * attributes of an Entry are later modified, we note that e->e_attr
+ * is always a constant offset from (e).
+ *
+ * Note: everything is stored in a single contiguous block, so
+ * you can not free individual attributes or names from this
+ * structure. Attempting to do so will likely corrupt memory.
+ */
+int entry_decode(struct berval *bv, Entry **e)
+{
+ int i, j;
+ int rc;
+ Attribute *a;
+ Entry *x;
+ const char *text;
+ AttributeDescription *ad;
+ unsigned char *ptr = (unsigned char *)bv->bv_val;
+ BerVarray bptr;
+
+ i = entry_getlen(&ptr);
+ x = ch_calloc(1, i);
+ i = entry_getlen(&ptr);
+ x->e_name.bv_val = ptr;
+ x->e_name.bv_len = i;
+ ptr += i+1;
+ i = entry_getlen(&ptr);
+ x->e_nname.bv_val = ptr;
+ x->e_nname.bv_len = i;
+ ptr += i+1;
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL2,
+ "entry_decode: \"%s\"\n", x->e_dn ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "entry_decode: \"%s\"\n",
+ x->e_dn, 0, 0 );
+#endif
+ x->e_bv = *bv;
+
+ /* A valid entry must have at least one attr, so this
+ * pointer can never be NULL
+ */
+ x->e_attrs = (Attribute *)(x+1);
+ bptr = (BerVarray)x->e_attrs;
+ a = NULL;
+
+ while ((i = entry_getlen(&ptr))) {
+ struct berval bv;
+ bv.bv_len = i;
+ bv.bv_val = ptr;
+ if (a) {
+ a->a_next = (Attribute *)bptr;
+ }
+ a = (Attribute *)bptr;
+ ad = NULL;
+ rc = slap_bv2ad( &bv, &ad, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
+ "entry_decode: str2ad(%s): %s\n", ptr, text ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "<= entry_decode: str2ad(%s): %s\n", ptr, text, 0 );
+#endif
+ rc = slap_bv2undef_ad( &bv, &ad, &text );
+
+ if( rc != LDAP_SUCCESS ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "operation", LDAP_LEVEL_INFO,
+ "entry_decode: str2undef_ad(%s): %s\n", ptr, text));
+#else
+ Debug( LDAP_DEBUG_ANY,
+ "<= entry_decode: str2undef_ad(%s): %s\n",
+ ptr, text, 0 );
+#endif
+ return rc;
+ }
+ }
+ ptr += i + 1;
+ a->a_desc = ad;
+ bptr = (BerVarray)(a+1);
+ a->a_vals = bptr;
+ a->a_flags = 0;
+ j = entry_getlen(&ptr);
+
+ while (j) {
+ i = entry_getlen(&ptr);
+ bptr->bv_len = i;
+ bptr->bv_val = (char *)ptr;
+ ptr += i+1;
+ bptr++;
+ j--;
+ }
+ bptr->bv_val = NULL;
+ bptr->bv_len = 0;
+ bptr++;
+ }
+ if (a)
+ a->a_next = NULL;
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "operation", LDAP_LEVEL_DETAIL1,
+ "entry_decode: %s\n", x->e_dn ));
+#else
+ Debug(LDAP_DEBUG_TRACE, "<= entry_decode(%s)\n",
+ x->e_dn, 0, 0 );
+#endif
+ *e = x;
+ return 0;
+}
+#endif