File Coverage

blib/lib/Net/DSML.pm
Criterion Covered Total %
statement 399 613 65.0
branch 151 288 52.4
condition 1 3 33.3
subroutine 32 42 76.1
pod 30 30 100.0
total 613 976 62.8


line stmt bran cond sub pod time code
1             package Net::DSML;
2              
3              
4 2     2   30218 use warnings;
  2         5  
  2         76  
5 2     2   12 use strict;
  2         4  
  2         72  
6             #use Carp;
7 2     2   2113 use Class::Std::Utils;
  2         9078  
  2         12  
8 2     2   2435 use LWP::UserAgent;
  2         204217  
  2         95  
9              
10             # Copyright (c) 2007 Clif Harden . All rights reserved.
11             # This program is free software; you can redistribute it and/or
12             # modify it under the same terms as Perl itself.
13              
14 2     2   23 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  2         4  
  2         185  
15 2     2   10 use version; $VERSION = version->new('0.003');
  2         5  
  2         18  
16              
17             {
18              
19             BEGIN
20             {
21 2     2   186 use Exporter ();
  2         3  
  2         77  
22              
23 2     2   41 @ISA = qw(Exporter);
24 2         5 @EXPORT = qw();
25 2         7 %EXPORT_TAGS = ();
26 2         15859 @EXPORT_OK = ();
27             }
28              
29             my %ops; # items container
30             my %pid; # process id container
31             my %content; # Returned ldap data
32             my %prepostData; # Returned ldap data
33             my %errMsg; # no error this will be a null string.
34             my %psize; # Size of xml string.
35             my %postData; # Actual xml data string.
36             my %operations; # operations container
37             my %authentication; # authentication container
38              
39             #
40             # Method new
41             #
42             # The method new creates a new DSML oject.
43             #
44             # There are two possible input options.
45             #
46             # $dsml = Net::DSML->new( debug => 1, url => "http://system.company.com:8080/dsml" );
47             #
48             # Input option "debug": Sets the debug variable to the input value.
49             # Input option "url": Sets the host variable to the input value.
50             #
51             #
52             # Input option "process": String that contains the LDAP process value;
53             # sequential or parallel. Default is sequential.
54             # Input option "type": String that contains the LDAP scope value;
55             # true or false. Default is false.
56             # Input option "referral": String that contains the referral control value;
57             # neverDerefAliases, derefInSearching, derefFindingBaseObj or derefAlways.
58             # Default is neverDerefAliases.
59             # Input option "scope": String that contains the LDAP scope value;
60             # singleLevel, baseObject or wholeSubtree. Default is singleLevel.
61             # Input option "order": String that contains the LDAP order value;
62             # sequential or unordered. Default is sequential.
63             # Input option "error": String that contains the LDAP onError value;
64             # exit or resume. Default is exit.
65             # Input option "time": String that contains the time limit of the
66             # LDAP search. Default is "0".
67             # Input option "size": String that contains the size limit of the
68             # LDAP search. Default is "0".
69             # Input option "base": String that contains the LDAP search base.
70             # Input option "bid": String that contains the batch request ID
71             #
72             #
73             # Method output; Returns a new DSML object.
74             #
75              
76             sub new
77             {
78 25     25 1 12417 my ($class, $opt) = @_;
79 25         73 my $self = bless anon_scalar(),$class;
80 25         132 my $id = ident($self);
81 25         31 my $initerror = "";
82 25         29 my $pnumber = 0;
83 25         25 my $result;
84             #
85             # Initailize the data to a default value.
86             #
87 25         64 $content{$id} = ""; # Returned ldap data
88 25         42 $psize{$id} = ""; # Size of xml string.
89 25         35 $postData{$id} = ""; # Actual xml data string.
90 25         30 $prepostData{$id} = ""; # Actual xml data string.
91 25         39 $errMsg{$id} = ""; # error messages, no error this will be a null string.
92              
93 25         59 $ops{$id}->{processing} = " processing=\"sequential\""; # Processing type
94 25         45 $ops{$id}->{sbase} = ""; # search base
95 25         39 $ops{$id}->{sizelimit} = " sizeLimit=\"0\""; # search size limit
96 25         35 $ops{$id}->{timelimit} = " timeLimit=\"0\""; # search time limit
97 25         38 $ops{$id}->{onerror} = " onError=\"exit\""; # search time limit
98 25         41 $ops{$id}->{responseOrder} = " responseOrder=\"sequential\""; # search time limit
99 25         34 $ops{$id}->{scope} = " scope=\"singleLevel\""; # search scope
100 25         72 $ops{$id}->{derefAliases} = " derefAliases=\"neverDerefAliases\"";
101 25         39 $ops{$id}->{typesOnly} = " typesOnly=\"false\">"; #
102 25         40 $ops{$id}->{auth} = ""; # authRequest data
103              
104 25         39 $ops{$id}->{control} = ""; # Control data
105              
106 25         35 $ops{$id}->{reqid} = " requestID=\"batch request\""; # request ID
107 25 0       77 $ops{$id}->{host} = (ref($opt->{url}) ? ${$opt->{url}} : $opt->{url}) if ( $opt->{url} ); # ldap host
  0 50       0  
108 25 50       63 $ops{$id}->{debug} = $opt->{debug} ? 1 : 0; # debug flage
109 25         41 $ops{$id}->{pid} = ""; # initial process id.
110 25         57 $pid{$id}->{pid} = 1; # initial process id.
111              
112 25         53 $operations{$id} = [];
113 25         35 $result = 1;
114              
115 25 0       49 $result = $self->setProcess({ process => (ref($opt->{process}) ? ${$opt->{process}} : $opt->{process}) }) if ( $opt->{process});
  0 50       0  
116 25 50       51 $initerror .= $errMsg{$id} if (!$result);
117              
118 25 100       66 $result = $self->setType( { type => (ref($opt->{type}) ? ${$opt->{type}} : $opt->{type}) } ) if ( $opt->{type} );
  1 100       4  
119 25 50       56 $initerror .= "\t" . $errMsg{$id} if (!$result);
120              
121 25 100       100 $result = $self->setReferral( { referral => (ref($opt->{referral}) ? ${$opt->{referral}} : $opt->{referral}) } ) if ( $opt->{referral} );
  1 100       4  
122 25 50       48 $initerror .= "\t" . $errMsg{$id} if (!$result);
123              
124 25 100       58 $result = $self->setScope( { scope => (ref($opt->{scope}) ? ${$opt->{scope}} : $opt->{scope}) } ) if ( $opt->{scope} );
  1 100       5  
125 25 50       53 $initerror .= "\t" . $errMsg{$id} if (!$result);
126              
127 25 0       51 $result = $self->setOrder( { order => (ref($opt->{order}) ? ${$opt->{order}} : $opt->{order}) } ) if ( $opt->{order} );
  0 50       0  
128 25 50       42 $initerror .= "\t" . $errMsg{$id} if (!$result);
129              
130 25 0       47 $result = $self->setOnError( { error => (ref($opt->{error}) ? ${$opt->{error}} : $opt->{error})} ) if ( $opt->{error} );
  0 50       0  
131 25 50       42 $initerror .= "\t" . $errMsg{$id} if (!$result);
132              
133 25 100       66 $result = $self->setTime( { time => (ref($opt->{time}) ? ${$opt->{time}} : $opt->{time}) } ) if ( $opt->{time} );
  1 100       4  
134 25 50       45 $initerror .= "\t" . $errMsg{$id} if (!$result);
135              
136 25 100       60 $result = $self->setSize( { size => (ref($opt->{size}) ? ${$opt->{size}} : $opt->{size}) } ) if ( $opt->{size} );
  1 100       5  
137 25 50       55 $initerror .= "\t" . $errMsg{$id} if (!$result);
138              
139 25 100       56 $result = $self->setBase( { base => (ref($opt->{base}) ? ${$opt->{base}} : $opt->{base}) } ) if ( $opt->{base} );
  1 100       5  
140 25 50       51 $initerror .= "\t" . $errMsg{$id} if (!$result);
141              
142 25 0       46 $result = $self->setProxy( { dn => (ref($opt->{proxyid}) ? ${$opt->{proxyid}} : $opt->{proxyid}) } ) if ( $opt->{proxyid} );
  0 50       0  
143 25 50       44 $initerror .= "\t" . $errMsg{$id} if (!$result);
144              
145 25 0       48 $result = $self->setBatchId( { id => (ref($opt->{bid}) ? ${$opt->{bid}} : $opt->{bid}) } ) if ( $opt->{bid} );
  0 50       0  
146 25 50       48 $initerror .= "\t" . $errMsg{$id} if (!$result);
147              
148 25         39 $errMsg{$id} = $initerror;
149              
150              
151 25 50 33     62 if ( $opt->{dn} && $opt->{password} )
152             {
153 0 0       0 $authentication{$id}->{dn} = (ref($opt->{dn}) ? ${$opt->{dn}} : $opt->{dn});
  0         0  
154 0 0       0 $authentication{$id}->{password} = (ref($opt->{password}) ? ${$opt->{password}} : $opt->{password});
  0         0  
155             }
156              
157 25         81 return $self;
158             }
159              
160             #
161             # inside-out classes have to have a DESTROY subrountine.
162             #
163             sub DESTROY
164             {
165 25     25   89 my ($dsml) = @_;
166 25         47 my $id = ident($dsml);
167              
168 25         93 delete $ops{$id}; # items container
169 25         39 delete $content{$id}; # Returned ldap data
170 25         31 delete $psize{$id}; # Size of xml string.
171 25         30 delete $postData{$id}; # Actual xml data string.
172 25         31 delete $prepostData{$id}; # Copy of actual xml data string.
173 25         29 delete $errMsg{$id}; # no error this will be a null string.
174 25         52 delete $operations{$id}; # operations container
175 25         24 delete $authentication{$id}; # authentication container
176 25         37 delete $pid{$id}; # initial process id.
177 25         337 return;
178             }
179              
180             # 1. & - &
181             # 2. < - <
182             # 3. > - >
183             # 4. " - "
184             # 5. ' - '
185             #
186             # Convert special characters to xml standards.
187             #
188             sub _specialChar
189             {
190 14     14   19 my ($char) = @_;
191              
192 14         26 $$char =~ s/&/&/g;
193 14         17 $$char =~ s/
194 14         17 $$char =~ s/>/>/g;
195 14         17 $$char =~ s/"/"/g;
196 14         16 $$char =~ s/'/'/g;
197 14         17 return;
198             }
199              
200             #
201             # Constant values
202             #
203             # The string postHead provides the xml "Header" string.
204             # This "Header" string is standard with all DSML XML strings.
205             #
206             my $postHead = "";
207              
208             # The string postTail provides the xml "Tail" string.
209             # This "Tail" string is standard with all DSML XML strings.
210             #
211             my $postTail = "";
212              
213             # The string postPing provides the xml "Body" string for a DSML ping request.
214             # The DSML ping request is used to tell if the DSML functions are provided.
215             #
216             my $postPing = "";
217              
218             # The string postDSE provides the ending xml "Body" string for a DSML
219             # rootDSE request. The DSML rootDSE request is used to get the directory
220             # rootDSE information.
221             #
222             my $postDSE = "";
223              
224             # The string preBatch provides the initial batchRequest xml "Body" string
225             # for a DSML request.
226             #
227             my $preBatch = "
228              
229             # The string postBatch provides the ending batchRequest xml "Body"
230             # string for a DSML request.
231             #
232             my $postBatch = "";
233              
234             # The string preAuth provides the authorization xml "Body" string for a DSML
235             # authRequest.
236             #
237             my $preAuth = "
238              
239             # The string postAuth provides the ending authorization xml "Body" string for a
240             # DSML authRequest.
241             #
242             my $postAuth = "\"/>";
243              
244             # The string postSearch provides the ending xml "Body" string for a
245             # DSML search request.
246             #
247             my $postSearch = "";
248              
249             # The string postCompare provides the ending xml "Body" string for a
250             # DSML search request.
251             #
252             my $postCompare = "";
253              
254             # The string reqID provides the initial part of the scope attribute of
255             # the batchRequest element.
256             #
257             my $reqID = " requestID=\"";
258              
259             my $prescope = " scope=\"";
260              
261             # The string deref provides the initial part of the derefAliases attribute
262             # of the batchRequest element.
263             #
264             my $deref = " derefAliases=\"";
265              
266             # The string types provides the initial part of the typesOnly attribute
267             # of the batchRequest element.
268             #
269             my $types = " typesOnly=\"";
270             my $sizel = " sizeLimit=\"";
271             my $timel = " timeLimit=\"";
272             my $orders = " responseOrder=\"";
273             my $proc = " processing=\"";
274             my $onE = " onError=\"";
275              
276             #
277             # End of constant values.
278             #
279              
280             #
281             # Method setScope
282             #
283             # The method setScope sets the LDAP search scope.
284             #
285             # There is one required input option.
286             #
287             # $return = $dsml->setScope( { scope => "singleLevel" } );
288             #
289             # Input option "scope": String that contains the LDAP scope value;
290             # singleLevel, baseObject or wholeSubtree. Default is singleLevel.
291             #
292             # Method output; Returns true on success; false on error, error message
293             # can be gotten with error method.
294             #
295              
296             sub setScope
297             {
298 5     5 1 7 my ($dsml, $opt) = @_;
299 5         12 my $id = ident $dsml;
300              
301 5         10 $errMsg{$id} = "";
302              
303 5 100       29 if ((ref($opt->{scope}) ? ${$opt->{scope}} : $opt->{scope}) =~ /^(singleLevel||baseObject||wholeSubtree)$/)
  1 50       6  
304             {
305 5         17 $ops{$id}->{scope} = $prescope . $1 . "\"";
306 5         11 return 1;
307             }
308              
309 0         0 $errMsg{$id} = "Requested scope value does not match singleLevel, baseObject or wholeSubtree";
310 0         0 return 0;
311             }
312              
313             #
314             # Method setReferral
315             #
316             # The method setReferral sets the LDAP referral status.
317             #
318             # There is one required input option.
319             #
320             # $return = $dsml->setReferral( { referral => "neverDerefAliases" } );
321             #
322             # Input option "referral": String that contains the referral control value;
323             # neverDerefAliases, derefInSearching, derefFindingBaseObj or derefAlways.
324             # Default is neverDerefAliases.
325             #
326             # Method output; Returns true on success; false on error, error message
327             # can be gotten with error method.
328             #
329              
330             sub setReferral
331             {
332 5     5 1 8 my ($dsml,$opt) = @_;
333 5         10 my $id = ident $dsml;
334              
335 5         10 $errMsg{$id} = "";
336              
337 5 100       29 if ((ref($opt->{referral}) ? ${$opt->{referral}} : $opt->{referral}) =~ /^(neverDerefAliases||derefInSearching||derefFindingBaseObj||derefalways)$/)
  1 50       6  
338             {
339 5         16 $ops{$id}->{derefAliases} = $deref . $1 . "\"";
340 5         10 return 1;
341             }
342              
343 0         0 $errMsg{$id} = "Requested setReferral derefAliases value does not match neverDerefAliases, derefInSearching, derefFindingBaseObj or derefAlways.";
344 0         0 return 0;
345             }
346              
347             # Method setType
348             #
349             # The method setType sets the LDAP search scope.
350             #
351             # There is one required input option.
352             #
353             # $return = $dsml->setType( { type => "false" } );
354             #
355             # Input option "type": String that contains the LDAP scope value;
356             # true or false. Default is false.
357             #
358             # Method output; Returns true on success; false on error, error message
359             # can be gotten with error method.
360             #
361              
362             sub setType
363             {
364 5     5 1 15 my ($dsml, $opt) = @_;
365 5         13 my $id = ident $dsml;
366              
367 5         9 $errMsg{$id} = "";
368              
369 5 100       40 if (lc((ref($opt->{type}) ? ${$opt->{type}} : $opt->{type})) =~ /^(false||true)$/ )
  1 50       5  
370             {
371 5         20 $ops{$id}->{typesOnly} = $types . $1 . "\">"; # The > ends an xml element.
372 5         12 return 1;
373             }
374              
375 0         0 $errMsg{$id} = "Requested setType value does not match true or false.";
376 0         0 return 0;
377             }
378              
379              
380             # Method setSize
381             #
382             # The method setSize sets the size limit of the LDAP search.
383             #
384             # There is one required input option.
385             #
386             # $return = $dsml->setSize( { size => "0" } );
387             #
388             # Input option "size": String that contains the size limit of the
389             # LDAP search. Default is "0".
390             #
391             # Method output; Returns true on success; false on error, error message
392             # can be gotten with error method.
393             #
394              
395             sub setSize
396             {
397 5     5 1 9 my ($dsml, $opt) = @_;
398 5         12 my $id = ident $dsml;
399 5         7 my $refvalue;
400              
401 5         8 $errMsg{$id} = "";
402 5 100       14 $refvalue = (ref($opt->{size}) ? ${$opt->{size}} : $opt->{size});
  1         3  
403              
404 5 50       15 if (!(length($refvalue)) )
405             {
406 0         0 $errMsg{$id} = "Subroutine setSize size value is not defined.";
407 0         0 return 0;
408             }
409              
410 5         14 $ops{$id}->{sizelimit} = $sizel . $refvalue ."\""; # The > ends an xml element.
411 5         11 return 1;
412             }
413              
414              
415             # Method setTime
416             #
417             # The method setTime sets the time limit of the LDAP search.
418             #
419             # There is one required input option.
420             #
421             # $return = $dsml->setTime( { time => "0" } );
422             #
423             # Input option "time": String that contains the time limit of the
424             # LDAP search. Default is "0".
425             #
426             # Method output; Returns true on success; false on error, error message
427             # can be gotten with error method.
428             #
429              
430             sub setTime
431             {
432 5     5 1 9 my ($dsml, $opt) = @_;
433 5         11 my $id = ident $dsml;
434 5         6 my $refvalue;
435 5         10 $errMsg{$id} = "";
436            
437 5 100       15 $refvalue = (ref($opt->{time}) ? ${$opt->{time}} : $opt->{time});
  1         3  
438              
439 5 50       13 if ( !(length($refvalue)) )
440             {
441 0         0 $errMsg{$id} = "Subroutine setTime time value is not defined.";
442 0         0 return 0;
443             }
444              
445 5         14 $ops{$id}->{timelimit} = $timel . $refvalue . "\"";
446 5         11 return 1;
447             }
448              
449              
450             # Method setOrder
451             #
452             # The method setOrder sets the order of the returned LDAP data.
453             #
454             # There is one required input option.
455             #
456             # $return = $dsml->setOrder( { order => "sequential" } );
457             #
458             # Input option "order": String that contains the LDAP order value;
459             # sequential or unordered. Default is sequential.
460             #
461             # Method output; Returns true on success; false on error, error message
462             # can be gotten with error method.
463             #
464              
465             sub setOrder
466             {
467 2     2 1 3 my ($dsml, $opt) = @_;
468 2         6 my $id = ident $dsml;
469              
470 2         5 $errMsg{$id} = "";
471              
472 2 100       11 if (lc((ref($opt->{order}) ? ${$opt->{order}} : $opt->{order})) =~ /^(sequential||unordered)$/ )
  1 50       6  
473             {
474 2         8 $ops{$id}->{responseOrder} = $orders . $1 . "\"";
475 2         5 return 1;
476             }
477              
478 0         0 $errMsg{$id} = "Requested responseOrder value does not match sequential or unordered.";
479 0         0 return 0;
480             }
481              
482              
483             # Method setProcess
484             #
485             # The method setProcess sets the LDAP DSML processing mode; sequential
486             # or parallel. If you use parallel you must set up a seperate unique
487             # requestId for each requested chunk of data.
488             #
489             # There is one required input option.
490             #
491             # $return = $dsml->setProcess( { process => "sequential" } );
492             #
493             # Input option "process": String that contains the LDAP process value;
494             # sequential or parallel. Default is sequential.
495             #
496             # Method output; Returns true on success; false on error, error message
497             # can be gotten with error method.
498             #
499              
500             sub setProcess
501             {
502 2     2 1 4 my ($dsml, $opt) = @_;
503 2         6 my $id = ident $dsml;
504              
505 2         5 $errMsg{$id} = "";
506              
507 2 100       15 if (lc((ref($opt->{process}) ? ${$opt->{process}} : $opt->{process})) =~ /^(sequential||parallel)$/)
  1 50       6  
508             {
509 2         7 $ops{$id}->{processing} = $proc . $1 . "\""; # Processing type
510 2         5 return 1;
511             }
512              
513 0         0 $errMsg{$id} = "Requested process value does not match sequential or parallel.";
514 0         0 return 0;
515             }
516              
517              
518             # Method setOnError
519             #
520             # The method setOnError sets the LDAP DSML processing mode for errors; exit
521             # or resume.
522             #
523             # There is one required input option.
524             #
525             # $return = $dsml->setOnError( { error => "exit" } );
526             #
527             # Input option "error": String that contains the LDAP onError value;
528             # exit or resume. Default is exit.
529             #
530             # Method output; Returns true on success; false on error, error message
531             # can be gotten with error method.
532             #
533              
534             sub setOnError
535             {
536 2     2 1 5 my ($dsml, $opt) = @_;
537 2         4 my $id = ident $dsml;
538              
539 2         7 $errMsg{ident $dsml} = "";
540 2 50       8 if ( !(length($opt->{error})) )
541             {
542 0         0 $errMsg{$id} = "Subroutine setOnError required attribute is not defined.";
543 0         0 return 0;
544             }
545              
546 2 100       12 if ( lc((ref($opt->{error}) ? ${$opt->{error}} : $opt->{error})) =~ /^(exit||resume)$/ )
  1 50       6  
547             {
548 2         8 $ops{$id}->{onerror} = $onE . $1 . "\""; # On error action to take
549 2         5 return 1;
550             }
551              
552 0         0 $errMsg{$id} = "Requested onError value does not match exit or resume.";
553 0         0 return 0;
554             }
555              
556             # Method setBatchId
557             #
558             # The method setBatchId sets the batch operation request id.
559             #
560             # There is one required input option.
561             #
562             # $return = $dsml->setBatchId( { id => "batch request id" });
563             #
564             # Input option "id": String that contains the batch operation request id.
565             # Default is "search request".
566             #
567             # Method output; Returns true on success; false on error, error message
568             # can be gotten with error method.
569             #
570              
571             sub setBatchId
572             {
573 2     2 1 5 my ($dsml, $opt) = @_;
574 2         4 my $id = ident $dsml;
575 2         3 my $refvalue;
576              
577 2         6 $errMsg{$id} = "";
578 2 100       16 $refvalue = (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id});
  1         2  
579              
580 2 50       7 if ( !(length($refvalue)) )
581             {
582 0         0 $errMsg{$id} = "Subroutine setBatchId id string is not defined.";
583 0         0 return 0;
584             }
585              
586 2         6 $ops{$id}->{reqid} = $reqID . $refvalue . "\"";
587 2         5 return 1;
588             }
589              
590              
591             # Method setProcessId
592             #
593             # The method setProcessId sets the LDAP process operation request id.
594             # Very important method if parallel processing is enabled because each
595             # parallel operation must have a unique request id.
596             #
597             # There is one required input option.
598             #
599             # $return = $dsml->setProcessId( { id => "request id" });
600             #
601             # Input option "id": String that contains the LDAP operation request id.
602             # Default value: 1, incremented after each process.
603             #
604             # Method output; Returns true on success; false on error, error message
605             # can be gotten with error method.
606             #
607              
608             sub setProcessId
609             {
610 13     13 1 19 my ($dsml, $opt) = @_;
611 13         66 my $id = ident $dsml;
612 13         11 my $refvalue;
613 13         25 $errMsg{$id} = "";
614 13 100       32 $refvalue = (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id});
  2         5  
615 13 50       28 if ( !(length($refvalue)) )
616             {
617 0         0 $errMsg{$id} = "Subroutine setProcessId id value is not defined.";
618 0         0 return 0;
619             }
620              
621 13         33 $ops{$id}->{pid} = $reqID . $refvalue . "\"";
622 13         24 return 1;
623             }
624              
625             # Method setBase
626             #
627             # The method setBase sets the LDAP search base.
628             # This is a required method, program must set it.
629             #
630             # There is one required input option.
631             #
632             # $return = $dsml->setBase( { base => "dc=company,dc=com" } );
633             #
634             # Input option "base": String that contains the LDAP search base.
635             #
636             # Method output; Returns true on success; false on error, error message
637             # can be gotten with error method.
638             #
639              
640             sub setBase
641             {
642 12     12 1 23 my ($dsml, $opt) = @_;
643 12         23 my $id = ident $dsml;
644 12         11 my $refvalue;
645 12         22 $errMsg{$id} = "";
646 12 100       31 $refvalue = (ref($opt->{base}) ? ${$opt->{base}} : $opt->{base});
  2         6  
647              
648 12 50       33 if ( !(length($refvalue)) )
649             {
650 0         0 $errMsg{$id} = "Subroutine setBase base value is not defined.";
651 0         0 return 0;
652             }
653 12 50       57 _specialChar(\$refvalue) if ( $refvalue =~ /(&||<||>||"||')/);
654 12         36 $ops{$id}->{sbase} = "\"" . $refvalue . "\"";
655 12         24 return 1;
656             }
657              
658              
659             # Method debug
660             #
661             # The method debug sets or returns the object debug flag.
662             #
663             # If there is one required input option.
664             #
665             # $return = $dsml->debug( 1 );
666             #
667             # Input option: Debug value; 1 or 0. Default is 0.
668             #
669             # Method output; Returns debug value.
670             #
671              
672             sub debug
673             {
674 0     0 1 0 my $dsml = shift;
675 0 0       0 $ops{ident $dsml}->{debug} = shift if ( @_ >= 1 );
676 0         0 return $ops{ident $dsml}->{debug};
677             }
678              
679              
680             # Method url
681             #
682             # The method url sets or returns the object url value.
683             #
684             # If there is one required input option.
685             #
686             # $return = $dsml->url( "http://xyz.company.com:8080/dsml" );
687             #
688             # Input option: Host system name.
689             #
690             # Method output; Returns host value.
691             #
692              
693             sub url
694             {
695 0     0 1 0 my ($dsml, $opt) = @_;
696 0         0 my $id = ident $dsml;
697 0         0 my $refvalue;
698 0 0       0 $refvalue = (ref($opt) ? ${$opt} : $opt);
  0         0  
699 0         0 $ops{$id}->{host} = $refvalue;
700 0         0 return $ops{$id}->{host};
701             }
702              
703              
704             #
705             # Method error
706             #
707             # The method error returns the error message for the object.
708             # $message = $dsml->error();
709             #
710              
711             sub error
712             {
713 0     0 1 0 my $dsml = shift;
714 0         0 return $errMsg{ident $dsml};
715             }
716              
717              
718             # Method size
719             #
720             # The method size returns the size of the last dsml message sent to the dsml
721             # server.
722             #
723             # $size = $dsml->size();
724             #
725              
726             sub size
727             {
728 0     0 1 0 my $dsml = shift;
729 0         0 return $psize{ident $dsml};
730             }
731              
732              
733             # Method content
734             #
735             # The method content returns the last dsml message received from the
736             # dsml server.
737             # Once the user has the content he or she can use whatever XML parser they
738             # choose.
739             #
740             # $returnXmlMessage = $dsml->content();
741             #
742              
743             sub content
744             {
745 0     0 1 0 my $dsml = shift;
746 0         0 return $content{ident $dsml};
747             }
748              
749              
750             # Method Ping
751             #
752             # The method Ping builds a Ping batch request to be sent to the dsml server.
753             # A Ping requests is used to confirm the existance of a dsml server on a
754             # directory server system.
755             #
756             #
757             # $return = $dsml->Ping();
758             # $return = $dsml->send(); # Post the xml message to the DSML server
759             # $return = $dsml->content(); # Get the data returned from the DSML server.
760             #
761             # There are no inputs options for this method.
762             #
763             # Method output; Returns true on success; false on error, error message
764             # can be gotten with error method.
765             #
766             # The user must call the send method to actually send the ping request and
767             # parse the returned xml message to determine if the dsml server responded.
768             #
769              
770             sub Ping
771             {
772 0     0 1 0 my $dsml = shift;
773 0         0 my $id = ident $dsml;
774 0         0 my $result;
775 0         0 $dsml->setBatchId({id => "Ping!"});
776 0         0 $result = "";
777 0         0 push(@{$operations{$id}},$result);
  0         0  
778 0         0 return 1;
779             }
780              
781              
782             # Method rootDSE
783             #
784             # The method DSE the searchs the root, or dse, of the dsml server.
785             #
786             # There is one required input option.
787             # Input option "attributes": Array of attributes to get information on.
788             #
789             # There is one optional input option.
790             # Input option "id": The request ID for this operation.
791             #
792             # $return = $dsml->rootDSE( { attributes => \@attributes } );
793             # $return = $dsml->send(); # Post the xml message to the DSML server
794             # $return = $dsml->content(); # Get the data returned from the DSML server.
795             #
796             #
797             # The scope will automatically be set to the correct value for the user.
798             #
799             # Method output; Returns true on success; false on error, error message
800             # can be gotten with error method.
801             #
802             # The user must parse the returned xml message to determine what the
803             # dsml server responded with.
804             #
805              
806             sub rootDSE
807             {
808 3     3 1 5 my ($dsml,$opt) = @_;
809 3         3 my $size;
810             my $count;
811 0         0 my $oldscope;
812 3         6 my $id = ident $dsml;
813 3         2 my $result;
814              
815 3         6 $oldscope = $ops{$id}->{scope};
816              
817 3         4 $count = @{$opt->{attributes}};
  3         4  
818              
819 3         4 $result = "
820              
821             # Load Process ID
822              
823 3 100       10 if ( $opt->{id} )
    50          
824             {
825 2 100       8 $result .= $reqID . (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id}) . "\"";
  1         4  
826             }
827             elsif ( $ops{$id}->{pid} )
828             {
829 1         2 $result .= $ops{$id}->{pid};
830 1         3 delete($ops{$id}->{pid});
831             }
832             else
833             {
834 0         0 $result .= $reqID . $pid{$id}->{pid} . "\"";
835 0         0 ++$pid{$id}->{pid};
836             }
837              
838 3         18 $result .= " dn=\"\"" . " scope=\"baseObject\"" . $ops{$id}->{derefAliases} . $ops{$id}->{timelimit} . $ops{$id}->{sizelimit} . $ops{$id}->{typesOnly} . "";
839              
840 3         9 for (my $i = 0; $i < $count; $i++)
841             {
842 3         4 $result .= "
843 3         4 $result .= ${$opt->{attributes}}[$i];
  3         4  
844 3         8 $result .= "\"/>";
845             }
846              
847 3         4 $result .= $postDSE;
848 3 50       7 $result .= $opt->{control} if ( defined($opt->{control}));
849 3         4 $result .= "";
850 3         4 push(@{$operations{$id}},$result);
  3         5  
851 3         6 return 1;
852              
853             }
854              
855             #
856             # Method setProxy
857             #
858             # The method setProxy sets the LDAP authenication dn.
859             #
860             # There is one required input option.
861             #
862             # $return = $dsml->setProxy( { dn => "cn=directory manager" } );
863             #
864             # Input option "dn": String that contains the LDAP authenication dn .
865             #
866              
867             sub setProxy
868             {
869 0     0 1 0 my ($dsml, $opt) = @_;
870 0         0 my $id = ident $dsml;
871 0         0 my $refvalue;
872              
873 0         0 $errMsg{$id} = "";
874 0 0       0 $refvalue = (ref($opt->{dn}) ? ${$opt->{dn}} : $opt->{dn});
  0         0  
875 0 0       0 if ( !(length($refvalue)) )
876             {
877 0         0 $errMsg{$id} = "Subroutine setProxy dn value is not defined.";
878 0         0 return 0;
879             }
880              
881 0         0 $ops{$id}->{auth} = $preAuth . $refvalue . $postAuth;
882 0         0 return 1;
883             }
884              
885             # Method search
886             #
887             # The method search searchs the dsml server for the requested information.
888             #
889             # If there are two required input options.
890             # Input option "sfilter": The filter object that contains the filter string.
891             # Input option "attributes": Array reference of attributes to get
892             # information on.
893             #
894             # There are 3 optional input options.
895             # Input option "id": The request ID for this operation.
896             # Input option "control": The Control object that contains the control string.
897             # Input option "base": The search base dn.
898             #
899             # $return = $dsml->search( { sfilter => $dsml->getFilter(),
900             # attributes => \@attributes },
901             # control => $control->getControl() );
902             # $return = $dsml->send(); # Post the xml message to the DSML server
903             # $content = $dsml->content(); # Get the data returned from the DSML server.
904             #
905             # Method output; Returns true on success; false on error, error message
906             # can be gotten with error method.
907             #
908             # The user must parse the returned xml message to determine what the
909             # dsml server responded with.
910             #
911              
912             sub search
913             {
914 12     12 1 20 my ($dsml, $opt) = @_;
915 12         12 my $count;
916 12         22 my $id = ident $dsml;
917 12         14 my $result;
918 12         13 $count = @{$opt->{attributes}};
  12         21  
919 12         23 $errMsg{$id} = "";
920              
921 12 50       27 if ( !$count )
922             {
923 0         0 $errMsg{$id} = "Subroutine search attributes are not defined.";
924 0         0 return 0;
925             }
926              
927 12 50       27 if ( !(length($opt->{sfilter})) )
928             {
929 0         0 $errMsg{$id} = "Subroutine search search filter is not defined.";
930 0         0 return 0;
931             }
932              
933 12 100       32 if ( $opt->{base} )
934             {
935 1 50       6 if (!$dsml->setBase( {base => (ref($opt->{base}) ? ${$opt->{base}} : $opt->{base}) }))
  1 50       4  
936             {
937 0         0 return 0;
938             }
939             }
940            
941             #
942             # build search xml message
943             #
944              
945 12         14 $result = "
946            
947             # Load Process ID
948 12 100       40 if ( $opt->{id} )
    50          
949             {
950 3 100       13 $result .= $reqID . (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id}) . "\"";
  2         8  
951             }
952             elsif ( $ops{$id}->{pid} )
953             {
954 9         21 $result .= $ops{$id}->{pid};
955 9         18 delete($ops{$id}->{pid});
956             }
957             else
958             {
959 0         0 $result .= $reqID . $pid{$id}->{pid} . "\"";
960 0         0 ++$pid{$id}->{pid};
961             }
962              
963 12         83 $result .= " dn=" . $ops{$id}->{sbase} . $ops{$id}->{scope} . $ops{$id}->{derefAliases} . $ops{$id}->{timelimit} . $ops{$id}->{sizelimit} . $ops{$id}->{typesOnly};
964             #
965             # Now add the filter xml string
966             #
967 12         19 $result .= $opt->{sfilter};
968              
969             #
970             # Now add the attribute list as a xml string.
971             #
972 12         14 $result .= "";
973              
974 12         35 for (my $i = 0; $i < $count; $i++)
975             {
976 60         62 $result .= "
977 60         53 $result .= ${$opt->{attributes}}[$i];
  60         90  
978 60         173 $result .= "\"/>";
979             }
980              
981 12         16 $result .= "";
982 12 100       30 $result .= $opt->{control} if ( defined($opt->{control}));
983 12         13 $result .= $postSearch;
984 12         13 push(@{$operations{$id}},$result);
  12         30  
985 12         29 return 1;
986             }
987              
988             # Method compare
989             #
990             # The method compare compares the dsml server for the requested information.
991             #
992             # There are three required input options.
993             # Input option "dn": The dn of the object that you wish to do the comparsion on
994             # Input option "attribute": attributes to compare the value of.
995             # Input option "value": value to compare against.
996             #
997             # There are two option input options.
998             # Input option "id": The request ID for this operation.
999             # Input option "control": A Net::DSML::Control object.
1000             #
1001             # $return = $dsml->compare( { dn => "cn=Super Man,ou=People,dc=xyz,dc=com", attibute => "sn", value => "manager" } );
1002             # $return = $dsml->send(); # Post the xml message to the DSML server
1003             # $content = $dsml->content(); # Get the data returned from the DSML server.
1004             #
1005             # Method output; Returns 1 (true) on success; 0 (false) on error, error
1006             # message can be gotten with error method.
1007             #
1008             # The user must parse the returned xml content message to determine what the
1009             # dsml server responded with.
1010             #
1011              
1012             sub compare
1013             {
1014 2     2 1 4 my ($dsml, $opt) = @_;
1015 2         3 my $size;
1016             my $count;
1017 2         4 my $id = ident $dsml;
1018 2         2 my $result;
1019             my $dn;
1020 0         0 my $attribute;
1021 0         0 my $value;
1022              
1023 2 50       6 $dn = (ref($opt->{dn}) ? ${$opt->{dn}} : $opt->{dn});
  0         0  
1024 2 50       6 $attribute = (ref($opt->{attribute}) ? ${$opt->{attribute}} : $opt->{attribute});
  0         0  
1025 2 50       3 $value = (ref($opt->{value}) ? ${$opt->{value}} : $opt->{value});
  0         0  
1026 2 50       16 if ( !(length($dn)) )
1027             {
1028 0         0 $errMsg{$id} = "Subroutine compare dn value is not defined.";
1029 0         0 return 0;
1030             }
1031              
1032 2 50       4 if ( !(length($attribute)) )
1033             {
1034 0         0 $errMsg{$id} = "Subroutine compare attribute is not defined.";
1035 0         0 return 0;
1036             }
1037              
1038 2 50       10 if ( !(length($value)) )
1039             {
1040 0         0 $errMsg{$id} = "Subroutine compare attribute value is not defined.";
1041 0         0 return 0;
1042             }
1043              
1044 2 50       11 _specialChar(\$value) if ( $value =~ /(&||<||>||"||')/);
1045              
1046 2         3 $result = "
1047              
1048             # Load Process ID
1049            
1050 2 100       7 if ( $opt->{id} )
    50          
1051             {
1052 1 50       6 $result .= $reqID . (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id}) . "\"";
  0         0  
1053             }
1054             elsif ( $ops{$id}->{pid} )
1055             {
1056 1         3 $result .= $ops{$id}->{pid};
1057 1         2 delete($ops{$id}->{pid});
1058             }
1059             else
1060             {
1061 0         0 $result .= $reqID . $pid{$id}->{pid} . "\"";
1062 0         0 ++$pid{$id}->{pid};
1063             }
1064              
1065 2         6 $result .= " dn=\"" . $dn . "\">" . $value;
1066              
1067 2         4 $result .= $postCompare;
1068 2 50       6 $result .= $opt->{control} if ( defined($opt->{control}));
1069 2         4 $result .= "";
1070 2         1 push(@{$operations{$id}},$result);
  2         5  
1071 2         5 return 1;
1072             }
1073              
1074              
1075             # Method delete
1076             #
1077             # The method delete deletes an entry from the directory server.
1078             #
1079             # There is one required input option.
1080             # Input option "dn": The dn of the entry that you wish to delete.
1081             # There are two optional input options.
1082             # Input option "control": The control object to be used with the delete
1083             # operation.
1084             # Input option "id": The request ID for this operation.
1085             #
1086             # $return = $dsml->delete( { dn => "cn=Super Man,ou=People,dc=xyz,dc=com" } );
1087             # $return = $dsml->send(); # Post the xml message to the DSML server
1088             # $content = $dsml->content(); # Get the data returned from the DSML server.
1089             #
1090             # Method output; Returns 1 (true) on success; 0 (false) on error, error
1091             # message can be gotten with error method.
1092             #
1093             # The user must parse the returned xml content message to determine what the
1094             # dsml server responded with.
1095             #
1096              
1097             sub delete
1098             {
1099 2     2 1 2 my ($dsml, $opt) = @_;
1100 2         3 my $size;
1101             my $count;
1102 2         4 my $id = ident $dsml;
1103 2         1 my $result;
1104             my $refvalue;
1105 2         5 $errMsg{$id} ="";
1106 2 50       4 $refvalue = (ref($opt->{dn}) ? ${$opt->{dn}} : $opt->{dn});
  0         0  
1107 2 50       6 if ( !(length($refvalue)) )
1108             {
1109 0         0 $errMsg{$id} = "Subroutine delete dn value is not defined.";
1110 0         0 return 0;
1111             }
1112              
1113 2 50       9 if (defined($opt->{control}))
1114             {
1115 0         0 $result = "
1116              
1117             # Load Process ID
1118              
1119 0 0       0 if ( $ops{$id}->{pid} )
1120             {
1121 0         0 $result .= $ops{$id}->{pid};
1122 0         0 delete($ops{$id}->{pid});
1123             }
1124             else
1125             {
1126 0         0 $result .= $reqID . $pid{$id}->{pid} . "\"";
1127 0         0 ++$pid{$id}->{pid};
1128             }
1129              
1130 0         0 $result .= " dn=\"" . $refvalue . "\" >";
1131 0         0 $result .= $opt->{control};
1132 0         0 $result .= "";
1133             }
1134             else
1135             {
1136 2         3 $result = "
1137              
1138             # Load Process ID
1139              
1140 2 50       9 if ( $opt->{id} )
    100          
1141             {
1142 0 0       0 $result .= $reqID . (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id}) . "\"";
  0         0  
1143             }
1144             elsif ( $ops{$id}->{pid} )
1145             {
1146 1         3 $result .= $ops{$id}->{pid};
1147 1         3 delete($ops{$id}->{pid});
1148             }
1149             else
1150             {
1151 1         3 $result .= $reqID . $pid{$id}->{pid} . "\"";
1152 1         2 ++$pid{$id}->{pid};
1153             }
1154              
1155 2         5 $result .= " dn=\"" . $refvalue . "\" />";
1156             }
1157              
1158 2         3 push(@{$operations{$id}},$result);
  2         4  
1159 2         5 return 1;
1160             }
1161              
1162              
1163             # Method modrdn
1164             #
1165             # The method modrdn renames an entry in the directory server.
1166             #
1167             # There are three required input options.
1168             # Input option "dn": The dn of the entry that you wish to delete.
1169             # Input option "newsuperior": The base dn of the entry that you wish to rename.
1170             # Input option "newrdn": The rdn of the new entry that you wish to create.
1171             # There are three optional input options.
1172             # Input option "deleteoldrdn": The flag that controls the deleting of the
1173             # entry: true -> delete entry, false -> keep entry.
1174             # Input option "id": The request ID for this operation.
1175             # Input option "control": A Net::DSML::Control object output.
1176             #
1177             # $return = $dsml->modrdn( { dn => "cn=Super Man,ou=People,dc=xyz,dc=com",
1178             # newrdn => "cn=Bad Boy",
1179             # deleteoldrdn => "true",
1180             # newsuperior => "ou=People,dc=xyz,dc=com" } );
1181             # $return = $dsml->send(); # Post the xml message to the DSML server
1182             # $content = $dsml->content(); # Get the data returned from the DSML server.
1183             #
1184             # Method output; Returns 1 (true) on success; 0 (false) on error, error
1185             # message can be gotten with error method.
1186             #
1187             # The user must parse the returned xml content message to determine what the
1188             # dsml server responded with.
1189             #
1190              
1191             sub modrdn
1192             {
1193 1     1 1 2 my ($dsml, $opt) = @_;
1194 1         2 my $size;
1195             my $count;
1196 1         4 my $id = ident $dsml;
1197 1         2 my $result;
1198             my $dn;
1199 0         0 my $newrdn;
1200 0         0 my $newsuperior;
1201 0         0 my $refvalue;
1202              
1203 1         8 $errMsg{$id} ="";
1204              
1205 1 50       6 $dn = (ref($opt->{dn}) ? ${$opt->{dn}} : $opt->{dn});
  0         0  
1206 1 50       6 $newrdn = (ref($opt->{newrdn}) ? ${$opt->{newrdn}} : $opt->{newrdn});
  0         0  
1207 1 50       4 $newsuperior = (ref($opt->{newsuperior}) ? ${$opt->{newsuperior}} : $opt->{newsuperior});
  0         0  
1208 1 50       7 $refvalue = (ref($opt->{deleteoldrdn}) ? ${$opt->{deleteoldrdn}} : $opt->{deleteoldrdn}) if ( $opt->{deleteoldrdn} );
  0 50       0  
1209              
1210 1 50       4 if ( !(length($dn)) )
1211             {
1212 0         0 $errMsg{$id} = "Subroutine modrdn dn value is not defined.";
1213 0         0 return 0;
1214             }
1215              
1216 1 50       3 if ( !(length($newrdn)) )
1217             {
1218 0         0 $errMsg{$id} = "Subroutine modrdn newrdn value is not defined.";
1219 0         0 return 0;
1220             }
1221              
1222 1 50       4 if ( !(length($newsuperior)) )
1223             {
1224 0         0 $errMsg{$id} = "Subroutine modrdn newsuperior value is not defined.";
1225 0         0 return 0;
1226             }
1227              
1228 1         2 $result = "
1229              
1230             # Load Process ID
1231              
1232 1 50       21 if ( $opt->{id} )
    50          
1233             {
1234 0 0       0 $result .= $reqID . (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id}) . "\"";
  0         0  
1235             }
1236             elsif ( $ops{$id}->{pid} )
1237             {
1238 1         4 $result .= $ops{$id}->{pid};
1239 1         8 delete($ops{$id}->{pid});
1240             }
1241             else
1242             {
1243 0         0 $result .= $reqID . $pid{$id}->{pid} . "\"";
1244 0         0 ++$pid{$id}->{pid};
1245             }
1246              
1247 1         4 $result .= " dn=\"" . $dn . "\" ";
1248 1         3 $result .= "newrdn=\"" . $newrdn . "\" ";
1249 1         3 $result .= "newSuperior=\"" . $newsuperior . "\" ";
1250 1 50       6 $result .= "deleteoldrdn=\"" . $refvalue . "\"" if ( $opt->{deleteoldrdn} );
1251 1         2 $result .= ">";
1252 1 50       5 $result .= $opt->{control} if ( defined($opt->{control}));
1253 1         2 $result .= "";
1254              
1255 1         2 push(@{$operations{$id}},$result);
  1         2  
1256 1         4 return 1;
1257             }
1258              
1259             #
1260             # Method add
1261             #
1262             # The method add adds an entry into the directory server.
1263             #
1264             # There are 2 required input options.
1265             # Input option "dn": The dn of the entry that you wish to add.
1266             # Input option "attr": A hash of the attributes and their values that are
1267             # that are to be in the entry.
1268             #
1269             # There are two optional input options.
1270             # Input option "control": A Net::DSML::Control object output.
1271             # Input option "id": The request ID for this operation.
1272             #
1273             #
1274             # $result = $dsml->add( { dn => 'cn=Barbara Jensen, o=University of Michigan, c=US',
1275             # attr => {
1276             # 'cn' => ['Barbara Jensen', 'Barbs Jensen'],
1277             # 'sn' => 'Jensen',
1278             # 'mail' => 'b.jensen@umich.edu',
1279             # 'objectclass' => ['top', 'person',
1280             # 'organizationalPerson',
1281             # 'inetOrgPerson' ],
1282             # }
1283             # }
1284             # );
1285             #
1286             # $return = $dsml->send(); # Post the xml message to the DSML server
1287             # $content = $dsml->content(); # Get the data returned from the DSML server.
1288             #
1289             # Method output; Returns 1 (true) on success; 0 (false) on error, error
1290             # message can be gotten with error method.
1291             #
1292             # The user must parse the returned xml content message to determine what the
1293             # dsml server responded with.
1294             #
1295              
1296             sub add
1297             {
1298 2     2 1 4 my ($dsml, $opt) = @_;
1299 2         7 my $id = ident $dsml;
1300 2         4 my $result;
1301             my @attributes;
1302 0         0 my $dn;
1303 2         4 $errMsg{$id} = "";
1304              
1305 2 50       8 $dn = (ref($opt->{dn}) ? ${$opt->{dn}} : $opt->{dn});
  0         0  
1306              
1307 2 50       7 if ( !(length($dn)) )
1308             {
1309 0         0 $errMsg{$id} = "Subroutine add dn value is not defined.";
1310 0         0 return 0;
1311             }
1312              
1313 2         3 @attributes = sort(keys(%{$opt->{attr}}));
  2         24  
1314              
1315             #
1316             # build search xml message
1317             #
1318              
1319 2         4 $result = "
1320            
1321             # Load Process ID
1322            
1323 2 50       8 if ( $opt->{id} )
    0          
1324             {
1325 2 100       9 $result .= $reqID . (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id}) . "\"";
  1         4  
1326             }
1327             elsif ( $ops{$id}->{pid} )
1328             {
1329 0         0 $result .= $ops{$id}->{pid};
1330 0         0 delete($ops{$id}->{pid});
1331             }
1332             else
1333             {
1334 0         0 $result .= $reqID . $pid{$id}->{pid} . "\"";
1335 0         0 ++$pid{$id}->{pid};
1336             }
1337              
1338 2         7 $result .= " dn=\"" . $dn . "\">";
1339              
1340             #
1341             # Now add the attribute list as a xml string.
1342             #
1343              
1344 2         3 foreach my $i (@attributes)
1345             {
1346 10 100       24 if ( ref($opt->{attr}{$i}))
1347             {
1348 4 50       16 if (ref($opt->{attr}{$i}) eq 'SCALAR')
    50          
1349             {
1350 0         0 $result .= "${$opt->{attr}{$i}}";
  0         0  
1351             }
1352             elsif (ref($opt->{attr}{$i}) eq 'ARRAY')
1353             {
1354 4         6 foreach my $val ( @{$opt->{attr}{$i}})
  4         9  
1355             {
1356 12         34 $result .= "$val";
1357             }
1358              
1359             }
1360             else
1361             {
1362 0         0 $errMsg{$id} = "Invalid object in add subroutine attr hash.";
1363 0         0 return 0;
1364             }
1365             }
1366             else
1367             {
1368 6         21 $result .= "$opt->{attr}{$i}";
1369             }
1370             }
1371              
1372 2 50       8 $result .= $opt->{control} if ( defined($opt->{control}));
1373 2         4 $result .= "";
1374 2         2 push(@{$operations{$id}},$result);
  2         6  
1375 2         7 return 1;
1376             }
1377              
1378              
1379             #
1380             # Method modify
1381             #
1382             # The method modify modifies attributes in an entry.
1383             #
1384             # There are 2 required input options.
1385             # Input option "dn": The dn of the entry that you wish to add.
1386             # Input option "attr": A hash of the attributes and their values that are
1387             # that are to be in the entry.
1388             #
1389             # There are two optional input option.
1390             # Input option "control": A Net::DSML::Control object output.
1391             # Input option "id": The request ID for this operation.
1392             #
1393             #
1394             # $result = $dsml->modify( {
1395             # dn => 'cn=Barbara Jensen, o=University of Michigan, c=US',
1396             # modify => {
1397             # add => {
1398             # 'telephoneNumber' => ['214-972-1212','972-123-0987'],
1399             # },
1400             # replace => {
1401             # 'mail' => 'barbara.jensen@umich.edu',
1402             # },
1403             # delete => {
1404             # 'cn' => 'Barbs Jensen',
1405             # 'title' => '',
1406             # }
1407             # } } );
1408             #
1409             # $return = $dsml->send(); # Post the xml message to the DSML server
1410             # $content = $dsml->content(); # Get the data returned from the DSML server.
1411             #
1412             # Method output; Returns 1 (true) on success; 0 (false) on error, error
1413             # message can be gotten with error method.
1414             #
1415             # The user must parse the returned xml content message to determine what the
1416             # dsml server responded with.
1417             #
1418              
1419             sub modify
1420             {
1421 2     2 1 6 my ($dsml, $opt) = @_;
1422 2         6 my $id = ident $dsml;
1423 2         2 my $result;
1424             my @changes;
1425 0         0 my @action;
1426 0         0 my @attributes;
1427 0         0 my $dn;
1428 2         5 $errMsg{$id} = "";
1429              
1430 2 50       6 $dn = (ref($opt->{dn}) ? ${$opt->{dn}} : $opt->{dn});
  0         0  
1431 2 50       8 if ( !(length($dn)) )
1432             {
1433 0         0 $errMsg{$id} = "Subroutine modify dn value is not defined.";
1434 0         0 return 0;
1435             }
1436              
1437              
1438 2         3 @changes = sort(keys(%{$opt->{modify}}));
  2         12  
1439              
1440             #
1441             # build search xml message
1442             #
1443              
1444 2         5 $result = "
1445            
1446             # Load Process ID
1447            
1448 2 50       6 if ( $opt->{id} )
    0          
1449             {
1450 2 100       10 $result .= $reqID . (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id}) . "\"";
  1         5  
1451             }
1452             elsif ( $ops{$id}->{pid} )
1453             {
1454 0         0 $result .= $ops{$id}->{pid};
1455 0         0 delete($ops{$id}->{pid});
1456             }
1457             else
1458             {
1459 0         0 $result .= $reqID . $pid{$id}->{pid} . "\"";
1460 0         0 ++$pid{$id}->{pid};
1461             }
1462              
1463 2         6 $result .= " dn=\"" . $dn . "\">";
1464              
1465             #
1466             # Now add the attribute list as a xml string.
1467             #
1468              
1469 2         5 foreach my $action (@changes)
1470             {
1471              
1472 6         7 @action = sort(keys(%{$opt->{modify}{$action}}));
  6         56  
1473 6         11 foreach my $i ( @action)
1474             {
1475              
1476 6 100       17 if ( ref($opt->{modify}{$action}{$i}))
1477             {
1478 2 50       8 if (ref($opt->{modify}{$action}{$i}) eq 'SCALAR')
    0          
1479             {
1480 2 50       14 if ( !(length(${$opt->{modify}{$action}{$i}})))
  2         22  
1481             {
1482 0         0 $result .= "";
1483             }
1484             else
1485             {
1486 2         6 $result .= "${$opt->{modify}{$action}{$i}}";
  2         12  
1487             }
1488             }
1489             elsif (ref($opt->{modify}{$action}{$i}) eq 'ARRAY')
1490             {
1491 0         0 $result .= "";
1492 0         0 foreach my $val ( @{$opt->{modify}{$action}{$i}})
  0         0  
1493             {
1494 0 0       0 if ( length($val))
1495             {
1496 0         0 $result .= "$val";
1497             }
1498             }
1499 0         0 $result .= "";
1500            
1501             }
1502             else
1503             {
1504 0         0 $errMsg{$id} = "Invalid object in add subroutine modify hash.";
1505 0         0 return 0;
1506             }
1507             }
1508             else
1509             {
1510 4         12 $result .= "";
1511 4 50       12 if ( length($opt->{modify}{$action}{$i}))
1512             {
1513 4         10 $result .= "$opt->{modify}{$action}{$i}";
1514             }
1515 4         13 $result .= "";
1516             }
1517              
1518             }
1519             }
1520              
1521 2 50       7 $result .= $opt->{control} if ( defined($opt->{control}));
1522 2         3 $result .= "";
1523 2         3 push(@{$operations{$id}},$result);
  2         6  
1524 2         8 return 1;
1525              
1526             }
1527              
1528             #
1529             # Method abandon
1530             #
1531             # The method abandon request that the DSML server abandon the
1532             # batch request with the given ID.
1533             #
1534             # There is 1 required input option.
1535             # Input option "id": The id of the batch request to abandon.
1536             # This id may be referenced.
1537             #
1538             #
1539             # $result = $dsml->abandon( { id => $id } );
1540             #
1541             # $return = $dsml->send(); # Post the xml message to the DSML server
1542             # $content = $dsml->content(); # Get the data returned from the DSML server.
1543             #
1544             # Method output; Returns 1 (true) on success; 0 (false) on error, error
1545             # message can be gotten with error method.
1546             #
1547             # The user must parse the returned xml content message to determine what the
1548             # dsml server responded with.
1549             #
1550              
1551             sub abandon
1552             {
1553 0     0 1 0 my ($dsml, $opt) = @_;
1554 0         0 my $id = ident $dsml;
1555 0         0 my $result;
1556             my $aid;
1557 0         0 $errMsg{$id} = "";
1558              
1559 0 0       0 $aid = (ref($opt->{id}) ? ${$opt->{id}} : $opt->{id});
  0         0  
1560 0 0       0 if ( !$id )
1561             {
1562 0         0 $errMsg{$id} = "Method abandon id value is not defined.";
1563 0         0 return 0;
1564             }
1565              
1566 0         0 $result = "";
1567 0         0 $result .= "";
1568 0         0 push(@{$operations{$id}},$result);
  0         0  
1569 0         0 return 1;
1570              
1571             }
1572              
1573             #
1574             # This method is used mainly for debugging purposes.
1575             #
1576              
1577             sub getOperations
1578             {
1579 24     24 1 29 my ($dsml) = @_;
1580 24         100 my $id = ident $dsml;
1581 24         24 my $data;
1582              
1583 24         24 $data = "";
1584             #
1585             # load each operation into the xml string in order.
1586             #
1587 24         21 foreach my $str (@{$operations{$id}})
  24         51  
1588             {
1589 24         75 $data .= $str;
1590             }
1591            
1592 24         128 return $data;
1593             }
1594              
1595             # Method getPostData
1596             #
1597             # The method getPostData the xml data string that was posted to the
1598             # DSML server. It is used mainly for debugging problems.
1599             #
1600             # There are no required input options.
1601             #
1602             # $content = $dsml->getPostData();
1603             #
1604             # Method output; Always returns 1 (true).
1605             #
1606             # The user must parse the returned xml content message to determine what
1607             # was posted to the dsml server.
1608             #
1609              
1610             sub getPostData
1611             {
1612 2     2 1 12 my ($dsml) = @_;
1613 2         7 my $id = ident $dsml;
1614              
1615 2         18 return $postData{$id};
1616             }
1617              
1618             # Method send
1619             #
1620             # The method send sends the xml data string that was created to the
1621             # DSML server.
1622             #
1623             # There are no required input options.
1624             #
1625             # $result = $dsml->send();
1626             # $content = $dsml->content(); # Get the data returned from the DSML server.
1627             #
1628             # Method output; Returns 1 (true) on success; 0 (false) on error, error
1629             # message can be gotten with error method. This error code is from the
1630             # http process and NOT the DSML process
1631             #
1632             # The user must parse the returned xml content message to determine what
1633             # was recieved from the dsml server.
1634             #
1635              
1636             sub send
1637             {
1638 4     4 1 907 my ($dsml, $opt) = @_;
1639 4         9 my $id = ident $dsml;
1640 4         4 my $size;
1641              
1642 4         4 $size = @{$operations{$id}};
  4         10  
1643 4 50       9 if ( !$size )
1644             {
1645 0         0 $errMsg{$id} = "No XML query data string present.";
1646 0         0 return 0;
1647             }
1648              
1649             # start xml string
1650 4         28 $postData{$id} = $postHead . $preBatch . $ops{$id}->{reqid} . $ops{$id}->{onerror} . $ops{$id}->{responseOrder} . $ops{$id}->{processing} . ">";
1651            
1652 4 50       12 $postData{$id} .= $ops{$id}->{auth} if ( length($ops{$id}->{auth}));
1653              
1654             #
1655             # load each operation into the xml string in order.
1656             #
1657 4         4 foreach my $str (@{$operations{$id}})
  4         9  
1658             {
1659 4         19 $postData{$id} .= $str;
1660             }
1661            
1662             # terminate the xml string.
1663 4         11 $postData{$id} .= $postBatch . $postTail;
1664 4 50       10 if ( !defined($opt->{debug}))
1665             {
1666 0         0 return $dsml->_post(); # Send the data to the dsml server.
1667             }
1668             else
1669             {
1670 4         9 return 1;
1671             }
1672             }
1673              
1674             #
1675             # This version of the method post uses a XML string
1676             # that has been built prior to calling this method.
1677             #
1678             # true on success, false on error.
1679             # Use errMsg method to get error message.
1680             #
1681             sub _post
1682             {
1683 0     0     my $dsml = shift;
1684 0           my $id = ident $dsml;
1685              
1686 0 0         if (length($postData{$id}) == 0 )
1687             {
1688 0           $errMsg{$id} = "No XML query data string present.";
1689 0           return 0;
1690             }
1691              
1692 0           return $dsml->_postit();
1693             }
1694              
1695             #
1696             #
1697             # The private method postit executes the HTTP DSML request.
1698             #
1699             # true on success, false on error.
1700             # Use errMsg method to get error message.
1701             #
1702             sub _postit
1703             {
1704 0     0     my $dsml = shift;
1705 0           my $ua;
1706             my $headers;
1707 0           my $req;
1708 0           my $res;
1709 0           my $psize;
1710 0           my $host;
1711 0           my $dsmlinfo;
1712 0           my $postData;
1713 0           my $uriString;
1714 0           my $code;
1715              
1716 0           my $id = ident $dsml;
1717              
1718 0           $psize{$id} = length($postData{$id});
1719 0           $psize = length($postData{$id});
1720 0           $uriString = $ops{$id}->{host};
1721 0           $postData = $postData{$id};
1722 0           $prepostData{$id} = $postData; # Copy of actual postData
1723              
1724 0           $ua = new LWP::UserAgent;
1725 0           $ua->agent('DSML HTTP/1.1');
1726 0 0         print $postData if ( $ops{$id}->{debug} );
1727              
1728 0           $headers = HTTP::Headers->new( 'content-length' => $psize,
1729             'HOST' => $uriString,
1730             'SOAPAction' => "",
1731             'Content-Type' => "text/xml",
1732             'Connection' => "close");
1733              
1734 0 0         $headers->authorization_basic($authentication{$id}->{dn}, $authentication{$id}->{password} ) if ( $authentication{$id} );
1735             #
1736             # Create the request
1737             #
1738 0           $req = new HTTP::Request ('POST',$uriString, $headers);
1739 0           $req->content($postData);
1740 0           $res = $ua->request($req);
1741              
1742            
1743             #
1744             # Check the outcome of the response
1745             #
1746 0 0         if ($res->is_success)
1747             {
1748 0 0         print "Success\n" if ( $ops{$id}->{debug});
1749 0           $content{$id} = $res->content;
1750             }
1751             else
1752             {
1753 0 0         print "No Success\n" if ( $ops{$id}->{debug});
1754 0           $code = $res->status_line;
1755 0           $errMsg{$id} = "$code";
1756 0           return 0;
1757             }
1758              
1759 0 0         if (length($content{$id}) == 0 )
1760             {
1761             # print "No Success return\n";
1762 0           $errMsg{$id} = "Error, no response data received from " . $uriString . ".";
1763 0           return 0;
1764             }
1765 0           $errMsg{$id} = ""; # Clear the error message string.
1766 0           return 1; # Exit the method with no errors, does not mean we got data!
1767             }
1768              
1769             }
1770              
1771             1; # Magic true value required at end of module
1772              
1773             __END__