shell bypass 403
##############################################################################
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Library General Public License for more details.
#
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
# Jabber
# Copyright (C) 1998-2004 Jabber Software Foundation http://jabber.org/
#
##############################################################################
package XML::Stream::XPath::Query;
use 5.008;
use strict;
use warnings;
use Carp;
use vars qw( $VERSION );
$VERSION = "1.24";
sub new
{
my $proto = shift;
my $self = { };
bless($self,$proto);
$self->{TOKENS} = [ '/','[',']','@','"',"'",'=','!','(',')',':',' ',','];
$self->{QUERY} = shift;
if (!defined($self->{QUERY}) || ($self->{QUERY} eq ""))
{
confess("No query string specified");
}
$self->parseQuery();
return $self;
}
sub getNextToken
{
my $self = shift;
my $pos = shift;
my @toks = grep{ $_ eq substr($self->{QUERY},$$pos,1)} @{$self->{TOKENS}};
while( $#toks == -1 )
{
$$pos++;
if ($$pos > length($self->{QUERY}))
{
$$pos = length($self->{QUERY});
return 0;
}
@toks = grep{ $_ eq substr($self->{QUERY},$$pos,1)} @{$self->{TOKENS}};
}
return $toks[0];
}
sub getNextIdentifier
{
my $self = shift;
my $pos = shift;
my $sp = $$pos;
$self->getNextToken($pos);
return substr($self->{QUERY},$sp,$$pos-$sp);
}
sub getOp
{
my $self = shift;
my $pos = shift;
my $in_context = shift;
$in_context = 0 unless defined($in_context);
my $ret_op;
my $loop = 1;
while( $loop )
{
my $pos_start = $$pos;
my $token = $self->getNextToken($pos);
if (($token eq "0") && $in_context)
{
return;
}
my $token_start = ++$$pos;
my $ident;
if (defined($token))
{
if ($pos_start != ($token_start-1))
{
$$pos = $pos_start;
my $temp_ident = $self->getNextIdentifier($pos);
$ret_op = XML::Stream::XPath::NodeOp->new($temp_ident,"0");
}
elsif ($token eq "/")
{
if (substr($self->{QUERY},$token_start,1) eq "/")
{
$$pos++;
my $temp_ident = $self->getNextIdentifier($pos);
$ret_op = XML::Stream::XPath::AllOp->new($temp_ident);
}
else
{
my $temp_ident = $self->getNextIdentifier($pos);
if ($temp_ident ne "")
{
$ret_op = XML::Stream::XPath::NodeOp->new($temp_ident,($pos_start == 0 ? "1" : "0"));
}
}
}
elsif ($token eq "\@")
{
$ret_op = XML::Stream::XPath::AttributeOp->new($self->getNextIdentifier($pos));
}
elsif ($token eq "]")
{
if ($in_context eq "[")
{
$ret_op = pop(@{$self->{OPS}});
$in_context = 0;
}
else
{
confess("Found ']' but not in context");
return;
}
}
elsif (($token eq "\"") || ($token eq "\'"))
{
$$pos = index($self->{QUERY},$token,$token_start);
$ret_op = XML::Stream::XPath::Op->new("LITERAL",substr($self->{QUERY},$token_start,$$pos-$token_start));
$$pos++;
}
elsif ($token eq " ")
{
$ident = $self->getNextIdentifier($pos);
if ($ident eq "and")
{
$$pos++;
my $tmp_op = $self->getOp($pos,$in_context);
if (!defined($tmp_op))
{
confess("Invalid 'and' operation");
return;
}
$ret_op = XML::Stream::XPath::AndOp->new($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
$in_context = 0;
pop(@{$self->{OPS}});
}
elsif ($ident eq "or")
{
$$pos++;
my $tmp_op = $self->getOp($pos,$in_context);
if (!defined($tmp_op))
{
confess("Invalid 'or' operation");
return;
}
$ret_op = XML::Stream::XPath::OrOp->new($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
$in_context = 0;
pop(@{$self->{OPS}});
}
}
elsif ($token eq "[")
{
if ($self->getNextToken($pos) eq "]")
{
if ($$pos == $token_start)
{
confess("Nothing in the []");
return;
}
$$pos = $token_start;
my $val = $self->getNextIdentifier($pos);
if ($val =~ /^\d+$/)
{
$ret_op = XML::Stream::XPath::PositionOp->new($val);
$$pos++;
}
else
{
$$pos = $pos_start + 1;
$ret_op = XML::Stream::XPath::ContextOp->new($self->getOp($pos,$token));
}
}
else
{
$$pos = $pos_start + 1;
$ret_op = XML::Stream::XPath::ContextOp->new($self->getOp($pos,$token));
}
}
elsif ($token eq "(")
{
#-------------------------------------------------------------
# The function name would have been mistaken for a NodeOp.
# Pop it off the back and get the function name.
#-------------------------------------------------------------
my $op = pop(@{$self->{OPS}});
if ($op->getType() ne "NODE")
{
confess("No function name specified.");
}
my $function = $op->getValue();
if (!exists($XML::Stream::XPath::FUNCTIONS{$function}))
{
confess("Undefined function \"$function\"");
}
$ret_op = XML::Stream::XPath::FunctionOp->new($function);
my $op_pos = $#{$self->{OPS}} + 1;
$self->getOp($pos,$token);
foreach my $arg ($op_pos..$#{$self->{OPS}})
{
$ret_op->addArg($self->{OPS}->[$arg]);
}
splice(@{$self->{OPS}},$op_pos);
}
elsif ($token eq ")")
{
if ($in_context eq "(")
{
$ret_op = undef;
$in_context = 0;
}
else
{
confess("Found ')' but not in context");
}
}
elsif ($token eq ",")
{
if ($in_context ne "(")
{
confess("Found ',' but not in a function");
}
}
elsif ($token eq "=")
{
my $tmp_op;
while(!defined($tmp_op))
{
$tmp_op = $self->getOp($pos);
}
$ret_op = XML::Stream::XPath::EqualOp->new($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
pop(@{$self->{OPS}});
}
elsif ($token eq "!")
{
if (substr($self->{QUERY},$token_start,1) ne "=")
{
confess("Badly formed !=");
}
$$pos++;
my $tmp_op;
while(!defined($tmp_op))
{
$tmp_op = $self->getOp($pos);
}
$ret_op = XML::Stream::XPath::NotEqualOp->new($self->{OPS}->[$#{$self->{OPS}}],$tmp_op);
pop(@{$self->{OPS}});
}
else
{
confess("Unhandled \"$token\"");
}
if ($in_context)
{
if (defined($ret_op))
{
push(@{$self->{OPS}},$ret_op);
}
$ret_op = undef;
}
}
else
{
confess("Token undefined");
}
$loop = 0 unless $in_context;
}
return $ret_op;
}
sub parseQuery
{
my $self = shift;
my $query = shift;
my $op;
my $pos = 0;
while($pos < length($self->{QUERY}))
{
$op = $self->getOp(\$pos);
if (defined($op))
{
push(@{$self->{OPS}},$op);
}
}
#foreach my $op (@{$self->{OPS}})
#{
# $op->display();
#}
return 1;
}
sub execute
{
my $self = shift;
my $root = shift;
my $ctxt = XML::Stream::XPath::Value->new($root);
foreach my $op (@{$self->{OPS}})
{
if (!$op->isValid(\$ctxt))
{
$ctxt->setValid(0);
return $ctxt;
}
}
$ctxt->setValid(1);
return $ctxt;
}
sub check
{
my $self = shift;
my $root = shift;
my $ctxt = $self->execute($root);
return $ctxt->check();
}
1;