first commit
This commit is contained in:
31
dockers/apikaz/source/Dockerfile
Normal file
31
dockers/apikaz/source/Dockerfile
Normal file
@ -0,0 +1,31 @@
|
||||
FROM python:3.11
|
||||
|
||||
#cette image permet d'avoir l'env python ainsi que le mode "reload on change", pratique quand on modifie les sources *.py
|
||||
|
||||
# maj des packages dispo
|
||||
RUN apt-get update
|
||||
|
||||
#ldap pour le pip install python-ldap car apt-get python-ldap marche po
|
||||
RUN apt-get install -y libsasl2-dev python3-dev libldap2-dev libssl-dev ldap-utils
|
||||
|
||||
#pour l'api soap sympa', perl est déjà installé mais il faut les modules suivant
|
||||
RUN cpan App::cpanminus
|
||||
RUN cpanm SOAP::Lite XML::LibXML MIME::EncWords Text::LineFold Class::Singleton Locale::Messages
|
||||
|
||||
#installer le truc de génération de mot de mdp
|
||||
RUN apt-get -y install apg
|
||||
|
||||
#installer mmctl pour mattermost
|
||||
RUN mkdir -p /mm/ && cd /mm/ && \
|
||||
curl -vfsSL -O https://releases.mattermost.com/mmctl/v9.7.1/linux_amd64.tar && \
|
||||
tar -xf linux_amd64.tar
|
||||
|
||||
#l'api Kaz
|
||||
RUN mkdir /usr/src/app/
|
||||
COPY . /usr/src/app/
|
||||
WORKDIR /usr/src/app/
|
||||
EXPOSE 5000
|
||||
|
||||
#les modules python à installer lors du build
|
||||
RUN pip install -r requirements.txt
|
||||
CMD ["python", "app.py"]
|
75
dockers/apikaz/source/Sympa/Constants.pm
Normal file
75
dockers/apikaz/source/Sympa/Constants.pm
Normal file
@ -0,0 +1,75 @@
|
||||
# -*- indent-tabs-mode: nil; -*-
|
||||
# vim:ft=perl:et:sw=4
|
||||
# $Id$
|
||||
|
||||
# Sympa - SYsteme de Multi-Postage Automatique
|
||||
#
|
||||
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
|
||||
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
|
||||
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
|
||||
# Copyright 2018 The Sympa Community. See the AUTHORS.md file at the
|
||||
# top-level directory of this distribution and at
|
||||
# <https://github.com/sympa-community/sympa.git>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package Sympa::Constants;
|
||||
|
||||
use strict;
|
||||
|
||||
use constant VERSION => '--VERSION--';
|
||||
use constant USER => '--USER--';
|
||||
use constant GROUP => '--GROUP--';
|
||||
|
||||
use constant CONFIG => '--CONFIG--';
|
||||
use constant WWSCONFIG => '--WWSCONFIG--';
|
||||
use constant SENDMAIL_ALIASES => '--SENDMAIL_ALIASES--';
|
||||
|
||||
use constant PIDDIR => '--piddir--';
|
||||
use constant EXPLDIR => '--expldir--';
|
||||
use constant SPOOLDIR => '--spooldir--';
|
||||
use constant SYSCONFDIR => '--sysconfdir--';
|
||||
use constant LOCALEDIR => '--localedir--';
|
||||
use constant LIBEXECDIR => '--libexecdir--';
|
||||
use constant SBINDIR => '--sbindir--';
|
||||
use constant SCRIPTDIR => '--scriptdir--';
|
||||
use constant MODULEDIR => '--modulesdir--';
|
||||
use constant DEFAULTDIR => '--defaultdir--';
|
||||
use constant ARCDIR => '--arcdir--';
|
||||
use constant BOUNCEDIR => '--bouncedir--';
|
||||
use constant EXECCGIDIR => '--execcgidir--';
|
||||
use constant STATICDIR => '--staticdir--';
|
||||
use constant CSSDIR => '--cssdir--';
|
||||
use constant PICTURESDIR => '--picturesdir--';
|
||||
|
||||
use constant EMAIL_LEN => 100;
|
||||
use constant FAMILY_LEN => 50;
|
||||
use constant LIST_LEN => 50;
|
||||
use constant ROBOT_LEN => 80;
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=encoding utf-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Sympa::Constants - Definition of constants
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module keeps definition of constants used by Sympa software.
|
||||
|
||||
=cut
|
1225
dockers/apikaz/source/Sympa/Language.pm
Normal file
1225
dockers/apikaz/source/Sympa/Language.pm
Normal file
File diff suppressed because it is too large
Load Diff
128
dockers/apikaz/source/Sympa/Regexps.pm
Normal file
128
dockers/apikaz/source/Sympa/Regexps.pm
Normal file
@ -0,0 +1,128 @@
|
||||
# -*- indent-tabs-mode: nil; -*-
|
||||
# vim:ft=perl:et:sw=4
|
||||
|
||||
# Sympa - SYsteme de Multi-Postage Automatique
|
||||
#
|
||||
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
|
||||
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
|
||||
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
|
||||
# Copyright 2017, 2021, 2022, 2023 The Sympa Community. See the
|
||||
# AUTHORS.md file at the top-level directory of this distribution and at
|
||||
# <https://github.com/sympa-community/sympa.git>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package Sympa::Regexps;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# domain name.
|
||||
use constant domain => qr'[-\w]+(?:[.][-\w]+)+';
|
||||
|
||||
# These are relaxed variants of the syntax for mailbox described in RFC 5322.
|
||||
# See also RFC 5322, 3.2.3 & 3.4.1 for details on format.
|
||||
use constant email =>
|
||||
qr{(?:[A-Za-z0-9!\#\$%\&'*+\-/=?^_`{|}~.]+|"(?:\\.|[^\\"])*")\@[-\w]+(?:[.][-\w]+)+};
|
||||
|
||||
# This is older definition used by 6.2.65b and earlier.
|
||||
#use constant addrspec => qr{(?:[-&+'./\w=]+|".*")\@[-\w]+(?:[.][-\w]+)+};
|
||||
|
||||
# This is the same as above except that it gave some groups, then regexp
|
||||
# using it should also be changed. By this reason it has been deprecated.
|
||||
#use constant email => qr'([\w\-\_\.\/\+\=\'\&]+|\".*\")\@[\w\-]+(\.[\w\-]+)+';
|
||||
|
||||
use constant family_name => qr'[a-z0-9][a-z0-9\-\.\+_]*';
|
||||
## Allow \s for template names
|
||||
use constant template_name => qr'[a-zA-Z0-9][a-zA-Z0-9\-\.\+_\s]*';
|
||||
#FIXME: Not matching with IPv6 address.
|
||||
use constant host => qr'[\w\.\-]+';
|
||||
use constant hostport => qr{(?:
|
||||
[-.\w]+ (?::\d+)?
|
||||
| [:0-9a-f]*:[:0-9a-f]*:[:0-9a-f]*
|
||||
| \[ [:0-9a-f]*:[:0-9a-f]*:[:0-9a-f]* \] (?::\d+)?
|
||||
)}ix;
|
||||
use constant html_date =>
|
||||
qr'[0-9]{4}[0-9]*-(?:0[1-9]|1[0-2])-(?:0[1-9]|[12][0-9]|3[01])';
|
||||
use constant ipv6 => qr'[:0-9a-f]*:[:0-9a-f]*:[:0-9a-f]*'i;
|
||||
#FIXME: Cannot contain IPv6 address.
|
||||
use constant multiple_host_with_port =>
|
||||
'[\w\.\-]+(:\d+)?(,[\w\.\-]+(:\d+)?)*';
|
||||
#FIXME: Cannot contain IPv6 address.
|
||||
use constant multiple_host_or_url =>
|
||||
qr'([-\w]+://.+|[-.\w]+(:\d+)?)(,([-\w]+://.+|[-.\w]+(:\d+)?))*';
|
||||
use constant listname => qr'[a-z0-9][a-z0-9\-\.\+_]*';
|
||||
|
||||
use constant ldap_attrdesc => qr'\w[-\w]*(?:;[-\w]+)*'; # RFC2251, 4.1.5
|
||||
|
||||
# "value" defined in RFC 2045, 5.1.
|
||||
use constant rfc2045_parameter_value =>
|
||||
qr'[^\s\x00-\x1F\x7F-\xFF()<>\@,;:\\/\[\]?=\"]+';
|
||||
|
||||
use constant sql_query => qr'(SELECT|select).*';
|
||||
|
||||
# "scenario" was deprecated. Use "scenario_name".
|
||||
# "scenario_config" is used for compatibility to earlier list config files.
|
||||
use constant scenario_config => qr'[-.,\w]+';
|
||||
use constant scenario_name => qr'[-.\w]+';
|
||||
|
||||
use constant task => qr'\w+';
|
||||
use constant datasource => qr'[\w-]+';
|
||||
use constant uid => qr'[\w\-\.\+]+';
|
||||
use constant time => qr'[012]?[0-9](?:\:[0-5][0-9])?';
|
||||
use constant time_range => __PACKAGE__->time . '-' . __PACKAGE__->time;
|
||||
use constant time_ranges => time_range() . '(?:\s+' . time_range() . ')*';
|
||||
|
||||
use constant re => qr{
|
||||
(?:
|
||||
Antw # Dutch
|
||||
| ATB # Welsh
|
||||
| ATB \. # Latvian
|
||||
| AW # German
|
||||
| Odp # Polish
|
||||
| R # Italian
|
||||
| Re (?: \s* \( \d+ \) | \s* \[ \d+ \] | \*{1,2} \d+ | \^ \d+ )?
|
||||
| REF # French
|
||||
| RES # Portuguese
|
||||
| Rif # Italian
|
||||
| SV # Scandinavian
|
||||
| V\x{00E1} # Magyar, "VA"
|
||||
| VS # Finnish
|
||||
| YNT # Turkish
|
||||
| \x{05D4}\x{05E9}\x{05D1} # Hebrew, "hashev"
|
||||
| \x{0391}\x{03A0} # Greek, "AP"
|
||||
| \x{03A3}\x{03A7}\x{0395}\x{03A4} # Greek, "SChET"
|
||||
| \x{041D}\x{0410} # some Slavic in Cyrillic, "na"
|
||||
| \x{56DE}\x{590D} # Simp. Chinese, "huifu"
|
||||
| \x{56DE}\x{8986} # Trad. Chinese, "huifu"
|
||||
)
|
||||
\s* [:\x{FF1A}]
|
||||
}ix;
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=encoding utf-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Sympa::Regexps - Definition of regular expressions
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This module keeps definition of regular expressions used by Sympa software.
|
||||
|
||||
=cut
|
506
dockers/apikaz/source/Sympa/Tools/Data.pm
Normal file
506
dockers/apikaz/source/Sympa/Tools/Data.pm
Normal file
@ -0,0 +1,506 @@
|
||||
# -*- indent-tabs-mode: nil; -*-
|
||||
# vim:ft=perl:et:sw=4
|
||||
# $Id$
|
||||
|
||||
# Sympa - SYsteme de Multi-Postage Automatique
|
||||
#
|
||||
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
|
||||
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
|
||||
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
|
||||
# Copyright 2018 The Sympa Community. See the AUTHORS.md file at the
|
||||
# top-level directory of this distribution and at
|
||||
# <https://github.com/sympa-community/sympa.git>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package Sympa::Tools::Data;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Encode qw();
|
||||
use English qw(-no_match_vars);
|
||||
use POSIX qw();
|
||||
use XML::LibXML qw();
|
||||
BEGIN { eval 'use Clone qw()'; }
|
||||
|
||||
use Sympa::Tools::Text;
|
||||
|
||||
## This applies recursively to a data structure
|
||||
## The transformation subroutine is passed as a ref
|
||||
sub recursive_transformation {
|
||||
my ($var, $subref) = @_;
|
||||
|
||||
return unless (ref($var));
|
||||
|
||||
if (ref($var) eq 'ARRAY') {
|
||||
foreach my $index (0 .. $#{$var}) {
|
||||
if (ref($var->[$index])) {
|
||||
recursive_transformation($var->[$index], $subref);
|
||||
} else {
|
||||
$var->[$index] = &{$subref}($var->[$index]);
|
||||
}
|
||||
}
|
||||
} elsif (ref($var) eq 'HASH') {
|
||||
foreach my $key (keys %{$var}) {
|
||||
if (ref($var->{$key})) {
|
||||
recursive_transformation($var->{$key}, $subref);
|
||||
} else {
|
||||
$var->{$key} = &{$subref}($var->{$key});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
## Dump a variable's content
|
||||
sub dump_var {
|
||||
my ($var, $level, $fd) = @_;
|
||||
|
||||
return undef unless ($fd);
|
||||
|
||||
if (ref($var)) {
|
||||
if (ref($var) eq 'ARRAY') {
|
||||
foreach my $index (0 .. $#{$var}) {
|
||||
print $fd "\t" x $level . $index . "\n";
|
||||
dump_var($var->[$index], $level + 1, $fd);
|
||||
}
|
||||
} elsif (ref($var) eq 'HASH'
|
||||
|| ref($var) eq 'Sympa::Scenario'
|
||||
|| ref($var) eq 'Sympa::List'
|
||||
|| ref($var) eq 'CGI::Fast') {
|
||||
foreach my $key (sort keys %{$var}) {
|
||||
print $fd "\t" x $level . '_' . $key . '_' . "\n";
|
||||
dump_var($var->{$key}, $level + 1, $fd);
|
||||
}
|
||||
} else {
|
||||
printf $fd "\t" x $level . "'%s'" . "\n", ref($var);
|
||||
}
|
||||
} else {
|
||||
if (defined $var) {
|
||||
print $fd "\t" x $level . "'$var'" . "\n";
|
||||
} else {
|
||||
print $fd "\t" x $level . "UNDEF\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## Dump a variable's content
|
||||
sub dump_html_var {
|
||||
my ($var) = shift;
|
||||
my $html = '';
|
||||
|
||||
if (ref($var)) {
|
||||
|
||||
if (ref($var) eq 'ARRAY') {
|
||||
$html .= '<ul>';
|
||||
foreach my $index (0 .. $#{$var}) {
|
||||
$html .= '<li> ' . $index . ':';
|
||||
$html .= dump_html_var($var->[$index]);
|
||||
$html .= '</li>';
|
||||
}
|
||||
$html .= '</ul>';
|
||||
} elsif (ref($var) eq 'HASH'
|
||||
|| ref($var) eq 'Sympa::Scenario'
|
||||
|| ref($var) eq 'Sympa::List') {
|
||||
$html .= '<ul>';
|
||||
foreach my $key (sort keys %{$var}) {
|
||||
$html .= '<li>' . $key . '=';
|
||||
$html .= dump_html_var($var->{$key});
|
||||
$html .= '</li>';
|
||||
}
|
||||
$html .= '</ul>';
|
||||
} else {
|
||||
$html .= 'EEEEEEEEEEEEEEEEEEEEE' . ref($var);
|
||||
}
|
||||
} else {
|
||||
if (defined $var) {
|
||||
$html .= Sympa::Tools::Text::encode_html($var);
|
||||
} else {
|
||||
$html .= 'UNDEF';
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
# Duplicates a complex variable (faster).
|
||||
# CAUTION: This duplicates blessed elements even if they are
|
||||
# singleton/multiton; this breaks subroutine references.
|
||||
sub clone_var {
|
||||
return Clone::clone($_[0]) if $Clone::VERSION;
|
||||
goto &dup_var; # '&' needed
|
||||
}
|
||||
|
||||
## Duplictate a complex variable
|
||||
sub dup_var {
|
||||
my ($var) = @_;
|
||||
|
||||
if (ref($var)) {
|
||||
if (ref($var) eq 'ARRAY') {
|
||||
my $new_var = [];
|
||||
foreach my $index (0 .. $#{$var}) {
|
||||
$new_var->[$index] = dup_var($var->[$index]);
|
||||
}
|
||||
return $new_var;
|
||||
} elsif (ref($var) eq 'HASH') {
|
||||
my $new_var = {};
|
||||
foreach my $key (sort keys %{$var}) {
|
||||
$new_var->{$key} = dup_var($var->{$key});
|
||||
}
|
||||
return $new_var;
|
||||
}
|
||||
}
|
||||
|
||||
return $var;
|
||||
}
|
||||
|
||||
####################################################
|
||||
# get_array_from_splitted_string
|
||||
####################################################
|
||||
# return an array made on a string splited by ','.
|
||||
# It removes spaces.
|
||||
#
|
||||
#
|
||||
# IN : -$string (+): string to split
|
||||
#
|
||||
# OUT : -ref(ARRAY)
|
||||
#
|
||||
######################################################
|
||||
# Note: This is used only by Sympa::List.
|
||||
sub get_array_from_splitted_string {
|
||||
my ($string) = @_;
|
||||
my @array;
|
||||
|
||||
foreach my $word (split /,/, $string) {
|
||||
$word =~ s/^\s+//;
|
||||
$word =~ s/\s+$//;
|
||||
push @array, $word;
|
||||
}
|
||||
|
||||
return \@array;
|
||||
}
|
||||
|
||||
####################################################
|
||||
# diff_on_arrays
|
||||
####################################################
|
||||
# Makes set operation on arrays (seen as set, with no double) :
|
||||
# - deleted : A \ B
|
||||
# - added : B \ A
|
||||
# - intersection : A /\ B
|
||||
# - union : A \/ B
|
||||
#
|
||||
# IN : -$setA : ref(ARRAY) - set
|
||||
# -$setB : ref(ARRAY) - set
|
||||
#
|
||||
# OUT : -ref(HASH) with keys :
|
||||
# deleted, added, intersection, union
|
||||
#
|
||||
#######################################################
|
||||
sub diff_on_arrays {
|
||||
my ($setA, $setB) = @_;
|
||||
my $result = {
|
||||
'intersection' => [],
|
||||
'union' => [],
|
||||
'added' => [],
|
||||
'deleted' => []
|
||||
};
|
||||
my %deleted;
|
||||
my %added;
|
||||
my %intersection;
|
||||
my %union;
|
||||
|
||||
my %hashA;
|
||||
my %hashB;
|
||||
|
||||
foreach my $eltA (@$setA) {
|
||||
$hashA{$eltA} = 1;
|
||||
$deleted{$eltA} = 1;
|
||||
$union{$eltA} = 1;
|
||||
}
|
||||
|
||||
foreach my $eltB (@$setB) {
|
||||
$hashB{$eltB} = 1;
|
||||
$added{$eltB} = 1;
|
||||
|
||||
if ($hashA{$eltB}) {
|
||||
$intersection{$eltB} = 1;
|
||||
$deleted{$eltB} = 0;
|
||||
} else {
|
||||
$union{$eltB} = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $eltA (@$setA) {
|
||||
if ($hashB{$eltA}) {
|
||||
$added{$eltA} = 0;
|
||||
}
|
||||
}
|
||||
|
||||
foreach my $elt (keys %deleted) {
|
||||
next unless $elt;
|
||||
push @{$result->{'deleted'}}, $elt if ($deleted{$elt});
|
||||
}
|
||||
foreach my $elt (keys %added) {
|
||||
next unless $elt;
|
||||
push @{$result->{'added'}}, $elt if ($added{$elt});
|
||||
}
|
||||
foreach my $elt (keys %intersection) {
|
||||
next unless $elt;
|
||||
push @{$result->{'intersection'}}, $elt if ($intersection{$elt});
|
||||
}
|
||||
foreach my $elt (keys %union) {
|
||||
next unless $elt;
|
||||
push @{$result->{'union'}}, $elt if ($union{$elt});
|
||||
}
|
||||
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
####################################################
|
||||
# is_in_array
|
||||
####################################################
|
||||
# Test if a value is on an array
|
||||
#
|
||||
# IN : -$setA : ref(ARRAY) - set
|
||||
# -$value : a serached value
|
||||
#
|
||||
# OUT : boolean
|
||||
#######################################################
|
||||
sub is_in_array {
|
||||
my $set = shift;
|
||||
die 'missing parameter "$value"' unless @_;
|
||||
my $value = shift;
|
||||
|
||||
if (defined $value) {
|
||||
foreach my $elt (@{$set || []}) {
|
||||
next unless defined $elt;
|
||||
return 1 if $elt eq $value;
|
||||
}
|
||||
} else {
|
||||
foreach my $elt (@{$set || []}) {
|
||||
return 1 unless defined $elt;
|
||||
}
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
=over
|
||||
|
||||
=item smart_eq ( $a, $b )
|
||||
|
||||
I<Function>.
|
||||
Check if two strings are identical.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item $a, $b
|
||||
|
||||
Operands.
|
||||
|
||||
If both of them are undefined, they are equal.
|
||||
If only one of them is undefined, the are not equal.
|
||||
If C<$b> is a L<Regexp> object and it matches to C<$a>, they are equal.
|
||||
Otherwise, they are compared as strings.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
If arguments matched, true value. Otherwise false value.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub smart_eq {
|
||||
die 'missing argument' if scalar @_ < 2;
|
||||
my ($a, $b) = @_;
|
||||
|
||||
if (defined $a and defined $b) {
|
||||
if (ref $b eq 'Regexp') {
|
||||
return 1 if $a =~ $b;
|
||||
} else {
|
||||
return 1 if $a eq $b;
|
||||
}
|
||||
} elsif (!defined $a and !defined $b) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
## convert a string formated as var1="value1";var2="value2"; into a hash.
|
||||
## Used when extracting from session table some session properties or when
|
||||
## extracting users preference from user table
|
||||
## Current encoding is NOT compatible with encoding of values with '"'
|
||||
##
|
||||
sub string_2_hash {
|
||||
my $data = shift;
|
||||
my %hash;
|
||||
|
||||
pos($data) = 0;
|
||||
while ($data =~ /\G;?(\w+)\=\"((\\[\"\\]|[^\"])*)\"(?=(;|\z))/g) {
|
||||
my ($var, $val) = ($1, $2);
|
||||
$val =~ s/\\([\"\\])/$1/g;
|
||||
$hash{$var} = $val;
|
||||
}
|
||||
|
||||
return (%hash);
|
||||
|
||||
}
|
||||
## convert a hash into a string formated as var1="value1";var2="value2"; into
|
||||
## a hash
|
||||
sub hash_2_string {
|
||||
my $refhash = shift;
|
||||
|
||||
return undef unless ref $refhash eq 'HASH';
|
||||
|
||||
my $data_string;
|
||||
foreach my $var (keys %$refhash) {
|
||||
next unless length $var;
|
||||
my $val = $refhash->{$var};
|
||||
$val = '' unless defined $val;
|
||||
|
||||
$val =~ s/([\"\\])/\\$1/g;
|
||||
$data_string .= ';' . $var . '="' . $val . '"';
|
||||
}
|
||||
return ($data_string);
|
||||
}
|
||||
|
||||
## compare 2 scalars, string/numeric independant
|
||||
sub smart_lessthan {
|
||||
my ($stra, $strb) = @_;
|
||||
$stra =~ s/^\s+//;
|
||||
$stra =~ s/\s+$//;
|
||||
$strb =~ s/^\s+//;
|
||||
$strb =~ s/\s+$//;
|
||||
$ERRNO = 0;
|
||||
my ($numa, $unparsed) = POSIX::strtod($stra);
|
||||
my $numb;
|
||||
$numb = POSIX::strtod($strb)
|
||||
unless ($ERRNO || $unparsed != 0);
|
||||
|
||||
if (($stra eq '') || ($strb eq '') || ($unparsed != 0) || $ERRNO) {
|
||||
return $stra lt $strb;
|
||||
} else {
|
||||
return $stra < $strb;
|
||||
}
|
||||
}
|
||||
|
||||
=over
|
||||
|
||||
=item sort_uniq ( [ \&comp ], @items )
|
||||
|
||||
Returns sorted array of unique elements in the list.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item \&comp
|
||||
|
||||
Optional subroutine reference to compare each pairs of elements.
|
||||
It should take two arguments and return negative, zero or positive result.
|
||||
|
||||
=item @items
|
||||
|
||||
Items to be sorted.
|
||||
|
||||
=back
|
||||
|
||||
This function was added on Sympa 6.2.16.
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub sort_uniq {
|
||||
my $comp;
|
||||
if (ref $_[0] eq 'CODE') {
|
||||
$comp = shift;
|
||||
}
|
||||
|
||||
my %items;
|
||||
@items{@_} = ();
|
||||
|
||||
if ($comp) {
|
||||
return sort { $comp->($a, $b) } keys %items;
|
||||
} else {
|
||||
return sort keys %items;
|
||||
}
|
||||
}
|
||||
|
||||
# Create a custom attribute from an XML description
|
||||
# IN : A string, XML formed data as stored in database
|
||||
# OUT : HASH data storing custome attributes.
|
||||
# Old name: Sympa::List::parseCustomAttribute().
|
||||
sub decode_custom_attribute {
|
||||
my $xmldoc = shift;
|
||||
return undef unless defined $xmldoc and length $xmldoc;
|
||||
|
||||
my $parser = XML::LibXML->new();
|
||||
my $tree;
|
||||
|
||||
## We should use eval to parse to prevent the program to crash if it fails
|
||||
if (ref($xmldoc) eq 'GLOB') {
|
||||
$tree = eval { $parser->parse_fh($xmldoc) };
|
||||
} else {
|
||||
$tree = eval { $parser->parse_string($xmldoc) };
|
||||
}
|
||||
|
||||
return undef unless defined $tree;
|
||||
|
||||
my $doc = $tree->getDocumentElement;
|
||||
|
||||
my @custom_attr = $doc->getChildrenByTagName('custom_attribute');
|
||||
my %ca;
|
||||
foreach my $ca (@custom_attr) {
|
||||
my $id = Encode::encode_utf8($ca->getAttribute('id'));
|
||||
my $value = Encode::encode_utf8($ca->getElementsByTagName('value'));
|
||||
$ca{$id} = {value => $value};
|
||||
}
|
||||
return \%ca;
|
||||
}
|
||||
|
||||
# Create an XML Custom attribute to be stored into data base.
|
||||
# IN : HASH data storing custome attributes
|
||||
# OUT : string, XML formed data to be stored in database
|
||||
# Old name: Sympa::List::createXMLCustomAttribute().
|
||||
sub encode_custom_attribute {
|
||||
my $custom_attr = shift;
|
||||
return
|
||||
'<?xml version="1.0" encoding="UTF-8" ?><custom_attributes></custom_attributes>'
|
||||
if (not defined $custom_attr);
|
||||
my $XMLstr = '<?xml version="1.0" encoding="UTF-8" ?><custom_attributes>';
|
||||
foreach my $k (sort keys %{$custom_attr}) {
|
||||
my $value = $custom_attr->{$k}{value};
|
||||
$value = '' unless defined $value;
|
||||
|
||||
$XMLstr .=
|
||||
"<custom_attribute id=\"$k\"><value>"
|
||||
. Sympa::Tools::Text::encode_html($value, '\000-\037')
|
||||
. "</value></custom_attribute>";
|
||||
}
|
||||
$XMLstr .= "</custom_attributes>";
|
||||
$XMLstr =~ s/\s*\n\s*/ /g;
|
||||
|
||||
return $XMLstr;
|
||||
}
|
||||
|
||||
1;
|
942
dockers/apikaz/source/Sympa/Tools/Text.pm
Normal file
942
dockers/apikaz/source/Sympa/Tools/Text.pm
Normal file
@ -0,0 +1,942 @@
|
||||
# -*- indent-tabs-mode: nil; -*-
|
||||
# vim:ft=perl:et:sw=4
|
||||
# $Id$
|
||||
|
||||
# Sympa - SYsteme de Multi-Postage Automatique
|
||||
#
|
||||
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
|
||||
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
|
||||
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
|
||||
# Copyright 2018, 2020 The Sympa Community. See the AUTHORS.md
|
||||
# file at the top-level directory of this distribution and at
|
||||
# <https://github.com/sympa-community/sympa.git>.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package Sympa::Tools::Text;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use Encode qw();
|
||||
use English qw(-no_match_vars);
|
||||
use Encode::MIME::Header; # 'MIME-Q' encoding.
|
||||
use HTML::Entities qw();
|
||||
use MIME::EncWords;
|
||||
use Text::LineFold;
|
||||
use Unicode::GCString;
|
||||
use URI::Escape qw();
|
||||
use if ($] < 5.016), qw(Unicode::CaseFold fc);
|
||||
use if (5.016 <= $]), qw(feature fc);
|
||||
BEGIN { eval 'use Unicode::Normalize qw()'; }
|
||||
BEGIN { eval 'use Unicode::UTF8 qw()'; }
|
||||
|
||||
use Sympa::Language;
|
||||
use Sympa::Regexps;
|
||||
|
||||
# Old name: tools::addrencode().
|
||||
sub addrencode {
|
||||
my $addr = shift;
|
||||
my $phrase = (shift || '');
|
||||
my $charset = (shift || 'utf8');
|
||||
my $comment = (shift || '');
|
||||
|
||||
return undef unless $addr =~ /\S/;
|
||||
|
||||
if ($phrase =~ /[^\s\x21-\x7E]/) {
|
||||
$phrase = MIME::EncWords::encode_mimewords(
|
||||
Encode::decode('utf8', $phrase),
|
||||
'Encoding' => 'A',
|
||||
'Charset' => $charset,
|
||||
'Replacement' => 'FALLBACK',
|
||||
'Field' => 'Resent-Sender', # almost longest
|
||||
'Minimal' => 'DISPNAME', # needs MIME::EncWords >= 1.012.
|
||||
);
|
||||
} elsif ($phrase =~ /\S/) {
|
||||
$phrase =~ s/([\\\"])/\\$1/g;
|
||||
$phrase = '"' . $phrase . '"';
|
||||
}
|
||||
if ($comment =~ /[^\s\x21-\x27\x2A-\x5B\x5D-\x7E]/) {
|
||||
$comment = MIME::EncWords::encode_mimewords(
|
||||
Encode::decode('utf8', $comment),
|
||||
'Encoding' => 'A',
|
||||
'Charset' => $charset,
|
||||
'Replacement' => 'FALLBACK',
|
||||
'Minimal' => 'DISPNAME',
|
||||
);
|
||||
} elsif ($comment =~ /\S/) {
|
||||
$comment =~ s/([\\\"])/\\$1/g;
|
||||
}
|
||||
|
||||
return
|
||||
($phrase =~ /\S/ ? "$phrase " : '')
|
||||
. ($comment =~ /\S/ ? "($comment) " : '')
|
||||
. "<$addr>";
|
||||
}
|
||||
|
||||
# Old names: tools::clean_email(), tools::get_canonical_email().
|
||||
sub canonic_email {
|
||||
my $email = shift;
|
||||
|
||||
return undef unless defined $email;
|
||||
|
||||
# Remove leading and trailing white spaces.
|
||||
$email =~ s/\A\s+//;
|
||||
$email =~ s/\s+\z//;
|
||||
|
||||
# Lower-case.
|
||||
$email =~ tr/A-Z/a-z/;
|
||||
|
||||
return (length $email) ? $email : undef;
|
||||
}
|
||||
|
||||
# Old name: tools::clean_msg_id().
|
||||
sub canonic_message_id {
|
||||
my $msg_id = shift;
|
||||
|
||||
return $msg_id unless defined $msg_id;
|
||||
|
||||
chomp $msg_id;
|
||||
|
||||
if ($msg_id =~ /\<(.+)\>/) {
|
||||
$msg_id = $1;
|
||||
}
|
||||
|
||||
return $msg_id;
|
||||
}
|
||||
|
||||
sub canonic_text {
|
||||
my $text = shift;
|
||||
|
||||
return undef unless defined $text;
|
||||
|
||||
# Normalize text. See also discussion on
|
||||
# https://listes.renater.fr/sympa/arc/sympa-developpers/2018-03/thrd1.html
|
||||
#
|
||||
# N.B.: Corresponding modules are optional by now, and should be
|
||||
# mandatory in the future.
|
||||
my $utext;
|
||||
if (Encode::is_utf8($text)) {
|
||||
$utext = $text;
|
||||
} elsif ($Unicode::UTF8::VERSION) {
|
||||
no warnings 'utf8';
|
||||
$utext = Unicode::UTF8::decode_utf8($text);
|
||||
} else {
|
||||
$utext = Encode::decode_utf8($text);
|
||||
}
|
||||
if ($Unicode::Normalize::VERSION) {
|
||||
$utext = Unicode::Normalize::normalize('NFC', $utext);
|
||||
}
|
||||
|
||||
# Remove DOS linefeeds (^M) that cause problems with Outlook 98, AOL,
|
||||
# and EIMS:
|
||||
$utext =~ s/\r\n|\r/\n/g;
|
||||
|
||||
if (Encode::is_utf8($text)) {
|
||||
return $utext;
|
||||
} else {
|
||||
return Encode::encode_utf8($utext);
|
||||
}
|
||||
}
|
||||
|
||||
sub slurp {
|
||||
my $path = shift;
|
||||
|
||||
my $ifh;
|
||||
return undef unless open $ifh, '<', $path;
|
||||
my $text = do { local $RS; <$ifh> };
|
||||
close $ifh;
|
||||
|
||||
return canonic_text($text);
|
||||
}
|
||||
|
||||
sub wrap_text {
|
||||
my $text = shift;
|
||||
my $init = shift;
|
||||
my $subs = shift;
|
||||
my $cols = shift;
|
||||
|
||||
$init //= '';
|
||||
$subs //= '';
|
||||
$cols //= 78;
|
||||
return $text unless $cols;
|
||||
|
||||
my $email_re = Sympa::Regexps::email();
|
||||
my $linefold = Text::LineFold->new(
|
||||
Language => Sympa::Language->instance->get_lang,
|
||||
Prep => 'NONBREAKURI',
|
||||
prep => [$email_re, sub { shift; @_ }],
|
||||
ColumnsMax => $cols,
|
||||
Format => sub {
|
||||
shift;
|
||||
my $event = shift;
|
||||
my $str = shift;
|
||||
if ($event =~ /^eo/) { return "\n"; }
|
||||
if ($event =~ /^so[tp]/) { return $init . $str; }
|
||||
if ($event eq 'sol') { return $subs . $str; }
|
||||
undef;
|
||||
},
|
||||
);
|
||||
|
||||
my $t = Encode::is_utf8($text) ? $text : Encode::decode_utf8($text);
|
||||
|
||||
my $ret = '';
|
||||
while (1000 < length $t) {
|
||||
my $s = substr $t, 0, 1000;
|
||||
$ret .= $linefold->break_partial($s);
|
||||
$t = substr $t, 1000;
|
||||
}
|
||||
$ret .= $linefold->break_partial($t) if length $t;
|
||||
$ret .= $linefold->break_partial(undef);
|
||||
|
||||
return Encode::is_utf8($text) ? $ret : Encode::encode_utf8($ret);
|
||||
}
|
||||
|
||||
sub decode_filesystem_safe {
|
||||
my $str = shift;
|
||||
return '' unless defined $str and length $str;
|
||||
|
||||
$str = Encode::encode_utf8($str) if Encode::is_utf8($str);
|
||||
# On case-insensitive filesystem "_XX" along with "_xx" should be decoded.
|
||||
$str =~ s/_([0-9A-Fa-f]{2})/chr hex "0x$1"/eg;
|
||||
return $str;
|
||||
}
|
||||
|
||||
sub decode_html {
|
||||
my $str = shift;
|
||||
|
||||
Encode::encode_utf8(
|
||||
HTML::Entities::decode_entities(Encode::decode_utf8($str)));
|
||||
}
|
||||
|
||||
sub encode_filesystem_safe {
|
||||
my $str = shift;
|
||||
return '' unless defined $str and length $str;
|
||||
|
||||
$str = Encode::encode_utf8($str) if Encode::is_utf8($str);
|
||||
$str =~ s/([^-+.0-9\@A-Za-z])/sprintf '_%02x', ord $1/eg;
|
||||
return $str;
|
||||
}
|
||||
|
||||
sub encode_html {
|
||||
my $str = shift;
|
||||
my $additional_unsafe = shift || '';
|
||||
|
||||
HTML::Entities::encode_entities($str, '<>&"' . $additional_unsafe);
|
||||
}
|
||||
|
||||
sub encode_uri {
|
||||
my $str = shift;
|
||||
my %options = @_;
|
||||
|
||||
# Note: URI-1.35 (URI::Escape 3.28) or later is required.
|
||||
return Encode::encode_utf8(
|
||||
URI::Escape::uri_escape_utf8(
|
||||
Encode::decode_utf8($str),
|
||||
'^-A-Za-z0-9._~' . (exists $options{omit} ? $options{omit} : '')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
# Old name: tools::escape_chars().
|
||||
sub escape_chars {
|
||||
my $s = shift;
|
||||
my $except = shift; ## Exceptions
|
||||
my $ord_except = ord $except if defined $except;
|
||||
|
||||
## Escape chars
|
||||
## !"#$%&'()+,:;<=>?[] AND accented chars
|
||||
## escape % first
|
||||
foreach my $i (
|
||||
0x25,
|
||||
0x20 .. 0x24,
|
||||
0x26 .. 0x2c,
|
||||
0x3a .. 0x3f,
|
||||
0x5b, 0x5d,
|
||||
0x80 .. 0x9f,
|
||||
0xa0 .. 0xff
|
||||
) {
|
||||
next if defined $ord_except and $i == $ord_except;
|
||||
my $hex_i = sprintf "%lx", $i;
|
||||
$s =~ s/\x$hex_i/%$hex_i/g;
|
||||
}
|
||||
## Special traetment for '/'
|
||||
$s =~ s/\//%a5/g unless defined $except and $except eq '/';
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
# Old name: tt2::escape_url().
|
||||
# DEPRECATED. Use Sympa::Tools::Text::escape_uri() or
|
||||
# Sympa::Tools::Text::mailtourl().
|
||||
#sub escape_url;
|
||||
|
||||
sub foldcase {
|
||||
my $str = shift;
|
||||
|
||||
return '' unless defined $str and length $str;
|
||||
# Perl 5.16.0 and later have built-in fc(). Earlier uses Unicode::CaseFold.
|
||||
return Encode::encode_utf8(fc(Encode::decode_utf8($str)));
|
||||
}
|
||||
|
||||
my %legacy_charsets = (
|
||||
'ar' => [qw(iso-8859-6)],
|
||||
'bs' => [qw(iso-8859-2)],
|
||||
'cs' => [qw(iso-8859-2)],
|
||||
'eo' => [qw(iso-8859-3)],
|
||||
'et' => [qw(iso-8859-4)],
|
||||
'he' => [qw(iso-8859-8)],
|
||||
'hr' => [qw(iso-8859-2)],
|
||||
'hu' => [qw(iso-8859-2)],
|
||||
'ja' => [qw(euc-jp cp932 MacJapanese)],
|
||||
'kl' => [qw(iso-8859-4)],
|
||||
'ko' => [qw(cp949)],
|
||||
'lt' => [qw(iso-8859-4)],
|
||||
'lv' => [qw(iso-8859-4)],
|
||||
'mt' => [qw(iso-8859-3)],
|
||||
'pl' => [qw(iso-8859-2)],
|
||||
'ro' => [qw(iso-8859-2)],
|
||||
'ru' => [qw(koi8-r cp1251)], # cp866? MacCyrillic?
|
||||
'sk' => [qw(iso-8859-2)],
|
||||
'sl' => [qw(iso-8859-2)],
|
||||
'th' => [qw(iso-8859-11 cp874 MacThai)],
|
||||
'tr' => [qw(iso-8859-9)],
|
||||
'uk' => [qw(koi8-u)], # MacUkrainian?
|
||||
'zh-CN' => [qw(euc-cn)],
|
||||
'zh-TW' => [qw(big5-eten)],
|
||||
);
|
||||
|
||||
sub guessed_to_utf8 {
|
||||
my $text = shift;
|
||||
my @langs = @_;
|
||||
|
||||
return Encode::encode_utf8($text) if Encode::is_utf8($text);
|
||||
return $text
|
||||
unless defined $text
|
||||
and length $text
|
||||
and $text =~ /[^\x00-\x7F]/;
|
||||
|
||||
my $utf8;
|
||||
if ($Unicode::UTF8::VERSION) {
|
||||
$utf8 =
|
||||
eval { Unicode::UTF8::decode_utf8($text, Encode::FB_CROAK()) };
|
||||
}
|
||||
unless (defined $utf8) {
|
||||
foreach my $charset (map { $_ ? @$_ : () } @legacy_charsets{@langs}) {
|
||||
$utf8 =
|
||||
eval { Encode::decode($charset, $text, Encode::FB_CROAK()) };
|
||||
last if defined $utf8;
|
||||
}
|
||||
}
|
||||
unless (defined $utf8) {
|
||||
$utf8 = Encode::decode('iso-8859-1', $text);
|
||||
}
|
||||
|
||||
# Apply NFC: e.g. for modified-NFD by Mac OS X.
|
||||
$utf8 = Unicode::Normalize::normalize('NFC', $utf8)
|
||||
if $Unicode::Normalize::VERSION;
|
||||
|
||||
return Encode::encode_utf8($utf8);
|
||||
}
|
||||
|
||||
sub mailtourl {
|
||||
my $text = shift;
|
||||
my %options = @_;
|
||||
|
||||
my $dtext =
|
||||
(not defined $text) ? ''
|
||||
: $options{decode_html} ? Sympa::Tools::Text::decode_html($text)
|
||||
: $text;
|
||||
$dtext =~ s/\A\s+//;
|
||||
$dtext =~ s/\s+\z//;
|
||||
$dtext =~ s/(?:\r\n|\r|\n)(?=[ \t])//g;
|
||||
$dtext =~ s/\r\n|\r|\n/ /g;
|
||||
|
||||
# The ``@'' in email address should not be encoded because some MUAs
|
||||
# aren't able to decode ``%40'' in e-mail address of mailto: URL.
|
||||
# Contrary, ``@'' in query component should be encoded because some
|
||||
# MUAs take it for a delimiter to separate URL from the rest.
|
||||
my ($format, $utext, $qsep);
|
||||
if ($dtext =~ /[()<>\[\]:;,\"\s]/) {
|
||||
# Use "to" header if source text includes any of RFC 5322
|
||||
# "specials", minus ``@'' and ``\'', plus whitespaces.
|
||||
$format = 'mailto:?to=%s%s';
|
||||
$utext = Sympa::Tools::Text::encode_uri($dtext);
|
||||
$qsep = '&';
|
||||
} else {
|
||||
$format = 'mailto:%s%s';
|
||||
$utext = Sympa::Tools::Text::encode_uri($dtext, omit => '@');
|
||||
$qsep = '?';
|
||||
}
|
||||
my $qstring = _url_query_string(
|
||||
$options{query},
|
||||
decode_html => $options{decode_html},
|
||||
leadchar => $qsep,
|
||||
sepchar => '&',
|
||||
trim_values => 1,
|
||||
);
|
||||
|
||||
return sprintf $format, $utext, $qstring;
|
||||
}
|
||||
|
||||
sub _url_query_string {
|
||||
my $query = shift;
|
||||
my %options = @_;
|
||||
|
||||
unless (ref $query eq 'HASH' and %$query) {
|
||||
return '';
|
||||
} else {
|
||||
my $decode_html = $options{decode_html};
|
||||
my $trim_values = $options{trim_values};
|
||||
return ($options{leadchar} || '?') . join(
|
||||
($options{sepchar} || ';'),
|
||||
map {
|
||||
my ($dkey, $dval) = map {
|
||||
(not defined $_) ? ''
|
||||
: $decode_html ? Sympa::Tools::Text::decode_html($_)
|
||||
: $_;
|
||||
} ($_, $query->{$_});
|
||||
if ($trim_values and lc $dkey ne 'body') {
|
||||
$dval =~ s/\A\s+//;
|
||||
$dval =~ s/\s+\z//;
|
||||
$dval =~ s/(?:\r\n|\r|\n)(?=[ \t])//g;
|
||||
$dval =~ s/\r\n|\r|\n/ /g;
|
||||
}
|
||||
|
||||
sprintf '%s=%s',
|
||||
Sympa::Tools::Text::encode_uri($dkey),
|
||||
Sympa::Tools::Text::encode_uri($dval);
|
||||
} sort keys %$query
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub pad {
|
||||
my $str = shift;
|
||||
my $width = shift;
|
||||
|
||||
return $str unless $width and defined $str;
|
||||
|
||||
my $ustr = Encode::is_utf8($str) ? $str : Encode::decode_utf8($str);
|
||||
my $cols = Unicode::GCString->new($ustr)->columns;
|
||||
|
||||
unless ($cols < abs $width) {
|
||||
return $str;
|
||||
} elsif ($width < 0) {
|
||||
return $str . (' ' x (-$width - $cols));
|
||||
} else {
|
||||
return (' ' x ($width - $cols)) . $str;
|
||||
}
|
||||
}
|
||||
|
||||
# Old name: tools::qdecode_filename().
|
||||
sub qdecode_filename {
|
||||
my $filename = shift;
|
||||
|
||||
## We don't use MIME::Words here because it does not encode properly
|
||||
## Unicode
|
||||
## Check if string is already Q-encoded first
|
||||
#if ($filename =~ /\=\?UTF-8\?/) {
|
||||
$filename = Encode::encode_utf8(Encode::decode('MIME-Q', $filename));
|
||||
#}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
# Old name: tools::qencode_filename().
|
||||
sub qencode_filename {
|
||||
my $filename = shift;
|
||||
|
||||
## We don't use MIME::Words here because it does not encode properly
|
||||
## Unicode
|
||||
## Check if string is already Q-encoded first
|
||||
## Also check if the string contains 8bit chars
|
||||
unless ($filename =~ /\=\?UTF-8\?/
|
||||
|| $filename =~ /^[\x00-\x7f]*$/) {
|
||||
|
||||
## Don't encode elements such as .desc. or .url or .moderate
|
||||
## or .extension
|
||||
my $part = $filename;
|
||||
my ($leading, $trailing);
|
||||
$leading = $1 if ($part =~ s/^(\.desc\.)//); ## leading .desc
|
||||
$trailing = $1 if ($part =~ s/((\.\w+)+)$//); ## trailing .xx
|
||||
|
||||
my $encoded_part = MIME::EncWords::encode_mimewords(
|
||||
$part,
|
||||
Charset => 'utf8',
|
||||
Encoding => 'q',
|
||||
MaxLineLen => 1000,
|
||||
Minimal => 'NO'
|
||||
);
|
||||
|
||||
$filename = $leading . $encoded_part . $trailing;
|
||||
}
|
||||
|
||||
return $filename;
|
||||
}
|
||||
|
||||
# Old name: tools::unescape_chars().
|
||||
sub unescape_chars {
|
||||
my $s = shift;
|
||||
|
||||
$s =~ s/%a5/\//g; ## Special traetment for '/'
|
||||
foreach my $i (0x20 .. 0x2c, 0x3a .. 0x3f, 0x5b, 0x5d, 0x80 .. 0x9f,
|
||||
0xa0 .. 0xff) {
|
||||
my $hex_i = sprintf "%lx", $i;
|
||||
my $hex_s = sprintf "%c", $i;
|
||||
$s =~ s/%$hex_i/$hex_s/g;
|
||||
}
|
||||
|
||||
return $s;
|
||||
}
|
||||
|
||||
# Old name: tools::valid_email().
|
||||
sub valid_email {
|
||||
my $email = shift;
|
||||
|
||||
my $email_re = Sympa::Regexps::email();
|
||||
return undef unless $email =~ /^${email_re}$/;
|
||||
|
||||
# Forbidden characters.
|
||||
return undef if $email =~ /[\|\$\*\?\!]/;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
sub weburl {
|
||||
my $base = shift;
|
||||
my $paths = shift;
|
||||
my %options = @_;
|
||||
|
||||
my @paths = map {
|
||||
Sympa::Tools::Text::encode_uri(
|
||||
(not defined $_) ? ''
|
||||
: $options{decode_html} ? Sympa::Tools::Text::decode_html($_)
|
||||
: $_
|
||||
);
|
||||
} @{$paths || []};
|
||||
|
||||
my $qstring = _url_query_string(
|
||||
$options{query},
|
||||
decode_html => $options{decode_html},
|
||||
sepchar => '&',
|
||||
);
|
||||
|
||||
my $fstring;
|
||||
my $fragment = $options{fragment};
|
||||
if (defined $fragment) {
|
||||
$fstring = '#'
|
||||
. Sympa::Tools::Text::encode_uri(
|
||||
$options{decode_html}
|
||||
? Sympa::Tools::Text::decode_html($fragment)
|
||||
: $fragment
|
||||
);
|
||||
} else {
|
||||
$fstring = '';
|
||||
}
|
||||
|
||||
return sprintf '%s%s%s', join('/', grep { defined $_ } ($base, @paths)),
|
||||
$qstring, $fstring;
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
|
||||
=encoding utf-8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Sympa::Tools::Text - Text-related functions
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This package provides some text-related functions.
|
||||
|
||||
=head2 Functions
|
||||
|
||||
=over
|
||||
|
||||
=item addrencode ( $addr, [ $phrase, [ $charset, [ $comment ] ] ] )
|
||||
|
||||
Returns formatted (and encoded) name-addr as RFC5322 3.4.
|
||||
|
||||
=item canonic_email ( $email )
|
||||
|
||||
I<Function>.
|
||||
Returns canonical form of e-mail address.
|
||||
|
||||
Leading and trailing white spaces are removed.
|
||||
Latin letters without accents are lower-cased.
|
||||
|
||||
For malformed inputs returns C<undef>.
|
||||
|
||||
=item canonic_message_id ( $message_id )
|
||||
|
||||
Returns canonical form of message ID without trailing or leading whitespaces
|
||||
or C<E<lt>>, C<E<gt>>.
|
||||
|
||||
=item canonic_text ( $text )
|
||||
|
||||
Canonicalizes text.
|
||||
C<$text> should be a binary string encoded by UTF-8 character set or
|
||||
a Unicode string.
|
||||
Forbidden sequences in binary string will be replaced by
|
||||
U+FFFD REPLACEMENT CHARACTERs, and Normalization Form C (NFC) will be applied.
|
||||
|
||||
=item decode_filesystem_safe ( $str )
|
||||
|
||||
I<Function>.
|
||||
Decodes a string encoded by encode_filesystem_safe().
|
||||
|
||||
Parameter:
|
||||
|
||||
=over
|
||||
|
||||
=item $str
|
||||
|
||||
String to be decoded.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Decoded string, stripped C<utf8> flag if any.
|
||||
|
||||
=item decode_html ( $str )
|
||||
|
||||
I<Function>.
|
||||
Decodes HTML entities in a string encoded by UTF-8 or a Unicode string.
|
||||
|
||||
Parameter:
|
||||
|
||||
=over
|
||||
|
||||
=item $str
|
||||
|
||||
String to be decoded.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Decoded string, stripped C<utf8> flag if any.
|
||||
|
||||
=item encode_filesystem_safe ( $str )
|
||||
|
||||
I<Function>.
|
||||
Encodes a string $str to be suitable for filesystem.
|
||||
|
||||
Parameter:
|
||||
|
||||
=over
|
||||
|
||||
=item $str
|
||||
|
||||
String to be encoded.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Encoded string, stripped C<utf8> flag if any.
|
||||
All bytes except C<'-'>, C<'+'>, C<'.'>, C<'@'>
|
||||
and alphanumeric characters are encoded to sequences C<'_'> followed by
|
||||
two hexdigits.
|
||||
|
||||
Note that C<'/'> will also be encoded.
|
||||
|
||||
=item encode_html ( $str, [ $additional_unsafe ] )
|
||||
|
||||
I<Function>.
|
||||
Encodes characters in a string $str to HTML entities.
|
||||
By default
|
||||
C<'E<lt>'>, C<'E<gt>'>, C<'E<amp>'> and C<'E<quot>'> are encoded.
|
||||
|
||||
Parameter:
|
||||
|
||||
=over
|
||||
|
||||
=item $str
|
||||
|
||||
String to be encoded.
|
||||
|
||||
=item $additional_unsafe
|
||||
|
||||
Character or range of characters additionally encoded as entity references.
|
||||
|
||||
This optional parameter was introduced on Sympa 6.2.37b.3.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Encoded string, I<not> stripping utf8 flag if any.
|
||||
|
||||
=item encode_uri ( $str, [ omit => $chars ] )
|
||||
|
||||
I<Function>.
|
||||
Encodes potentially unsafe characters in the string using "percent" encoding
|
||||
suitable for URIs.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item $str
|
||||
|
||||
String to be encoded.
|
||||
|
||||
=item omit =E<gt> $chars
|
||||
|
||||
By default, all characters except those defined as "unreserved" in RFC 3986
|
||||
are encoded, that is, C<[^-A-Za-z0-9._~]>.
|
||||
If this parameter is given, it will prevent encoding additional characters.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Encoded string, stripped C<utf8> flag if any.
|
||||
|
||||
=item escape_chars ( $str )
|
||||
|
||||
Escape weird characters.
|
||||
|
||||
ToDo: This should be obsoleted in the future release: Would be better to use
|
||||
L</encode_filesystem_safe>.
|
||||
|
||||
=item escape_url ( $str )
|
||||
|
||||
DEPRECATED.
|
||||
Would be better to use L</"encode_uri"> or L</"mailtourl">.
|
||||
|
||||
=item foldcase ( $str )
|
||||
|
||||
I<Function>.
|
||||
Returns "fold-case" string suitable for case-insensitive match.
|
||||
For example, a code below looks for a needle in haystack not regarding case,
|
||||
even if they are non-ASCII UTF-8 strings.
|
||||
|
||||
$haystack = Sympa::Tools::Text::foldcase($HayStack);
|
||||
$needle = Sympa::Tools::Text::foldcase($NeedLe);
|
||||
if (index $haystack, $needle >= 0) {
|
||||
...
|
||||
}
|
||||
|
||||
Parameter:
|
||||
|
||||
=over
|
||||
|
||||
=item $str
|
||||
|
||||
A string.
|
||||
|
||||
=back
|
||||
|
||||
=item guessed_to_utf8( $text, [ lang, ... ] )
|
||||
|
||||
I<Function>.
|
||||
Guesses text charset considering language context
|
||||
and returns the text reencoded by UTF-8.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item $text
|
||||
|
||||
Text to be reencoded.
|
||||
|
||||
=item lang, ...
|
||||
|
||||
Language tag(s) which may be given by L<Sympa::Language/"implicated_langs">.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Reencoded text.
|
||||
If any charsets could not be guessed, C<iso-8859-1> will be used
|
||||
as the last resort, just because it covers full range of 8-bit.
|
||||
|
||||
=item mailtourl ( $email, [ decode_html =E<gt> 1 ],
|
||||
[ query =E<gt> {key =E<gt> val, ...} ] )
|
||||
|
||||
I<Function>.
|
||||
Constructs a C<mailto:> URL for given e-mail.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item $email
|
||||
|
||||
E-mail address.
|
||||
|
||||
=item decode_html =E<gt> 1
|
||||
|
||||
If set, arguments are assumed to include HTML entities.
|
||||
|
||||
=item query =E<gt> {key =E<gt> val, ...}
|
||||
|
||||
Optional query.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Constructed URL.
|
||||
|
||||
=item pad ( $str, $width )
|
||||
|
||||
Pads space a string so that result will not be narrower than given width.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item $str
|
||||
|
||||
A string.
|
||||
|
||||
=item $width
|
||||
|
||||
If $width is false value or width of $str is not less than $width,
|
||||
does nothing.
|
||||
If $width is less than C<0>, pads right.
|
||||
Otherwise, pads left.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
Padded string.
|
||||
|
||||
=item qdecode_filename ( $filename )
|
||||
|
||||
Q-Decodes web file name.
|
||||
|
||||
ToDo:
|
||||
This should be obsoleted in the future release: Would be better to use
|
||||
L</decode_filesystem_safe>.
|
||||
|
||||
=item qencode_filename ( $filename )
|
||||
|
||||
Q-Encodes web file name.
|
||||
|
||||
ToDo:
|
||||
This should be obsoleted in the future release: Would be better to use
|
||||
L</encode_filesystem_safe>.
|
||||
|
||||
=item slurp ( $file )
|
||||
|
||||
Get entire content of the file.
|
||||
Normalization by canonic_text() is applied.
|
||||
C<$file> is the path to text file.
|
||||
|
||||
=item unescape_chars ( $str )
|
||||
|
||||
Unescape weird characters.
|
||||
|
||||
ToDo: This should be obsoleted in the future release: Would be better to use
|
||||
L</decode_filesystem_safe>.
|
||||
|
||||
=item valid_email ( $string )
|
||||
|
||||
Basic check of an email address.
|
||||
|
||||
=item weburl ( $base, \@paths, [ decode_html =E<gt> 1 ],
|
||||
[ fragment =E<gt> $fragment ], [ query =E<gt> \%query ] )
|
||||
|
||||
Constructs a C<http:> or C<https:> URL under given base URI.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item $base
|
||||
|
||||
Base URI.
|
||||
|
||||
=item \@paths
|
||||
|
||||
Additional path components.
|
||||
|
||||
=item decode_html =E<gt> 1
|
||||
|
||||
If set, arguments are assumed to include HTML entities.
|
||||
Exception is $base:
|
||||
It is assumed not to include entities.
|
||||
|
||||
=item fragment =E<gt> $fragment
|
||||
|
||||
Optional fragment.
|
||||
|
||||
=item query =E<gt> \%query
|
||||
|
||||
Optional query.
|
||||
|
||||
=back
|
||||
|
||||
Returns:
|
||||
|
||||
A URI.
|
||||
|
||||
=item wrap_text ( $text, [ $init_tab, [ $subsequent_tab, [ $cols ] ] ] )
|
||||
|
||||
I<Function>.
|
||||
Returns line-wrapped text.
|
||||
|
||||
Parameters:
|
||||
|
||||
=over
|
||||
|
||||
=item $text
|
||||
|
||||
The text to be folded.
|
||||
|
||||
=item $init_tab
|
||||
|
||||
Indentation prepended to the first line of paragraph.
|
||||
Default is C<''>, no indentation.
|
||||
|
||||
=item $subsequent_tab
|
||||
|
||||
Indentation prepended to each subsequent line of folded paragraph.
|
||||
Default is C<''>, no indentation.
|
||||
|
||||
=item $cols
|
||||
|
||||
Max number of columns of folded text.
|
||||
Default is C<78>.
|
||||
|
||||
=back
|
||||
|
||||
=back
|
||||
|
||||
=head1 HISTORY
|
||||
|
||||
L<Sympa::Tools::Text> appeared on Sympa 6.2a.41.
|
||||
|
||||
decode_filesystem_safe() and encode_filesystem_safe() were added
|
||||
on Sympa 6.2.10.
|
||||
|
||||
decode_html(), encode_html(), encode_uri() and mailtourl()
|
||||
were added on Sympa 6.2.14, and escape_url() was deprecated.
|
||||
|
||||
guessed_to_utf8() and pad() were added on Sympa 6.2.17.
|
||||
|
||||
canonic_text() and slurp() were added on Sympa 6.2.53b.
|
||||
|
||||
=cut
|
327
dockers/apikaz/source/Sympa/sympa_soap_client.pl
Executable file
327
dockers/apikaz/source/Sympa/sympa_soap_client.pl
Executable file
@ -0,0 +1,327 @@
|
||||
#!/usr/bin/perl
|
||||
# -*- indent-tabs-mode: nil; -*-
|
||||
# vim:ft=perl:et:sw=4
|
||||
# $Id$
|
||||
|
||||
# Sympa - SYsteme de Multi-Postage Automatique
|
||||
#
|
||||
# Copyright (c) 1997, 1998, 1999 Institut Pasteur & Christophe Wolfhugel
|
||||
# Copyright (c) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
||||
# 2006, 2007, 2008, 2009, 2010, 2011 Comite Reseau des Universites
|
||||
# Copyright (c) 2011, 2012, 2013, 2014, 2015, 2016, 2017 GIP RENATER
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use lib '/usr/share/sympa/lib';
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long;
|
||||
use HTTP::Cookies;
|
||||
#use SOAP::Lite +trace;
|
||||
use SOAP::Lite;
|
||||
|
||||
use Sympa::Tools::Data;
|
||||
|
||||
my ($reponse, @ret, $val, %fault);
|
||||
|
||||
my $usage =
|
||||
"$0 is a perl soap client for Sympa for TEST ONLY. Use it to illustrate how to
|
||||
code access to features of Sympa soap server. Authentication can be done via
|
||||
user/password or user cookie or as a trusted remote application
|
||||
|
||||
Usage: $0 <with the following options:>
|
||||
--soap_url=<soap sympa server url>
|
||||
--service=<a sympa service>
|
||||
--trusted_application=<app name>
|
||||
--trusted_application_password=<password>
|
||||
--proxy_vars=<id=value,id2=value2>
|
||||
--service_parameters=<value1,value2,value3>
|
||||
|
||||
|
||||
OR usage: $0 <with the following options:>
|
||||
--soap_url=<soap sympa server url>
|
||||
--user_email=<email>
|
||||
--user_password=<password>
|
||||
--session_id=<sessionid>
|
||||
--service=<a sympa service>
|
||||
--service_parameters=<value1,value2,value3>
|
||||
|
||||
|
||||
OR usage: $0 <with the following options:>
|
||||
--soap_url=<soap sympa server url>
|
||||
--cookie=<sympauser cookie string>
|
||||
|
||||
Example:
|
||||
$0 --soap_url=<soap sympa server url> --cookie=sympauser=someone\@cru.fr
|
||||
";
|
||||
|
||||
my %options;
|
||||
unless (
|
||||
GetOptions(
|
||||
\%main::options, 'soap_url=s',
|
||||
'service=s', 'trusted_application=s',
|
||||
'trusted_application_password=s', 'user_email=s',
|
||||
'user_password=s', 'cookie=s',
|
||||
'proxy_vars=s', 'service_parameters=s',
|
||||
'session_id=s'
|
||||
)
|
||||
) {
|
||||
printf "";
|
||||
}
|
||||
|
||||
my $soap_url = $main::options{'soap_url'};
|
||||
unless (defined $soap_url) {
|
||||
printf "error : missing soap_url parameter\n";
|
||||
printf $usage;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $user_email = $main::options{'user_email'};
|
||||
my $user_password = $main::options{'user_password'};
|
||||
my $session_id = $main::options{'session_id'};
|
||||
my $trusted_application = $main::options{'trusted_application'};
|
||||
my $trusted_application_password =
|
||||
$main::options{'trusted_application_password'};
|
||||
my $proxy_vars = $main::options{'proxy_vars'};
|
||||
my $service = $main::options{'service'};
|
||||
my $service_parameters = $main::options{'service_parameters'};
|
||||
my $cookie = $main::options{'cookie'};
|
||||
|
||||
if (defined $trusted_application) {
|
||||
unless (defined $trusted_application_password) {
|
||||
printf "error : missing trusted_application_password parameter\n";
|
||||
printf $usage;
|
||||
exit 1;
|
||||
}
|
||||
unless (defined $service) {
|
||||
printf "error : missing service parameter\n";
|
||||
printf $usage;
|
||||
exit 1;
|
||||
}
|
||||
unless (defined $proxy_vars) {
|
||||
printf "error : missing proxy_vars parameter\n";
|
||||
printf $usage;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
play_soap_as_trusted($soap_url, $trusted_application,
|
||||
$trusted_application_password, $service, $proxy_vars,
|
||||
$service_parameters);
|
||||
} elsif ($service eq 'getUserEmailByCookie') {
|
||||
play_soap(
|
||||
soap_url => $soap_url,
|
||||
session_id => $session_id,
|
||||
service => $service
|
||||
);
|
||||
|
||||
} elsif (defined $cookie) {
|
||||
printf "error : get_email_cookie\n";
|
||||
get_email($soap_url, $cookie);
|
||||
exit 1;
|
||||
} else {
|
||||
unless (defined $session_id
|
||||
|| (defined $user_email && defined $user_password)) {
|
||||
printf
|
||||
"error : missing session_id OR user_email+user_passwors parameters\n";
|
||||
printf $usage;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
play_soap(
|
||||
soap_url => $soap_url,
|
||||
user_email => $user_email,
|
||||
user_password => $user_password,
|
||||
session_id => $session_id,
|
||||
service => $service,
|
||||
service_parameters => $service_parameters
|
||||
);
|
||||
}
|
||||
|
||||
sub play_soap_as_trusted {
|
||||
my $soap_url = shift;
|
||||
my $trusted_application = shift;
|
||||
my $trusted_application_password = shift;
|
||||
my $service = shift;
|
||||
my $proxy_vars = shift;
|
||||
my $service_parameters = shift;
|
||||
|
||||
my $soap = SOAP::Lite->new();
|
||||
$soap->uri('urn:sympasoap');
|
||||
$soap->proxy($soap_url);
|
||||
|
||||
my @parameters;
|
||||
if (defined $service_parameters) {
|
||||
@parameters = split /,/, $service_parameters;
|
||||
} else {
|
||||
@parameters = ();
|
||||
}
|
||||
my $p = join(',', @parameters);
|
||||
printf
|
||||
"calling authenticateRemoteAppAndRun( $trusted_application, $trusted_application_password, $proxy_vars,$service,$p)\n";
|
||||
|
||||
my $reponse =
|
||||
$soap->authenticateRemoteAppAndRun($trusted_application,
|
||||
$trusted_application_password, $proxy_vars, $service, \@parameters);
|
||||
print_result($reponse);
|
||||
}
|
||||
|
||||
sub get_email {
|
||||
my $soap_url = shift;
|
||||
my $cookie = shift;
|
||||
|
||||
my ($service, $reponse, @ret, $val, %fault);
|
||||
|
||||
## Cookies management
|
||||
# my $uri = URI->new($soap_url);
|
||||
|
||||
# my $cookies = HTTP::Cookies->new(ignore_discard => 1,
|
||||
# file => '/tmp/my_cookies' );
|
||||
# $cookies->load();
|
||||
printf "cookie : %s\n", $cookie;
|
||||
|
||||
my $soap = SOAP::Lite->new();
|
||||
#$soap->on_debug(sub{print@_});
|
||||
$soap->uri('urn:sympasoap');
|
||||
$soap->proxy($soap_url);
|
||||
#, cookie_jar =>$cookies);
|
||||
|
||||
print "\n\ngetEmailUserByCookie....\n";
|
||||
$reponse = $soap->getUserEmailByCookie($cookie);
|
||||
print_result($reponse);
|
||||
exit;
|
||||
|
||||
}
|
||||
|
||||
sub play_soap {
|
||||
my %param = @_;
|
||||
|
||||
my $soap_url = $param{'soap_url'};
|
||||
my $user_email = $param{'user_email'};
|
||||
my $user_password = $param{'user_password'};
|
||||
my $session_id = $param{'session_id'};
|
||||
my $service = $param{'service'};
|
||||
my $service_parameters = $param{'service_parameters'};
|
||||
|
||||
my ($reponse, @ret, $val, %fault);
|
||||
|
||||
## Cookies management
|
||||
# my $uri = URI->new($soap_url);
|
||||
|
||||
my $cookies = HTTP::Cookies->new(
|
||||
ignore_discard => 1,
|
||||
file => '/tmp/my_cookies'
|
||||
);
|
||||
$cookies->load();
|
||||
printf "cookie : %s\n", $cookies->as_string();
|
||||
|
||||
my @parameters;
|
||||
@parameters = split(/,/, $service_parameters)
|
||||
if (defined $service_parameters);
|
||||
my $p = join(',', @parameters);
|
||||
foreach my $tmpParam (@parameters) {
|
||||
printf "param: %s\n", $tmpParam;
|
||||
}
|
||||
|
||||
# Change to the path of Sympa.wsdl
|
||||
#$service = SOAP::Lite->service($soap_url);
|
||||
#$reponse = $service->login($user_email,$user_password);
|
||||
#my $soap = SOAP::Lite->service($soap_url);
|
||||
|
||||
my $soap = SOAP::Lite->new() || die;
|
||||
#$soap->on_debug(sub{print@_});
|
||||
$soap->uri('urn:sympasoap');
|
||||
$soap->proxy($soap_url, cookie_jar => $cookies);
|
||||
|
||||
## Do the login unless a session_id is provided
|
||||
if ($session_id) {
|
||||
print "Using Session_id $session_id\n";
|
||||
|
||||
} else {
|
||||
print "LOGIN....\n";
|
||||
|
||||
#$reponse = $soap->casLogin($soap_url);
|
||||
$reponse = $soap->login($user_email, $user_password);
|
||||
$cookies->save;
|
||||
print_result($reponse);
|
||||
$session_id = $reponse->result;
|
||||
}
|
||||
|
||||
## Don't use authenticateAndRun for lists command
|
||||
|
||||
## Split parameters
|
||||
if ($service_parameters && $service_parameters ne '') {
|
||||
@parameters = split /,/, $service_parameters;
|
||||
}
|
||||
|
||||
if ($service eq 'lists') {
|
||||
printf "\n\nlists....\n";
|
||||
$reponse = $soap->lists();
|
||||
|
||||
} elsif ($service eq 'subscribe') {
|
||||
printf "\n\n$service....\n";
|
||||
$reponse = $soap->subscribe(@parameters);
|
||||
|
||||
} elsif ($service eq 'signoff') {
|
||||
printf "\n\n$service....\n";
|
||||
$reponse = $soap->signoff(@parameters);
|
||||
|
||||
} elsif ($service eq 'add') {
|
||||
printf "\n\n$service....\n";
|
||||
$reponse = $soap->add(@parameters);
|
||||
|
||||
} elsif ($service eq 'del') {
|
||||
printf "\n\n$service....\n";
|
||||
$reponse = $soap->del(@parameters);
|
||||
|
||||
} elsif ($service eq 'getUserEmailByCookie') {
|
||||
printf "\n\n$service....\n";
|
||||
$reponse = $soap->getUserEmailByCookie($session_id);
|
||||
|
||||
} else {
|
||||
printf "\n\nAuthenticateAndRun service=%s;(session_id=%s)....\n",
|
||||
$service, $session_id;
|
||||
$reponse =
|
||||
$soap->authenticateAndRun($user_email, $session_id, $service,
|
||||
\@parameters);
|
||||
}
|
||||
|
||||
print_result($reponse);
|
||||
|
||||
}
|
||||
|
||||
sub print_result {
|
||||
my $r = shift;
|
||||
|
||||
# If we get a fault
|
||||
if (defined $r && $r->fault) {
|
||||
print "Soap error :\n";
|
||||
my %fault = %{$r->fault};
|
||||
foreach $val (keys %fault) {
|
||||
print "$val = $fault{$val}\n";
|
||||
}
|
||||
} else {
|
||||
if (ref($r->result) =~ /^ARRAY/) {
|
||||
#printf "R: $r->result\n";
|
||||
@ret = @{$r->result};
|
||||
} elsif (ref $r->result) {
|
||||
print "Pb " . ($r->result) . "\n";
|
||||
return undef;
|
||||
} else {
|
||||
@ret = $r->result;
|
||||
}
|
||||
Sympa::Tools::Data::dump_var(\@ret, 0, \*STDOUT);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
1851
dockers/apikaz/source/app.py
Normal file
1851
dockers/apikaz/source/app.py
Normal file
File diff suppressed because it is too large
Load Diff
1
dockers/apikaz/source/index.html
Normal file
1
dockers/apikaz/source/index.html
Normal file
@ -0,0 +1 @@
|
||||
<!-- silence is golden -->
|
9
dockers/apikaz/source/requirements.txt
Normal file
9
dockers/apikaz/source/requirements.txt
Normal file
@ -0,0 +1,9 @@
|
||||
flask
|
||||
flask-restful
|
||||
flask-mail
|
||||
requests
|
||||
flasgger
|
||||
passlib
|
||||
unidecode
|
||||
email-validator
|
||||
python-ldap
|
BIN
dockers/apikaz/source/static/favicon.ico
Normal file
BIN
dockers/apikaz/source/static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
82
dockers/apikaz/source/templates/email.css
Normal file
82
dockers/apikaz/source/templates/email.css
Normal file
@ -0,0 +1,82 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f4;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.email-content {
|
||||
background-color: #f0f0f0; /* Light gray background */
|
||||
margin: 20px auto;
|
||||
padding: 20px;
|
||||
border: 1px solid #dddddd;
|
||||
max-width: 600px;
|
||||
width: 90%; /* This makes the content take 90% width of its container */
|
||||
text-align: left; /* Remove text justification */
|
||||
}
|
||||
|
||||
header {
|
||||
background-color: #E16969;
|
||||
color: white;
|
||||
text-align: center;
|
||||
height: 50px; /* Fixed height for header */
|
||||
line-height: 50px; /* Vertically center the text */
|
||||
width: 100%; /* Make header full width */
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: #E16969;
|
||||
color: white;
|
||||
text-align: center;
|
||||
height: 50px; /* Fixed height for footer */
|
||||
line-height: 50px; /* Vertically center the text */
|
||||
width: 100%; /* Make footer full width */
|
||||
}
|
||||
|
||||
.header-container {
|
||||
position: relative; /* Pour positionner le logo et le texte dans le header */
|
||||
height: 50px; /* Hauteur maximale du header */
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: absolute; /* Pour positionner le logo */
|
||||
max-height: 100%; /* Taille maximale du logo égale à la hauteur du header */
|
||||
top: 0; /* Aligner le logo en haut */
|
||||
left: 0; /* Aligner le logo à gauche */
|
||||
margin-right: 10px; /* Marge à droite du logo */
|
||||
}
|
||||
|
||||
.header-container h1, .footer-container p {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.footer-container p {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.footer-container a {
|
||||
color: #FFFFFF; /* White color for links in footer */
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.footer-container a:hover {
|
||||
text-decoration: underline; /* Optional: add underline on hover */
|
||||
}
|
||||
|
||||
a {
|
||||
color: #E16969; /* Same color as header/footer background for all other links */
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration: underline; /* Optional: add underline on hover */
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #E16969;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.6;
|
||||
}
|
9
dockers/apikaz/source/templates/email_footer.html
Normal file
9
dockers/apikaz/source/templates/email_footer.html
Normal file
@ -0,0 +1,9 @@
|
||||
<footer>
|
||||
<div class="footer-container">
|
||||
<p>
|
||||
© {{ now().year }} Kaz. Ici, on prend soin de vos données et on ne les vend pas !
|
||||
<br>
|
||||
<a href="https://kaz.bzh">https://kaz.bzh</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
6
dockers/apikaz/source/templates/email_header.html
Normal file
6
dockers/apikaz/source/templates/email_header.html
Normal file
@ -0,0 +1,6 @@
|
||||
<header>
|
||||
<div class="header-container">
|
||||
<img class="logo" src="https://kaz-cloud.kaz.bzh/apps/theming/image/logo?v=33" alt="KAZ Logo">
|
||||
<h1>Kaz : Le numérique sobre, libre, éthique et local</h1>
|
||||
</div>
|
||||
</header>
|
94
dockers/apikaz/source/templates/email_inscription.html
Normal file
94
dockers/apikaz/source/templates/email_inscription.html
Normal file
@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="fr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Email d'inscription'</title>
|
||||
<style>
|
||||
{% include 'email.css' %}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
{% include 'email_header.html' %}
|
||||
|
||||
<div class="email-content">
|
||||
|
||||
<p>
|
||||
Bonjour {{NOM}}!<br><br>
|
||||
|
||||
Bienvenue chez KAZ!<br><br>
|
||||
|
||||
Vous disposez de :
|
||||
<ul>
|
||||
<li>une messagerie classique : <a href={{URL_WEBMAIL}}>{{URL_WEBMAIL}}</a></li>
|
||||
<li>une messagerie instantanée pour discuter au sein d'équipes : <a href={{URL_AGORA}}>{{URL_AGORA}}</a></li>
|
||||
</ul>
|
||||
Votre email et identifiant pour ces services : {{EMAIL_SOUHAITE}}<br>
|
||||
Le mot de passe : <b>{{PASSWORD}}</b><br><br>
|
||||
|
||||
Pour changer votre mot de passe de messagerie, c'est ici: <a href={{URL_MDP}}>{{URL_MDP}}</a><br>
|
||||
Si vous avez perdu votre mot de passe, c'est ici: <a href={{URL_MDP}}/?action=sendtoken>{{URL_MDP}}/?action=sendtoken</a><br><br>
|
||||
|
||||
Vous pouvez accéder à votre messagerie classique:
|
||||
<ul>
|
||||
<li>soit depuis votre webmail : <a href={{URL_WEBMAIL}}>{{URL_WEBMAIL}}</a></li>
|
||||
<li>soit depuis votre bureau virtuel : <a href={{URL_CLOUD}}>{{URL_CLOUD}}</a></li>
|
||||
<li>soit depuis un client de messagerie comme thunderbird<br>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
{% if ADMIN_ORGA == '1' %}
|
||||
<p>
|
||||
En tant qu'association/famille/société. Vous avez la possibilité d'ouvrir, quand vous le voulez, des services kaz, il vous suffit de nous le demander.<br><br>
|
||||
|
||||
Pourquoi n'ouvrons-nous pas tous les services tout de suite ? parce que nous aimons la sobriété et que nous préservons notre espace disque ;)<br>
|
||||
A quoi sert d'avoir un site web si on ne l'utilise pas, n'est-ce pas ?<br><br>
|
||||
|
||||
Par retour de mail, dites-nous de quoi vous avez besoin tout de suite entre:
|
||||
<ul>
|
||||
<li>une comptabilité : un service de gestion adhérents/clients</li>
|
||||
<li>un site web de type WordPress</li>
|
||||
<li>un cloud : bureau virtuel pour stocker des fichiers/calendriers/contacts et partager avec vos connaissances</li>
|
||||
</ul>
|
||||
Une fois que vous aurez répondu à ce mail, votre demande sera traitée manuellement.
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
Vous avez quelques docs intéressantes sur le wiki de kaz:
|
||||
<ul>
|
||||
<li>Migrer son site internet wordpress vers kaz : <a href="https://wiki.kaz.bzh/wordpress/start#migrer_son_site_wordpress_vers_kaz">https://wiki.kaz.bzh/wordpress/start#migrer_son_site_wordpress_vers_kaz</a></li>
|
||||
<li>Migrer sa messagerie vers kaz : <a href="https://wiki.kaz.bzh/messagerie/gmail/start">https://wiki.kaz.bzh/messagerie/gmail/start</a></li>
|
||||
<li>Démarrer simplement avec son cloud : <a href="https://wiki.kaz.bzh/nextcloud/start">https://wiki.kaz.bzh/messagerie/gmail/start</a></li>
|
||||
</ul>
|
||||
|
||||
Votre quota est de {{QUOTA}}GB. Si vous souhaitez plus de place pour vos fichiers ou la messagerie, faites-nous signe !<br><br>
|
||||
|
||||
Pour accéder à la messagerie instantanée et communiquer avec les membres de votre équipe ou ceux de kaz : <a href={{URL_AGORA}}/login>{{URL_AGORA}}/login</a><br>
|
||||
</p>
|
||||
|
||||
{% if ADMIN_ORGA == '1' %}
|
||||
<p>
|
||||
Comme administrateur de votre organisation, vous pouvez créer des listes de diffusion en vous rendant sur <a href={{URL_LISTE}}>{{URL_LISTE}}</a><br>
|
||||
</p>
|
||||
{% endif %}
|
||||
|
||||
<p>
|
||||
Enfin, vous disposez de tous les autres services KAZ où l'authentification n'est pas nécessaire : <a href={{URL_SITE}}>{{URL_SITE}}</a><br><br>
|
||||
|
||||
En cas de soucis, n'hésitez pas à poser vos questions sur le canal 'Une question ? un soucis' de l'agora dispo ici : <a href={{URL_AGORA}}>{{URL_AGORA}}</a><br><br>
|
||||
|
||||
Si vous avez besoin d'accompagnement pour votre site, votre cloud, votre compta, votre migration de messagerie,...<br>nous proposons des formations mensuelles gratuites. Si vous souhaitez être accompagné par un professionnel, nous pouvons vous donner une liste de pros, référencés par KAZ.<br><br>
|
||||
|
||||
À bientôt 😉<br><br>
|
||||
|
||||
La collégiale de KAZ.<br>
|
||||
|
||||
</p>
|
||||
|
||||
</div> <!-- <div class="email-content"> -->
|
||||
|
||||
{% include 'email_footer.html' %}
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user