Skip to content

Commit f754e35

Browse files
committed
Attach msgid/controls/... to exceptions (Closes python-ldap#177, python-ldap#208)
Closes: python-ldap#177 (msgid) python-ldap#208 (controls)
1 parent 7d92e0f commit f754e35

File tree

3 files changed

+91
-23
lines changed

3 files changed

+91
-23
lines changed

Modules/LDAPObject.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1172,9 +1172,8 @@ l_ldap_result4(LDAPObject *self, PyObject *args)
11721172
else
11731173
e = "ldap_parse_result";
11741174
ldap_controls_free(serverctrls);
1175-
ldap_msgfree(msg);
11761175
Py_XDECREF(valuestr);
1177-
return LDAPerror(self->ldap, e);
1176+
return LDAPraise_for_message(self->ldap, e, msg);
11781177
}
11791178

11801179
if (!(pyctrls = LDAPControls_to_List(serverctrls))) {

Modules/constants.c

Lines changed: 89 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "common.h"
55
#include "constants.h"
6+
#include "ldapcontrol.h"
67
#include "lber.h"
78
#include "ldap.h"
89

@@ -48,38 +49,81 @@ LDAPerr(int errnum)
4849

4950
/* Convert an LDAP error into an informative python exception */
5051
PyObject *
51-
LDAPerror(LDAP *l, char *msg)
52+
LDAPraise_for_message(LDAP *l, char *msg, LDAPMessage *m)
5253
{
5354
if (l == NULL) {
5455
PyErr_SetFromErrno(LDAPexception_class);
56+
ldap_msgfree(m);
5557
return NULL;
5658
}
5759
else {
58-
int myerrno, errnum, opt_errnum;
60+
int myerrno, errnum, opt_errnum, msgid = -1, msgtype = 0;
5961
PyObject *errobj;
6062
PyObject *info;
6163
PyObject *str;
6264
PyObject *pyerrno;
63-
char *matched, *error;
65+
PyObject *pyresult;
66+
PyObject *pyctrls = NULL;
67+
char *matched = NULL,
68+
*error = NULL,
69+
**refs = NULL;
70+
LDAPControl **serverctrls = NULL;
6471

6572
/* at first save errno for later use before it gets overwritten by another call */
6673
myerrno = errno;
6774

68-
opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum);
69-
if (opt_errnum != LDAP_OPT_SUCCESS)
70-
errnum = opt_errnum;
75+
if (m != NULL) {
76+
msgid = ldap_msgid(m);
77+
msgtype = ldap_msgtype(m);
78+
ldap_parse_result(l, m, &errnum, &matched, &error, &refs,
79+
&serverctrls, 1);
80+
}
7181

72-
if (errnum == LDAP_NO_MEMORY)
73-
return PyErr_NoMemory();
82+
if (msgtype <= 0) {
83+
opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum);
84+
if (opt_errnum != LDAP_OPT_SUCCESS)
85+
errnum = opt_errnum;
86+
87+
if (errnum == LDAP_NO_MEMORY) {
88+
return PyErr_NoMemory();
89+
}
90+
91+
ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched);
92+
ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error);
93+
}
7494

7595
if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX)
7696
errobj = errobjects[errnum + LDAP_ERROR_OFFSET];
7797
else
7898
errobj = LDAPexception_class;
7999

80100
info = PyDict_New();
81-
if (info == NULL)
101+
if (info == NULL) {
102+
ldap_memfree(matched);
103+
ldap_memfree(error);
104+
ldap_memvfree((void **)refs);
105+
ldap_controls_free(serverctrls);
82106
return NULL;
107+
}
108+
109+
if (msgtype > 0) {
110+
pyresult = PyInt_FromLong(msgtype);
111+
if (pyresult)
112+
PyDict_SetItemString(info, "msgtype", pyresult);
113+
Py_XDECREF(pyresult);
114+
}
115+
116+
if (msgid >= 0) {
117+
pyresult = PyInt_FromLong(msgid);
118+
if (pyresult)
119+
PyDict_SetItemString(info, "msgid", pyresult);
120+
Py_XDECREF(pyresult);
121+
}
122+
123+
pyresult = PyInt_FromLong(errnum);
124+
if (pyresult)
125+
PyDict_SetItemString(info, "result", pyresult);
126+
Py_XDECREF(pyresult);
83127

84128
str = PyUnicode_FromString(ldap_err2string(errnum));
85129
if (str)
@@ -93,8 +137,21 @@ LDAPerror(LDAP *l, char *msg)
93137
Py_XDECREF(pyerrno);
94138
}
95139

96-
if (ldap_get_option(l, LDAP_OPT_MATCHED_DN, &matched) >= 0
97-
&& matched != NULL) {
140+
if (!(pyctrls = LDAPControls_to_List(serverctrls))) {
141+
int err = LDAP_NO_MEMORY;
142+
143+
ldap_set_option(l, LDAP_OPT_ERROR_NUMBER, &err);
144+
ldap_memfree(matched);
145+
ldap_memfree(error);
146+
ldap_memvfree((void **)refs);
147+
ldap_controls_free(serverctrls);
148+
return PyErr_NoMemory();
149+
}
150+
ldap_controls_free(serverctrls);
151+
PyDict_SetItemString(info, "ctrls", pyctrls);
152+
Py_XDECREF(pyctrls);
153+
154+
if (matched != NULL) {
98155
if (*matched != '\0') {
99156
str = PyUnicode_FromString(matched);
100157
if (str)
@@ -104,27 +161,38 @@ LDAPerror(LDAP *l, char *msg)
104161
ldap_memfree(matched);
105162
}
106163

107-
if (errnum == LDAP_REFERRAL) {
164+
if (errnum == LDAP_REFERRAL && refs != NULL && refs[0] != NULL) {
165+
/* Keep old behaviour, overshadow error message */
166+
char err[1024];
167+
168+
snprintf(err, sizeof(err), "Referral:\n%s", refs[0]);
169+
str = PyUnicode_FromString(err);
170+
PyDict_SetItemString(info, "info", str);
171+
Py_XDECREF(str);
172+
}
173+
else if (msg != NULL || (error != NULL && *error != '\0')) {
174+
msg = msg ? msg : error;
175+
108176
str = PyUnicode_FromString(msg);
109177
if (str)
110178
PyDict_SetItemString(info, "info", str);
111179
Py_XDECREF(str);
112180
}
113-
else if (ldap_get_option(l, LDAP_OPT_ERROR_STRING, &error) >= 0) {
114-
if (error != NULL && *error != '\0') {
115-
str = PyUnicode_FromString(error);
116-
if (str)
117-
PyDict_SetItemString(info, "info", str);
118-
Py_XDECREF(str);
119-
}
120-
ldap_memfree(error);
121-
}
181+
122182
PyErr_SetObject(errobj, info);
123183
Py_DECREF(info);
184+
ldap_memvfree((void **)refs);
185+
ldap_memfree(error);
124186
return NULL;
125187
}
126188
}
127189

190+
PyObject *
191+
LDAPerror(LDAP *l, char *msg)
192+
{
193+
return LDAPraise_for_message(l, msg, NULL);
194+
}
195+
128196
/* initialise the module constants */
129197

130198
int

Modules/constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ extern PyObject *LDAPconstant(int);
1212

1313
extern PyObject *LDAPexception_class;
1414
extern PyObject *LDAPerror(LDAP *, char *msg);
15+
extern PyObject *LDAPraise_for_message(LDAP *, char *msg, LDAPMessage *m);
1516
PyObject *LDAPerr(int errnum);
1617

1718
#ifndef LDAP_CONTROL_PAGE_OID

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy