8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libbsm / auditxml.pm
blob01589bcf5dbf8577f312177be8bb06de8af20690
2 # CDDL HEADER START
4 # The contents of this file are subject to the terms of the
5 # Common Development and Distribution License (the "License").
6 # You may not use this file except in compliance with the License.
8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 # or http://www.opensolaris.org/os/licensing.
10 # See the License for the specific language governing permissions
11 # and limitations under the License.
13 # When distributing Covered Code, include this CDDL HEADER in each
14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 # If applicable, add the following below this CDDL HEADER, with the
16 # fields enclosed by brackets "[]" replaced with your own identifying
17 # information: Portions Copyright [yyyy] [name of copyright owner]
19 # CDDL HEADER END
22 # Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 # Use is subject to license terms.
25 # ident "%Z%%M% %I% %E% SMI"
28 use xmlHandlers;
30 package externalEvent;
34 sub new {
35 my $pkg = shift;
36 my $id = shift;
37 my $obj = shift;
39 my @kid = $obj->getKids(); # kids of event are entry or allowed_types
41 # separate kids into classes and create hash of entries and an
42 # array of includes
44 my %entry = ();
45 my @entry = ();
46 my @allowed_types = ();
47 my @include = ();
48 my $internalName = '';
50 my $kid;
51 foreach $kid (@kid) {
52 my $class = $kid->getClass();
53 my $kidId = $kid->getAttr('id');
55 if ($class eq 'entry') {
56 my $tokenId = 'undefined';
57 my $format = '';
58 my $internal = $kid->getKid('internal');
59 if (defined $internal) {
60 $tokenId = $internal->getAttr('token');
61 $format = $internal->getAttr('format');
62 $format = '' unless defined $format;
64 my $comment;
65 my $commentKid = $kid->getKid('comment');
66 if (defined $commentKid) {
67 $comment = $commentKid->getContent;
69 my $external = $kid->getKid('external');
70 if (defined ($external)) {
71 $entry{$kidId} = [$external, $kid, $tokenId, $format, $comment];
72 push (@entry, $kidId);
74 else {
75 print STDERR "no external attributes defined for $id/$kidId\n";
77 } # handle event id translation...
78 elsif ($class eq 'altname') {
79 $internalName = $kid->getAttr('id');
80 unless (defined $internalName) {
81 print STDERR "missing id for internal name of $id\n";
82 $internalName = 'error';
85 elsif ($class eq 'allowed_types') {
86 my $content = $kid->getContent();
87 @allowed_types = (@allowed_types, split(/\s*,\s*/, $content));
90 my @entryCopy = @entry;
91 return bless {'id' => $id,
92 'internalName' => $internalName,
93 'allowed_types' => \@allowed_types,
94 'entry' => \%entry,
95 'entryList' => \@entry,
96 'entryListCopy' => \@entryCopy,
97 'include' => \@include,
98 'xmlObj' => $obj}, $pkg;
101 # return id
103 sub getExternalName {
104 my $pkg = shift;
106 return $pkg->{'id'};
110 # return internal name if it exists, else id
112 sub getInternalName {
113 $pkg = shift;
115 if ($pkg->{'internalName'}) {
116 return $pkg->{'internalName'};
118 else {
119 return $pkg->{'id'};
123 # getNextEntry reads from 'entryList' destructively
124 # but resets when the list after the list is emptied
126 sub getNextEntry {
127 my $pkg = shift;
129 unless (@{$pkg->{'entryList'}}) {
130 @{$pkg->{'entryList'}} = @{$pkg->{'entryListCopy'}};
131 return undef;
133 my $id = shift @{$pkg->{'entryList'}};
135 return ($pkg->getEntry($id)); # getEntry returns an array
138 # getEntryIds returns list of all ids from entryList
140 sub getEntryIds {
141 my $pkg = shift;
142 return (@{$pkg->{'entryList'}});
145 # getEntry returns a selected entry for the current event
147 sub getEntry {
148 my $pkg = shift;
149 my $id = shift; #entry id
151 my $ref = $pkg->{'entry'};
152 my $array = $$ref{$id};
154 return @$array;
157 # getNextInclude reads from 'include' destructively
159 sub getNextInclude {
160 my $pkg = shift;
162 return shift @{$pkg->{'include'}};
165 # getIncludes returns list of 'include'
167 sub getIncludes {
168 my $pkg = shift;
169 return @{$pkg->{'include'}};
172 # return a reference to the list of event id's allowed for
173 # this generic event
175 sub getAllowedTypes {
176 my $pkg = shift;
178 return $pkg->{'allowed_types'};
181 package internalEvent;
185 sub new {
186 my $pkg = shift;
187 my $id = shift;
188 my $obj = shift;
190 my @kid = $obj->getKids(); # kids of event are entry
192 my @entry = ();
194 my $reorder = 0;
195 if ($reorder = $obj->getAttr('reorder')) {
196 $reorder = 1 if $reorder eq 'yes';
198 my $kid;
199 foreach $kid (@kid) {
200 my $class = $kid->getClass();
201 my $id = $kid->getAttr('id');
203 if ($class eq 'entry') {
204 my $internal = $kid->getKid('internal');
205 if (defined ($internal)) {
206 push (@entry, [$internal, $kid]);
208 else {
209 print STDERR "no internal attributes defined for $id\n";
213 return bless {'id' => $id,
214 'reorder' => $reorder,
215 'entry' => \@entry,
216 'xmlObj' => $obj}, $pkg;
219 # getEntries returns a list of all entry references
221 sub getEntries {
222 my $pkg = shift;
224 return undef unless @{$pkg->{'entry'}};
226 return @{$pkg->{'entry'}};
229 sub isReorder {
230 my $pkg = shift;
232 return $pkg->{'reorder'};
235 sub getId {
236 my $pkg = shift;
238 return $pkg->{'id'};
241 package eventDef;
243 %uniqueId = ();
247 sub new {
248 my $pkg = shift;
249 my $id = shift;
250 my $obj = shift;
251 my $super = shift;
253 my $omit;
254 my $type;
255 my $header;
256 my $idNo;
257 my $javaToo;
258 my $title = '';
259 my @program = ();
260 my @see = ();
262 $omit = '' unless $omit = $obj->getAttr('omit');
263 $type = '' unless $type = $obj->getAttr('type');
264 $header = 0 unless $header = $obj->getAttr('header');
265 $idNo = '' unless $idNo = $obj->getAttr('idNo');
267 if ($idNo ne '' && $uniqueId{$idNo}) {
268 print STDERR "$uniqueId{$idNo} and $id have the same id ($idNo)\n";
270 else {
271 $uniqueId{$idNo} = $id;
274 return bless {'id' => $id,
275 'header' => $header,
276 'idNo' => $idNo,
277 'omit' => $omit,
278 'super' => $super,
279 'type' => $type,
280 'title' => $title,
281 'program' => \@program,
282 'see' => \@see,
283 'external' => 0,
284 'internal' => 0}, $pkg;
287 # putDef is called at the end of an <event></event> block, so
288 # it sees a completed object.
290 sub putDef {
291 my $pkg = shift;
292 my $obj = shift; # ref to xmlHandlers event object
293 my $context = shift;
295 my $id = $pkg->{'id'};
297 if ($context eq 'internal') {
298 $pkg->{$context} = new internalEvent($id, $obj);
299 return undef;
300 } elsif ($context eq 'external') {
301 my $ref = $pkg->{$context} = new externalEvent($id, $obj);
302 return $ref->{'internalName'};
306 sub getId {
307 my $pkg = shift;
309 return $pkg->{'id'};
312 sub getHeader {
313 my $pkg = shift;
315 return $pkg->{'header'};
318 sub getIdNo {
319 my $pkg = shift;
321 return $pkg->{'idNo'};
324 sub getSuperClass {
325 my $pkg = shift;
327 return $pkg->{'super'};
330 sub getOmit {
331 my $pkg = shift;
333 return $pkg->{'omit'};
336 sub getType {
337 my $pkg = shift;
339 return $pkg->{'type'};
342 sub getTitle {
343 return shift->{'title'};
346 sub getProgram {
347 return shift->{'program'};
350 sub getSee {
351 return shift->{'see'};
354 sub getInternal {
355 my $pkg = shift;
357 return $pkg->{'internal'};
360 sub getExternal {
361 my $pkg = shift;
363 return $pkg->{'external'};
366 # this isn't fully implemented; just a skeleton
368 package tokenDef;
372 sub new {
373 my $pkg = shift;
374 my $obj = shift;
375 my $id = shift;
377 $usage = $obj->getAttr('usage');
378 $usage = '' unless defined $usage;
380 return bless {'id' => $id,
381 'usage' => $usage
382 }, $pkg;
385 sub getId {
386 my $pkg = shift;
388 return $pkg->{'id'};
391 sub getUsage {
392 my $pkg = shift;
394 return $pkg->{'usage'};
397 package messageList;
401 sub new {
402 my $pkg = shift;
403 my $obj = shift;
404 my $id = shift;
405 my $header = shift;
406 my $start = shift;
407 my $public = shift;
408 my $deprecated = shift;
410 my @msg = ();
412 my @kid = $obj->getKids(); # kids of msg_list are msg
413 my $kid;
414 foreach $kid (@kid) {
415 my $class = $kid->getClass();
416 if ($class eq 'msg') {
417 my $text = $kid->getContent();
418 $text = '' unless defined ($text);
419 my $msgId = $kid->getAttr('id');
420 if (defined ($msgId)) {
421 push(@msg, join('::', $msgId, $text));
423 else {
424 print STDERR "missing id for $class <msg>\n";
427 else {
428 print STDERR "invalid tag in <msg_list> block: $class\n";
432 return bless {'id' => $id,
433 'header' => $header,
434 'msg' => \@msg,
435 'start' => $start,
436 'public' => $public,
437 'deprecated' => $deprecated
438 }, $pkg;
441 sub getId {
442 my $pkg = shift;
444 return $pkg->{'id'};
447 sub getMsgStart {
448 my $pkg = shift;
450 return $pkg->{'start'};
453 sub getDeprecated {
454 my $pkg = shift;
456 return $pkg->{'deprecated'};
459 sub getMsgPublic {
460 my $pkg = shift;
462 return $pkg->{'public'};
465 sub getHeader {
466 my $pkg = shift;
468 return $pkg->{'header'};
471 # destructive read of @msg...
473 sub getNextMsg {
474 my $pkg = shift;
476 my @msg = @{$pkg->{'msg'}};
478 return undef unless @msg;
480 my $text = pop(@msg);
481 $pkg->{'msg'} = \@msg;
482 return $text;
485 # returns all msgs
486 sub getMsgs {
487 my $pkg = shift;
489 return @{$pkg->{'msg'}};
493 package auditxml;
495 # These aren't internal state because the callback functions don't
496 # have the object handle.
498 @debug = (); # stack for nesting debug state
499 %event = (); # event name => $objRef
500 @event = (); # event id
501 %token = (); # token name => $objRef
502 @token = (); # token id
503 %msg_list = (); # messageList string list id to obj
504 @msg_list = (); # id list
505 %service = (); # valid service names
506 %externalToInternal = (); # map external event name to internal event name
510 sub new {
511 my $pkg = shift;
512 my $file = shift; # xml file to be parsed
514 register('event', \&eventStart, \&eventEnd);
515 register('entry', 0, \&entry);
516 register('external', 0, \&external);
517 register('internal', 0, \&internal);
518 register('include', 0, \&include);
519 register('token', 0, \&token);
520 register('service', 0, \&service);
521 register('msg_list', 0, \&msg_list);
522 register('msg', 0, \&msg);
524 # do not use register() for debug because register generates extra
525 # debug information
527 xmlHandlers::registerStartCallback('debug', \&debugStart);
528 xmlHandlers::registerEndCallback('debug', \&debugEnd);
530 $xml = new xmlHandlers(0, 'top level', $file);
532 return bless {'xmlObj' => $xml,
533 'firstToken' => 1,
534 'firstEvent' => 1}, $pkg;
537 # local function -- register both the auditxml function and the
538 # xmlHandler callback
540 sub register {
541 my $localName = shift;
542 my $startFunction = shift;
543 my $endFunction = shift;
545 if ($startFunction) {
546 xmlHandlers::registerStartCallback($localName, \&completed);
547 $startFunction{$localName} = $startFunction;
549 if ($endFunction) {
550 xmlHandlers::registerEndCallback($localName, \&completed);
551 $endFunction{$localName} = $endFunction;
555 sub completed {
556 my $obj = shift;
557 my $callbackSource = shift;
559 my $id = $obj->getAttr('id');
560 my $class = $obj->getClass();
562 if ($main::debug) {
563 print "*** $callbackSource: $class", (defined ($id)) ? "= $id\n" : "\n";
565 my %attributes = $obj->getAttributes();
566 my $attribute;
567 foreach $attribute (keys %attributes) {
568 print "*** $attribute = $attributes{$attribute}\n";
570 my $content = $obj->getContent();
571 print "*** content = $content\n" if defined $content;
573 if ($callbackSource eq 'start') {
574 &{$startFunction{$class}}($obj);
576 elsif ($callbackSource eq 'end') {
577 &{$endFunction{$class}}($obj);
579 else {
580 print STDERR "no auditxml function defined for $class\n";
584 # getNextEvent reads from @event destructively. 'firstEvent' could
585 # be used to make a copy from which to read.
587 sub getNextEvent {
588 my $pkg = shift;
590 return undef unless (@event);
591 if ($pkg->{'firstEvent'}) {
592 @token = sort @token;
593 $pkg->{'firstEvent'} = 1;
596 my $id = shift @event;
598 return $event{$id};
601 # returns all event ids
602 sub getEventIds {
603 my $pkg = shift;
605 return @event;
608 # returns event for id
609 sub getEvent {
610 my $pkg = shift;
611 my $id = shift;
613 return $event{$id};
616 sub getToken {
617 my $pkg = shift;
618 my $id = shift;
620 return $token{$id};
623 # getNextToken reads from @token destructively. 'firstToken' could
624 # be used to make a copy from which to read.
626 sub getNextToken {
627 my $pkg = shift;
629 return undef unless (@token);
631 if ($pkg->{'firstToken'}) {
632 @token = sort @token;
633 $pkg->{'firstToken'} = 1;
635 my $id = shift @token;
637 return $token{$id};
640 # return token Ids
642 sub getTokenIds {
643 my $pkg = shift;
645 return @token;
648 # getNextMsgId reads from @msg_list destructively.
650 sub getNextMsgId {
651 my $pkg = shift;
653 return undef unless (@msg_list);
655 my $id = shift @msg_list;
657 return ($id, $msg_list{$id});
660 sub getMsgIds {
661 my $pkg = shift;
663 return @msg_list;
666 sub getMsg {
667 my $pkg = shift;
668 my $id = shift;
670 return $msg_list{$id};
673 sub external {
676 sub internal {
680 sub eventStart {
681 my $obj = shift;
683 my $id = $obj->getAttr('id');
685 unless ($id) {
686 print STDERR "eventStart can't get a valid id\n";
687 return;
689 unless (defined $event{$id}) {
690 my $super;
691 if ($super = $obj->getAttr('instance_of')) {
692 $super = $event{$super};
693 } else {
694 $super = 0;
696 $event{$id} = new eventDef($id, $obj, $super);
697 push (@event, $id);
698 } else {
699 print STDERR "duplicate event id: $id\n";
703 sub eventEnd {
704 my $obj = shift;
706 my $id = $obj->getAttr('id');
707 unless (defined $id) {
708 print STDERR "event element is missing required id attribute\n";
709 return;
711 print "event = $id\n" if $main::debug;
713 foreach my $kid ($obj->getKids) {
714 my $class = $kid->getClass;
715 next unless ($class =~ /title|program|see/);
716 my $content = $kid->getContent;
717 if ($class eq 'title') {
718 $event{$id}->{$class} = $content;
719 } else {
720 push @{$event{$id}->{$class}}, $content;
723 $event{$id}->putDef($obj, 'internal');
725 my $internalName = $event{$id}->putDef($obj, 'external');
727 $externalToInternal{$id} = $internalName if $internalName;
730 # class method
732 #sub getInternalName {
733 # my $name = shift;
735 # return $externalToInternal{$name};
738 sub entry {
741 #sub include {
742 # my $obj = shift;
744 # my $id = $obj->getAttr('id');
746 # if (defined $id) {
747 # print "include = $id\n" if $main::debug;
749 # else {
750 # print STDERR "include element is missing required id attribute\n";
754 sub token {
755 my $obj = shift;
757 my $id = $obj->getAttr('id');
759 if (defined $id) {
760 print "token = $id\n" if $main::debug;
761 $token{$id} = new tokenDef($obj, $id);
762 push (@token, $id);
764 else {
765 print STDERR "token element is missing required id attribute\n";
769 sub msg_list {
770 my $obj = shift;
772 my $id = $obj->getAttr('id');
773 my $header = $obj->getAttr('header');
774 my $start = $obj->getAttr('start');
775 my $public = $obj->getAttr('public');
776 my $deprecated = $obj->getAttr('deprecated');
778 $header = 0 unless $header;
779 $start = 0 unless $start;
780 $public = ($public) ? 1 : 0;
781 $deprecated = ($deprecated) ? 1 : 0;
783 if (defined $id) {
784 print "msg_list = $id\n" if $main::debug;
785 $msg_list{$id} = new messageList($obj, $id, $header, $start,
786 $public, $deprecated);
787 push (@msg_list, $id);
789 else {
790 print STDERR
791 "msg_list element is missing required id attribute\n";
795 sub msg {
796 # my $obj = shift;
799 # Service name was dropped during PSARC review
801 sub service {
802 my $obj = shift;
804 my $name = $obj->getAttr('name');
805 my $id = $obj->getAttr('id');
807 if ((defined $id) && (defined $name)) {
808 print "service $name = $id\n" if $main::debug;
809 $service{$name} = $id;
811 elsif (defined $name) {
812 print STDERR "service $name is missing an id number\n";
814 elsif (defined $id) {
815 print STDERR "service name missing for id = $id\n";
817 else {
818 print STDERR "missing both name and id for a service entry\n";
822 #sub getServices {
824 # return %service;
827 # <debug set="on"> or <debug set="off"> or <debug>
828 # if the set attribute is omitted, debug state is toggled
830 # debugStart / debugEnd are used to insure debug state is
831 # scoped to the block between <debug> and </debug>
833 sub debugStart {
834 my $obj = shift;
836 push (@debug, $main::debug);
837 my $debug = $main::debug;
839 my $state = $obj->getAttr('set');
841 if (defined $state) {
842 $main::debug = ($state eq 'on') ? 1 : 0;
844 else {
845 $main::debug = !$debug;
847 if ($debug != $main::debug) {
848 print 'debug is ', $main::debug ? 'on' : 'off', "\n";
852 sub debugEnd {
853 my $obj = shift;
855 my $debug = $main::debug;
856 $main::debug = pop (@debug);
858 if ($debug != $main::debug) {
859 print 'debug is ', $main::debug ? 'on' : 'off', "\n";