richedit: Now painting the newly supported underline types.
[wine] / dlls / wldap32 / parse.c
1 /*
2  * WLDAP32 - LDAP support for Wine
3  *
4  * Copyright 2005 Hans Leidekker
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include "config.h"
22
23 #include "wine/port.h"
24 #include "wine/debug.h"
25
26 #include <stdarg.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winnls.h"
31
32 #ifdef HAVE_LDAP_H
33 #include <ldap.h>
34 #endif
35
36 #include "winldap_private.h"
37 #include "wldap32.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(wldap32);
40
41 /***********************************************************************
42  *      ldap_parse_extended_resultA     (WLDAP32.@)
43  *
44  * See ldap_parse_extended_resultW.
45  */
46 ULONG CDECL ldap_parse_extended_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
47     PCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free )
48 {
49     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
50 #ifdef HAVE_LDAP
51     WCHAR *oidW = NULL;
52
53     TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free );
54
55     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
56     if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED;
57
58     ret = ldap_parse_extended_resultW( ld, result, &oidW, data, free );
59
60     if (oid) {
61         *oid = strWtoA( oidW );
62         if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY;
63         ldap_memfreeW( oidW );
64     }
65
66 #endif
67     return ret;
68 }
69
70 /***********************************************************************
71  *      ldap_parse_extended_resultW     (WLDAP32.@)
72  *
73  * Parse the result of an extended operation. 
74  *
75  * PARAMS
76  *  ld      [I] Pointer to an LDAP context.
77  *  result  [I] Result message from an extended operation.
78  *  oid     [O] OID of the extended operation.
79  *  data    [O] Result data.
80  *  free    [I] Free the result message?
81  *
82  * RETURNS
83  *  Success: LDAP_SUCCESS
84  *  Failure: An LDAP error code.
85  *
86  * NOTES
87  *  Free the OID and result data with ldap_memfree. Pass a nonzero
88  *  value for 'free' or call ldap_msgfree to free the result message.
89  */
90 ULONG CDECL ldap_parse_extended_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
91     PWCHAR *oid, struct WLDAP32_berval **data, BOOLEAN free )
92 {
93     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
94 #ifdef HAVE_LDAP
95     char *oidU = NULL;
96
97     TRACE( "(%p, %p, %p, %p, 0x%02x)\n", ld, result, oid, data, free );
98
99     if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
100     if (!result) return WLDAP32_LDAP_NO_RESULTS_RETURNED;
101
102     ret = ldap_parse_extended_result( ld, result, &oidU, (struct berval **)data, free );
103
104     if (oid) {
105         *oid = strUtoW( oidU );
106         if (!*oid) ret = WLDAP32_LDAP_NO_MEMORY;
107         ldap_memfree( oidU );
108     }
109
110 #endif
111     return ret;
112 }
113
114 /***********************************************************************
115  *      ldap_parse_referenceA     (WLDAP32.@)
116  *
117  * See ldap_parse_referenceW.
118  */
119 ULONG CDECL ldap_parse_referenceA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message,
120     PCHAR **referrals )
121 {
122     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
123 #ifdef HAVE_LDAP
124     WCHAR **referralsW = NULL;
125
126     TRACE( "(%p, %p, %p)\n", ld, message, referrals );
127
128     if (!ld) return ~0UL;
129
130     ret = ldap_parse_referenceW( ld, message, &referralsW );
131
132     *referrals = strarrayWtoA( referralsW );
133     ldap_value_freeW( referralsW );
134
135 #endif 
136     return ret;
137 }
138
139 /***********************************************************************
140  *      ldap_parse_referenceW     (WLDAP32.@)
141  *
142  * Return any referrals from a result message.
143  *
144  * PARAMS
145  *  ld         [I] Pointer to an LDAP context.
146  *  result     [I] Result message.
147  *  referrals  [O] Array of referral URLs.
148  *
149  * RETURNS
150  *  Success: LDAP_SUCCESS
151  *  Failure: An LDAP error code.
152  *
153  * NOTES
154  *  Free the referrals with ldap_value_free.
155  */
156 ULONG CDECL ldap_parse_referenceW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *message,
157     PWCHAR **referrals )
158 {
159     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
160 #ifdef HAVE_LDAP_PARSE_REFERENCE
161     char **referralsU = NULL;
162
163     TRACE( "(%p, %p, %p)\n", ld, message, referrals );
164
165     if (!ld) return ~0UL;
166     
167     ret = ldap_parse_reference( ld, message, &referralsU, NULL, 0 );
168
169     *referrals = strarrayUtoW( referralsU );
170     ldap_memfree( referralsU );
171
172 #endif
173     return ret;
174 }
175
176 /***********************************************************************
177  *      ldap_parse_resultA     (WLDAP32.@)
178  *
179  * See ldap_parse_resultW.
180  */
181 ULONG CDECL ldap_parse_resultA( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
182     ULONG *retcode, PCHAR *matched, PCHAR *error, PCHAR **referrals,
183     PLDAPControlA **serverctrls, BOOLEAN free )
184 {
185     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
186 #ifdef HAVE_LDAP
187     WCHAR **matchedW = NULL, **errorW = NULL, **referralsW = NULL;
188     LDAPControlW **serverctrlsW = NULL;
189
190     TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode,
191            matched, error, referrals, serverctrls, free );
192
193     if (!ld) return ~0UL;
194
195     ret = ldap_parse_resultW( ld, result, retcode, matchedW, errorW,
196                               &referralsW, &serverctrlsW, free );
197
198     matched = strarrayWtoA( matchedW );
199     error = strarrayWtoA( errorW );
200
201     *referrals = strarrayWtoA( referralsW );
202     *serverctrls = controlarrayWtoA( serverctrlsW );
203
204     ldap_value_freeW( matchedW );
205     ldap_value_freeW( errorW );
206     ldap_value_freeW( referralsW );
207     ldap_controls_freeW( serverctrlsW );
208
209 #endif
210     return ret;
211 }
212
213 /***********************************************************************
214  *      ldap_parse_resultW     (WLDAP32.@)
215  *
216  * Parse a result message. 
217  *
218  * PARAMS
219  *  ld           [I] Pointer to an LDAP context.
220  *  result       [I] Result message.
221  *  retcode      [O] Return code for the server operation.
222  *  matched      [O] DNs matched in the operation.
223  *  error        [O] Error message for the operation.
224  *  referrals    [O] Referrals found in the result message.
225  *  serverctrls  [O] Controls used in the operation.
226  *  free         [I] Free the result message?
227  *
228  * RETURNS
229  *  Success: LDAP_SUCCESS
230  *  Failure: An LDAP error code.
231  *
232  * NOTES
233  *  Free the DNs and error message with ldap_memfree. Free
234  *  the referrals with ldap_value_free and the controls with
235  *  ldap_controls_free. Pass a nonzero value for 'free' or call
236  *  ldap_msgfree to free the result message.
237  */
238 ULONG CDECL ldap_parse_resultW( WLDAP32_LDAP *ld, WLDAP32_LDAPMessage *result,
239     ULONG *retcode, PWCHAR *matched, PWCHAR *error, PWCHAR **referrals,
240     PLDAPControlW **serverctrls, BOOLEAN free )
241 {
242     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
243 #ifdef HAVE_LDAP
244     char **matchedU = NULL, **errorU = NULL, **referralsU = NULL;
245     LDAPControl **serverctrlsU = NULL;
246
247     TRACE( "(%p, %p, %p, %p, %p, %p, %p, 0x%02x)\n", ld, result, retcode,
248            matched, error, referrals, serverctrls, free );
249
250     if (!ld) return ~0UL;
251
252     ret = ldap_parse_result( ld, result, (int *)retcode, matchedU, errorU,
253                              &referralsU, &serverctrlsU, free );
254
255     matched = strarrayUtoW( matchedU );
256     error = strarrayUtoW( errorU );
257
258     *referrals = strarrayUtoW( referralsU );
259     *serverctrls = controlarrayUtoW( serverctrlsU );
260
261     ldap_memfree( matchedU );
262     ldap_memfree( errorU );
263     ldap_memfree( referralsU );
264     ldap_controls_free( serverctrlsU );
265
266 #endif
267     return ret;
268 }
269
270 /***********************************************************************
271  *      ldap_parse_sort_controlA     (WLDAP32.@)
272  *
273  * See ldap_parse_sort_controlW.
274  */
275 ULONG CDECL ldap_parse_sort_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control,
276     ULONG *result, PCHAR *attr )
277 {
278     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
279 #ifdef HAVE_LDAP
280     WCHAR *attrW = NULL;
281     LDAPControlW **controlW = NULL;
282
283     TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr );
284
285     if (!ld) return ~0UL;
286
287     if (control) {
288         controlW = controlarrayAtoW( control );
289         if (!controlW) return WLDAP32_LDAP_NO_MEMORY;
290     }
291
292     ret = ldap_parse_sort_controlW( ld, controlW, result, &attrW );
293
294     *attr = strWtoA( attrW );
295     controlarrayfreeW( controlW );
296
297 #endif
298     return ret;
299 }
300
301 /***********************************************************************
302  *      ldap_parse_sort_controlW     (WLDAP32.@)
303  *
304  * Parse a sort control.
305  *
306  * PARAMS
307  *  ld       [I] Pointer to an LDAP context.
308  *  control  [I] Control obtained from a result message.
309  *  result   [O] Result code.
310  *  attr     [O] Failing attribute.
311  *
312  * RETURNS
313  *  Success: LDAP_SUCCESS
314  *  Failure: An LDAP error code.
315  *
316  * NOTES
317  *  If the function fails, free the failing attribute with ldap_memfree.
318  */
319 ULONG CDECL ldap_parse_sort_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control,
320     ULONG *result, PWCHAR *attr )
321 {
322     ULONG ret = WLDAP32_LDAP_NOT_SUPPORTED;
323 #ifdef HAVE_LDAP
324     char *attrU = NULL;
325     LDAPControl **controlU = NULL;
326 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL
327     unsigned long res;
328 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL)
329     ber_int_t res;
330     LDAPControl *sortcontrol = NULL;
331     unsigned int i;
332 #endif
333
334     TRACE( "(%p, %p, %p, %p)\n", ld, control, result, attr );
335
336     if (!ld) return ~0UL;
337
338     if (control) {
339         controlU = controlarrayWtoU( control );
340         if (!controlU) return WLDAP32_LDAP_NO_MEMORY;
341     }
342
343 #ifdef HAVE_LDAP_PARSE_SORT_CONTROL
344     if (!(ret = ldap_parse_sort_control( ld, controlU, &res, &attrU )))
345     {
346         *result = res;
347         *attr = strUtoW( attrU );
348     }
349 #elif defined(HAVE_LDAP_PARSE_SORTRESPONSE_CONTROL)
350     for (i = 0; controlU[i]; i++)
351     {
352         if (!strcmp( LDAP_SERVER_RESP_SORT_OID, controlU[i]->ldctl_oid ))
353             sortcontrol = controlU[i];
354     }
355     if (!sortcontrol)
356     {
357         controlarrayfreeU( controlU );
358         return WLDAP32_LDAP_CONTROL_NOT_FOUND;
359     }
360     if (!(ret = ldap_parse_sortresponse_control( ld, sortcontrol, &res, &attrU )))
361     {
362         *result = res;
363         *attr = strUtoW( attrU );
364     }
365 #endif
366     controlarrayfreeU( controlU );
367
368 #endif
369     return ret;
370 }
371
372 /***********************************************************************
373  *      ldap_parse_vlv_controlA     (WLDAP32.@)
374  *
375  * See ldap_parse_vlv_controlW.
376  */
377 INT CDECL ldap_parse_vlv_controlA( WLDAP32_LDAP *ld, PLDAPControlA *control,
378     PULONG targetpos, PULONG listcount,
379     struct WLDAP32_berval **context, PINT errcode )
380 {
381     int ret = WLDAP32_LDAP_NOT_SUPPORTED;
382 #ifdef HAVE_LDAP
383     LDAPControlW **controlW = NULL;
384
385     TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos,
386            listcount, context, errcode );
387
388     if (!ld) return ~0UL;
389
390     if (control) {
391         controlW = controlarrayAtoW( control );
392         if (!controlW) return WLDAP32_LDAP_NO_MEMORY;
393     }
394
395     ret = ldap_parse_vlv_controlW( ld, controlW, targetpos, listcount,
396                                    context, errcode );
397
398     controlarrayfreeW( controlW );
399
400 #endif
401     return ret;
402 }
403
404 /***********************************************************************
405  *      ldap_parse_vlv_controlW     (WLDAP32.@)
406  *
407  * Parse a virtual list view control.
408  *
409  * PARAMS
410  *  ld         [I] Pointer to an LDAP context.
411  *  control    [I] Controls obtained from a result message.
412  *  targetpos  [O] Positition of the target in the result list. 
413  *  listcount  [O] Estimate of the number of results in the list.
414  *  context    [O] Server side context.
415  *  errcode    [O] Error code from the listview operation.
416  *
417  * RETURNS
418  *  Success: LDAP_SUCCESS
419  *  Failure: An LDAP error code.
420  *
421  * NOTES
422  *  Free the server context with ber_bvfree.
423  */
424 INT CDECL ldap_parse_vlv_controlW( WLDAP32_LDAP *ld, PLDAPControlW *control,
425     PULONG targetpos, PULONG listcount,
426     struct WLDAP32_berval **context, PINT errcode )
427 {
428     int ret = WLDAP32_LDAP_NOT_SUPPORTED;
429 #ifdef HAVE_LDAP
430     LDAPControl **controlU = NULL;
431 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL
432     unsigned long pos, count;
433 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL)
434     ber_int_t pos, count;
435     LDAPControl *vlvcontrol = NULL;
436     unsigned int i;
437 #endif
438
439     TRACE( "(%p, %p, %p, %p, %p, %p)\n", ld, control, targetpos,
440            listcount, context, errcode );
441
442     if (!ld) return ~0UL;
443
444     if (control) {
445         controlU = controlarrayWtoU( control );
446         if (!controlU) return WLDAP32_LDAP_NO_MEMORY;
447     }
448
449 #ifdef HAVE_LDAP_PARSE_VLV_CONTROL
450     if (!(ret = ldap_parse_vlv_control( ld, controlU, &pos, &count,
451                                         (struct berval **)context, errcode )))
452     {
453         *targetpos = pos;
454         *listcount = count;
455     }
456 #elif defined(HAVE_LDAP_PARSE_VLVRESPONSE_CONTROL)
457     for (i = 0; controlU[i]; i++)
458     {
459         if (!strcmp( LDAP_CONTROL_VLVRESPONSE, controlU[i]->ldctl_oid ))
460             vlvcontrol = controlU[i];
461     }
462     if (!vlvcontrol)
463     {
464         controlarrayfreeU( controlU );
465         return WLDAP32_LDAP_CONTROL_NOT_FOUND;
466     }
467     if (!(ret = ldap_parse_vlvresponse_control( ld, vlvcontrol, &pos, &count,
468                                                 (struct berval **)context, errcode )))
469     {
470         *targetpos = pos;
471         *listcount = count;
472     }
473 #endif
474     controlarrayfreeU( controlU );
475
476 #endif
477     return ret;
478 }