/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
  * Copyright 1998-2006 The OpenLDAP Foundation.
+ * Portions Copyright 2006 Howard Chu.
  * Portions Copyright 1998-2003 Kurt D. Zeilenga.
  * Portions Copyright 1998-2001 Net Boolean Incorporated.
  * Portions Copyright 2001-2003 IBM Corporation.
  * include:
  *   Kurt D. Zeilenga
  *   Norbert Klasen
+ *   Howard Chu
  */
 
 #include "portable.h"
                                goto short_input;
                        if ( BVICMP( btype+i, &BV_NEWRDN )) {
                                fprintf( stderr, _("%s: expecting \"%s:\" but saw"
-                                       " \"%s:\" (line %d of entry \"%s\")\n"),
+                                       " \"%s:\" (line %d, entry \"%s\")\n"),
                                        prog, BV_NEWRDN.bv_val, btype[i].bv_val, linenum+i, dn );
                                rc = LDAP_PARAM_ERROR;
                                goto leave;
                                goto short_input;
                        if ( BVICMP( btype+i, &BV_DELETEOLDRDN )) {
                                fprintf( stderr, _("%s: expecting \"%s:\" but saw"
-                                       " \"%s:\" (line %d of entry \"%s\")\n"),
+                                       " \"%s:\" (line %d, entry \"%s\")\n"),
                                        prog, BV_DELETEOLDRDN.bv_val, btype[i].bv_val, linenum+i, dn );
                                rc = LDAP_PARAM_ERROR;
                                goto leave;
                        if ( i < lines ) {
                                if ( BVICMP( btype+i, &BV_NEWSUP )) {
                                        fprintf( stderr, _("%s: expecting \"%s:\" but saw"
-                                               " \"%s:\" (line %d of entry \"%s\")\n"),
+                                               " \"%s:\" (line %d, entry \"%s\")\n"),
                                                prog, BV_NEWSUP.bv_val, btype[i].bv_val, linenum+i, dn );
                                        rc = LDAP_PARAM_ERROR;
                                        goto leave;
        if ( got_all ) {
                if ( i < lines ) {
                        fprintf( stderr,
-                               _("%s: extra lines at end (line %d of entry \"%s\")\n"),
+                               _("%s: extra lines at end (line %d, entry \"%s\")\n"),
                                prog, linenum+i, dn );
                        rc = LDAP_PARAM_ERROR;
                        goto leave;
     
                        if ( ++icnt != vals[i].bv_len ) {
                                fprintf( stderr, _("%s: illegal trailing space after"
-                                       " \"%s: %s\" trimmed (line %d of entry \"%s\")\n"),
-                                       prog, type, vals[i].bv_val, linenum, dn );
+                                       " \"%s: %s\" trimmed (line %d, entry \"%s\")\n"),
+                                       prog, type, vals[i].bv_val, linenum+i, dn );
                                vals[i].bv_val[icnt] = '\0';
                        }
 #endif /* LIBERAL_CHANGETYPE_MODOP */
                                modop = LDAP_MOD_INCREMENT;
                                mops[i] = M_SEP;
                                nmods--;
-                       } else {        /* no modify op:  use default */
-                               modop = ldapadd ? LDAP_MOD_ADD : LDAP_MOD_REPLACE;
-                               mops[i] = modop;
+                       } else {        /* no modify op: invalid LDIF */
+                               fprintf( stderr, _("%s: modify operation type is missing at"
+                                       " line %d, entry \"%s\"\n"),
+                                       prog, linenum+i, dn );
+                               rc = LDAP_PARAM_ERROR;
+                               goto leave;
                        }
+                       bv = vals[i];
                } else if ( expect_sep && BER_BVISEMPTY( btype+i )) {
                        mops[i] = M_SEP;
                        expect_sep = 0;
                        expect_modop = 1;
                        nmods--;
                } else {
+                       if ( BVICMP( btype+i, &bv )) {
+                               fprintf( stderr, _("%s: wrong attributeType at"
+                                       " line %d, entry \"%s\"\n"),
+                                       prog, linenum+i, dn );
+                               rc = LDAP_PARAM_ERROR;
+                               goto leave;
+                       }
                        mops[i] = modop;
                        /* If prev op was deferred and matches this type,
                         * clear the flag
                }
        }
 
+#if 0  /* we should faithfully encode the LDIF, not combine */
        /* Make sure all modops with multiple values are contiguous */
        for (i=idn; i<lines; i++) {
                if ( mops[i] == M_SEP )
                        }
                }
        }
+#endif
 
        /* Allocate space for array of mods, array of pointers to mods,
         * and array of pointers to values, allowing for NULL terminators