lemonldap-ng/modules/lemonldap-ng-manager/lib/Lemonldap/NG/Manager/Uploader.pm

319 lines
10 KiB
Perl
Raw Normal View History

2009-12-17 20:20:17 +01:00
## @file
# Test uploaded parameters and store new configuration
## @class
# Test uploaded parameters and store new configuration
2009-12-11 19:17:00 +01:00
package Lemonldap::NG::Manager::Uploader;
use strict;
use XML::LibXML;
use XML::LibXSLT;
use MIME::Base64;
# TODO
use Data::Dumper;
2009-12-17 20:20:17 +01:00
use Lemonldap::NG::Common::Safelib; #link protected safe Safe object
use Lemonldap::NG::Manager::Downloader; #inherits
use Lemonldap::NG::Manager::_Struct; #link protected struct _Struct object
use Lemonldap::NG::Manager::_i18n;
use Lemonldap::NG::Common::Conf::Constants; #inherits
2009-12-11 19:17:00 +01:00
our $VERSION = '0.1';
our ( $stylesheet, $parser );
2009-12-17 20:20:17 +01:00
## @method void confUpload(ref rdata)
# Parse rdata to find parameters using XSLT, test them and tries to store the
# new configuration
# @param $rdata pointer to posted datas
2009-12-11 19:17:00 +01:00
sub confUpload {
my ( $self, $rdata ) = @_;
$$rdata =~ s/<img.*?>//g;
$$rdata =~ s/<li class="line".*?<\/li>//g;
# Apply XSLT stylesheet to returned datas
my $result =
$self->stylesheet->transform(
$self->parser->parse_string( '<root>' . $$rdata . '</root>' ) )
->documentElement();
# Get configuration number
unless ( $self->{cfgNum} =
$result->getChildrenByTagName('conf')->[0]->getAttribute('value') )
{
die "No configuration number found";
}
my $newConf = { cfgNum => $self->{cfgNum} };
# Loading returned parameters
my $errors = {};
2009-12-11 19:17:00 +01:00
foreach ( @{ $result->getChildrenByTagName('element') } ) {
my ( $id, $name, $value ) = (
$_->getAttribute('id'),
$_->getAttribute('name'),
$_->getAttribute('value')
);
my $NK = 0;
$id =~
s/^text_(NewID_)?li_(\w+)(\d)(?:_\d+)?$/decode_base64($2.'='x $3)/e;
$NK = 1 if ($1);
2009-12-16 17:49:17 +01:00
$id =~ s/\r//g;
2009-12-11 19:17:00 +01:00
$id =~ s/^\///;
$id =~ s/(?:\/[^\/]*)?$/\/$name/ if ($NK);
2009-12-17 20:20:17 +01:00
print STDERR "$id\n" if ($NK);
2009-12-11 19:17:00 +01:00
next if ( $id =~ /^(generalParameters|virtualHosts)/ );
my ( $confKey, $test ) = $self->getConfTests($id);
my ( $res, $m );
if ( !defined($test) ) {
$errors->{errors}->{$name} =
2009-12-11 19:17:00 +01:00
"Key $name: Lemonldap::NG::Manager error, see Apache's logs";
$self->lmLog(
"Unknown configuration key $id (name: $name, value: $value)",
'error' );
next;
}
if ( $test->{'*'} and $id =~ /\// ) { $test = $test->{'*'} }
# Tests (no test for hash root nodes)
unless ( $test->{keyTest} and ( $id !~ /\// or $test->{'*'} ) ) {
if ( $test->{keyTest} ) {
( $res, $m ) = $self->applyTest( $test->{keyTest}, $name );
unless ($res) {
$errors->{errors}->{$name} = $m || $test->{keyMsgFail};
2009-12-11 19:17:00 +01:00
next;
}
}
if ( $test->{test} ) {
( $res, $m ) = $self->applyTest( $test->{test}, $value );
unless ($res) {
$errors->{errors}->{$name} = $m || $test->{msgFail};
2009-12-11 19:17:00 +01:00
next;
}
}
if ( $test->{warnKeyTest} ) {
( $res, $m ) = $self->applyTest( $test->{warnKeyTest}, $name );
unless ($res) {
$errors->{warnings}->{$name} = $m || $test->{keyMsgWarn};
2009-12-11 19:17:00 +01:00
}
}
if ( $test->{warnTest} ) {
( $res, $m ) = $self->applyTest( $test->{warnTest}, $value );
unless ($res) {
$errors->{warnings}->{$name} = $m || $test->{keyMsgWarn};
2009-12-11 19:17:00 +01:00
}
}
}
$self->setKeyToH( $newConf, $confKey,
$test->{keyTest}
? ( ( $id !~ /\// or $test->{'*'} ) ? {} : ( $name => $value ) )
: $value );
}
# Loading unchanged parameters (ajax nodes not open)
foreach ( @{ $result->getChildrenByTagName('ignore') } ) {
my $node = $_->getAttribute('value');
$node =~ s/^.*node=(.*?)(?:&.*)?\}$/$1/;
2009-12-17 20:20:17 +01:00
foreach my $k ( $self->findAllConfKeys( $self->corresp( $node, 1 ) ) ) {
2009-12-11 19:17:00 +01:00
my $v = $self->keyToH( $k, $self->conf );
$v = $self->keyToH( $k, $self->defaultConf ) unless ( defined $v );
if ( defined $v ) {
$self->setKeyToH( $newConf, $k, $v );
}
else {
$self->lmLog( "No default value found for $k", 'warn' );
}
}
}
#print STDERR Dumper( $newConf, $errors );
print STDERR Dumper($errors);
if ( $errors->{errors} ) {
$errors->{result}->{cfgNum} = 0;
$errors->{result}->{msg} = $self->translate('syntaxError');
}
else {
$errors->{result}->{cfgNum} = $self->confObj->saveConf($newConf);
$errors->{result}->{msg} = (
$errors->{result}->{cfgNum} > 0
? $self->translate('confSaved')
: $self->translate(
{
CONFIG_WAS_CHANGED => 'confWasChanged',
UNKNOWN_ERROR => 'unknownError',
DATABASE_LOCKED => 'databaseLocked',
UPLOAD_DENIED => 'uploadDenied',
SYNTAX_ERROR => 'syntaxError',
}->{ $errors->{result}->{cfgNum} }
)
);
}
2009-12-11 19:17:00 +01:00
my $buf = '{';
2009-12-17 20:20:17 +01:00
my $i = 0;
while ( my ( $type, $h ) = each %$errors ) {
2009-12-17 20:20:17 +01:00
$buf .= ',' if ($i);
2009-12-11 22:17:06 +01:00
$buf .= "'$type':{";
$buf .= join(
',',
map {
$h->{$_} =~ s/'/\\'/;
$h->{$_} =~ s/\n/ /g;
"'$_':'$h->{$_}'"
} keys %$h
);
2009-12-11 19:17:00 +01:00
$buf .= '}';
$i++;
}
$buf .= '}';
2009-12-17 20:20:17 +01:00
print $self->header(
-type => 'application/json',
-Content_Length => length($buf)
) . $buf;
2009-12-11 19:17:00 +01:00
$self->quit();
}
2009-12-17 20:20:17 +01:00
## @method protected array applyTest(void* test,string value)
# Apply the test to the value and return the result and an optional message
# returned by the test if the sub ref.
# @param $test Ref to a regexp or a sub
# @param $value Value to test
# @return Array containing:
# - the test result
# - an optional message
2009-12-11 19:17:00 +01:00
sub applyTest {
my ( $self, $test, $value ) = @_;
my ( $res, $msg );
if ( ref($test) eq 'CODE' ) {
( $res, $msg ) = &$test($value);
}
else {
$res = ( $value =~ $test ? 1 : 0 );
}
return ( $res, $msg );
}
2009-12-17 20:20:17 +01:00
## @method protected array getConfTests(string id)
# Call Lemonldap::NG::Manager::_Struct::testStruct().
2009-12-11 19:17:00 +01:00
sub getConfTests {
my ( $self, $id ) = @_;
my ( $confKey, $tmp ) = ( $id =~ /^(.*?)(?:\/(.*))?$/ );
my $h = $self->testStruct()->{$confKey};
if ( $h and $h->{'*'} and my ( $k, $v ) = ( $tmp =~ /^(.*?)\/(.*)$/ ) ) {
return ( "$confKey/$k", $h->{'*'} );
}
return ( $confKey, $h );
}
2009-12-17 20:20:17 +01:00
## @method protected array findAllConfKeys(hashref h)
# Parse a tree structure to find all nodes corresponding to a configuration
# value.
# @param $h Tree structure
# @return Array of configuration parameter names
2009-12-11 19:17:00 +01:00
sub findAllConfKeys {
my ( $self, $h ) = @_;
my @res = ();
foreach my $n ( @{ $h->{_nodes} } ) {
$n =~ s/^.*?:(.*?)(?:\:.*)?$/$1/;
if ( ref( $h->{$n} ) ) {
push @res, $self->findAllConfKeys( $h->{$n} );
}
else {
my $m = $h->{$n} || $n;
push @res, ( $m =~ /^(?:.*?:)?(.*?)(?:\:.*)?$/ ? $1 : () );
}
}
2009-12-17 20:20:17 +01:00
push @res, @{ $h->{_upload} } if ( $h->{_upload} );
2009-12-11 19:17:00 +01:00
return @res;
}
2009-12-17 20:20:17 +01:00
## @method protected void setKeyToH(hashref h,string key,string k2,string value)
# Insert key=>$value in $h at the position declared with $key. If $k2 is set,
# insert key=>{$k2=>$value}. Note that $key is splited with "/". The last part
# is used as key.
# @param $h New Lemonldap::NG configuration
# @param $key String "/path/key"
# @param $k2 Optional subkey
2009-12-11 19:17:00 +01:00
sub setKeyToH {
my $value = pop;
my ( $self, $h, $key, $k2 ) = @_;
my $tmp = $h;
$key =~ s/^\///;
while (1) {
if ( $key =~ /\// ) {
my $k = $`;
$key = $';
$tmp = $tmp->{$k} ||= {};
}
else {
if ($k2) {
$tmp->{$key} = {} unless ( ref( $tmp->{$key} ) );
$tmp->{$key}->{$k2} = $value;
}
else {
$tmp->{$key} = $value;
}
last;
}
}
}
2009-12-17 20:20:17 +01:00
## @method private XML::LibXML parser()
# @return XML::LibXML object (cached in global $parser variable)
2009-12-11 19:17:00 +01:00
sub parser {
my $self = shift;
return $parser if ($parser);
$parser = XML::LibXML->new();
}
2009-12-17 20:20:17 +01:00
## @method private XML::LibXSLT stylesheet()
# Returns XML::LibXSLT parser (cached in global $stylesheet variable). Use
# datas stored at the end of this file to initialize the object.
# @return XML::LibXSLT object
2009-12-11 19:17:00 +01:00
sub stylesheet {
my $self = shift;
return $stylesheet if ($stylesheet);
my $xslt = XML::LibXSLT->new();
my $style_doc = $self->parser->parse_string( join( '', <DATA> ) );
close DATA;
$stylesheet = $xslt->parse_stylesheet($style_doc);
}
1;
__DATA__
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"
encoding="UTF-8"/>
<xsl:template match="/">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="li">
<xsl:choose>
<xsl:when test="starts-with(.,'.')">
<ignore><xsl:attribute name="value"><xsl:value-of select="."/></xsl:attribute></ignore>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="span">
<xsl:choose>
<xsl:when test="@id='text_li_cm9vdA2'">
<conf><xsl:attribute name="value"><xsl:value-of select="@value"/></xsl:attribute></conf>
</xsl:when>
<xsl:otherwise>
<element>
<xsl:attribute name="name"><xsl:value-of select="@name"/></xsl:attribute>
<xsl:attribute name="id"><xsl:value-of select="@id"/></xsl:attribute>
<xsl:attribute name="value"><xsl:value-of select="@value"/></xsl:attribute>
</element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>