 770611a056
			
		
	
	770611a056
	
	
	
		
			
			With this commit, all ldap connections accept a new parameter, ``bytes_mode``. When set to ``True``, this flag emulates the old Python 2 behavior, where all fields are bytes - including those declared as UTF-8 by the RFC (DN, RDN, attribute names). If this flag is set to ``False``, the code works with text (unicode) for all text fields (everything except attribute values). If no value is set under Python 2, the code will raise a BytesWarning and proceed with the flag set to ``True``, for backwards compatibility. Under Python 3, the value can only be set to ``False``. For safety and ease of upgrade, the code checks that all provided arguments are of the expected type (unicode with ``bytes_mode=False``, bytes with ``bytes_mode=True``).
		
			
				
	
	
		
			279 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* See http://www.python-ldap.org/ for details.
 | |
|  * $Id: message.c,v 1.19 2011/10/26 18:38:06 stroeder Exp $ */
 | |
| 
 | |
| #include "common.h"
 | |
| #include "message.h"
 | |
| #include "berval.h"
 | |
| #include "errors.h"
 | |
| #include "ldapcontrol.h"
 | |
| #include "constants.h"
 | |
| 
 | |
| /*
 | |
|  * Converts an LDAP message into a Python structure.
 | |
|  *
 | |
|  * On success, returns a list of dictionaries.
 | |
|  * On failure, returns NULL, and sets an error.
 | |
|  *
 | |
|  * The message m is always freed, regardless of return value.
 | |
|  *
 | |
|  * If add_ctrls is non-zero, per-entry/referral/partial/intermediate
 | |
|  * controls will be added as a third item to each entry tuple
 | |
|  *
 | |
|  * If add_intermediates is non-zero, intermediate/partial results will
 | |
|  * be returned
 | |
|  */
 | |
| PyObject *
 | |
| LDAPmessage_to_python(LDAP *ld, LDAPMessage *m, int add_ctrls, int add_intermediates)
 | |
| {
 | |
|     /* we convert an LDAP message into a python structure.
 | |
|      * It is always a list of dictionaries.
 | |
|      * We always free m.
 | |
|      */
 | |
| 
 | |
|      PyObject *result, *pyctrls = 0;
 | |
|      LDAPMessage* entry;
 | |
|      LDAPControl **serverctrls = 0;
 | |
|      int rc;
 | |
| 
 | |
|      result = PyList_New(0);
 | |
|      if (result == NULL) {
 | |
|         ldap_msgfree( m );
 | |
| 	return NULL;
 | |
|      }
 | |
| 
 | |
|      for(entry = ldap_first_entry(ld,m);
 | |
|          entry != NULL;
 | |
| 	 entry = ldap_next_entry(ld,entry))
 | |
|      {
 | |
| 	 char *dn;
 | |
| 	 char *attr;
 | |
| 	 BerElement *ber = NULL;
 | |
| 	 PyObject* entrytuple; 
 | |
| 	 PyObject* attrdict; 
 | |
|          PyObject* pydn;
 | |
| 
 | |
| 	 dn = ldap_get_dn( ld, entry );
 | |
| 	 if (dn == NULL)  {
 | |
| 	     Py_DECREF(result);
 | |
|              ldap_msgfree( m );
 | |
| 	     return LDAPerror( ld, "ldap_get_dn" );
 | |
| 	 }
 | |
|          pydn = PyUnicode_FromString(dn);
 | |
|          if (pydn == NULL) {
 | |
|              Py_DECREF(result);
 | |
|              ldap_msgfree( m );
 | |
|              ldap_memfree(dn);
 | |
|              return NULL;
 | |
|          }
 | |
| 
 | |
| 	 attrdict = PyDict_New();
 | |
| 	 if (attrdict == NULL) {
 | |
|                 Py_DECREF(pydn);
 | |
| 		Py_DECREF(result);
 | |
| 		ldap_msgfree( m );
 | |
| 		ldap_memfree(dn);
 | |
| 		return NULL;
 | |
| 	 }
 | |
| 
 | |
| 	 rc = ldap_get_entry_controls( ld, entry, &serverctrls );
 | |
| 	 if (rc) {
 | |
|             Py_DECREF(pydn);
 | |
| 	    Py_DECREF(result);
 | |
| 	    ldap_msgfree( m );
 | |
| 	    ldap_memfree(dn);
 | |
| 	    return LDAPerror( ld, "ldap_get_entry_controls" );
 | |
| 	 }
 | |
| 
 | |
| 	 /* convert serverctrls to list of tuples */
 | |
| 	 if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
 | |
| 	    int err = LDAP_NO_MEMORY;
 | |
| 	    ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
 | |
|             Py_DECREF(pydn);
 | |
| 	    Py_DECREF(result);
 | |
| 	    ldap_msgfree( m );
 | |
| 	    ldap_memfree(dn);
 | |
| 	    ldap_controls_free(serverctrls);
 | |
| 	    return LDAPerror( ld, "LDAPControls_to_List" );
 | |
| 	 }
 | |
| 	 ldap_controls_free(serverctrls);
 | |
| 
 | |
|   	 /* Fill attrdict with lists */
 | |
| 	 for( attr = ldap_first_attribute( ld, entry, &ber );
 | |
| 	      attr != NULL;
 | |
| 	      attr = ldap_next_attribute( ld, entry, ber )
 | |
| 	 ) {
 | |
| 	     PyObject* valuelist;
 | |
|              PyObject* pyattr;
 | |
|              pyattr = PyUnicode_FromString(attr);
 | |
| 
 | |
| 	     struct berval ** bvals =
 | |
| 	     	ldap_get_values_len( ld, entry, attr );
 | |
| 
 | |
| 	     /* Find which list to append to */
 | |
| 	     if ( PyDict_Contains( attrdict, pyattr ) ) {
 | |
| 		 valuelist = PyDict_GetItem( attrdict, pyattr );
 | |
| 	     } else {
 | |
| 		 valuelist = PyList_New(0);
 | |
| 		 if (valuelist != NULL && PyDict_SetItem(attrdict,
 | |
| 		     pyattr, valuelist) == -1) {
 | |
| 			Py_DECREF(valuelist);
 | |
| 			valuelist = NULL;	/* catch error later */
 | |
| 		 }
 | |
| 	     }
 | |
| 
 | |
| 	     if (valuelist == NULL) {
 | |
|                 Py_DECREF(pydn);
 | |
|                 Py_DECREF(pyattr);
 | |
| 		Py_DECREF(attrdict);
 | |
| 		Py_DECREF(result);
 | |
| 		if (ber != NULL)
 | |
| 		    ber_free(ber, 0);
 | |
| 		ldap_msgfree( m );
 | |
| 		ldap_memfree(attr);
 | |
| 		ldap_memfree(dn);
 | |
| 		Py_XDECREF(pyctrls);
 | |
| 		return NULL;
 | |
| 	     }
 | |
| 
 | |
| 	     if (bvals != NULL) {
 | |
| 	        Py_ssize_t i;
 | |
| 		for (i=0; bvals[i]; i++) {
 | |
| 		    PyObject *valuestr;
 | |
| 
 | |
| 		    valuestr = LDAPberval_to_object(bvals[i]);
 | |
| 		    if (PyList_Append( valuelist, valuestr ) == -1) {
 | |
|                         Py_DECREF(pydn);
 | |
|                         Py_DECREF(pyattr);
 | |
| 			Py_DECREF(attrdict);
 | |
| 			Py_DECREF(result);
 | |
| 			Py_DECREF(valuestr);
 | |
| 			Py_DECREF(valuelist);
 | |
| 			if (ber != NULL)
 | |
| 			    ber_free(ber, 0);
 | |
| 			ldap_msgfree( m );
 | |
| 			ldap_memfree(attr);
 | |
| 			ldap_memfree(dn);
 | |
| 			Py_XDECREF(pyctrls);
 | |
| 			return NULL;
 | |
| 		    }
 | |
| 		    Py_DECREF(valuestr);
 | |
| 	    	}
 | |
| 		ldap_value_free_len(bvals);
 | |
| 	     }
 | |
|              Py_DECREF(pyattr);
 | |
| 	     Py_DECREF( valuelist );
 | |
| 	     ldap_memfree(attr);
 | |
| 	 }
 | |
| 
 | |
| 	 if (add_ctrls) {
 | |
| 	    entrytuple = Py_BuildValue("(OOO)", pydn, attrdict, pyctrls);
 | |
| 	 } else {
 | |
| 	    entrytuple = Py_BuildValue("(OO)", pydn, attrdict);
 | |
| 	 }
 | |
|          Py_DECREF(pydn);
 | |
| 	 ldap_memfree(dn);
 | |
| 	 Py_DECREF(attrdict);
 | |
| 	 Py_XDECREF(pyctrls);
 | |
| 	 PyList_Append(result, entrytuple);
 | |
| 	 Py_DECREF(entrytuple);
 | |
| 	 if (ber != NULL)
 | |
| 		 ber_free(ber, 0);
 | |
|      }
 | |
|      for(entry = ldap_first_reference(ld,m);
 | |
| 	 entry != NULL;
 | |
| 	 entry = ldap_next_reference(ld,entry))
 | |
|      {
 | |
| 	 char **refs = NULL;
 | |
| 	 PyObject* entrytuple;
 | |
| 	 PyObject* reflist = PyList_New(0);
 | |
| 
 | |
| 	 if (reflist == NULL)  {
 | |
| 	     Py_DECREF(result);
 | |
| 	     ldap_msgfree( m );
 | |
| 	     return NULL;
 | |
| 	 }
 | |
| 	 if (ldap_parse_reference(ld, entry, &refs, &serverctrls, 0) != LDAP_SUCCESS) {
 | |
|              Py_DECREF(reflist);
 | |
| 	     Py_DECREF(result);
 | |
| 	     ldap_msgfree( m );
 | |
| 	     return LDAPerror( ld, "ldap_parse_reference" );
 | |
| 	 }
 | |
| 	 /* convert serverctrls to list of tuples */
 | |
| 	 if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
 | |
| 	     int err = LDAP_NO_MEMORY;
 | |
| 	     ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
 | |
|              Py_DECREF(reflist);
 | |
| 	     Py_DECREF(result);
 | |
| 	     ldap_msgfree( m );
 | |
| 	     ldap_controls_free(serverctrls);
 | |
| 	     return LDAPerror( ld, "LDAPControls_to_List" );
 | |
| 	 }
 | |
| 	 ldap_controls_free(serverctrls);
 | |
| 	 if (refs) {
 | |
| 	     Py_ssize_t i;
 | |
| 	     for (i=0; refs[i] != NULL; i++) {
 | |
|                  /* A referal is a distinguishedName => unicode */
 | |
| 		 PyObject *refstr = PyUnicode_FromString(refs[i]);
 | |
| 		 PyList_Append(reflist, refstr);
 | |
| 		 Py_DECREF(refstr);
 | |
| 	     }
 | |
| 	     ber_memvfree( (void **) refs );
 | |
| 	 }
 | |
| 	 if (add_ctrls) {
 | |
| 	    entrytuple = Py_BuildValue("(sOO)", NULL, reflist, pyctrls);
 | |
| 	 } else {
 | |
| 	    entrytuple = Py_BuildValue("(sO)", NULL, reflist);
 | |
| 	 }
 | |
| 	 Py_DECREF(reflist);
 | |
| 	 Py_XDECREF(pyctrls);
 | |
| 	 PyList_Append(result, entrytuple);
 | |
| 	 Py_DECREF(entrytuple);
 | |
|      }
 | |
|      if (add_intermediates) {
 | |
| 	for(entry = ldap_first_message(ld,m);
 | |
| 	    entry != NULL;
 | |
| 	    entry = ldap_next_message(ld,entry))
 | |
| 	   {
 | |
| 	      /* list of tuples */
 | |
| 	      /* each tuple is OID, Berval, controllist */
 | |
| 	      if ( LDAP_RES_INTERMEDIATE == ldap_msgtype( entry ) ) {
 | |
| 		 PyObject* valtuple;
 | |
| 		 PyObject *valuestr;
 | |
| 		 char *retoid = 0;
 | |
| 		 struct berval *retdata = 0;
 | |
| 
 | |
| 		 if (ldap_parse_intermediate( ld, entry, &retoid, &retdata, &serverctrls, 0 ) != LDAP_SUCCESS) {
 | |
| 		    Py_DECREF(result);
 | |
| 		    ldap_msgfree( m );
 | |
| 		    return LDAPerror( ld, "ldap_parse_intermediate" );
 | |
| 		 }
 | |
| 		 /* convert serverctrls to list of tuples */
 | |
| 		 if ( ! ( pyctrls = LDAPControls_to_List( serverctrls ) ) ) {
 | |
| 		    int err = LDAP_NO_MEMORY;
 | |
| 		    ldap_set_option( ld, LDAP_OPT_ERROR_NUMBER, &err );
 | |
| 		    Py_DECREF(result);
 | |
| 		    ldap_msgfree( m );
 | |
| 		    ldap_controls_free(serverctrls);
 | |
| 		    ldap_memfree( retoid );
 | |
| 		    ber_bvfree( retdata );
 | |
| 		    return LDAPerror( ld, "LDAPControls_to_List" );
 | |
| 		 }
 | |
| 		 ldap_controls_free(serverctrls);
 | |
| 
 | |
| 		 valuestr = LDAPberval_to_object(retdata);
 | |
| 		 ber_bvfree( retdata );
 | |
| 		 valtuple = Py_BuildValue("(sOO)", retoid,
 | |
| 					  valuestr ? valuestr : Py_None,
 | |
| 					  pyctrls);
 | |
| 		 ldap_memfree( retoid );
 | |
| 		 Py_DECREF(valuestr);
 | |
| 		 Py_XDECREF(pyctrls);
 | |
| 		 PyList_Append(result, valtuple);
 | |
| 		 Py_DECREF(valtuple);
 | |
| 	      }
 | |
| 	   }
 | |
|      }
 | |
|      ldap_msgfree( m );
 | |
|      return result;
 | |
| }
 |