# FILE: webtags.pl
# DESCRIPTION: Discus Formatting Tags (to and from)
#-------------------------------------------------------------------------------
# DISCUS COPYRIGHT NOTICE
#
# Discus is copyright (c) 2002 by DiscusWare, LLC, all rights reserved.
# The use of Discus is governed by the Discus License Agreement which is
# available from the Discus WWW site at:
#    http://www.discusware.com/discus/license
#
# Pursuant to the Discus License Agreement, this copyright notice may not be
# removed or altered in any way.
#-------------------------------------------------------------------------------

use strict;
use vars qw($GLOBAL_OPTIONS $PARAMS $DCONF);

###
### webtags
###
### Takes input containing \b{formatting tags} and converts it into HTML code as
### normally used.
###

sub webtags {
	my ($text_in, $context_code, $situation, $is_moderator, $is_superuser, $topic_number, $force_refresh) = @_;
	return ("", $text_in) if ($GLOBAL_OPTIONS->{'allow_arb_html'} && $situation != 0);
	return ($text_in, $text_in) if ($GLOBAL_OPTIONS->{'allow_arb_html'} && $situation == 0);
	return ("", $text_in) if $text_in !~ /\S/ && $situation != 0;
	return ($text_in, $text_in) if $text_in !~ /\S/ && $situation == 0;
	my @u = ();
	$text_in =~ s/\r\n/\n/g; $text_in =~ s/\r/\n/g;
	while ($text_in =~ /(?:^|\n)\s*?\\\*\s*?\n(.*?)\n\s*?\*\\\s*?(?:\n|$)/s) {
		$text_in = $';
		push @u, $`;
		my $one = $1;
		$one =~ s/\\/\\\\/g;
		$one =~ s/\{/\\\{/g;
		$one =~ s/\}/\\\}/g;
		push @u, join("", "\n", $one, "\n");
	}
	push @u, $text_in if $text_in ne "";
	$text_in = char_convert(join("", @u));
	if ($text_in !~ m|\\(\S+)\{|) {
		return ("", $text_in) if $situation != 0;
		return ($text_in, $text_in) if $situation == 0;
	}
	my ($tags, $char) = read_tags($context_code, $is_moderator, $is_superuser, $topic_number, $force_refresh);
	my ($messages, $formatted) = parse("", $text_in, $tags, $char);
	undef my %flagged;
	if ($messages ne "!Error") {
		$formatted =~ s/\\/&#92;/g;
		while ($formatted =~ m|/(\w+)&#40;|g) {
			$messages .= "<LI><B>/$1(...)</B> " . read_language()->{COULDMEAN} . " <B>\\$1\{...\}</B><BR>\n" if ($tags->{$1} ne "" && $flagged{$1} == 0);
			$flagged{$1} = 1;
		}
		while ($formatted =~ m|\\(\w+)&#40;|g) {
			$messages .= "<LI><B>&#92;$1(...)</B> " . read_language()->{COULDMEAN} . " <B>\\$1\{...\}</B><BR>\n" if ($tags->{$1} ne "" && $flagged{$1} == 0);
			$flagged{$1} = 1;
		}
		while ($formatted =~ m|/(\w+)\{|g) {
			$messages .= "<LI><B>/$1\{...\}</B> " . read_language()->{COULDMEAN} . " <B>\\$1\{...\}</B><BR>\n" if ($tags->{$1} ne "" && $flagged{$1} == 0);
			$flagged{$1} = 1;
		}
		while ($formatted =~ m|/(\w+) \{|g) {
			$messages .= "<LI><B>/$1\{...\}</B> " . read_language()->{COULDMEAN} . " <B>\\$1\{...\}</B><BR>\n" if ($tags->{$1} ne "" && $flagged{$1} == 0);
			$flagged{$1} = 1;
		}
		while ($formatted =~ m|/(\w+) &#40;|g) {
			$messages .= "<LI><B>/$1\{...\}</B> " . read_language()->{COULDMEAN} . " <B>\\$1\{...\}</B><BR>\n" if ($tags->{$1} ne "" && $flagged{$1} == 0);
			$flagged{$1} = 1;
		}
		while ($formatted =~ m|\\(\w+) \{|g) {
			$messages .= "<LI><B>/$1\{...\}</B> " . read_language()->{COULDMEAN} . " <B>\\$1\{...\}</B><BR>\n" if ($tags->{$1} ne "" && $flagged{$1} == 0);
			$flagged{$1} = 1;
		}
		while ($formatted =~ m|\\(\w+) &#40;|g) {
			$messages .= "<LI><B>/$1\{...\}</B> " . read_language()->{COULDMEAN} . " <B>\\$1\{...\}</B><BR>\n" if ($tags->{$1} ne "" && $flagged{$1} == 0);
			$flagged{$1} = 1;
		}
	} else {
		$formatted = "<H3>" . read_language()->{FORMATTINGERROR} . "</H3>$formatted";
	}
	if ($situation == 0) {
		return ($formatted, $formatted);
	} else {
		return ($messages, $formatted);
	}
}

###
### inverse_webtags
###
### Takes perfect HTML, presumably generated by "webtags", and converts it
### to the formatting tags that would give that output.
###

sub inverse_webtags {
	my ($string, $topic_number, $escaped) = @_;
#	$string =~ s/<BR>/\n/gi;
	if ($string =~ /^[\w\s]*$/) {
		$string =~ s/<BR>/\n/gi;
		if ($escaped) {
			$string =~ s/&/&amp;/g;
			$string =~ s/</&lt;/g;
			$string =~ s/>/&gt;/g;
			$string =~ s/"/&quot;/g;
		}
		return $string;
	}
	my $tags = read_webtags_conf();
	my @taglist = keys(%{ $tags->{args} });
	my $restrict_tags = {
		mail => 1,
		newurl => 2,
		topurl => 3,
		link => 4,
		rgb => 5,
		font => 6,
		imagelink => 100,
	};
	my $transit_tags = {
		'table' => 1,
		'tablenb' => 2,
		'tablebg' => 2,
		'list' => 5,
		'olist' => 6,
	};
	my $restrict_chars = {
		'**br' => 1,
	};
	if (read_language()->{TABLE_TAG} ne "" && read_language()->{TABLE_TAG} ne "table") {
		$transit_tags->{read_language()->{TABLE_TAG}} = 3;
	}
	if (read_language()->{TABLE_NB_TAG} ne "" && read_language()->{TABLE_NB_TAG} ne "tablenb") {
		$transit_tags->{read_language()->{TABLE_NB_TAG}} = 4;
	}
	if (read_language()->{LIST_TAG} ne "" && read_language()->{LIST_TAG} ne "list") {
		$transit_tags->{read_language()->{LIST_TAG}} = 7;
	}
	if (read_language()->{OLIST_TAG} ne "" && read_language()->{OLIST_TAG} ne "olist") {
		$transit_tags->{read_language()->{OLIST_TAG}} = 8;
	}
	@taglist = sort {
			if ($tags->{cont}->{$b} =~ /c/i && $tags->{cont}->{$a} !~ /c/i) {
				return 1 if ! $restrict_chars->{$b};
			}
			if ($tags->{cont}->{$b} !~ /c/i && $tags->{cont}->{$a} =~ /c/i) {
				return -1 if ! $restrict_chars->{$a};
			}
			return -1 if $tags->{tags}->{$b}->[0]->{rexp} =~ /^\\<\w+\\>$/ && $tags->{tags}->{$a}->[0]->{rexp} !~ /^\\<\w+\\>$/;
			return  1 if $tags->{tags}->{$a}->[0]->{rexp} =~ /^\\<\w+\\>$/ && $tags->{tags}->{$b}->[0]->{rexp} !~ /^\\<\w+\\>$/;
			return -1 if $tags->{tags}->{$b}->[0]->{rexp} =~ /^\\&\w+\\;$/ && $tags->{tags}->{$a}->[0]->{rexp} !~ /^\\&\w+\\;$/;
			return  1 if $tags->{tags}->{$a}->[0]->{rexp} =~ /^\\&\w+\\;$/ && $tags->{tags}->{$b}->[0]->{rexp} !~ /^\\&\w+\\;$/;
			return -1 if $tags->{tags}->{$b}->[0]->{rexp} =~ /^\\&\\#\d+\\;$/ && $tags->{tags}->{$a}->[0]->{rexp} !~ /^\\&\\#\d+\\;$/;
			return  1 if $tags->{tags}->{$a}->[0]->{rexp} =~ /^\\&\\#\d+\\;$/ && $tags->{tags}->{$b}->[0]->{rexp} !~ /^\\&\\#\d+\\;$/;
			return  1 if $restrict_tags->{$a} > $restrict_tags->{$b};
			return -1 if $restrict_tags->{$a} < $restrict_tags->{$b};
			return  1 if $transit_tags->{$a} > $transit_tags->{$b};
			return -1 if $transit_tags->{$a} < $transit_tags->{$b};
			return  1 if $tags->{args}->{$a} < $tags->{args}->{$b};
			return -1 if $tags->{args}->{$a} > $tags->{args}->{$b};
			return  1 if length ($tags->{tags}->{$b}->[0]->{rexp}) > length ($tags->{tags}->{$a}->[0]->{rexp});
			return -1 if length ($tags->{tags}->{$b}->[0]->{rexp}) < length ($tags->{tags}->{$a}->[0]->{rexp});
			return  1 if $tags->{order}->{$a} < $tags->{order}->{$b};
			return -1 if $tags->{order}->{$a} > $tags->{order}->{$b};
			return $a cmp $b;
		} @taglist;
	my $did_charconvert = 0;
	while ($string =~ m%<!--?\*(\d+)-[-!]>.*<!--?\*\1:(.*?)-[-!]>%s) {
		$string = join("", $`, unescape($2), $');
	}
FT:	foreach my $tag (@taglist) {
		my @u = sort { length($b->{rexp}) <=> length($a->{rexp}) } @{ $tags->{tags}->{$tag} };
		if ($restrict_tags->{$tag} >= 100 && ! $did_charconvert) {
			$string =~ s/\\char\{(\d+)\}/&#$1;/g;
			$string = char_convert($string, 1);
			$string =~ s/&#(\d+);/\\char\{$1\}/g;
			$did_charconvert = 1;
		}
		my $xxflag = 0;
UI:		foreach my $u (@u) {
			next UI if $u->{rexp} !~ /\S/;
			my $STRING_HOLD = "";
WI:			while ($string =~ /$u->{rexp}/is) {
				my ($bef, $aft, $mat, $i) = find_inner($string, $u->{rexp});
				my @i = @{$i};
				if ($tags->{cont}->{$tag} =~ /c/i) {
					my $tag2 = $tag;
					$tag2 = $' if $tag =~ /^\*\*/;
					$string = join("", $bef, "\\ch\{$tag2\}", $aft);
				} else {
					if ($transit_tags->{$tag} > 0) {
						my $t = "\\$tag\{";
						my @t = (); my $ctr = 0;
						foreach my $k (keys(%{ $u->{lookup} })) {
							$t[$k-1] = $i[$u->{lookup}->{$k}->{num}-1] if ! $u->{lookup}->{$k}->{esc};
							$t[$k-1] = unescape($i[$u->{lookup}->{$k}->{num}-1]) if $u->{lookup}->{$k}->{esc};
						}
						$t[$#t] = transit($t[$#t], $transit_tags->{$tag});
						$t .= join(",", @t);
						$t .= "}";
						if ($t =~ /^([^<]*)>/) {
							$mat =~ /(.*?)>/;
							$string = join("", $', $aft);
							$STRING_HOLD = join("", $STRING_HOLD, $bef, $1, ">");
							next WI;
						}
						$string = join("", $bef, $t, $aft);
					} else {
						my $t = "\\$tag\{";
						my @t = (); my $ctr = 0;
						foreach my $k (keys(%{ $u->{lookup} })) {
							$t[$k-1] = $i[$u->{lookup}->{$k}->{num}-1] if ! $u->{lookup}->{$k}->{esc};
							$t[$k-1] = unescape($i[$u->{lookup}->{$k}->{num}-1]) if $u->{lookup}->{$k}->{esc};
						}
						$t .= join(",", @t);
						$t .= "}";
						if ($t =~ /^([^<]*)>/) {
							$mat =~ /(.*?)>/;
							$string = join("", $', $aft);
							$STRING_HOLD = join("", $STRING_HOLD, $bef, $1, ">");
							next WI;
						}
						$string = join("", $bef, $t, $aft);
					}
				}
			}
		$string = join("", $STRING_HOLD, $string);
		}
	}
	if (! $did_charconvert) {
		$string =~ s/\\char\{(\d+)\}/&#$1;/g;
		$string = char_convert($string, 1);
		$string =~ s/&#$1;/\\char\{$1\}/g;
	}
	if ($escaped) {
		$string =~ s/&/&amp;/g;
		$string =~ s/</&lt;/g;
		$string =~ s/>/&gt;/g;
		$string =~ s/"/&quot;/g;
	}
	return $string;
}

sub find_inner {
	my ($string, $rexp) = @_;
	my $rexpnew = $rexp;
	$rexpnew =~ s/\\(\d+)/join("", "\\", 2+$1)/ge;
	$string =~ /(.*)($rexpnew)/is;
	my $bef = join("", $`, $1);
	my $str = $2;
	my $aft = $';

	my @i = $str =~ /$rexp/is;
	$bef .= $`; $aft = join("", $', $aft);
	my $mat = $&;

	return ($bef, $aft, $mat, \@i);
}

###
### read_webtags_conf
###
### Reads the configuration file for the formatting tags for the purposes of
### doing inverse conversion of tags.
###

sub read_webtags_conf {
	my ($forcerefresh) = @_;
	return \%{ $PARAMS->{webtags_inverse} } if ! $forcerefresh && defined $PARAMS->{webtags_inverse};
	my $wt = readfile("$DCONF->{admin_dir}/webtags.conf", "read_webtags_conf", { no_lock => 1, no_unlock => 1 });
	my @wt = @{ $wt };
	@wt = grep(/\S/, @wt);
	@wt = grep(!/^\s*#/, @wt);
	my $buf = "";
	my $tags = undef;
	my $order = 0;
	foreach my $line (@wt) {
		$line =~ s/^\s+//; $line =~ s/\s+$//;
		if ($line =~ /\\\s*$/) {
			$buf .= $` . ' ';
			next;
		} else {
			my $j = join("", $buf, $line);
			$buf = ""; $order++;
			my ($context, $tag, $definition) = split(/\s+/, $j, 3);
			next if $context =~ /^\*/;
			chomp $definition;
			my @u = ();
			my @v = ();
			while ($definition =~ /\|(\d+)\|/) {
				my ($bef, $mat, $aft) = ($`, $1, $');
				if ($bef =~ /\!esc\($/ && $aft =~ /^\)\!/) {
					push @v, { num => $mat, esc => 1 };
					$bef =~ /\!esc\($/; push @u, $`;
					$aft =~ /^\)\!/; $definition = $';
				} else {
					push @v, { num => $mat, esc => 0 };
					push @u, $bef;
					$definition = $aft;
				}
			}
			push @u, $definition;
			my $rexp = ""; my $ctr = 0;
			my $taken = {};
			if (scalar(@v)) {
				while (scalar(@u) + scalar(@v)) {
					my $U = quotemeta(shift @u);
					my $V = shift @v;
					while ($U =~ m|\\!VAR\\\((\w+)\\\)\\!|i) {
						$U = join("", $`, $PARAMS->{$1}, $') if defined $PARAMS->{$1};
						$U = join("", $`, $DCONF->{$1}, $') if defined $DCONF->{$1};
						$U = join("", $`, ".*?", $') if !(defined($PARAMS->{$1}) || defined($DCONF->{$1}));
					}
					$rexp .= $U;
					next if $V->{num} == 0;
					if ($taken->{$V->{num}}->{num}) {
						$V->{esc} = $taken->{$V->{num}}->{esc};
#						$rexp .= '.*?';
						$rexp .= $V->{esc} ? '.*?' : "\\$taken->{$V->{num}}->{num}";
					} else {
						$ctr++;
						$taken->{$V->{num}}->{num} = $ctr;
						$taken->{$V->{num}}->{esc} = $V->{esc};
						$rexp .= $V->{esc} ? '([\w\%\+]*?)' : "(.*?)";
					}
				}
			} else {
				$rexp = quotemeta($definition);
			}
			$rexp =~ s/\\\s/\\s\*/g;
			$tag = "**$tag" if $context eq 'c';
			push @{ $tags->{tags}->{$tag} }, { rexp => $rexp, lookup => $taken };
			$tags->{args}->{$tag} = $ctr;
			$tags->{cont}->{$tag} = $context;
			$tags->{order}->{$tag} = $order;
		}
	}
	$PARAMS->{webtags_inverse} = $tags;
	return $tags;
}

###
### read_tags
###
### Reads formatting tags for the purpose of the "webtags" subroutine
###

sub read_tags {
	my ($cont_code, $is_moderator, $is_superuser, $topic_number, $force_refresh) = @_;
	undef my %char;
	undef my %tags;
	undef my $cont;
	undef my $code;
	undef my $act;
	my $noactive = {};
	my $wtc = defined $PARAMS->{webtags_conf} ? $PARAMS->{webtags_conf} : readfile("$DCONF->{admin_dir}/webtags.conf", "read_tags", { no_lock => 1, no_unlock => 1 });
	$PARAMS->{webtags_conf} = $wtc;
	my @wtc = @{ $wtc };
	my $evaltag;
	my $str = "";
	foreach $_ (@wtc) {
		next if /^#/ || ! /\S/;
		$_ = join("", $str, $_);
		$_ = trim($_);
		if (($evaltag, $cont, $code, $act) = m|^(\*?)([cC0-9sSmM]\*?)\s*(\S+)\s*(.*)|) {
			if ($act =~ m|\\$|) { $str .= join("", $evaltag, $cont, " ", $code, " ", $`); next; }
			$str = "";
			$code = char_convert(lc($code));
			$cont = $` if $cont =~ /\*$/;
			if ($cont =~ m|^[cC]|) {
				$char{$code} = $act;
			} elsif ($cont > $cont_code || (($is_moderator || $is_superuser) && $cont != 1) || ($is_moderator && $cont =~ m|^[mM]|) || ($is_superuser && $cont =~ m|^[sS]|)) {
				next if ($cont == 1 && $GLOBAL_OPTIONS->{'images'} == 0 && $GLOBAL_OPTIONS->{'options_used'} == 1);
				next if $code eq "attach" && !$DCONF->{pro};
				next if ($cont =~ m|^[mM]| && !$is_moderator);
				next if ($cont =~ m|^[sS]| && !$is_superuser);
				my $str_ = $act;
				while ($str_ =~ m|!VAR\((\w+)\)!|i) {
					$str_ = join("", $`, $PARAMS->{$1}, $') if defined $PARAMS->{$1};
					$str_ = join("", $`, $DCONF->{$1}, $') if defined $DCONF->{$1};
					$str_ = join("", $`, $') if !(defined($PARAMS->{$1}) || defined($DCONF->{$1}));
					$str_ = join("", $`, $topic_number, $') if $1 eq "topic_number" && $topic_number != 0;
				}
				$tags{$code} = join("", $evaltag ? "\r" : "", $str_);
			}
		} else {
			$str = "";
		}
	}
	$PARAMS->{webtags_tags} = \%tags;
	$PARAMS->{webtags_chars} = \%char;
	return ($PARAMS->{webtags_tags}, $PARAMS->{webtags_chars});
}

###
### transit
###
### Transforms special tags, like tables and lists, with their special formatting
### properties.
###

sub transit {
	my ($string, $type) = @_;
	if ($type <= 4) {
		if ($string =~ /[^\\],/) {
			$string =~ s%</TD><TD>%\t%gi;
		} else {
			$string =~ s%</TD><TD>%,%gi;
		}
		$string =~ s%\s?</TD></TR><TR><TD>%\n%gi;
	} elsif ($type >= 5) {
		$string =~ s%\s?<LI>%\n%gi;
	}
	return $string;
}

###
### parse
###
### Internal parser for incoming formatting tags
###

sub parse {
	my ($messages, $text_in, $tags, $char) = @_;
	return ("!Error", $text_in) if $messages eq "!Error";
	my ($v1, $v2, $v3, $v4, $v5, $v6, $v7, $match);
	while ($text_in =~ m|\\([^\{\s]*)\{|) {
		($v1, $v2, $v3, $match) = ($`, case_lower($1), $', $&);
		($v4, $v3) = &parse($messages, $v3, $tags, $char);
		return ($v4, $v3) if $v4 eq "!Error";
		$messages .= $v4;
		if ($v3 =~ m|^([^\}]*)\}|) {
			($v6, $v7) = ($1, $');
		} else {
			my $ncb = read_language()->{NOCLOSINGBRACE};
			$ncb =~ s/\%code/$v2/g;
			return ("!Error", "$ncb");
		}
		$v2 = case_lower($v2);
		if ($v2 eq "ch" && $char->{lc($v6)} ne "") {
			$text_in = join("", $v1, $char->{lc($v6)}, $v7);
		} elsif ($v2 eq "ch") {
			my $sc = read_language()->{NOSPECIALCHARACTER};
			$sc =~ s/\%char/$v6/g;
			return ("!Error", "$sc");
		} elsif (defined($tags->{$v2})) {
			my $temp = $tags->{$v2};
			my $maxtest = 0;
			if ($temp =~ m%\|(\d+)\|%) {
				while ($temp =~ m%\|(\d+)\|%g) {
					$maxtest = $1 if $1 > $maxtest;
				}
			}
			my @splits = ();
			@splits = split(/,/, $v6, $maxtest) if $maxtest > 0;
			my $sc = scalar(@splits);
			if ($sc < $maxtest) {
				my $wnarg = read_language()->{WRONGNUMBEROFARGUMENTS};
				$wnarg =~ s/\%code/$v2/g;
				$wnarg =~ s/\%required/$maxtest/g;
				$wnarg =~ s/\%your/$sc/g;
				return ("!Error", "$wnarg");
			}
			if ($temp =~ /^\r/) {
				$temp = $';
				$PARAMS->{specialwebtags}++;
				my $tagone = $GLOBAL_OPTIONS->{special2_in_subjects} ? "" : "-";
				my $tagtwo = $GLOBAL_OPTIONS->{special2_in_subjects} ? "!" : "-";
				if ($temp =~ /^&(\w+)\s*\((.*?)\)/) {
					my ($subname, $inner) = ($1, $2);
					my @args = ();
					my @spl = split(/,/, $inner);
					foreach my $inner (@spl) {
						my $text = "";
						while ($inner =~ m%\|(\d+)\|%) {
							$text .= join("", $`, $splits[($1)-1]);
							$inner = $';
						}
						push @args, join("", $text, $inner);
					}
					dreq("webtags2");
					$temp = join("", "<!-$tagone*$PARAMS->{specialwebtags}-$tagtwo>", &{ \&{$subname} }(@args), "<!-$tagone/*$PARAMS->{specialwebtags}-$tagtwo>");
					$temp .= join("", "<!-$tagone*$PARAMS->{specialwebtags}:", escape(join("", $match, $v6, "}")), "-$tagtwo>");
				} else {
					while ($temp =~ m%!esc\(\|(\d+)\|\)\!%) {
						$temp = join("", $`, escape($splits[($1)-1]), $');
					}
					while ($temp =~ m%\|(\d+)\|%) {
						$temp = join("", $`, $splits[($1)-1], $');
					}
					$temp = join($temp, "<!-$tagone*$PARAMS->{specialwebtags}-$tagtwo>", "<!-$tagone/*$PARAMS->{specialwebtags}-$tagtwo>");
					$temp .= join("", "<!-$tagone*$PARAMS->{specialwebtags}:", escape(join("", $match, $v6, "}")), "-$tagtwo>");
				}
				$text_in = join("", $v1, $temp, $v7);
			} else {
				if ($v2 eq "link" || $v2 eq "topurl" || $v2 eq "newurl") {
					if ($GLOBAL_OPTIONS->{'smart_rfc_2141'}) {
						my $arg = join("", @splits);
						if ($arg =~ m%^(.*/[\d\,]+\.\w+),((?:.|\n)*?)$%) {
							$splits[0] = $1;
							$splits[1] = $2;
							$splits[0] =~ s/,/\%2C/g;
						}
					}
					$splits[0] =~ s/\&#44;/\%2C/g;
#					$splits[0] =~ s/\&#43;/\%2B/g;
					$splits[0] =~ s/\&#43;/\+/g;
					$splits[0] =~ s/\&#39;/\%27/g;
					$splits[0] =~ s/ /\%20/g;
					if ($splits[0] =~ m|[<>]| || $splits[0] =~ m|^\s*javascript:|i) {
						my $f = read_language()->{NONESTHTML};
						$f =~ s/\%code/$v2/g;
						return ("!Error", $f);
					}
				}
				if ($v2 =~ m%^pop(attach|gif|jpeg|png)% || $v2 eq "attach" || $v2 eq read_language()->{ATTACH_TAG_NAME} || $v2 eq "image" || $v2 eq read_language()->{IMAGE_TAG_NAME}) {
					if ($splits[0] =~ m|[<>]|) {
						my $f = read_language()->{NONESTHTML};
						$f =~ s/\%code/$v2/g;
						return ("!Error", $f);
					}
#					$splits[0] =~ s/(^|[^\\]),/$1\\,/g;
#					$splits[0] =~ s/,//g;
				}
				while ($temp =~ m%!esc\(\|(\d+)\|\)\!%) {
					$temp = join("", $`, escape($splits[($1)-1]), $');
				}
				while ($temp =~ m%\|(\d+)\|%) {
					$temp = join("", $`, $splits[($1)-1], $');
				}
				if ($v2 =~ m|^table| || $v2 eq read_language()->{TABLE_TAG} || $v2 eq read_language()->{TABLE_NB_TAG}) {
					if ($temp =~ m|\t|) {
						$temp =~ s%\t%</TD><TD>%g;
					} else {
						$temp =~ s%,%</TD><TD>%g;
					}
					$temp =~ s%<BR>%</TD></TR><TR><TD>%g;
				} elsif ($v2 eq "list" || $v2 eq read_language()->{LIST_TAG} || $v2 eq "olist" || read_language()->{OLIST_TAG} eq $v2) {
					$temp =~ s%<BR>%<LI>%g;
				}
				$text_in = join("", $v1, $temp, $v7);
			}
		} else {
			my $sc = read_language()->{CODEDOESNOTEXIST};
			$sc =~ s/\%code/$v2/g;
			if ($v2 eq "attach" && !$DCONF->{pro}) {
				$sc .= "<P>" . read_language()->{FEATURE_NOT_SUPPORTED_DESCR} . "\n";
			}
			return ("!Error", "$sc");
		}
	}
	return ($messages, $text_in);
}

1;
