1 # bsta_lib.pm is generated from bsta_lib.1.pm
5 # Copyright (C) 2016, 2017, 2019, 2020, 2022, 2023 Balthasar Szczepański
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
27 use constant entitycode => {
282 use constant tagsbb => {
289 'ni' => '[color=#0057AF]',
291 'br' => '[color=#BB6622]',
293 'po' => '[color=#FF8800]',
304 '/list' => '[/list]',
308 '/?' => '[/unknown!]',
310 use constant tagsht => {
313 'fq' => '<div class="fq">',
315 'tq' => '<div class="tq">',
317 'ni' => '<span class="ni">',
319 'br' => '<span class="br">',
321 'po' => '<span class="po">',
323 'url' => '<a href="#">',#think: how to add selfincluding?
324 'url=' => '<a href="',
330 'list=' => '<ol style="list-style-type: ',
331 'list=1' => 'decimal',
332 'list=A' => 'upper-alpha',
333 'list=a' => 'lower-alpha',
334 'list=I' => 'upper-roman',
335 'list=i' => 'lower-roman',
342 '/?' => '[/unknown!]',
345 ###PERL_EXPORT_VERSION: our $VERSION = 'x.x.x';
346 our @ISA = qw(Exporter);
348 our @EXPORT_OK = qw(entityencode failpage gethttpheader getcgi urldecode readdatafile writedatafile printdatafile printdatafileht urlencode linehtml bb2ht bb2bb);
349 our %EXPORT_TAGS = ();
351 # Function to show an error page
352 # arguments: 1 - header fields, 2 - page title, 3 - error message, 4 method
354 (my $header, my $title, my $message, my $method)=@_;
358 if($method eq 'HEAD') {
362 print "Content-type: text/html\n\n";
363 print '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "">'."\n";
364 print '<html lang="en"><head>'."\n";
366 print '<title>'.entityencode($title).'</title>'."\n";
368 print '<meta http-equiv="Content-type" content="text/html; charset=UTF-8">'."\n";
369 print '</head><body>'."\n";
371 print '<h1>'.entityencode($title).'</h1>'."\n";
374 print '<p>'.entityencode($message).'</p>'."\n";
376 print '</body></html>'."\n";
379 # function to encode entities, decimal,
381 (my $t, my $all) = @_;
383 $t =~ s/(.)/sprintf('\&#%02hu;',ord($1))/eg;
386 $t =~ s/([\"=><\&])/sprintf('&#%02hu;',ord($1))/eg;
391 # function to get values of http header fields. Returns a hash. names of header
392 # fields are lowercase
398 foreach my $ind (keys %$env) {
402 if ($ind =~ /^HTTP_([A-Z0-9_]+)$/) {
405 elsif ($ind =~ /^(CONTENT_[A-Z0-9_]+)$/) {
413 if ($$env{$ind} =~ /^([\x20-\x7e]*)$/) {
424 # The function to get CGI parameters from string.
425 # Format is: name=url_encoded_value&name=url_encoded_value& ... &name=url_encoded_value
432 my @s = split('&',$i);
433 foreach my $l ( @s) {
434 ($arg,$val)=split('=',$l);
435 $cgi{$arg}=urldecode($val);
440 # Function for decoding URL-encoded text
444 $t =~ s/%([a-fA-F0-9]{2})/chr(hex($1))/eg;
448 # Function to read data from datafiles.
449 # Very similar to http header file reading. (function readheaderfile() in proxy
454 # 1. After field name and colon there must be exactly one whitespace (space or
455 # tab). Any other leading or trailing whitespace (but not the newline character
456 # at the end of the line) is treated as part of the field value.
458 # 2. Instead of colon an equal sign can be used. The number of whitespaces after
459 # it is then zero and not one.
461 # 3. When header field is split into multiple lines the next lines must start
462 # with exactly one whitespace (tab or space) Any other leading or trailing
463 # whitespace (but not the newline character at the end of the line) is treated
464 # as part of the field value. the lines will be joined with a newline between
467 # 4. When the same field name appears it replaces the previous one.
469 # 5. Line separator is LF and not CR LF. The CR character is treated as part of
472 # 6. After the end of header (double newline) all next lines are treated as the
473 # value of the "content" field.
475 # Returns a hash containing the values.
476 # Names are case sensitive and are converted to lowercase
478 # Argument can be a path or a file handle. In case of a file handle it will just
479 # read the file. In case of path it opens the file before reading and closes
480 # after. On failure (file not open) returns empty hash.
488 # check if $datapath is actually a path or maybe a filehandle
489 # filehandles are references.
492 unless (seek($datafile, 0, 0)) {
497 unless (open ($datafile, "<", $datapath)) {
502 # The name of header field in previous line. Required for header fields that
503 # occupy multiple lines.
506 while (defined(my $line = <$datafile>)) {
512 $data{'content'} = $data{'content'}.$line;
519 # Empty line - end of header.
523 # Line starts with whitespace. It's a continuation of the previous line.
524 # Concatenate the field value, separated by newline.
525 elsif($line =~ /^[ \t](.*)$/){
526 if($lastname ne '') {
527 $data{$lastname}.="\n".$1;
530 # Line starts with a name followed by colon/equal sign. Save the value
531 elsif ($line =~ /^([^:=]+)((:[ \t])|=)(.*)$/) {
541 # If argument was a path the file must be closed.
542 unless (ref($datapath)) {
549 # the function to write data to datafiles (see readdatafile() description)
551 # First argument can be a path or a file handle. In case of a file handle it
552 # will just write the file. In case of path it opens the file before writing and
555 # On failure (file not open) returns 0.
556 # On success returns 1.
559 (my $headerpath, my %header) = @_;
562 if(ref($headerpath)) {
563 $headerfile=$headerpath;
564 unless (seek($headerfile, 0, 0)) {
569 unless (open ($headerfile, ">", $headerpath)) {
574 foreach my $ind (keys %header) {
575 unless($ind eq 'content') {
577 my $headval = $header{$ind};
579 $headval =~ s/\n/\n /g;
580 print $headerfile "$headname: $headval\n";
583 print $headerfile "\n".$header{'content'};
585 unless (ref($headerpath)) {
589 truncate ($headerfile , tell($headerfile));
595 # the function to print data to stdout (see readdatafile() description)
597 # On success returns 1.
602 foreach my $ind (keys %header) {
603 unless($ind eq 'content') {
605 my $headval = $header{$ind};
607 $headval =~ s/\n/\n /g;
608 print "$headname: $headval\n";
611 print "\n".$header{'content'};
616 # the function to print data to stdout as html (see readdatafile() description)
618 # On success returns 1.
620 sub printdatafileht {
623 foreach my $ind (keys %header) {
624 unless($ind eq 'content') {
626 my $headval = $header{$ind};
628 $headval =~ s/\n/\n /g;
629 print linehtml("$headname: $headval\n");
632 print linehtml("\n".$header{'content'});
639 (my $t, my $all) = @_;
641 $t =~ s/(.)/sprintf('%%%02hX',ord($1))/eg;
644 $t =~ s/([^0-9A-Za-z.~\-_])/sprintf('%%%02hX',ord($1))/eg;
649 #analyse bbcode text to build tag tree #TODO make [/*] optional!
651 (my $bb, my $printdebug) = @_;
669 $debug .= debug($printdebug, "\n<!--GENERATING BBCODE TREE:\n".'[_]automatic tag: [ht]'."\n");
672 if($bb =~ m/(\[(\/?)([a-z]+|\*)(=([^\[\]]*))?\])/g) {
677 $pretext = substr($bb,0,pos ($bb)-length($tag));
678 $bb = substr ($bb,pos ($bb));
680 if ($pretext ne '') {
681 $debug .= debug($printdebug, '['.$ind.'.'.$bbtree{$ind.'.e'}.']text: '.$pretext."\n");
682 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.t'}='tx';
683 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.v'}=$pretext;
684 $bbtree{$ind.'.e'} += 1;
687 if($tagname =~ /^(fq|tq|br|ni|po|url|i|list|\*)$/) {
689 if(($tagname ne $bbtree{$ind.'.n'}) || ($level <= 0)) {
690 $debug .= debug($printdebug, '['.$ind.'.'.$bbtree{$ind.'.e'}.']text: '.$tag."\n");
691 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.t'}='tx';
692 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.v'}=$tag;
693 $bbtree{$ind.'.e'} += 1;
696 $debug .= debug($printdebug, '['.$ind.'.'.$bbtree{$ind.'.e'}.']tag: '.$tag."\n");
697 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.t'}='tg';
698 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.n'}='/'.$tagname;
699 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.v'}=$tagvalue;
700 $bbtree{$ind.'.e'} += 1;
701 $bbtree{$ind.'.c'}=1;
703 $ind =~ s/\.[0-9]+$//;
708 $debug .= debug($printdebug, '['.$ind.'.'.$bbtree{$ind.'.e'}.']tag: '.$tag."\n");
709 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.t'}='tg';
710 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.n'}=$tagname;
711 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.v'}=$tagvalue;
712 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.e'}=0;
713 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.c'}='';
714 $bbtree{$ind.'.e'} += 1;
716 $ind = $ind.'.'.($bbtree{$ind.'.e'}-1);
720 $debug .= debug($printdebug, '['.$ind.'.'.$bbtree{$ind.'.e'}.']text: '.$tag."\n");
721 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.t'}='tx';
722 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.v'}=$tag;
723 $bbtree{$ind.'.e'} += 1;
727 $debug .= debug($printdebug, '['.$ind.'.'.$bbtree{$ind.'.e'}.']text: '.$bb."\n");
728 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.t'}='tx';
729 $bbtree{$ind.'.'.$bbtree{$ind.'.e'}.'.v'}=$bb;
730 $bbtree{$ind.'.e'} += 1;
734 $debug .= debug($printdebug, '[_.'.$bbtree{'_.e'}.']automatic tag: [/ht]'."\n -->\n");
735 $bbtree{'_.'.$bbtree{"_.e"}.'.t'}="tg";
736 $bbtree{'_.'.$bbtree{"_.e"}.'.n'}='/ht';
740 return ($debug, %bbtree);
743 #convert tag tree to final text
745 (my $printdebug, my $debug, my $lang, my %bbtree) = @_;
750 my $tagsr = ($lang eq 'html') ? tagsht : tagsbb;
752 my $escape = ($lang eq 'html');
754 # $debug .= debug($printdebug, "\n****\n");
755 # foreach my $iiii (keys %tags) {
756 # $debug .= debug($printdebug, $iiii.'='.$tags{$iiii}."\n");
758 # $debug .= debug($printdebug, "****\n");
763 $debug .= debug($printdebug, "\n<!--PROCESSING BBCODE TREE:\n");
766 $debug .= debug($printdebug, "[$level:$ind:".int($bbtree{$ind.'.e'})."]");
768 if($bbtree{$ind.'.t'} eq 'tx') {
769 $debug .= debug($printdebug, "text: ".$bbtree{$ind.'.v'});
770 $ht = $ht.($escape?(linehtml($bbtree{$ind.'.v'})):($bbtree{$ind.'.v'}));
773 $ind =~ s/\.([0-9]+)$//;
775 if ($indd < $bbtree{$ind.'.e'}){
776 $ind = $ind.'.'.$indd;
780 #should not occur with a correct bbtree
781 $debug .= debug($printdebug, "[<tx]");
784 } while ($level>=0);}
787 elsif($bbtree{$ind.'.t'} eq 'tg') {
789 if($bbtree{$ind.'.n'} =~ /^\//) {
790 $debug .= debug($printdebug, "tag: [".$bbtree{$ind.'.n'}."]");
792 $indd =~ s/\.([0-9]+)$//;
793 if (exists($tags{$bbtree{$ind.'.n'}.'='}) && ($bbtree{$indd.'.v'} ne '')) {
794 $ht = $ht.$tags{$bbtree{$ind.'.n'}.'='};
796 elsif (exists($tags{$bbtree{$ind.'.n'}})) {
797 $ht = $ht.$tags{$bbtree{$ind.'.n'}};
800 $ht = $ht.$tags{'/?'};
801 $debug .= debug($printdebug, "[unknown!]");
804 $ind =~ s/\.([0-9]+)$//;
806 $debug .= debug($printdebug, "[<]");
809 $ind =~ s/\.([0-9]+)$//;
811 if ($indd < $bbtree{$ind.'.e'}){
812 $ind = $ind.'.'.$indd;
816 #should not occur with a correct bbtree
817 $debug .= debug($printdebug, "[<nd]");
820 } while ($level>=0);}
829 if($bbtree{$ind.'.c'} ne '') {
830 $debug .= debug($printdebug, "tag: [".$bbtree{$ind.'.n'}."]");
832 if (exists($tags{$bbtree{$ind.'.n'}.'='}) && ($bbtree{$ind.'.v'} ne '')) {
833 if (exists($tags{$bbtree{$ind.'.n'}.'='.$bbtree{$ind.'.v'}})) {
834 $ht = $ht.$tags{$bbtree{$ind.'.n'}.'='}.$tags{$bbtree{$ind.'.n'}.'='.$bbtree{$ind.'.v'}}.$tags{$bbtree{$ind.'.n'}.'/='};
837 $ht = $ht.$tags{$bbtree{$ind.'.n'}.'='}.($escape?entityencode($bbtree{$ind.'.v'}):$bbtree{$ind.'.v'}).$tags{$bbtree{$ind.'.n'}.'/='};
840 elsif (exists($tags{$bbtree{$ind.'.n'}})) {
841 $ht = $ht.$tags{$bbtree{$ind.'.n'}};
844 $ht = $ht.$tags{'?'};
845 $debug .= debug($printdebug, "[unknown!]");
849 $debug .= debug($printdebug, "unclosed tag: [".$bbtree{$ind.'.n'}."]");
850 $ht = $ht.'['.($escape?linehtml($bbtree{$ind.'.n'}):$bbtree{$ind.'.n'}).']';
852 if($bbtree{$ind.'.e'}>0) {
855 $debug .= debug($printdebug, "[>]");
859 $ind =~ s/\.([0-9]+)$//;
861 if ($indd < $bbtree{$ind.'.e'}){
862 $ind = $ind.'.'.$indd;
866 #should not occur with a correct bbtree
867 $debug .= debug($printdebug, "[<st]");
870 } while ($level>=0);}
876 $debug .= debug($printdebug, "unknown thing: ".$bbtree{$ind.'.t'});
877 #should not occur with a correct bbtree
878 #unless unimplemented
879 $ind =~ s/\.([0-9]+)$//;
881 $debug .= debug($printdebug, "[<ui]");
884 $ind =~ s/\.([0-9]+)$//;
886 if ($indd < $bbtree{$ind.'.e'}){
887 $ind = $ind.'.'.$indd;
891 #should not occur with a correct bbtree
892 $debug .= debug($printdebug, "[<un]");
895 } while ($level>=0);}
902 $debug .= debug($printdebug, "[>$level:$ind]\n");
905 $debug .= debug($printdebug, "-->\n");
906 return ($debug, $ht);
911 (my $bb, my $printdebug) = @_;
916 ($debug, %bbtree) = bbtree($bb,$printdebug);
917 ($debug, $ht) = convtree ($printdebug, $debug, 'html', %bbtree);
924 # $debug .= debug($printdebug, "\n<!--PROCESSING BBCODE TREE:\n");
926 # while ($level >=0) {
927 # $debug .= debug($printdebug, "[$level:$ind:".int($bbtree{$ind.'.e'})."]");
928 # if($bbtree{$ind.'.t'} eq 'tx') {
929 # $debug .= debug($printdebug, "text: ".$bbtree{$ind.'.v'});
930 # $ht = $ht.linehtml($bbtree{$ind.'.v'});
933 # $ind =~ s/\.([0-9]+)$//;
935 # if ($indd < $bbtree{$ind.'.e'}){
936 # $ind = $ind.'.'.$indd;
940 # #should not occur with a correct bbtree
941 # $debug .= debug($printdebug, "[<tx]");
944 # } while ($level>=0);}
946 # elsif($bbtree{$ind.'.t'} eq 'tg') {
947 # if($bbtree{$ind.'.n'} =~ /^\//) {
948 # $debug .= debug($printdebug, "tag: [".$bbtree{$ind.'.n'}."]");
949 # if($bbtree{$ind.'.n'} eq '/ht') {
952 # elsif ($bbtree{$ind.'.n'} =~ /^\/(fq|tq)$/) {
953 # $ht = $ht.'</div>';
955 # elsif ($bbtree{$ind.'.n'} =~ /^\/(br|ni|po)$/) {
956 # $ht = $ht.'</span>';
958 # elsif ($bbtree{$ind.'.n'} eq '/url') {
961 # elsif ($bbtree{$ind.'.n'} eq '/i') {
965 # $ht = $ht.'['.linehtml($bbtree{$ind.'.n'}).']';
966 # $debug .= debug($printdebug, "[unknown!]");
968 # $ind =~ s/\.([0-9]+)$//;
970 # $debug .= debug($printdebug, "[<]");
973 # $ind =~ s/\.([0-9]+)$//;
975 # if ($indd < $bbtree{$ind.'.e'}){
976 # $ind = $ind.'.'.$indd;
980 # #should not occur with a correct bbtree
981 # $debug .= debug($printdebug, "[<nd]");
984 # } while ($level>=0);}
992 # if($bbtree{$ind.'.c'} ne '') {
993 # if($bbtree{$ind.'.n'} eq 'ht') {
996 # elsif($bbtree{$ind.'.n'} eq 'fq') {
997 # $ht = $ht.'<div class="fq">';
999 # elsif($bbtree{$ind.'.n'} eq 'tq') {
1000 # $ht = $ht.'<div class="tq">';
1002 # elsif($bbtree{$ind.'.n'} eq 'br') {
1003 # $ht = $ht.'<span class="br">';
1005 # elsif($bbtree{$ind.'.n'} eq 'ni') {
1006 # $ht = $ht.'<span class="ni">';
1008 # elsif($bbtree{$ind.'.n'} eq 'po') {
1009 # $ht = $ht.'<span class="po">';
1011 # elsif($bbtree{$ind.'.n'} eq 'i') {
1014 # elsif($bbtree{$ind.'.n'} eq 'url') {
1015 # $ht = $ht.'<a href="'.entityencode($bbtree{$ind.'.v'}).'">';
1018 # $ht = $ht.'['.linehtml($bbtree{$ind.'.n'}).(($bbtree{$ind.'.v'} ne '' )?entityencode($bbtree{$ind.'.v'}):'').']';
1019 # $debug .= debug($printdebug, "[unknown!]");
1023 # $debug .= debug($printdebug, "unclosed tag: [".$bbtree{$ind.'.n'}."]");
1024 # $ht = $ht.'['.linehtml($bbtree{$ind.'.n'}).']';
1026 # if($bbtree{$ind.'.e'}>0) {
1029 # $debug .= debug($printdebug, "[>]");
1033 # $ind =~ s/\.([0-9]+)$//;
1034 # $indd = int($1)+1;
1035 # if ($indd < $bbtree{$ind.'.e'}){
1036 # $ind = $ind.'.'.$indd;
1040 # #should not occur with a correct bbtree
1041 # $debug .= debug($printdebug, "[<st]");
1044 # } while ($level>=0);}
1049 # $debug .= debug($printdebug, "unknown thing: ".$bbtree{$ind.'.t'});
1050 # #should not occur with a correct bbtree
1051 # #unless unimplemented
1052 # $ind =~ s/\.([0-9]+)$//;
1054 # $debug .= debug($printdebug, "[<ui]");
1057 # $ind =~ s/\.([0-9]+)$//;
1058 # $indd = int($1)+1;
1059 # if ($indd < $bbtree{$ind.'.e'}){
1060 # $ind = $ind.'.'.$indd;
1064 # #should not occur with a correct bbtree
1065 # $debug .= debug($printdebug, "[<un]");
1068 # } while ($level>=0);}
1071 # # time to end this
1075 # $debug .= debug($printdebug, "[>$level:$ind]\n");
1078 # $debug .= debug($printdebug, "-->\n");
1087 (my $bb, my $printdebug) = @_;
1092 ($debug, %bbtree) = bbtree($bb,$printdebug);
1093 ($debug, $ht) = convtree ($printdebug, $debug, 'bb', %bbtree);
1100 # $debug .= debug($printdebug, "\n<!--PROCESSING BBCODE TREE:\n");
1102 # while ($level >=0) {
1103 # $debug .= debug($printdebug, "[$level:$ind:".int($bbtree{$ind.'.e'})."]");
1104 # if($bbtree{$ind.'.t'} eq 'tx') {
1105 # $debug .= debug($printdebug, "text: ".$bbtree{$ind.'.v'});
1106 # $ht = $ht.$bbtree{$ind.'.v'};
1109 # $ind =~ s/\.([0-9]+)$//;
1110 # $indd = int($1)+1;
1111 # if ($indd < $bbtree{$ind.'.e'}){
1112 # $ind = $ind.'.'.$indd;
1116 # #should not occur with a correct bbtree
1117 # $debug .= debug($printdebug, "[<tx]");
1120 # } while ($level>=0);}
1122 # elsif($bbtree{$ind.'.t'} eq 'tg') {
1123 # if($bbtree{$ind.'.n'} =~ /^\//) {
1124 # $debug .= debug($printdebug, "tag: [".$bbtree{$ind.'.n'}."]");
1125 # if($bbtree{$ind.'.n'} eq '/ht') {
1128 # elsif ($bbtree{$ind.'.n'} =~ /^\/(fq|tq)$/) {
1129 # $ht = $ht.'[/quote]';
1131 # elsif ($bbtree{$ind.'.n'} =~ /^\/(br|ni|po)$/) {
1132 # $ht = $ht.'[/color]';
1134 # elsif ($bbtree{$ind.'.n'} eq '/url') {
1135 # $ht = $ht.'[/url]';
1137 # elsif ($bbtree{$ind.'.n'} eq '/i') {
1141 # $ht = $ht.'['.$bbtree{$ind.'.n'}.']';
1142 # $debug .= debug($printdebug, "[unknown!]");
1144 # $ind =~ s/\.([0-9]+)$//;
1146 # $debug .= debug($printdebug, "[<]");
1149 # $ind =~ s/\.([0-9]+)$//;
1150 # $indd = int($1)+1;
1151 # if ($indd < $bbtree{$ind.'.e'}){
1152 # $ind = $ind.'.'.$indd;
1156 # #should not occur with a correct bbtree
1157 # $debug .= debug($printdebug, "[<nd]");
1160 # } while ($level>=0);}
1163 # # time to end this
1168 # if($bbtree{$ind.'.c'} ne '') {
1169 # $debug .= debug($printdebug, "tag: [".$bbtree{$ind.'.n'}."]");
1170 # if($bbtree{$ind.'.n'} eq 'ht') {
1173 # elsif($bbtree{$ind.'.n'} =~ /^(fq|tq)$/) {
1174 # $ht = $ht.'[quote]';
1176 # elsif($bbtree{$ind.'.n'} eq 'br') {
1177 # $ht = $ht.'[color=#BB6622]';
1179 # elsif($bbtree{$ind.'.n'} eq 'po') {
1180 # $ht = $ht.'[color=#FF8800]';
1182 # elsif($bbtree{$ind.'.n'} eq 'ni') {
1183 # $ht = $ht.'[color=#0057AF]';
1185 # elsif($bbtree{$ind.'.n'} eq 'url') {
1186 # $ht = $ht.'[url='.$bbtree{$ind.'.v'}.']';
1188 # elsif($bbtree{$ind.'.n'} eq 'i') {
1192 # $ht = $ht.'['.$bbtree{$ind.'.n'}.(($bbtree{$ind.'.v'} ne '' )?($bbtree{$ind.'.v'}):'').']';
1193 # $debug .= debug($printdebug, "[unknown!]");
1197 # $debug .= debug($printdebug, "unclosed tag: [".$bbtree{$ind.'.n'}."]");
1198 # $ht = $ht.'['.$bbtree{$ind.'.n'}.']';
1200 # if($bbtree{$ind.'.e'}>0) {
1203 # $debug .= debug($printdebug, "[>]");
1207 # $ind =~ s/\.([0-9]+)$//;
1208 # $indd = int($1)+1;
1209 # if ($indd < $bbtree{$ind.'.e'}){
1210 # $ind = $ind.'.'.$indd;
1214 # #should not occur with a correct bbtree
1215 # $debug .= debug($printdebug, "[<st]");
1218 # } while ($level>=0);}
1223 # $debug .= debug($printdebug, "unknown thing: ".$bbtree{$ind.'.t'});
1224 # #should not occur with a correct bbtree
1225 # #unless unimplemented
1226 # $ind =~ s/\.([0-9]+)$//;
1228 # $debug .= debug($printdebug, "[<ui]");
1231 # $ind =~ s/\.([0-9]+)$//;
1232 # $indd = int($1)+1;
1233 # if ($indd < $bbtree{$ind.'.e'}){
1234 # $ind = $ind.'.'.$indd;
1238 # #should not occur with a correct bbtree
1239 # $debug .= debug($printdebug, "[<un]");
1242 # } while ($level>=0);}
1245 # # time to end this
1249 # $debug .= debug($printdebug, "[>$level:$ind]\n");
1252 # $debug .= debug($printdebug, "-->\n");
1268 $ind = index($ht,"\n");
1270 $esc = $esc.entityencode(substr($ht,0,$ind))."<br>\n";
1271 $ht=substr($ht,$ind+1);
1275 $esc = $esc.entityencode($ht);
1283 (my $print, my $text) = @_;