mirror of
https://gitlab.easter-eggs.com/ee/ldapsaisie.git
synced 2024-05-19 20:15:27 +02:00
Compare commits
27 commits
Author | SHA1 | Date | |
---|---|---|---|
151b229c3d | |||
118b784a5d | |||
2db4d0fbae | |||
bd98a8b8ef | |||
1a88707f87 | |||
4ce95e54b8 | |||
2ccf579125 | |||
171161ae18 | |||
d26c52400e | |||
62759330a8 | |||
5e9773a015 | |||
557db5d456 | |||
15f67ef00d | |||
753f47fa97 | |||
89c363bd80 | |||
e59ab4a94c | |||
87e58e6425 | |||
e9c49c242f | |||
e8781ab779 | |||
15e3ffe6ef | |||
34396a5fe1 | |||
Benjamin Renard | dc8e08b5d1 | ||
bf1a3affe4 | |||
2104187b14 | |||
78af62d428 | |||
2d08374a53 | |||
129cfa537b |
|
@ -7,6 +7,7 @@ require '/usr/share/php/phpseclib/autoload.php';
|
|||
require 'CAS.php';
|
||||
require 'Mail.php';
|
||||
require 'Mail/mime.php';
|
||||
require 'Html2Text.php';
|
||||
|
||||
spl_autoload_register(array('LSsession', 'loadLSclass'));
|
||||
LSsession :: initialize();
|
||||
|
|
|
@ -114,10 +114,11 @@ $GITDCH \
|
|||
--code-name $DEBIAN_CODENAME \
|
||||
--output $DIST_DIR/debian/changelog \
|
||||
--release-notes ../release-notes.md \
|
||||
--exclude "^Docker: " \
|
||||
--exclude "^CI: " \
|
||||
--exclude "^debian: " \
|
||||
--exclude "\.gitlab-ci\.yml" \
|
||||
--exclude "build\.sh" \
|
||||
--exclude "build-deb\.sh" \
|
||||
--exclude "README\.md" \
|
||||
--exclude "^Merge branch " \
|
||||
--verbose "${GITDCH_EXTRA_ARGS[@]}"
|
||||
|
|
2
debian/control
vendored
2
debian/control
vendored
|
@ -7,7 +7,7 @@ Maintainer: Benjamin Renard <brenard@easter-eggs.com>
|
|||
Package: ldapsaisie
|
||||
Architecture: all
|
||||
Depends: apache2 | httpd, php-ldap | php5-ldap, php-fpm | libapache2-mod-php5 | libapache2-mod-php | php5-cli | php-cli, smarty | smarty3, php-net-ldap2, php-console-table
|
||||
Recommends: php-mbstring, php-phpseclib, php-unidecode, php-zxcvbn, php-ftp, php-mail, php-mail-mime
|
||||
Recommends: php-mbstring, php-phpseclib, php-unidecode, php-zxcvbn, php-ftp, php-mail, php-mail-mime, php-html2text, php-gnupg
|
||||
Description: web based interface for managing LDAP servers content
|
||||
LdapSaisie is a Web application developed to manage LDAP directory.
|
||||
It has been written in PHP / JavaScript and is published under the
|
||||
|
|
|
@ -97,6 +97,7 @@ nav:
|
|||
- Introduction: conf/LSobject/LSattribute/LSattr_html/index.md
|
||||
- boolean: conf/LSobject/LSattribute/LSattr_html/LSattr_html_boolean.md
|
||||
- date: conf/LSobject/LSattribute/LSattr_html/LSattr_html_date.md
|
||||
- gpg_pub_key: conf/LSobject/LSattribute/LSattr_html/LSattr_html_gpg_pub_key.md
|
||||
- image: conf/LSobject/LSattribute/LSattr_html/LSattr_html_image.md
|
||||
- jsonCompositeAttribute: conf/LSobject/LSattribute/LSattr_html/LSattr_html_jsonCompositeAttribute.md
|
||||
- labeledValue: conf/LSobject/LSattribute/LSattr_html/LSattr_html_labeledValue.md
|
||||
|
@ -127,6 +128,7 @@ nav:
|
|||
- differentPassword: conf/LSobject/LSattribute/check_data/differentPassword.md
|
||||
- email: conf/LSobject/LSattribute/check_data/email.md
|
||||
- filesize: conf/LSobject/LSattribute/check_data/filesize.md
|
||||
- gpg_pub_key: conf/LSobject/LSattribute/check_data/gpg_pub_key.md
|
||||
- imagefile: conf/LSobject/LSattribute/check_data/imagefile.md
|
||||
- imagesize: conf/LSobject/LSattribute/check_data/imagesize.md
|
||||
- inarray: conf/LSobject/LSattribute/check_data/inarray.md
|
||||
|
|
|
@ -176,7 +176,8 @@ HTTP 404 sera générée.
|
|||
|
||||
Permet de réclamer un résultat de recherche dans lequel, la clé `objects` sera une liste et
|
||||
non un dictionnaire. Dans ce cas, le DN de l'objet est fourni dans la clé `dn` des détails
|
||||
des objets.
|
||||
des objets. Seul la présence de ce paramètre suffit à activer ce comportement, sa valeur n'a pas
|
||||
d'importance.
|
||||
|
||||
- `withoutCache`
|
||||
|
||||
|
@ -397,6 +398,35 @@ HTTP 404 sera générée.
|
|||
}
|
||||
```
|
||||
|
||||
- `/api/1.0/object/[object type]/[dn]/customAction/[customAction]`
|
||||
|
||||
Cette méthode permet d'exécuter une [action personnalisée](../conf/LSobject/customActions.md) sur
|
||||
un objet dans l'annuaire. Le nom de l'action ainsi que le type de l'objet et son DN sont précisés
|
||||
dans l'URL et doivent être encodés en conséquence.
|
||||
|
||||
**Exemple :**
|
||||
|
||||
```
|
||||
# curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=people,o=ls/customAction/action?pretty'
|
||||
{
|
||||
"dn": "uid=foo.bar,ou=people,o=ls",
|
||||
"type": "LSpeople",
|
||||
"name": "Foo Bar",
|
||||
"success": true,
|
||||
"messages": [
|
||||
"L'action personnalis\u00e9e action a \u00e9t\u00e9 correctement ex\u00e9cut\u00e9e sur Foo Bar.",
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
Par défaut, une action personnalisée ne retourne qu'un booléen permettant de savoir si
|
||||
l'action a correctement été exécutée ou non. En outre, dans un contexte d'appel via l'API, il
|
||||
est possible de retourner des informations via un tableau associatif dont le contenu sera
|
||||
fusionné avec les données retournées par la requête. Pour plus d'informations à ce sujet,
|
||||
consultez la [documentation sur l'écriture d'une fonction implémentant une customAction](../conf/LSobject/customActions.md#ecriture-dune-fonction-implementant-une-customaction).
|
||||
|
||||
- `/api/1.0/object/[object type]/import`
|
||||
|
||||
Cette méthode permet d'importer des objets d'un type en particulier à partir de données d'import
|
||||
|
@ -560,3 +590,168 @@ HTTP 404 sera générée.
|
|||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `/api/1.0/search`
|
||||
|
||||
Cette méthode permet d'effectuer une recherche sur plusieurs types d'objets de l'annuaire à la
|
||||
fois. Par mimétisme du comportement de l'interface web, la recherche est paginée et accepte des
|
||||
paramètres similaires en plus de paramètre plus appropriés à un fonctionnement programmatique.
|
||||
|
||||
Les paramètres acceptés par cette méthode sont sensiblement les mêmes que ceux acceptés par la
|
||||
méthode de recherche d'un type d'objet de l'annuaire en particulier et ils ne seront donc pas
|
||||
tous redocumentés ici :
|
||||
|
||||
- `filter`
|
||||
|
||||
- `predefinedFilter`
|
||||
|
||||
- `pattern`
|
||||
|
||||
- `approx`
|
||||
|
||||
- `basedn`
|
||||
|
||||
- `subDn`
|
||||
|
||||
- `scope`
|
||||
|
||||
- `recursive`
|
||||
|
||||
- `displayFormat`
|
||||
|
||||
- `extraDisplayedColumns`
|
||||
|
||||
- `attributes`
|
||||
|
||||
- `attributesDetails`
|
||||
|
||||
- `page`
|
||||
|
||||
- `all`
|
||||
|
||||
- `as_list`
|
||||
|
||||
- `withoutCache`
|
||||
|
||||
- `keepParamsBetweenSearches`
|
||||
|
||||
- `nbObjectsByPage`
|
||||
|
||||
Permet de préciser le nombre maximum d'objets retournés par type d'objet ET par page du résultat
|
||||
de recherche.
|
||||
|
||||
- `types`
|
||||
|
||||
Permet de limiter les types d'objets à inclure dans le résultat de recherche. Par défaut, tous
|
||||
les types d'objets auxquels l'utilisateur à accès et dont la recherche globale n'est pas
|
||||
désactivée seront inclus.
|
||||
|
||||
- `splited_result`
|
||||
|
||||
Permet de faire en sorte que les objets inclus dans le résultat de recherche soient séparés par
|
||||
type dans des sous-clés de `objects`. Par défaut, tous les objets sont retournés dans la clé
|
||||
`objects` et une sous-clé `type` est ajouté à chacun d'eux pour les distinguer. Seul la présence
|
||||
de ce paramètre suffit à activer ce comportement, sa valeur n'a pas d'importance.
|
||||
|
||||
!!! important
|
||||
|
||||
**Pour chaque type d'objets inclus dans la recherche, un filtre et/ou un mot clé de recherche
|
||||
doit être spécifié.** Cette méthode n'a pas vocation à permettre de lister tous les objets de
|
||||
l'annuaire.
|
||||
|
||||
|
||||
**Exemple :**
|
||||
|
||||
```
|
||||
# curl -u username:secret 'https://ldapsaisie/api/1.0/search?pattern=LdapSaisie&pretty'
|
||||
{
|
||||
"success": true,
|
||||
"objects": {
|
||||
"uid=s.ldapsaisie,ou=people,o=ls": {
|
||||
"name": "Secretariat LdapSaisie",
|
||||
"type": "LSpeople",
|
||||
"Mail": "secretariat@ldapsaisie.biz"
|
||||
},
|
||||
"uid=ls,ou=people,o=ls": {
|
||||
"name": "LdapSaisie",
|
||||
"type": "LSpeople",
|
||||
"Mail": "ldap.saisie@ls.com"
|
||||
},
|
||||
"uid=erwpa,ou=people,o=ls": {
|
||||
"name": "Erwan PAGE",
|
||||
"type": "LSpeople",
|
||||
"Mail": "erwan.page@ldapsaisie.biz"
|
||||
},
|
||||
"uid=invite,ou=people,o=ls": {
|
||||
"name": "Utilisateur de passage",
|
||||
"type": "LSpeople",
|
||||
"Mail": "invite@ldapsaisie.biz"
|
||||
},
|
||||
"uid=demo,ou=people,o=ls": {
|
||||
"name": "Demonstration LdapSaisie",
|
||||
"type": "LSpeople",
|
||||
"Mail": "demo@ls.com"
|
||||
},
|
||||
"uid=admin,ou=people,o=ls": {
|
||||
"name": "Administration LdapSaisie",
|
||||
"type": "LSpeople",
|
||||
"Mail": "admin@ls.com"
|
||||
},
|
||||
"uid=admin3,ou=people,o=ls": {
|
||||
"name": "ZAdministration LdapSaisie",
|
||||
"type": "LSpeople",
|
||||
"Mail": "admin@ls.com"
|
||||
},
|
||||
"uid=ldapsaisie,ou=sysaccounts,o=ls": {
|
||||
"name": "ldapsaisie",
|
||||
"type": "LSsysaccount"
|
||||
}
|
||||
},
|
||||
"total": null,
|
||||
"params": {
|
||||
"keepParamsBetweenSearches": false,
|
||||
"LSpeople": {
|
||||
"filter": null,
|
||||
"pattern": "LdapSaisie",
|
||||
"predefinedFilter": false,
|
||||
"basedn": null,
|
||||
"scope": null,
|
||||
"sizelimit": 0,
|
||||
"attronly": false,
|
||||
"approx": false,
|
||||
"recursive": true,
|
||||
"attributes": [],
|
||||
"onlyAccessible": true,
|
||||
"sortDirection": null,
|
||||
"sortBy": null,
|
||||
"sortlimit": 0,
|
||||
"displayFormat": "%{cn}",
|
||||
"nbObjectsByPage": 25,
|
||||
"withoutCache": false,
|
||||
"extraDisplayedColumns": true
|
||||
},
|
||||
"LSsysaccount": {
|
||||
"filter": null,
|
||||
"pattern": "LdapSaisie",
|
||||
"predefinedFilter": false,
|
||||
"basedn": null,
|
||||
"scope": null,
|
||||
"sizelimit": 0,
|
||||
"attronly": false,
|
||||
"approx": false,
|
||||
"recursive": false,
|
||||
"attributes": [],
|
||||
"onlyAccessible": true,
|
||||
"sortDirection": null,
|
||||
"sortBy": null,
|
||||
"sortlimit": 0,
|
||||
"displayFormat": "%{uid}",
|
||||
"nbObjectsByPage": 30,
|
||||
"withoutCache": false,
|
||||
"extraDisplayedColumns": true
|
||||
}
|
||||
},
|
||||
"page": 1,
|
||||
"nbPages": 1
|
||||
}
|
||||
```
|
||||
|
|
|
@ -1,8 +1,35 @@
|
|||
# LSaddon_mail
|
||||
|
||||
Cet [LSaddon](index.md#configuration-des-lsaddons) est utilisé pour gérer l'envoie de mail. Il
|
||||
Cet [LSaddon](index.md#configuration-des-lsaddons) est utilisé pour gérer l'envoi de courriels. Il
|
||||
utilise pour cela les librairies [PEAR](http://pear.php.net/) *Mail* et *Mail_Mime* qui doivent être
|
||||
installés. Cet [LSaddon](index.md#configuration-des-lsaddons) doit être configuré en éditant son
|
||||
installés.
|
||||
|
||||
Cet [LSaddon](index.md#configuration-des-lsaddons) offre aussi la possibilité d'envoyer des
|
||||
courriels dont le contenu est construit à partir de modèles. Ces modèles sont enregistrés dans des
|
||||
fichiers textes stockés (voir `$GLOBALS['MAIL_TEMPLATES_DIRECTORIES']`). Pour chaque modèle, vous
|
||||
devez fournir trois fichiers portant le même nom mais avec des extensions différentes :
|
||||
|
||||
- `template.subject` : le sujet du courriel. Note : seule la première ligne du fichier est utilisé
|
||||
(et passée dans la fonction `trim()`)
|
||||
- `template.html` : le contenu HTML du courriel
|
||||
- `template.txt`: le contenu texte du courriel
|
||||
|
||||
Ces trois fichiers sont utilisés en tant que modèle [Smarty](http://www.smarty.net/) et seront
|
||||
construit en utilisant les variables fournies dans le contexte d'envoi des courriels. À noter que le
|
||||
moteur Smarty utilisé pour la génération du contenu de ces courriels n'est pas le même que celui
|
||||
utilisé par LdapSaisie pour l'affichage des pages.
|
||||
|
||||
Par ailleurs, cet [LSaddon](index.md#configuration-des-lsaddons) fourni une vue de gestion des
|
||||
modèles de courriels existants (voir `$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS']` pour la
|
||||
configuration des accès).
|
||||
|
||||
!!! warning
|
||||
|
||||
Cette vue n'est pas conçues pour être mise entre toutes les mains. La sécurisation de modèles de
|
||||
courriels étant très complexe, il est fortement recommandé de n'ouvrir l'accès à cette vue
|
||||
qu'aux utilisateurs avertis et de confiances.
|
||||
|
||||
Cet [LSaddon](index.md#configuration-des-lsaddons) doit être configuré en éditant son
|
||||
fichier de configuration `config.LSaddons.mail.php`.
|
||||
|
||||
```php
|
||||
|
@ -67,10 +94,43 @@ $GLOBALS['MAIL_HEARDERS = array();
|
|||
|
||||
// Catch all sent emails
|
||||
$GLOBALS['MAIL_CATCH_ALL'] = array();
|
||||
|
||||
/**
|
||||
* Email templates
|
||||
*
|
||||
* This addon offer ability to send email by using templates. Email templates are stored in
|
||||
* full-text files in configured directories (see $GLOBALS['MAIL_TEMPLATES_DIRECTORIES']). For each
|
||||
* template, you have to provide three files with the same name but with different extensions:
|
||||
* - template.subject: the email subject. Note: only the first line is used (and stripped)
|
||||
* - template.html: the HTML content of the email
|
||||
* - template.txt: the text content of the email
|
||||
* All these files will be used as Smarty templates and will be computed using variables provided
|
||||
* in the sending context. Note that the Smarty object used to compute the template is not the same
|
||||
* as the one used by LdapSaisie to display pages.
|
||||
*
|
||||
* Futhermore, this addon offer a view to list and edit existing template (see
|
||||
* $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] to configured access).
|
||||
*/
|
||||
|
||||
// List of directory paths where as stored mail templates
|
||||
// Notes:
|
||||
// - provided path could be absolute or relative. Relative path are relative to the root base
|
||||
// sources LdapSaisie directory (commonly /usr/share/ldapsaisie or the src directory if you
|
||||
// installed it from sources). On Debian installation, you can specify 'local/email_templates' to
|
||||
// refer to /etc/ldapsaisie/local/email_templates directory/
|
||||
// - Multiple directories could be specified, sorted so that the first ones take priority over
|
||||
// the last one.
|
||||
// - To allow users to edit them using the editor view, these directories must be
|
||||
// writable by PHP process (commonly runed as www-data).
|
||||
$GLOBALS['MAIL_TEMPLATES_DIRECTORIES'] = array('local/email_templates');
|
||||
|
||||
// List of granted LSprofiles to access mail templates editor view
|
||||
// WARNING: Sanitizing mail templates is hell... EXPOSE THIS VIEW ONLY TO TRUSTED USERS!
|
||||
$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] = array('admin');
|
||||
```
|
||||
|
||||
Cet [LSaddon](index.md#configuration-des-lsaddons) offre la possibilité d'utilisé la fonction PHP
|
||||
`sendMail()` :
|
||||
Cet [LSaddon](index.md#configuration-des-lsaddons) offre avant tout la possibilité d'envoyer des
|
||||
courriels en utilisant la fonction PHP `sendMail()` :
|
||||
|
||||
```
|
||||
bool sendMail(
|
||||
|
@ -84,3 +144,16 @@ bool sendMail(
|
|||
<boolean> $html
|
||||
);
|
||||
```
|
||||
|
||||
Pour l'envoi de courriels en utilisant un modèle, il faut utiliser la fonction PHP
|
||||
`sendMailFromTemplate()` :
|
||||
|
||||
```
|
||||
bool sendMailFromTemplate(
|
||||
<string> $tplname,
|
||||
<string> $to,
|
||||
<array> $variables,
|
||||
<array(string)> $headers,
|
||||
<array> $attachments
|
||||
);
|
||||
```
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
# LSattr_html_gpg_pub_key
|
||||
|
||||
Ce type est utilisé pour la gestion des attributs dont la valeur est une clef publique GPG. Il
|
||||
permet dans l'interface, d'avoir un affichage adapté à ce type de donnée.
|
|
@ -0,0 +1,4 @@
|
|||
# gpg_pub_key
|
||||
|
||||
Cette règle vérifie que la valeur est une clé publique GPG. Pour cela, la clé est importée dans un
|
||||
_keyring_ GnuPG.
|
|
@ -33,6 +33,8 @@ tableau, les clé les noms des attributs et les valeurs liés sont la configurat
|
|||
'generate_function' => 'fonction1',
|
||||
'generate_value_format' => '[LSformat]',
|
||||
'default_value' => 'valeur1',
|
||||
'set_default_value_on_creation_if_empty' => [booleen],
|
||||
'force_generation_if_empty' => [booleen],
|
||||
'check_data' => array (
|
||||
// Régle de vérification syntaxique des données saisies
|
||||
),
|
||||
|
@ -157,6 +159,23 @@ tableau, les clé les noms des attributs et les valeurs liés sont la configurat
|
|||
l'attribut si aucune autre méthode n'est disponible (via une fonction ou un
|
||||
[LSformat](../../global/LSformat.md#format-parametrable)).
|
||||
|
||||
- `set_default_value_on_creation_if_empty`
|
||||
|
||||
Booléen permettant de définir si la valeur de l'attribut doit être initialisée avec sa valeur par
|
||||
défaut à la création de l'objet si aucune autre valeur n'as été fournie dans le contexte de
|
||||
création (par défaut : *1*).
|
||||
|
||||
- `force_generation_if_empty`
|
||||
|
||||
Booléen permettant de définir si la valeur de l'attribut doit être générée si elle est vide, que
|
||||
ce soit à la création ou la modification de l'objet (par défaut : *0*).
|
||||
|
||||
!!! warning
|
||||
|
||||
Si la génération échoue, cela bloquera l'action. Par ailleurs, cette génération est
|
||||
prioritaire sur l'utilisation de la valeur par défaut de l'attribut induit par le paramètre
|
||||
`set_default_value_on_creation_if_empty`.
|
||||
|
||||
- `check_data`
|
||||
|
||||
Tableau associatif contenant les règles de vérification syntaxique des données de l'attribut.
|
||||
|
|
|
@ -70,7 +70,8 @@ $GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSsearch'] = array (
|
|||
),
|
||||
'customActions' => array (
|
||||
// Configuration des customActions pour les recherches de ce type d'objet
|
||||
)
|
||||
),
|
||||
'showSelectionBoxes' => [boolean],
|
||||
);
|
||||
```
|
||||
|
||||
|
@ -295,6 +296,14 @@ $GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSsearch'] = array (
|
|||
Tableau associatif contenant les paramètres de configuration des
|
||||
[customActions](#customactions). [Voir la section concernée](#customactions).
|
||||
|
||||
- `showSelectionBoxes`
|
||||
|
||||
Booléen permettant de définir si les cases à cocher de sélections des objets doivent être
|
||||
affichées. Lorsqu'elles sont affichées, l'utilisateur pourra sélectionner un ou plusieurs objets
|
||||
dans la liste avant de déclencher une [customAction](#customsactions). Dans ce cas, les DNs de ces
|
||||
objets seront passés à la page d'exécution de la [customAction](#customsactions) via le paramètre
|
||||
`selected`.
|
||||
|
||||
## Les actions personnalisées (customActions)
|
||||
|
||||
Cette section décrit la manière de configurer les actions personnalisées exécutables sur les
|
||||
|
|
|
@ -17,6 +17,10 @@ $GLOBALS['LSobjects']['[nom du type d'LSobject]']['customActions'] = array (
|
|||
'noConfirmation' => '[booléen]',
|
||||
'redirectToObjectList' => '[booléen]',
|
||||
'noRedirect' => '[booléen]',
|
||||
'accessMethods' => array(
|
||||
'web',
|
||||
'api',
|
||||
),
|
||||
'rights' => array(
|
||||
'LSprofile1',
|
||||
'LSprofile2',
|
||||
|
@ -87,6 +91,13 @@ $GLOBALS['LSobjects']['[nom du type d'LSobject]']['customActions'] = array (
|
|||
[LSprofiles](../global/ldap/LSprofile.md#profils-dutilisateurs) ayant le droit d'exécuter cette
|
||||
action.
|
||||
|
||||
- `accessMethods`
|
||||
|
||||
Tableau permetant de restreindre les moyens d'accès possibles à cette action. Par défaut, tous les
|
||||
moyens d'accès possibles sont autorisés. Valeurs possibles : `web` pour les accès via l'interface
|
||||
web et `api` pour les accès via l'API.
|
||||
|
||||
|
||||
## Écriture d'une fonction implémentant une customAction
|
||||
|
||||
Une fonction implémentant une *customAction* se déclare de la manière suivante :
|
||||
|
@ -101,6 +112,9 @@ Une fonction implémentant une *customAction* se déclare de la manière suivant
|
|||
* Valeurs retournées :
|
||||
* - True : Tout s'est bien passé
|
||||
* - False : Une erreur est survenue
|
||||
* - Cas particulier pour une exécution via l'API : un tableau des données
|
||||
* à retourner. Exemple :
|
||||
* ["success" => true, "extra_info1" => "...", "extra_info2" => "..."]
|
||||
*/
|
||||
function maFonction ($object) {
|
||||
|
||||
|
@ -114,6 +128,14 @@ Cette fonction doit prendre pour seul paramètre, le [LSobject](index.md#configu
|
|||
lequel l'action personnalisée doit être exécutée et doit retourner soit `True` si tout s'est bien
|
||||
passé, soit `False` en cas de problème.
|
||||
|
||||
Une *customAction* pourra également être appelé via l'API. Dans ce cas, il est possible de
|
||||
retourner un tableau associatif et non un simple booléen. Le résultat retourné sera alors
|
||||
fusionné avec les données retournées par la requête. Ce tableau devra contenir à minima la clé
|
||||
`success` qui indiquera via un booléen si l'exécution est un succès ou non. Il est possible de
|
||||
détecter si la méthode est appelée via l'API en appelant la méthode
|
||||
`LSsession :: get('api_mode')`. Vous pouvez prendre exemple sur le code de la méthode
|
||||
`showTechInfo()` fournie par le LSaddon [showTechInfo](../LSaddon/LSaddon_showTechInfo.md).
|
||||
|
||||
!!! note
|
||||
|
||||
Ces fonctions sont le plus couramment définies au sein d'
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
FROM debian:11
|
||||
# Update/upgrade
|
||||
RUN apt-get update
|
||||
RUN apt-get upgrade -y
|
||||
# Install LdapSaisie APT repository
|
||||
RUN apt-get install -y --force-yes wget gnupg lsb-release
|
||||
RUN wget -O - http://ldapsaisie.org/debian/ldapsaisie.gpg.key | apt-key add -
|
||||
RUN echo "deb http://ldapsaisie.org/debian $( lsb_release -c -s ) main" > /etc/apt/sources.list.d/ldapsaisie.list
|
||||
RUN apt-get update
|
||||
# Install dependencies
|
||||
RUN DEBIAN_FRONTEND=noninteractive DEBIAN_PRIORITY=critical apt-get install -y git slapd apache2 php-ldap libapache2-mod-php php-cli smarty3 php-net-ldap2 php-net-ftp php-mail php-mail-mime php-console-table ldapvi locales sed bash-completion liquidprompt vim curl jq iproute2 net-tools composer php-cas php-zxcvbn php-phpseclib php-zip
|
||||
# Add fr_FR* locales
|
||||
RUN sed -i 's/^# fr_FR/fr_FR/' /etc/locale.gen
|
||||
RUN locale-gen
|
||||
# Clone sources
|
||||
RUN git clone https://gitlab.easter-eggs.com/ee/ldapsaisie.git /var/www/ldapsaisie
|
||||
# Fix www-data permission on temporary directory
|
||||
RUN chown www-data: -R /var/www/ldapsaisie/src/tmp/
|
||||
# Configure slapd and load lsexample directory
|
||||
RUN killall slapd || echo slapd is not running
|
||||
RUN /var/www/ldapsaisie/lsexample/restore_lsexample -v
|
||||
# Configure and enable ldapsaisie VirtualHost (as default)
|
||||
RUN a2dissite 000-default
|
||||
COPY apache2.conf /etc/apache2/sites-available/ldapsaisie.conf
|
||||
RUN a2ensite ldapsaisie
|
||||
RUN a2enmod rewrite
|
||||
RUN service apache2 restart
|
||||
# Install ldapsaisie binary (with its bash-completion config)
|
||||
RUN ln -s /var/www/ldapsaisie/src/bin/ldapsaisie.php /usr/local/sbin/ldapsaisie
|
||||
RUN ln -s /var/www/ldapsaisie/debian/ldapsaisie.bash-completion /usr/share/bash-completion/completions/ldapsaisie
|
||||
# Install vimrc.local file
|
||||
COPY vimrc.local /etc/vim/vimrc.local
|
||||
# Install entrypoint
|
||||
COPY bashrc /root/.bashrc
|
||||
COPY entrypoint.sh /usr/local/sbin/entrypoint.sh
|
||||
RUN echo "ldapsaisie-dev" > /etc/hostname
|
||||
ENTRYPOINT /usr/local/sbin/entrypoint.sh
|
||||
EXPOSE 80 389
|
5
docker/Dockerfile.bookworm
Normal file
5
docker/Dockerfile.bookworm
Normal file
|
@ -0,0 +1,5 @@
|
|||
# syntax = edrevo/dockerfile-plus
|
||||
|
||||
FROM debian:bookworm-slim
|
||||
|
||||
INCLUDE+ Dockerfile.common
|
5
docker/Dockerfile.bullseye
Normal file
5
docker/Dockerfile.bullseye
Normal file
|
@ -0,0 +1,5 @@
|
|||
# syntax = edrevo/dockerfile-plus
|
||||
|
||||
FROM debian:bullseye-slim
|
||||
|
||||
INCLUDE+ Dockerfile.common
|
5
docker/Dockerfile.buster
Normal file
5
docker/Dockerfile.buster
Normal file
|
@ -0,0 +1,5 @@
|
|||
# syntax = edrevo/dockerfile-plus
|
||||
|
||||
FROM debian:buster-slim
|
||||
|
||||
INCLUDE+ Dockerfile.common
|
55
docker/Dockerfile.common
Normal file
55
docker/Dockerfile.common
Normal file
|
@ -0,0 +1,55 @@
|
|||
ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Update/upgrade, configure LdapSaisie APT repo and install dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get upgrade -y && \
|
||||
apt-get install -y --force-yes wget gnupg lsb-release && \
|
||||
wget -O - http://ldapsaisie.org/debian/ldapsaisie.gpg.key | apt-key add - && \
|
||||
echo "deb http://ldapsaisie.org/debian $( lsb_release -c -s ) main" > /etc/apt/sources.list.d/ldapsaisie.list && \
|
||||
apt-get update && \
|
||||
apt-get install -y \
|
||||
git \
|
||||
slapd \
|
||||
apache2 \
|
||||
php-ldap \
|
||||
libapache2-mod-php \
|
||||
php-cli \
|
||||
smarty3 \
|
||||
php-net-ldap2 \
|
||||
php-net-ftp \
|
||||
php-mail \
|
||||
php-mail-mime \
|
||||
php-html2text \
|
||||
php-console-table \
|
||||
ldapvi \
|
||||
locales \
|
||||
sed \
|
||||
bash-completion \
|
||||
liquidprompt \
|
||||
vim \
|
||||
curl \
|
||||
jq \
|
||||
iproute2 \
|
||||
net-tools \
|
||||
composer \
|
||||
php-cas \
|
||||
php-zxcvbn \
|
||||
php-phpseclib \
|
||||
php-zip && \
|
||||
apt-get clean && \
|
||||
rm -fr rm -rf /var/lib/apt/lists/*
|
||||
COPY rootfs /
|
||||
# Install LdapSaisie from sources, configure slapd and load lsexample directory
|
||||
RUN git clone https://gitlab.easter-eggs.com/ee/ldapsaisie.git /var/www/ldapsaisie && \
|
||||
ln -s /var/www/ldapsaisie/src/bin/ldapsaisie.php /usr/local/sbin/ldapsaisie && \
|
||||
ln -s /var/www/ldapsaisie/debian/ldapsaisie.bash-completion /usr/share/bash-completion/completions/ldapsaisie && \
|
||||
chown www-data: -R /var/www/ldapsaisie/src/tmp/ && \
|
||||
sed -i 's/^# fr_FR/fr_FR/' /etc/locale.gen && \
|
||||
locale-gen && \
|
||||
a2dissite 000-default && \
|
||||
a2ensite ldapsaisie && \
|
||||
a2enmod rewrite && \
|
||||
/var/www/ldapsaisie/lsexample/restore_lsexample -v
|
||||
# Install entrypoint
|
||||
ENTRYPOINT /entrypoint.sh
|
||||
EXPOSE 80 389
|
22
docker/build-and-push-all.sh
Executable file
22
docker/build-and-push-all.sh
Executable file
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd $( dirname $0 )
|
||||
DIST="$1"
|
||||
|
||||
# Need to use Dockerfile+ (https://github.com/edrevo/dockerfile-plus)
|
||||
export DOCKER_BUILDKIT=1
|
||||
export COMPOSE_DOCKER_CLI_BUILD=1
|
||||
DISTS=(bookworm bullseye buster)
|
||||
LATEST_DIST=${DISTS[0]}
|
||||
|
||||
for dist in ${DISTS[@]}
|
||||
do
|
||||
[ -n "$DIST" -a "$DIST" != "$dist" ] && continue
|
||||
docker build -t docker.io/brenard/ldapsaisie:$dist -f Dockerfile.$dist .
|
||||
[ $? -eq 0 ] && docker push docker.io/brenard/ldapsaisie:$dist
|
||||
done
|
||||
|
||||
[ -n "$DIST" -a "$DIST" != "latest" ] && exit
|
||||
|
||||
docker build -t docker.io/brenard/ldapsaisie:latest -f Dockerfile.$LATEST_DIST .
|
||||
[ $? -eq 0 ] && docker push docker.io/brenard/ldapsaisie:latest
|
|
@ -32,6 +32,9 @@ define('PEAR_MAIL','/usr/share/php/Mail.php');
|
|||
// Pear :: Mail_mime
|
||||
define('PEAR_MAIL_MIME','/usr/share/php/Mail/mime.php');
|
||||
|
||||
// Html2Text
|
||||
define('HTML2TEXT','/usr/share/php/Html2Text.php');
|
||||
|
||||
/*
|
||||
* Méthode d'envoie :
|
||||
* - mail : envoie avec la méthode PHP mail()
|
||||
|
@ -82,3 +85,36 @@ $GLOBALS['MAIL_HEARDERS'] = array();
|
|||
|
||||
// Catch all sent emails
|
||||
$GLOBALS['MAIL_CATCH_ALL'] = array();
|
||||
|
||||
/**
|
||||
* Email templates
|
||||
*
|
||||
* This addon offer ability to send email by using templates. Email templates are stored in
|
||||
* full-text files in configured directories (see $GLOBALS['MAIL_TEMPLATES_DIRECTORIES']). For each
|
||||
* template, you have to provide three files with the same name but with different extensions:
|
||||
* - template.subject: the email subject. Note: only the first line is used (and stripped)
|
||||
* - template.html: the HTML content of the email
|
||||
* - template.txt: the text content of the email
|
||||
* All these files will be used as Smarty templates and will be computed using variables provided
|
||||
* in the sending context. Note that the Smarty object used to compute the template is not the same
|
||||
* as the one used by LdapSaisie to display pages.
|
||||
*
|
||||
* Futhermore, this addon offer a view to list and edit existing template (see
|
||||
* $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] to configured access).
|
||||
*/
|
||||
|
||||
// List of directory paths where as stored mail templates
|
||||
// Notes:
|
||||
// - provided path could be absolute or relative. Relative path are relative to the root base
|
||||
// sources LdapSaisie directory (commonly /usr/share/ldapsaisie or the src directory if you
|
||||
// installed it from sources). On Debian installation, you can specify 'local/email_templates' to
|
||||
// refer to /etc/ldapsaisie/local/email_templates directory/
|
||||
// - Multiple directories could be specified, sorted so that the first ones take priority over
|
||||
// the last one.
|
||||
// - To allow users to edit them using the editor view, these directories must be
|
||||
// writable by PHP process (commonly runed as www-data).
|
||||
$GLOBALS['MAIL_TEMPLATES_DIRECTORIES'] = array('local/email_templates');
|
||||
|
||||
// List of granted LSprofiles to access mail templates editor view
|
||||
// WARNING: Sanitizing mail templates is hell... EXPOSE THIS VIEW ONLY TO TRUSTED USERS!
|
||||
$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] = array('admin');
|
||||
|
|
|
@ -21,4 +21,8 @@
|
|||
******************************************************************************/
|
||||
|
||||
// PhpLdapAdmin View Object URL format
|
||||
define('LS_PHPLDAPADMIN_VIEW_OBJECT_URL_FORMAT','//'.$_SERVER['SERVER_NAME'].'/phpldapadmin/cmd.php?cmd=template_engine&server_id=0&dn=%{dn}');
|
||||
define(
|
||||
'LS_PHPLDAPADMIN_VIEW_OBJECT_URL_FORMAT',
|
||||
'//'.(isset($_SERVER['SERVER_NAME'])?$_SERVER['SERVER_NAME']:gethostname()).
|
||||
'/phpldapadmin/cmd.php?cmd=template_engine&server_id=0&dn=%{dn}'
|
||||
);
|
||||
|
|
|
@ -125,50 +125,6 @@ span.LSaccessRightsMatrixView_inherit {
|
|||
opacity: 0.3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tabs
|
||||
*/
|
||||
ul.LSaccessRightsMatrixView_tabs {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 1em;
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
ul.LSaccessRightsMatrixView_tabs li a {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
ul.LSaccessRightsMatrixView_tabs li {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
background-color: #52BCE5;
|
||||
border-radius: 3px 3px 0px 0px;
|
||||
padding: 4px;
|
||||
display: inline;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
|
||||
ul.LSaccessRightsMatrixView_tabs li.LSaccessRightsMatrixView_active_tab {
|
||||
color: #fff;
|
||||
background-color: #0072B8;
|
||||
}
|
||||
|
||||
div.LSaccessRightsMatrixView_tab_content {
|
||||
border: 1px solid #0072B8;
|
||||
margin: 1em;
|
||||
padding: 0.5em;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.LSaccessRightsMatrixView_tab_content h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Legend
|
||||
*/
|
||||
|
@ -198,15 +154,6 @@ div.LSaccessRightsMatrixView_tab_content h2 {
|
|||
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
div.LSaccessRightsMatrixView_tab_content {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul.LSaccessRightsMatrixView_tabs {
|
||||
margin: 0;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
#LSaccessRightsMatrixView table thead th:first-of-type, #LSaccessRightsMatrixView table tbody th {
|
||||
max-width: 25vw;
|
||||
}
|
||||
|
|
35
src/css/default/LSformElement_gpg_pub_key.css
Normal file
35
src/css/default/LSformElement_gpg_pub_key.css
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* LSformElement_gpg_pub_key
|
||||
*/
|
||||
.LSformElement_gpg_pub_key_value {
|
||||
display: none;
|
||||
width: 30em;
|
||||
font-style: italic;
|
||||
font-family: courier;
|
||||
background-color: #b5e4f6;
|
||||
border: 1px solid #ccc;
|
||||
overflow: auto;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.LSformElement_gpg_pub_key_short_display {
|
||||
font-style: italic;
|
||||
font-family: courier;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
textarea.LSformElement_gpg_pub_key {
|
||||
height: 10em;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
.LSformElement_gpg_pub_key_value {
|
||||
width: 40vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.LSformElement_gpg_pub_key_value {
|
||||
width: calc(100% - 1em);
|
||||
}
|
||||
}
|
|
@ -242,6 +242,15 @@ td.LSobject-list-names {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Selection */
|
||||
td.LSobject-list-selection, th.LSobject-list-selection {
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
.LSobject-list-selection input[type=checkbox] {
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Liste des pages
|
||||
*/
|
||||
|
@ -375,6 +384,55 @@ input[type='submit'].LSview_search, button {
|
|||
margin-left: 1.2rem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tabs
|
||||
*/
|
||||
ul.LStabs {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 1em;
|
||||
margin-bottom: 0;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
ul.LStabs li a {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
ul.LStabs li {
|
||||
text-decoration: none;
|
||||
color: #fff;
|
||||
background-color: #52BCE5;
|
||||
border-radius: 3px 3px 0px 0px;
|
||||
padding: 4px;
|
||||
display: inline;
|
||||
margin-right: 0.3rem;
|
||||
}
|
||||
|
||||
ul.LStabs li.LStabs_active {
|
||||
color: #fff;
|
||||
background-color: #0072B8;
|
||||
}
|
||||
|
||||
div.LStabs_content {
|
||||
border: 1px solid #0072B8;
|
||||
margin: 1em;
|
||||
padding: 0.5em;
|
||||
margin-top: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.LStabs_content_active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
div.LStabs_content h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************
|
||||
* Error page
|
||||
|
@ -474,6 +532,22 @@ input[type='submit'].LSview_search, button {
|
|||
margin-right: 1vw;
|
||||
}
|
||||
|
||||
table.LStable {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* LStabs
|
||||
*/
|
||||
div.LStabs_content {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
ul.LStabs {
|
||||
margin: 0;
|
||||
margin-top: 0.3rem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Manage menu toggle
|
||||
*/
|
||||
|
|
51
src/css/default/email_templates.css
Normal file
51
src/css/default/email_templates.css
Normal file
|
@ -0,0 +1,51 @@
|
|||
div.LStabs_content form {
|
||||
display: block;
|
||||
width: calc(100% - 0.5em);
|
||||
}
|
||||
|
||||
div.LStabs_content form input[type=text] {
|
||||
width: 100%;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
div.LStabs_content form textarea {
|
||||
width: 100%;
|
||||
min-height: 60vh;
|
||||
}
|
||||
|
||||
div.LStabs_content form div.form-footer {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
th.mail_subject, td.mail_subject {
|
||||
width: 20vw;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
th.mail_content, td.mail_content {
|
||||
width: 25vw;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@media (max-width: 1024px) {
|
||||
th.mail_subject, td.mail_subject {
|
||||
width: auto;
|
||||
max-width: 30vw;
|
||||
}
|
||||
th.mail_content, td.mail_content {
|
||||
max-width: 12em;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
th.mail_subject, td.mail_subject {
|
||||
max-width: 50vw;
|
||||
}
|
||||
th.mail_content, td.mail_content {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -253,7 +253,7 @@ td.LSobject-list, tr.LSobject-list, table.LStable tbody td, table.LStable th {
|
|||
}
|
||||
}
|
||||
|
||||
li.LSform_layout_active, ul.LSselect_selectable_object_types li, ul.LSaccessRightsMatrixView_tabs li {
|
||||
li.LSform_layout_active, ul.LSselect_selectable_object_types li, ul.LStabs li {
|
||||
border-radius: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
@ -287,11 +287,11 @@ ul.LSformElement_image_actions {
|
|||
|
||||
|
||||
/* ---- Medium ---- */
|
||||
li.LSform_layout_active, tr.LSobject-list:hover, table.LStable tr:hover, table.LStable tr.bis:hover, ul.LSaccessRightsMatrixView_tabs li, ul.LSselect_selectable_object_types li {
|
||||
li.LSform_layout_active, tr.LSobject-list:hover, table.LStable tr:hover, table.LStable tr.bis:hover, ul.LStabs li, ul.LSselect_selectable_object_types li {
|
||||
background-color: var(--medium-color);
|
||||
}
|
||||
|
||||
div.loginform, div.recoverpasswordform, .loginform input[type='text'], .loginform input[type='password'], .recoverpasswordform input[type='text'], .recoverpasswordform input[type='password'], li.LSview-actions, div.LSform_layout, h1, form.LSglobal_search, div.LSformElement_image {
|
||||
div.loginform, div.recoverpasswordform, .loginform input[type='text'], .loginform input[type='password'], .recoverpasswordform input[type='text'], .recoverpasswordform input[type='password'], li.LSview-actions, div.LSform_layout, h1, form.LSglobal_search, div.LSformElement_image, div.LStabs_content {
|
||||
border-color: var(--medium-color);
|
||||
}
|
||||
|
||||
|
@ -328,7 +328,7 @@ tr.LSobject-list-bis, table.LStable tr.bis, .LSform input[type=text], .LSform in
|
|||
}
|
||||
|
||||
/* ---- Dark ---- */
|
||||
li.LSform_layout_current, .LSform input[type=submit], input[type='submit'].LSview_search, button, ul.LSaccessRightsMatrixView_tabs li.LSaccessRightsMatrixView_active_tab, ul.LSselect_selectable_object_types li.current {
|
||||
li.LSform_layout_current, .LSform input[type=submit], input[type='submit'].LSview_search, button, ul.LStabs li.LStabs_active, ul.LSselect_selectable_object_types li.current {
|
||||
background-color: var(--dark-color);
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,7 @@ li.menu a, a.menu, h1 {
|
|||
color: var(--dark-color);
|
||||
}
|
||||
|
||||
input[type='submit'].LSview_search, input[type='text'].LSview_search, button, div.LSaccessRightsMatrixView_tab_content, ul.LSselect_selectable_object_types {
|
||||
input[type='submit'].LSview_search, input[type='text'].LSview_search, button, ul.LSselect_selectable_object_types {
|
||||
border-color: var(--dark-color);
|
||||
}
|
||||
|
||||
|
|
|
@ -111,8 +111,11 @@ function exportSearchResultAsCSV($LSsearch) {
|
|||
return false;
|
||||
}
|
||||
|
||||
$selected = isset($_REQUEST['selected'])?ensureIsArray($_REQUEST['selected']):[];
|
||||
|
||||
foreach ($LSsearch -> getSearchEntries() as $e) {
|
||||
if ($selected && !in_array($e -> dn, $selected))
|
||||
continue;
|
||||
$row = array(
|
||||
$e -> displayName,
|
||||
$e -> dn
|
||||
|
|
|
@ -24,19 +24,33 @@
|
|||
|
||||
// Support
|
||||
LSerror :: defineError('MAIL_SUPPORT_01',
|
||||
___("MAIL Support : Pear::MAIL is missing.")
|
||||
___("MAIL Support: Pear::MAIL is missing.")
|
||||
);
|
||||
LSerror :: defineError('MAIL_SUPPORT_02',
|
||||
___("MAIL Support : Pear::MAIL_MIME is missing.")
|
||||
___("MAIL Support: Pear::MAIL_MIME is missing.")
|
||||
);
|
||||
LSerror :: defineError('MAIL_SUPPORT_03',
|
||||
___("MAIL Support: Html2Text\Html2Text is missing.")
|
||||
);
|
||||
|
||||
// Other errors
|
||||
LSerror :: defineError('MAIL_00',
|
||||
___("MAIL Error : %{msg}")
|
||||
___("MAIL Error: %{msg}")
|
||||
);
|
||||
|
||||
LSerror :: defineError('MAIL_01',
|
||||
___("MAIL : Error sending your email")
|
||||
___("MAIL: Error sending your email")
|
||||
);
|
||||
LSerror :: defineError('MAIL_02',
|
||||
___("MAIL: Unknown template %{name}.")
|
||||
);
|
||||
LSerror :: defineError('MAIL_03',
|
||||
___("MAIL: Template %{name} is incomplete.")
|
||||
);
|
||||
LSerror :: defineError('MAIL_04',
|
||||
___("MAIL: No writable place to save your changes on this template.")
|
||||
);
|
||||
LSerror :: defineError('MAIL_05',
|
||||
___("MAIL: An error occured saving your changes on this template.")
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -64,20 +78,89 @@ function LSaddon_mail_support() {
|
|||
}
|
||||
}
|
||||
|
||||
if ($retval)
|
||||
LScli :: add_command(
|
||||
'test_send_mail',
|
||||
'cli_test_send_mail',
|
||||
'Send a test email',
|
||||
"[-s subject] [-b body] [recipient]",
|
||||
array (
|
||||
" -s/--subject The test email subject (optional)",
|
||||
" -b/--body The test email body (optional)",
|
||||
" recipient The test email recipient (required)",
|
||||
if (!$retval)
|
||||
return false;
|
||||
|
||||
$GLOBALS['MAIL_LOGGER'] = LSlog :: get_logger('LSaddon_mail');
|
||||
|
||||
LScli :: add_command(
|
||||
'test_send_mail',
|
||||
'cli_test_send_mail',
|
||||
'Send a test email',
|
||||
"[-s subject] [-b body] [-H] [recipient1] [...]",
|
||||
array (
|
||||
" -s/--subject The test email subject (optional)",
|
||||
" -b/--body The test email body (optional)",
|
||||
" -H/--HTML Enable HTML email body mode (optional)",
|
||||
" --header Email header using format:",
|
||||
" header_name=header_value",
|
||||
" Multiple headers could be specified by using this",
|
||||
" optional argument multiple time.",
|
||||
" -a|--attachment Email attachment using format:",
|
||||
" /path/to/attachment.file[:filename]",
|
||||
" The filename is optional (default: using source filename).",
|
||||
" Multiple attachments could be specified by using this",
|
||||
" optional argument multiple time.",
|
||||
" --bcc Add Blind Carbon Copy (BCC) recipient(s)",
|
||||
" --cc Add Carbon Copy (CC) recipient(s)",
|
||||
" recipients The test email recipient(s) (required).",
|
||||
),
|
||||
false, // This command does not need LDAP connection
|
||||
'cli_test_send_mail_autocompleter'
|
||||
);
|
||||
|
||||
// Handle mail templates stuff
|
||||
LScli :: add_command(
|
||||
'test_send_mail_template',
|
||||
'cli_test_send_mail_template',
|
||||
'Test to send an email template',
|
||||
'[template] [-V var1=value] [recipient1] [recipient2]',
|
||||
array(
|
||||
' - Positional arguments :',
|
||||
' - email template name',
|
||||
' - email recipient(s)',
|
||||
'',
|
||||
' - Optional arguments :',
|
||||
' -V|--variable Template variable using format:',
|
||||
' variable_name=variable_value',
|
||||
' Multiple variables could be specified by using this',
|
||||
' optional argument multiple time.',
|
||||
' -H|--header Email header using format:',
|
||||
' header_name=header_value',
|
||||
' Multiple headers could be specified by using this',
|
||||
' optional argument multiple time.',
|
||||
' -a|--attachment Email attachment using format:',
|
||||
' /path/to/attachment.file[:filename]',
|
||||
' The filename is optional (default: using source filename).',
|
||||
' Multiple attachments could be specified by using this',
|
||||
' optional argument multiple time.',
|
||||
' --bcc Add Blind Carbon Copy (BCC) recipient(s)',
|
||||
' --cc Add Carbon Copy (CC) recipient(s)',
|
||||
),
|
||||
false, // This command does not need LDAP connection
|
||||
'cli_test_send_mail_autocompleter'
|
||||
);
|
||||
'cli_test_send_mail_from_template_autocompleter'
|
||||
);
|
||||
if (
|
||||
isset($GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'])
|
||||
&& is_array($GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'])
|
||||
&& $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS']
|
||||
&& list_mail_templates()
|
||||
) {
|
||||
if (!class_exists('\Html2Text\Html2Text')) {
|
||||
if(!LSsession::includeFile(HTML2TEXT, true)) {
|
||||
LSerror :: addErrorCode('MAIL_SUPPORT_03');
|
||||
$retval = false;
|
||||
}
|
||||
}
|
||||
if ($retval)
|
||||
LSsession :: registerLSaddonView(
|
||||
'mail', 'templates',
|
||||
_('Email templates'),
|
||||
'email_templates_view',
|
||||
$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS']
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
return $retval;
|
||||
}
|
||||
|
@ -142,12 +225,11 @@ function sendMail($to, $subject, $msg, $headers=null, $attachments=null,
|
|||
|
||||
$headers["To"] = $to;
|
||||
|
||||
$to = array (
|
||||
'To' => $to
|
||||
);
|
||||
$to = ensureIsArray($to);
|
||||
|
||||
foreach(array_keys($headers) as $header) {
|
||||
if(in_array(strtoupper($header), array('BCC', 'CC'))) {
|
||||
$headers[$header] = ensureIsArray($headers[$header]);
|
||||
if (isset($MAIL_CATCH_ALL) && $MAIL_CATCH_ALL) {
|
||||
$logger -> debug("Mail catched: remove $header header");
|
||||
$msg .= sprintf(
|
||||
|
@ -157,11 +239,12 @@ function sendMail($to, $subject, $msg, $headers=null, $attachments=null,
|
|||
_("\n%s: %s")
|
||||
),
|
||||
strtoupper($header),
|
||||
(is_array($headers[$header])?implode(',', $headers[$header]):$headers[$header]));
|
||||
implode(', ', $headers[$header])
|
||||
);
|
||||
unset($headers[$header]);
|
||||
continue;
|
||||
}
|
||||
$to[strtoupper($header)] = $headers[$header];
|
||||
$to = array_merge($to, $headers[$header]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,6 +288,295 @@ function sendMail($to, $subject, $msg, $headers=null, $attachments=null,
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* List email templates directories
|
||||
* @return array<SplFileInfo>
|
||||
*/
|
||||
function list_mail_templates_directories() {
|
||||
if (isset($GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE']))
|
||||
return $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'];
|
||||
if (
|
||||
!isset($GLOBALS['MAIL_TEMPLATES_DIRECTORIES'])
|
||||
|| !is_array($GLOBALS['MAIL_TEMPLATES_DIRECTORIES'])
|
||||
)
|
||||
return [];
|
||||
$GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'] = [];
|
||||
foreach($GLOBALS['MAIL_TEMPLATES_DIRECTORIES'] as $directory) {
|
||||
$path = new SplFileInfo(
|
||||
substr($directory, 0,1) == '/'?
|
||||
$directory:
|
||||
LS_ROOT_DIR."/".$directory
|
||||
);
|
||||
if ($path && $path->isDir())
|
||||
$GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'][] = $path;
|
||||
else
|
||||
$GLOBALS['MAIL_LOGGER'] -> warning(
|
||||
"list_mail_templates_directories(): directory {$directory} does not exists."
|
||||
);
|
||||
}
|
||||
$GLOBALS['MAIL_LOGGER'] -> debug(
|
||||
"list_mail_templates_directories(): directories = ".
|
||||
implode(', ', $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'])
|
||||
);
|
||||
return $GLOBALS['MAIL_TEMPLATES_DIRECTORIES_CACHE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* List exiting email templates
|
||||
* @return array<string,array<string,string|null>>
|
||||
* [
|
||||
* '[name]' => [
|
||||
* 'subject' => '/path/to/name.subject' or null,
|
||||
* 'html' => '/path/to/name.html' or null,
|
||||
* 'txt' => '/path/to/name.txt' or null,
|
||||
* ],
|
||||
* [...]
|
||||
* ]
|
||||
*/
|
||||
function list_mail_templates() {
|
||||
if (isset($GLOBALS['MAIL_TEMPLATES']) && $GLOBALS['MAIL_TEMPLATES'])
|
||||
return $GLOBALS['MAIL_TEMPLATES'];
|
||||
$GLOBALS['MAIL_TEMPLATES'] = [];
|
||||
$expected_extensions = ['subject', 'html', 'txt'];
|
||||
foreach(list_mail_templates_directories() as $directory) {
|
||||
foreach (new DirectoryIterator($directory) as $fileInfo) {
|
||||
if(
|
||||
$fileInfo->isDot()
|
||||
|| !$fileInfo->isFile()
|
||||
|| !$fileInfo->isReadable()
|
||||
|| !in_array($fileInfo->getExtension(), $expected_extensions)
|
||||
)
|
||||
continue;
|
||||
$name = $fileInfo->getBasename(".".$fileInfo->getExtension());
|
||||
if (!array_key_exists($name, $GLOBALS['MAIL_TEMPLATES'])) {
|
||||
$GLOBALS['MAIL_TEMPLATES'][$name] = [];
|
||||
foreach($expected_extensions as $ext) $GLOBALS['MAIL_TEMPLATES'][$name][$ext] = null;
|
||||
}
|
||||
if (!$GLOBALS['MAIL_TEMPLATES'][$name][$fileInfo->getExtension()])
|
||||
$GLOBALS['MAIL_TEMPLATES'][$name][$fileInfo->getExtension()] = $fileInfo->getRealPath();
|
||||
}
|
||||
}
|
||||
return $GLOBALS['MAIL_TEMPLATES'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for writable path to save change of a template file
|
||||
* @param string $template The template name
|
||||
* @param string $extension The template file extension (subject, html or txt)
|
||||
* @return string|false The path of writable template file if found, false otherwise
|
||||
*/
|
||||
function get_mail_template_saved_path($template, $extension) {
|
||||
$templates = list_mail_templates();
|
||||
if (!array_key_exists($template, $templates))
|
||||
return false;
|
||||
$found = false;
|
||||
$first_writable = false;
|
||||
foreach(list_mail_templates_directories() as $directory) {
|
||||
$file_path = new SplFileInfo("$directory/$template.$extension");
|
||||
if ($file_path->isFile()) {
|
||||
// File exist, check is writable
|
||||
if ($file_path->isWritable())
|
||||
return $file_path->getRealPath();
|
||||
// If we don't find previously a writable file, trigger an error
|
||||
if (!$first_writable) {
|
||||
$GLOBALS['MAIL_LOGGER'] -> error(
|
||||
"get_mail_template_saved_path($template, $extension): file '{$file_path->getRealPath()}' ".
|
||||
"is not writable, can't saved this template file."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (!$first_writable && $directory->isWritable()) {
|
||||
$first_writable = strval($file_path);
|
||||
}
|
||||
}
|
||||
// No existing writable file found
|
||||
if ($first_writable) return $first_writable;
|
||||
$GLOBALS['MAIL_LOGGER'] -> error(
|
||||
"get_mail_template_saved_path($template, $extension): ".
|
||||
"no writable path found, can't saved this template file."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send email from template
|
||||
* @param string $tplname The email template name
|
||||
* @param string $to The email recipient
|
||||
* @param array<string,mixed> $variables Variables to use to compute the template
|
||||
* @param array<string,string>|null $headers Email headers
|
||||
* @param array<string,string>|null $attachments Email attachments as an array with
|
||||
* filepath as key and filename as value
|
||||
* @return boolean True if the email was sent, false otherwise
|
||||
*/
|
||||
function sendMailFromTemplate(
|
||||
$tplname, $to, $variables=null, $headers=null, $attachments=null
|
||||
) {
|
||||
$templates = list_mail_templates();
|
||||
if (!array_key_exists($tplname, $templates)) {
|
||||
LSerror :: addErrorCode('MAIL_02', $tplname);
|
||||
return False;
|
||||
}
|
||||
|
||||
$tpl = $templates[$tplname];
|
||||
if (!$tpl['subject'] || !($tpl['txt'] || $tpl['html'])) {
|
||||
LSerror :: addErrorCode('MAIL_03', $tplname);
|
||||
return False;
|
||||
}
|
||||
|
||||
$smarty = new Smarty();
|
||||
$smarty -> setCompileDir(LS_TMP_DIR_PATH);
|
||||
|
||||
if (is_array($variables))
|
||||
array_map([$smarty, "assign"], array_keys($variables), array_values($variables));
|
||||
|
||||
try {
|
||||
$subject = $smarty -> fetch("file:{$tpl['subject']}");
|
||||
// Multiple line from subject cause problem, trim it and only the first line
|
||||
$subject = explode("\n", trim($subject))[0];
|
||||
|
||||
$GLOBALS['MAIL_LOGGER'] -> debug(
|
||||
"sendMailFromTemplate($tplname, ".implode("|", $to)."): ".
|
||||
"subject compute from '{$tpl['subject']}'."
|
||||
);
|
||||
if ($tpl['html']) {
|
||||
$message = $smarty -> fetch("file:{$tpl['html']}");
|
||||
$html = true;
|
||||
$GLOBALS['MAIL_LOGGER'] -> debug(
|
||||
"sendMailFromTemplate($tplname, ".implode("|", $to)."): ".
|
||||
"HTML content compute from '{$tpl['html']}'."
|
||||
);
|
||||
}
|
||||
else {
|
||||
$message = $smarty -> fetch("file:{$tpl['txt']}");
|
||||
$html = false;
|
||||
$GLOBALS['MAIL_LOGGER'] -> debug(
|
||||
"sendMailFromTemplate($tplname, ".implode("|", $to)."): ".
|
||||
"text content compute from '{$tpl['txt']}'."
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$GLOBALS['MAIL_LOGGER'] -> exception(
|
||||
$e, getFData(
|
||||
_("An exception occured forging message from email template '%{template}'"),
|
||||
$tplname
|
||||
),
|
||||
false
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return sendMail($to, $subject, $message, $headers, $attachments, "\n", "utf8", $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Email templates management view
|
||||
* @return void
|
||||
*/
|
||||
function email_templates_view() {
|
||||
$template = isset($_REQUEST['name'])?$_REQUEST['name']:null;
|
||||
$templates = [];
|
||||
foreach(list_mail_templates() as $name => $tpl) {
|
||||
if ($template && $template != $name)
|
||||
continue;
|
||||
$templates[$name] = [
|
||||
'name' => $name,
|
||||
'subject' => $tpl['subject']?file_get_contents($tpl['subject']):null,
|
||||
'html' => $tpl['html']?file_get_contents($tpl['html']):null,
|
||||
'txt' => $tpl['txt']?file_get_contents($tpl['txt']):null,
|
||||
];
|
||||
if ($template) continue;
|
||||
if ($templates[$name]['html']) {
|
||||
$Html2Text = new \Html2Text\Html2Text($templates[$name]['html']);
|
||||
$templates[$name]['html'] = substr($Html2Text->getText(), 0, 70)."...";
|
||||
}
|
||||
if ($templates[$name]['txt']) {
|
||||
$templates[$name]['txt'] = substr($templates[$name]['txt'], 0, 70)."...";
|
||||
}
|
||||
}
|
||||
if ($template) {
|
||||
if (!array_key_exists($template, $templates)) {
|
||||
LSurl::redirect("addon/mail/templates");
|
||||
}
|
||||
LStemplate :: assign('pagetitle', getFData(_('Email template: %{name}'), $template));
|
||||
$tab = isset($_REQUEST['tab'])?$_REQUEST['tab']:'subject';
|
||||
$path = false;
|
||||
switch ($tab) {
|
||||
case 'subject':
|
||||
$path = get_mail_template_saved_path($template, $tab);
|
||||
if (array_key_exists('subject', $_POST)) {
|
||||
if (!$path)
|
||||
LSerror :: addErrorCode('MAIL_04');
|
||||
elseif (file_put_contents($path, $_POST['subject']) !== false) {
|
||||
LSsession :: addInfo(_("Your changes have been saved."));
|
||||
LSurl::redirect("addon/mail/templates?name=".urlencode($template)."&tab=$tab");
|
||||
}
|
||||
else {
|
||||
LSerror :: addErrorCode('MAIL_05');
|
||||
$tpl['subject'] = $_POST['subject'];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'html':
|
||||
$path = get_mail_template_saved_path($template, $tab);
|
||||
if (array_key_exists('html', $_POST)) {
|
||||
if (!$path)
|
||||
LSerror :: addErrorCode('MAIL_04');
|
||||
elseif (file_put_contents($path, $_POST['html']) !== false) {
|
||||
LSsession :: addInfo(_("Your changes have been saved."));
|
||||
LSurl::redirect("addon/mail/templates?name=".urlencode($template)."&tab=$tab");
|
||||
}
|
||||
else {
|
||||
LSerror :: addErrorCode('MAIL_05');
|
||||
$tpl['html'] = $_POST['html'];
|
||||
}
|
||||
}
|
||||
LStemplate :: addLibJSscript('tinymce/js/tinymce/tinymce.min.js');
|
||||
LStemplate :: addJSscript('email_templates.js');
|
||||
break;
|
||||
|
||||
case 'txt':
|
||||
$path = get_mail_template_saved_path($template, $tab);
|
||||
if (array_key_exists('txt', $_POST)) {
|
||||
if (!$path)
|
||||
LSerror :: addErrorCode('MAIL_04');
|
||||
elseif (file_put_contents($path, $_POST['txt']) !== false) {
|
||||
LSsession :: addInfo(_("Your changes have been saved."));
|
||||
LSurl::redirect("addon/mail/templates?name=".urlencode($template)."&tab=$tab");
|
||||
}
|
||||
else {
|
||||
LSerror :: addErrorCode('MAIL_05');
|
||||
$tpl['txt'] = $_POST['txt'];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
LSurl::redirect("addon/mail/templates?name=".urlencode($template));
|
||||
}
|
||||
LStemplate :: assign('template', $templates[$template]);
|
||||
LStemplate :: assign('tab', $tab);
|
||||
LStemplate :: assign('writable', boolval($path));
|
||||
$LSview_actions = array();
|
||||
$LSview_actions['return'] = array (
|
||||
'label' => _('Go back'),
|
||||
'url' => 'addon/mail/templates',
|
||||
'action' => 'view'
|
||||
);
|
||||
LStemplate :: assign('LSview_actions', $LSview_actions);
|
||||
LSsession :: setTemplate('email_template.tpl');
|
||||
}
|
||||
else {
|
||||
LStemplate :: assign('pagetitle', _('Email templates'));
|
||||
LStemplate :: assign('templates', $templates);
|
||||
LSsession :: setTemplate('email_templates.tpl');
|
||||
}
|
||||
LStemplate :: addCssFile('email_templates.css');
|
||||
}
|
||||
|
||||
|
||||
if (php_sapi_name() != 'cli')
|
||||
return true;
|
||||
|
@ -215,9 +587,12 @@ if (php_sapi_name() != 'cli')
|
|||
* @return bool
|
||||
*/
|
||||
function cli_test_send_mail($command_args) {
|
||||
$recipient = null;
|
||||
$recipients = array();
|
||||
$subject = "Test email";
|
||||
$body = "This is a test message.";
|
||||
$html = false;
|
||||
$headers = array();
|
||||
$attachments = array();
|
||||
for ($i=0; $i < count($command_args); $i++) {
|
||||
switch ($command_args[$i]) {
|
||||
case '--subject':
|
||||
|
@ -240,23 +615,68 @@ function cli_test_send_mail($command_args) {
|
|||
LScli :: usage("Invalid body provided.");
|
||||
break;
|
||||
|
||||
case '--html':
|
||||
case '-H':
|
||||
$html = true;
|
||||
break;
|
||||
|
||||
case '--header':
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
$parts = explode('=', $command_args[$i]);
|
||||
if (count($parts) != 2)
|
||||
LScli :: usage('Invalid header string ('.$command_args[$i].').');
|
||||
if (array_key_exists($parts[0], $headers))
|
||||
LScli :: usage('Header "'.$parts[0].'" already specified.');
|
||||
$headers[$parts[0]] = $parts[1];
|
||||
break;
|
||||
|
||||
case '-a':
|
||||
case '--attachment':
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
$parts = explode(':', $command_args[$i]);
|
||||
$path = $parts[0];
|
||||
if (!is_file($path))
|
||||
LScli :: usage('Invalid attachment "'.$command_args[$i].'": file not found.');
|
||||
$attachments[$path] = count($parts) >= 2?$parts[1]:basename($path);
|
||||
break;
|
||||
|
||||
case '--bcc':
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
if (!checkEmail($command_args[$i]))
|
||||
LScli :: usage('Invalid BCC recipient "'.$command_args[$i].'".');
|
||||
$headers['BCC'] = isset($headers['BCC'])?ensureIsArray($headers['BCC']):[];
|
||||
$headers['BCC'][] = $command_args[$i];
|
||||
break;
|
||||
|
||||
case '--cc':
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
if (!checkEmail($command_args[$i]))
|
||||
LScli :: usage('Invalid CC recipient "'.$command_args[$i].'".');
|
||||
$headers['CC'] = isset($headers['CC'])?ensureIsArray($headers['CC']):[];
|
||||
$headers['CC'][] = $command_args[$i];
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!$recipient && checkEmail($command_args[$i]))
|
||||
$recipient = $command_args[$i];
|
||||
if (checkEmail($command_args[$i]))
|
||||
$recipients[] = $command_args[$i];
|
||||
else
|
||||
LScli :: usage("Invalid parameter '".$command_args[$i]."'.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!$recipient)
|
||||
LScli :: usage("You must provide test email recipient as first positional parameter");
|
||||
if (!$recipients)
|
||||
LScli :: usage("You must provide as least one email recipient as positional parameter");
|
||||
|
||||
$logger = LSlog :: get_logger('LSaddon_mail');
|
||||
if (!sendMail($recipient, $subject, $body)) {
|
||||
$logger -> error("Fail to send test email sent to '$recipient'.");
|
||||
if (!sendMail($recipients, $subject, $body, $headers, $attachments, null, null, $html)) {
|
||||
$logger -> error("Fail to send test email sent to '".implode(', ', $recipients)."'.");
|
||||
return false;
|
||||
}
|
||||
$logger -> info("Test email sent to '$recipient'.");
|
||||
$logger -> info("Test email sent to '".implode(', ', $recipients)."'.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -271,19 +691,158 @@ function cli_test_send_mail($command_args) {
|
|||
* @return array<string> List of available options for the word to autocomplete
|
||||
**/
|
||||
function cli_test_send_mail_autocompleter($comp_words, $comp_word_num, $comp_word, $opts) {
|
||||
switch ($comp_words[$comp_word_num-1]) {
|
||||
case '-s':
|
||||
case '--subject':
|
||||
case '-b':
|
||||
case '--body':
|
||||
return array();
|
||||
break;
|
||||
}
|
||||
if (isset($comp_words[$comp_word_num-1]))
|
||||
switch ($comp_words[$comp_word_num-1]) {
|
||||
case '-s':
|
||||
case '--subject':
|
||||
case '-b':
|
||||
case '--body':
|
||||
case '--header':
|
||||
case '-a':
|
||||
case '--attachment':
|
||||
case '--bcc':
|
||||
case '--cc':
|
||||
return array();
|
||||
break;
|
||||
}
|
||||
$opts = array_merge(
|
||||
$opts,
|
||||
array (
|
||||
'-s', '--subject',
|
||||
'-b', '--body',
|
||||
'-H', '--html',
|
||||
'--header',
|
||||
'-a', '--attachment',
|
||||
'--bcc', '--cc',
|
||||
)
|
||||
);
|
||||
return LScli :: autocomplete_opts($opts, $comp_word);
|
||||
}
|
||||
|
||||
/**
|
||||
* CLI test_send_mail_template command
|
||||
*
|
||||
* @param array $command_args Command arguments :
|
||||
* - Positional arguments :
|
||||
* - template name
|
||||
* - recipient
|
||||
* - Optional arguments :
|
||||
* - -V|--variable: template variable (format: variable=value)
|
||||
* - -H|--header: header (format: header=value)
|
||||
* - -a|--attachent: (format: /path/to/file.ext:filename or just /path/to/file.ext)
|
||||
* - -bcc: BCC recipient(s)
|
||||
* - -cc: CC recipient(s)
|
||||
*
|
||||
* @return boolean True on success, false otherwise
|
||||
**/
|
||||
function cli_test_send_mail_template($command_args) {
|
||||
$template = null;
|
||||
$recipients = array();
|
||||
$variables = array();
|
||||
$headers = array();
|
||||
$attachments = array();
|
||||
for ($i=0; $i < count($command_args); $i++) {
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
if (in_array($command_args[$i], array('-V', '--variable'))) {
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
$parts = explode('=', $command_args[$i]);
|
||||
if (count($parts) != 2)
|
||||
LScli :: usage('Invalid variable string ('.$command_args[$i].').');
|
||||
if (array_key_exists($parts[0], $variables))
|
||||
LScli :: usage('Variable "'.$parts[0].'" already specified.');
|
||||
$variables[$parts[0]] = $parts[1];
|
||||
}
|
||||
elseif (in_array($command_args[$i], array('-H', '--header'))) {
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
$parts = explode('=', $command_args[$i]);
|
||||
if (count($parts) != 2)
|
||||
LScli :: usage('Invalid header string ('.$command_args[$i].').');
|
||||
if (array_key_exists($parts[0], $headers))
|
||||
LScli :: usage('Header "'.$parts[0].'" already specified.');
|
||||
$headers[$parts[0]] = $parts[1];
|
||||
}
|
||||
elseif (in_array($command_args[$i], array('-a', '--attachent'))) {
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
$parts = explode(':', $command_args[$i]);
|
||||
$path = $parts[0];
|
||||
if (!is_file($path))
|
||||
LScli :: usage('Invalid attachment "'.$command_args[$i].'": file not found.');
|
||||
$attachments[$path] = count($parts) >= 2?$parts[1]:basename($path);
|
||||
}
|
||||
elseif ($command_args[$i] == '--bcc') {
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
if (!checkEmail($command_args[$i]))
|
||||
LScli :: usage('Invalid BCC recipient "'.$command_args[$i].'".');
|
||||
$headers['BCC'] = isset($headers['BCC'])?ensureIsArray($headers['BCC']):[];
|
||||
$headers['BCC'][] = $command_args[$i];
|
||||
}
|
||||
elseif ($command_args[$i] == '--cc') {
|
||||
$i++;
|
||||
LScli :: unquote_word($command_args[$i]);
|
||||
if (!checkEmail($command_args[$i]))
|
||||
LScli :: usage('Invalid CC recipient "'.$command_args[$i].'".');
|
||||
$headers['CC'] = isset($headers['CC'])?ensureIsArray($headers['CC']):[];
|
||||
$headers['CC'][] = $command_args[$i];
|
||||
}
|
||||
else if (is_null($template)) {
|
||||
$template = $command_args[$i];
|
||||
}
|
||||
else if (checkEmail($command_args[$i])) {
|
||||
$recipients[] = $command_args[$i];
|
||||
}
|
||||
else
|
||||
LScli :: usage('Invalid recipient "'.$command_args[$i].'".');
|
||||
}
|
||||
|
||||
if (is_null($template) || empty($recipients))
|
||||
LScli :: usage('You must provide email template name and at least one recipient.');
|
||||
|
||||
return sendMailFromTemplate(
|
||||
$template,
|
||||
$recipients,
|
||||
$variables,
|
||||
$headers,
|
||||
$attachments
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Args autocompleter for CLI test_send_mail_from_template command
|
||||
*
|
||||
* @param array<string> $comp_words List of already typed words of the command
|
||||
* @param int $comp_word_num The command word number to autocomplete
|
||||
* @param string $comp_word The command word to autocomplete
|
||||
* @param array<string> $opts List of global available options
|
||||
*
|
||||
* @return array<string> List of available options for the word to autocomplete
|
||||
**/
|
||||
function cli_test_send_mail_from_template_autocompleter(
|
||||
$comp_words, $comp_word_num, $comp_word, $opts
|
||||
) {
|
||||
if (isset($comp_words[$comp_word_num-1]))
|
||||
switch ($comp_words[$comp_word_num-1]) {
|
||||
case '-v':
|
||||
case '--variable':
|
||||
case '-H':
|
||||
case '--header':
|
||||
case '-a':
|
||||
case '--attachment':
|
||||
case '--bcc':
|
||||
case '--cc':
|
||||
return array();
|
||||
break;
|
||||
}
|
||||
$opts = array_merge(
|
||||
$opts,
|
||||
array (
|
||||
'-v', '--variable',
|
||||
'-H', '--header',
|
||||
'-a', '--attachment',
|
||||
'--bcc', '--cc',
|
||||
)
|
||||
);
|
||||
return LScli :: autocomplete_opts($opts, $comp_word);
|
||||
|
|
|
@ -86,7 +86,7 @@ function LSaddon_ppolicy_support() {
|
|||
if ($retval) {
|
||||
LSurl :: add_handler(
|
||||
'#^api/1.0/exportPpolicyInfo/(?P<LSobject>[^/]+)/?$#',
|
||||
'handle/export_api_LSobject_exportPpolicyInfo',
|
||||
'handle_api_LSobject_exportPpolicyInfo',
|
||||
true, false, true);
|
||||
}
|
||||
|
||||
|
@ -137,20 +137,22 @@ function get_ppolicy_password_max_age($ppolicy_dn=null) {
|
|||
* @param string $text The text of the badge
|
||||
* @param string $bg_color The background color of the badge (optional, default: green)
|
||||
* @param string $color The text color of the badge (optional, default: white)
|
||||
* @param string $title The text title of the badge (optional, default: empty string)
|
||||
*
|
||||
* @return string The HTML code of the badge
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*/
|
||||
function _ppolicy_badge($text, $bg_color='green', $color='white') {
|
||||
function _ppolicy_badge($text, $bg_color='green', $color='white', $title='') {
|
||||
// Disable HTML formating on PHP cli
|
||||
if (php_sapi_name() == 'cli') return $text;
|
||||
return sprintf(
|
||||
'<span style="
|
||||
background-color: %s; color: %s;
|
||||
padding: 0.2em; font-size: 0.8em; border-radius: 0.4em;"
|
||||
class="LStips" title="%s"
|
||||
>%s</span>',
|
||||
$bg_color, $color, $text
|
||||
$bg_color, $color, $title, $text
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -170,7 +172,10 @@ function ppolicy_extraDisplayColumn_password_expiration($entry) {
|
|||
$change_time = ldapDate2Timestamp($change_time);
|
||||
$max_age = get_ppolicy_password_max_age($entry->pwdPolicySubentry);
|
||||
if ($max_age === false)
|
||||
return _ppolicy_badge(__('Unknown'), 'gray');
|
||||
return _ppolicy_badge(
|
||||
__('Unknown'), 'gray', 'white',
|
||||
sprintf(_('Last password changed: %s, no duration of validity configured.'), date('Y-m-d H:i', $change_time))
|
||||
);
|
||||
if (!$max_age)
|
||||
return _('Never');
|
||||
$expiration_date = $change_time + $max_age;
|
||||
|
@ -178,7 +183,9 @@ function ppolicy_extraDisplayColumn_password_expiration($entry) {
|
|||
if ($expiration_date <= $now)
|
||||
return _ppolicy_badge(
|
||||
sprintf(_('Expired (since %s)'), date('Y-m-d H:i', $expiration_date)),
|
||||
'black');
|
||||
'black', 'white',
|
||||
sprintf(_('Last password changed: %s, duration of validity: %s days'), date('Y-m-d H:i', $change_time), floor($max_age/86400))
|
||||
);
|
||||
$delta = $expiration_date - $now;
|
||||
if ($delta <= LS_PPOLICY_CRITICAL_EXPIRATION_THRESHOLD)
|
||||
$badge_color = 'red';
|
||||
|
@ -188,7 +195,9 @@ function ppolicy_extraDisplayColumn_password_expiration($entry) {
|
|||
$badge_color = 'green';
|
||||
return _ppolicy_badge(
|
||||
sprintf(_('Expire on %s'), date('Y-m-d H:i', $expiration_date)),
|
||||
$badge_color);
|
||||
$badge_color, 'white',
|
||||
sprintf(_('Last password changed: %s, duration of validity: %s days'), date('Y-m-d H:i', $change_time), floor($max_age/86400))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -110,6 +110,17 @@ function showTechInfo($object) {
|
|||
// Sort other internal attributes by name
|
||||
ksort($internal_attrs);
|
||||
|
||||
// Handle API mode
|
||||
if (LSsession :: get('api_mode')) {
|
||||
return [
|
||||
"object_classes" => $object_classes,
|
||||
"structural_object_class" => $structural_object_class,
|
||||
"special_internal_attributes" => $special_internal_attributes,
|
||||
"other_internal_attrs" => $internal_attrs,
|
||||
"success" => true,
|
||||
];
|
||||
}
|
||||
|
||||
LStemplate :: assign('pagetitle', getFData(_('%{name}: Technical information'), $object -> getDisplayName()));
|
||||
|
||||
$LSview_actions=array();
|
||||
|
|
32
src/includes/class/class.LSattr_html_gpg_pub_key.php
Normal file
32
src/includes/class/class.LSattr_html_gpg_pub_key.php
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2007 Easter-eggs
|
||||
* https://ldapsaisie.org
|
||||
*
|
||||
* Author: See AUTHORS file in top-level directory.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* HTML attribute type for GPG public key
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*/
|
||||
class LSattr_html_gpg_pub_key extends LSattr_html {
|
||||
|
||||
var $LSformElement_type = 'gpg_pub_key';
|
||||
|
||||
}
|
|
@ -187,11 +187,11 @@ class LSattr_html_select_list extends LSattr_html{
|
|||
* Function use with uasort to sort two values in ASC order
|
||||
*
|
||||
* @param string $va One value
|
||||
* @param string $va One value
|
||||
* @param string $vb Another value
|
||||
*
|
||||
* @return int Value for uasort
|
||||
**/
|
||||
protected static function _sortTwoValuesAsc(&$va,&$vb) {
|
||||
protected static function _sortTwoValuesAsc($va,$vb) {
|
||||
if (is_array($va)) {
|
||||
// Force sub-options at the end
|
||||
$nva='ZZZZ'.$va['label'];
|
||||
|
@ -217,11 +217,11 @@ class LSattr_html_select_list extends LSattr_html{
|
|||
* Function use with uasort to sort two values in DESC order
|
||||
*
|
||||
* @param string $va One value
|
||||
* @param string $va One value
|
||||
* @param string $vb Another value
|
||||
*
|
||||
* @return int Value for uasort
|
||||
**/
|
||||
protected static function _sortTwoValuesDesc(&$va,&$vb) {
|
||||
protected static function _sortTwoValuesDesc($va,$vb) {
|
||||
return (-1 * static :: _sortTwoValuesAsc($va,$vb));
|
||||
}
|
||||
|
||||
|
|
|
@ -543,22 +543,22 @@ class LSattribute extends LSlog_staticLoggerClass {
|
|||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'attribut est obligatoire
|
||||
* Check if the attribute is required
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*
|
||||
* @return boolean true si l'attribut est obligatoire, false sinon
|
||||
* @return boolean True if the attribute is required, false otherwise.
|
||||
*/
|
||||
public function isRequired() {
|
||||
return $this -> getConfig('required', false, 'bool');
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la valeur de l'attribut peut être générée
|
||||
* Check if the attribute value could be generated
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*
|
||||
* @return boolean true si la valeur de l'attribut peut être générée, false sinon
|
||||
* @return boolean True if the attribute value could be generated, false otherwise.
|
||||
*/
|
||||
public function canBeGenerated() {
|
||||
$format = $this -> getConfig('generate_value_format', $this -> getConfig('default_value'));
|
||||
|
@ -571,11 +571,12 @@ class LSattribute extends LSlog_staticLoggerClass {
|
|||
}
|
||||
|
||||
/**
|
||||
* Génere la valeur de l'attribut à partir de la fonction de génération
|
||||
* Generate attribute value using its generation function, its generation format or its default
|
||||
* value.
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*
|
||||
* @return boolean true si la valeur à put être générée, false sinon
|
||||
* @return boolean True if value has been generated, false otherwise.
|
||||
*/
|
||||
public function generateValue() {
|
||||
$value = $this -> getConfig('default_value', false);
|
||||
|
@ -595,6 +596,23 @@ class LSattribute extends LSlog_staticLoggerClass {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set attribute value as default
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*
|
||||
* @return boolean True if value has been set as default, false otherwise
|
||||
*/
|
||||
public function setValueAsDefault() {
|
||||
$value = $this -> getConfig('default_value', false);
|
||||
if ($value !== false) {
|
||||
$this -> updateData = ensureIsArray($value);
|
||||
self :: log_debug($this."setValueAsDefault(): default values = ".varDump($this -> updateData));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la valeur de l'attribut pour son enregistrement dans l'annuaire
|
||||
* si l'attribut à été modifié.
|
||||
|
@ -820,29 +838,35 @@ class LSattribute extends LSlog_staticLoggerClass {
|
|||
* Error Codes
|
||||
**/
|
||||
LSerror :: defineError('LSattribute_01',
|
||||
___("LSattribute : Attribute %{attr} : LDAP or HTML types unknow (LDAP = %{ldap} & HTML = %{html}).")
|
||||
___("LSattribute: Attribute %{attr} : LDAP or HTML types unknow (LDAP = %{ldap} & HTML = %{html}).")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_02',
|
||||
___("LSattribute : The function %{func} to display the attribute %{attr} is unknow.")
|
||||
___("LSattribute: The function %{func} to display the attribute %{attr} is unknow.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_03',
|
||||
___("LSattribute : The rule %{rule} to validate the attribute %{attr} is unknow.")
|
||||
___("LSattribute: The rule %{rule} to validate the attribute %{attr} is unknow.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_04',
|
||||
___("LSattribute : Configuration data to verify the attribute %{attr} are incorrect.")
|
||||
___("LSattribute: Configuration data to verify the attribute %{attr} are incorrect.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_05',
|
||||
___("LSattribute : The function %{func} to save the attribute %{attr} is unknow.")
|
||||
___("LSattribute: The function %{func} to save the attribute %{attr} is unknow.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_06',
|
||||
___("LSattribute : The value of the attribute %{attr} can't be generated.")
|
||||
___("LSattribute: The value of the attribute %{attr} can't be generated.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_07',
|
||||
___("LSattribute : Generation of the attribute %{attr} failed.")
|
||||
___("LSattribute: Generation of the attribute %{attr} failed.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_08',
|
||||
___("LSattribute : Generation of the attribute %{attr} did not return a correct value.")
|
||||
___("LSattribute: Generation of the attribute %{attr} did not return a correct value.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_09',
|
||||
___("LSattribute : The attr_%{type} of the attribute %{name} is not yet defined.")
|
||||
___("LSattribute: The attr_%{type} of the attribute %{name} is not yet defined.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_10',
|
||||
___("LSattribute: The default value of the attribute %{attr} is invalid.")
|
||||
);
|
||||
LSerror :: defineError('LSattribute_11',
|
||||
___("LSattribute: Fail to set attribute %{attr} value as default.")
|
||||
);
|
||||
|
|
|
@ -819,7 +819,7 @@ class LScli extends LSlog_staticLoggerClass {
|
|||
* @return string The quote character or an empty string if word if not quoted
|
||||
*/
|
||||
public static function unquote_word(&$word) {
|
||||
if (in_array($word[0], array('"', "'"))) {
|
||||
if ($word && in_array($word[0], array('"', "'"))) {
|
||||
$quote_char = $word[0];
|
||||
$word = substr($word, 1);
|
||||
if ($word[strlen($word)-1] == $quote_char)
|
||||
|
|
114
src/includes/class/class.LSformElement_gpg_pub_key.php
Normal file
114
src/includes/class/class.LSformElement_gpg_pub_key.php
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2007 Easter-eggs
|
||||
* https://ldapsaisie.org
|
||||
*
|
||||
* Author: See AUTHORS file in top-level directory.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
/**
|
||||
* Form element for GPG public key
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*/
|
||||
|
||||
class LSformElement_gpg_pub_key extends LSformElement {
|
||||
|
||||
var $template = 'LSformElement_gpg_pub_key.tpl';
|
||||
var $fieldTemplate = 'LSformElement_gpg_pub_key_field.tpl';
|
||||
|
||||
|
||||
/**
|
||||
* Parse one value
|
||||
*
|
||||
* @param string $value The value to parse
|
||||
* @param boolean $details Enable/disable details return (optional, default: true)
|
||||
*
|
||||
* @return array|string Parsed value as array is $details is enabled, the raw value otherwise
|
||||
*/
|
||||
public function parseValue($value, $details=true) {
|
||||
if (!$details)
|
||||
return $value;
|
||||
if (class_exists('gnupg')) {
|
||||
// The home_dir parameter passed to gnupg_init() is not correctly handled in PHP 7.3, also set
|
||||
// the GNUPGHOME environment variable.
|
||||
putenv('GNUPGHOME='.LS_TMP_DIR_PATH);
|
||||
$gpg = new gnupg(["home_dir" => LS_TMP_DIR_PATH]);
|
||||
// Don't warn about (GNUPG_ERROR_SILENT is currently the default but ensure it)
|
||||
$gpg -> seterrormode(GNUPG_ERROR_SILENT);
|
||||
$info = $gpg -> import($value);
|
||||
}
|
||||
else {
|
||||
LSerror :: addErrorCode('LSformElement_gpg_pub_key_01');
|
||||
$info = false;
|
||||
}
|
||||
if (
|
||||
is_array($info)
|
||||
// @phpstan-ignore-next-line
|
||||
&& ($info['imported'] + $info['unchanged']) != 1
|
||||
)
|
||||
$info = false;
|
||||
return array(
|
||||
'fingerprint' => is_array($info)?$info["fingerprint"]:null,
|
||||
'value' => $value
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les infos d'affichage de l'élément
|
||||
*
|
||||
* Cette méthode retourne les informations d'affichage de l'élement
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDisplay(){
|
||||
LStemplate :: addCssFile('LSformElement_gpg_pub_key.css');
|
||||
$return = $this -> getLabelInfos();
|
||||
$params = array();
|
||||
if (!$this -> isFreeze()) {
|
||||
$params['values_txt'] = $this -> values;
|
||||
}
|
||||
else {
|
||||
LStemplate :: addJSscript('LSformElement_gpg_pub_key.js');
|
||||
LStemplate :: addHelpInfo(
|
||||
'LSformElement_gpg_pub_key',
|
||||
array(
|
||||
'display' => _("Display the full key.")
|
||||
)
|
||||
);
|
||||
|
||||
$values_txt = array();
|
||||
foreach ($this -> values as $value) {
|
||||
$parsedValue = $this -> parseValue($value);
|
||||
$values_txt[] = $parsedValue;
|
||||
}
|
||||
$params['values_txt'] = $values_txt;
|
||||
$params['invalidValueTxt'] = _('Invalid value');
|
||||
}
|
||||
$return['html'] = $this -> fetchTemplate(NULL, $params);
|
||||
return $return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Error Codes
|
||||
*/
|
||||
LSerror :: defineError('LSformElement_gpg_pub_key_01',
|
||||
___("LSformElement_gpg_pub_key: PHP GnuPG extension is missing, can't parse value.")
|
||||
);
|
|
@ -48,7 +48,7 @@ class LSformElement_postaladdress extends LSformElement_textarea {
|
|||
$return = parent :: getDisplay();
|
||||
if ($this -> isFreeze()) {
|
||||
if (!empty($this->values)) {
|
||||
$map_url_format = $this -> getParam('html_options.map_url_format', 'http://nominatim.openstreetmap.org/search.php?q=%{pattern}', 'string');
|
||||
$map_url_format = $this -> getParam('html_options.map_url_format', 'https://nominatim.openstreetmap.org/ui/search.html?q=%{pattern}', 'string');
|
||||
$map_url_pattern_generate_function = $this -> getParam('html_options.map_url_pattern_generate_function');
|
||||
$map_url_pattern_format = $this -> getParam('html_options.map_url_pattern_format');
|
||||
if ($map_url_pattern_generate_function) {
|
||||
|
|
|
@ -149,11 +149,11 @@ class LSformElement_select_object extends LSformElement {
|
|||
* Function use with uasort to sort two values
|
||||
*
|
||||
* @param array $va One value
|
||||
* @param array $va One value
|
||||
* @param array $va Another value
|
||||
*
|
||||
* @return int Value for uasort
|
||||
**/
|
||||
private function _sortTwoValues(&$va,&$vb) {
|
||||
private function _sortTwoValues($va, $vb) {
|
||||
if ($this -> getParam('html_options.sortDirection') == 'DESC') {
|
||||
$dir=-1;
|
||||
}
|
||||
|
|
62
src/includes/class/class.LSformRule_gpg_pub_key.php
Normal file
62
src/includes/class/class.LSformRule_gpg_pub_key.php
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
/*******************************************************************************
|
||||
* Copyright (C) 2007 Easter-eggs
|
||||
* https://ldapsaisie.org
|
||||
*
|
||||
* Author: See AUTHORS file in top-level directory.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
/**
|
||||
* LSformRule to check GPG public key
|
||||
*
|
||||
* @author Benjamin Renard <brenard@easter-eggs.com>
|
||||
*/
|
||||
class LSformRule_gpg_pub_key extends LSformRule {
|
||||
|
||||
/**
|
||||
* Validate SSH public key value
|
||||
*
|
||||
* @param string $value The value to validate
|
||||
* @param array $options Validation options
|
||||
* @param LSformElement &$formElement The related formElement object
|
||||
*
|
||||
* @return boolean true if the value is valide, false if not
|
||||
*/
|
||||
public static function validate($value, $options, &$formElement) {
|
||||
if (!class_exists('gnupg')) {
|
||||
LSerror :: addErrorCode('LSformRule_gpg_pub_key_01');
|
||||
return false;
|
||||
}
|
||||
// The home_dir parameter passed to gnupg_init() is not correctly handled in PHP 7.3, also set
|
||||
// the GNUPGHOME environment variable.
|
||||
putenv('GNUPGHOME='.LS_TMP_DIR_PATH);
|
||||
$gpg = new gnupg(["home_dir" => LS_TMP_DIR_PATH]);
|
||||
// Don't warn about (GNUPG_ERROR_SILENT is currently the default but ensure it)
|
||||
$gpg -> seterrormode(GNUPG_ERROR_SILENT);
|
||||
$info = $gpg -> import($value);
|
||||
// @phpstan-ignore-next-line
|
||||
return is_array($info) && ($info['imported'] + $info['unchanged']) == 1 && $info['fingerprint'];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Error Codes
|
||||
*/
|
||||
LSerror :: defineError('LSformRule_gpg_pub_key_01',
|
||||
___("LSformRule_gpg_pub_key: PHP GnuPG extension is missing, can't validate value.")
|
||||
);
|
|
@ -516,9 +516,10 @@ class LSldapObject extends LSlog_staticLoggerClass {
|
|||
unset($forceGeneration[$key]);
|
||||
}
|
||||
}
|
||||
if(
|
||||
if (
|
||||
in_array($attr_name, $forceGeneration)
|
||||
|| (empty($attr_values) && $attr -> isRequired())
|
||||
|| (empty($attr_values) && $attr -> getConfig('force_generation_if_empty', false, 'bool'))
|
||||
) {
|
||||
if ( $attr -> canBeGenerated()) {
|
||||
if ($attr -> generateValue()) {
|
||||
|
@ -541,6 +542,23 @@ class LSldapObject extends LSlog_staticLoggerClass {
|
|||
$retval = false;
|
||||
}
|
||||
}
|
||||
elseif (
|
||||
empty($attr_values)
|
||||
&& !is_empty($attr -> getConfig('default_value'))
|
||||
&& $idForm == 'create'
|
||||
&& $attr -> getConfig('set_default_value_on_creation_if_empty', true, 'bool')
|
||||
) {
|
||||
if ($attr -> setValueAsDefault()) {
|
||||
if (!$this -> validateAttrData($LSform, $attr, $justCheck)) {
|
||||
LSerror :: addErrorCode('LSattribute_10',$attr -> getLabel());
|
||||
$retval = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LSerror :: addErrorCode('LSattribute_11',$attr -> getLabel());
|
||||
$retval = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $retval;
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
******************************************************************************/
|
||||
|
||||
class LSmail {
|
||||
class LSmail extends LSlog_staticLoggerClass {
|
||||
|
||||
/*
|
||||
* Méthode chargeant les dépendances d'affichage
|
||||
|
|
|
@ -658,11 +658,13 @@ class LSsearch extends LSlog_staticLoggerClass {
|
|||
}
|
||||
|
||||
/**
|
||||
* Define search parameters by reading request data ($_REQUEST)
|
||||
* Define search parameters by reading request data
|
||||
*
|
||||
* @param array<string,mixed>|null $request The request (optional, default: $_REQUEST)
|
||||
*
|
||||
* @return boolean True if all parameters found in request data are handled, False otherwise
|
||||
*/
|
||||
public function setParamsFromRequest() {
|
||||
public function setParamsFromRequest($request=null) {
|
||||
$allowedParams = array(
|
||||
'pattern', 'approx', 'recursive', 'extraDisplayedColumns', 'nbObjectsByPage',
|
||||
'attributes', 'sortBy', 'sortDirection', 'withoutCache', 'predefinedFilter',
|
||||
|
@ -670,8 +672,9 @@ class LSsearch extends LSlog_staticLoggerClass {
|
|||
'filter', 'basedn', 'subDn', 'scope', 'attributes', 'displayFormat',
|
||||
);
|
||||
$data = array();
|
||||
$request = $request?$request:$_REQUEST;
|
||||
|
||||
foreach($_REQUEST as $key => $value) {
|
||||
foreach($request as $key => $value) {
|
||||
if (!in_array($key, $allowedParams))
|
||||
continue;
|
||||
switch($key) {
|
||||
|
@ -1392,12 +1395,12 @@ class LSsearch extends LSlog_staticLoggerClass {
|
|||
/**
|
||||
* Function use with uasort to sort two entry
|
||||
*
|
||||
* @param LSsearchEntry &$a One entry of result
|
||||
* @param LSsearchEntry &$b One entry of result
|
||||
* @param LSsearchEntry $a One entry of result
|
||||
* @param LSsearchEntry $b Another entry of result
|
||||
*
|
||||
* @return int Value for uasort
|
||||
**/
|
||||
private function _sortTwoEntry(&$a,&$b) {
|
||||
private function _sortTwoEntry($a, $b) {
|
||||
$sortBy = $this -> params['sortBy'];
|
||||
$sortDirection = $this -> params['sortDirection'];
|
||||
if ($sortDirection=='ASC') {
|
||||
|
|
|
@ -3210,6 +3210,9 @@ class LSsession {
|
|||
LSerror :: defineError('LSsession_27',
|
||||
___("LSsession : You always seem to use %{old} in your custom code: Please upgrade it and use %{new}.<pre>\nContext:\n%{context}</pre>")
|
||||
);
|
||||
LSerror :: defineError('LSsession_28',
|
||||
___("LSsession : This custom action can not be executed by this way.")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
23
src/includes/js/LSformElement_gpg_pub_key.js
Normal file
23
src/includes/js/LSformElement_gpg_pub_key.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
var LSformElement_gpg_pub_key = new Class({
|
||||
initialize: function(){
|
||||
$$('span.LSformElement_gpg_pub_key_short_display').each(function(span) {
|
||||
span.addEvent('click',this.onShortDisplayClick.bind(this,span));
|
||||
varLSdefault.addHelpInfo(span,'LSformElement_gpg_pub_key','display');
|
||||
}, this);
|
||||
},
|
||||
|
||||
onShortDisplayClick: function(span) {
|
||||
var p = span.getParent().getFirst('p.LSformElement_gpg_pub_key_value');
|
||||
if (typeof(p)) {
|
||||
if (p.getStyle('display')=='none') {
|
||||
p.setStyle('display','block');
|
||||
}
|
||||
else {
|
||||
p.setStyle('display',' none');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
window.addEvent(window.ie ? 'load' : 'domready', function() {
|
||||
varLSformElement_gpg_pub_key = new LSformElement_gpg_pub_key();
|
||||
});
|
|
@ -50,6 +50,10 @@ var LSview = new Class({
|
|||
}, this);
|
||||
this.onWindowResized();
|
||||
window.addEvent('resize', this.onWindowResized.bind(this));
|
||||
|
||||
this.listSelectAll = $('LSobject-list-select-all');
|
||||
if (this.listSelectAll)
|
||||
this.listSelectAll.addEvent('click', this.toogleListSelectAll.bind(this));
|
||||
},
|
||||
|
||||
onWindowResized: function() {
|
||||
|
@ -127,10 +131,10 @@ var LSview = new Class({
|
|||
},
|
||||
|
||||
onCustomActionBtnClick: function(event,a) {
|
||||
if (a.hasClass('LScustomActions_noConfirmation')) {
|
||||
return true;
|
||||
}
|
||||
Event(event).stop();
|
||||
if (a.hasClass('LScustomActions_noConfirmation')) {
|
||||
return this.executeCustomActionFromA(a);
|
||||
}
|
||||
if (!this._confirmBoxOpen) {
|
||||
this._confirmBoxOpen = 1;
|
||||
var getName = new RegExp('customAction/([^/]*)');
|
||||
|
@ -157,6 +161,11 @@ var LSview = new Class({
|
|||
executeCustomActionFromA: function(a) {
|
||||
var validatedURL = new URL(a.href);
|
||||
validatedURL.searchParams.set('valid', '1');
|
||||
$$('td.LSobject-list-selection input')
|
||||
.filter(function(x) {return x.checked})
|
||||
.each(function(el, idx) {
|
||||
validatedURL.searchParams.set(`selected[${idx}]`, el.value);
|
||||
})
|
||||
document.location = validatedURL.href;
|
||||
},
|
||||
|
||||
|
@ -164,6 +173,12 @@ var LSview = new Class({
|
|||
if (ul.hasClass('LSview-actions-dropdown')) {
|
||||
ul.toggleClass('LSview-actions-dropdown-opened');
|
||||
}
|
||||
},
|
||||
|
||||
toogleListSelectAll: function() {
|
||||
$$('td.LSobject-list-selection input').each(function(el){
|
||||
el.checked = !el.checked;
|
||||
}, this);
|
||||
}
|
||||
|
||||
});
|
||||
|
|
20
src/includes/js/email_templates.js
Normal file
20
src/includes/js/email_templates.js
Normal file
|
@ -0,0 +1,20 @@
|
|||
window.addEvent(window.ie ? 'load' : 'domready', function() {
|
||||
var textarea = document.getElement('textarea[name=html]');
|
||||
if (!textarea) return;
|
||||
var options = {};
|
||||
if (textarea.disabled) {
|
||||
options.readonly = 1;
|
||||
options.setup = function(editor) {
|
||||
editor.on('skinLoaded', function(e) {
|
||||
editor.notificationManager.open({
|
||||
text: textarea.get('title'),
|
||||
type: 'warning'
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
options.target = textarea;
|
||||
options.language = varLSdefault.getCurrentLang();
|
||||
tinymce.init(options);
|
||||
});
|
|
@ -311,11 +311,12 @@ LSurl :: add_handler('#^favicon\.ico#', 'handle_favicon_ico_view', false, true,
|
|||
function handle_libs_file($request) {
|
||||
$path = LStemplate :: getLibFilePath($request -> file);
|
||||
if ($path && is_file($path)) {
|
||||
switch (strtolower(substr($path, -4))) {
|
||||
case '.css':
|
||||
$info = new SplFileInfo($path);
|
||||
switch ($info -> getExtension()) {
|
||||
case 'css':
|
||||
$mime_type = 'text/css';
|
||||
break;
|
||||
case '.js':
|
||||
case 'js':
|
||||
$mime_type = 'text/javascript';
|
||||
break;
|
||||
default:
|
||||
|
@ -529,7 +530,10 @@ function handle_LSobject_search($request) {
|
|||
'hiddenFields' => $LSsearch -> getHiddenFieldForm(),
|
||||
'predefinedFilter' => $LSsearch -> getParam('predefinedFilter')
|
||||
));
|
||||
|
||||
LStemplate :: assign(
|
||||
'showSelectionBoxes',
|
||||
LSconfig :: get("LSobjects.$LSobject.LSsearch.showSelectionBoxes", false, "bool")
|
||||
);
|
||||
|
||||
if (LSsession :: loadLSclass('LSform')) {
|
||||
LSform :: loadDependenciesDisplayView($object, true);
|
||||
|
@ -1075,7 +1079,13 @@ function handle_LSobject_show($request) {
|
|||
$customActionsConfig = LSconfig :: get('LSobjects.'.$LSobject.'.customActions');
|
||||
if (is_array($customActionsConfig)) {
|
||||
foreach($customActionsConfig as $name => $config) {
|
||||
if (LSsession :: canExecuteCustomAction($dn, $LSobject, $name)) {
|
||||
if (
|
||||
LSsession :: canExecuteCustomAction($dn, $LSobject, $name)
|
||||
&& (
|
||||
! LSconfig :: get('accessMethods', [], 'array', $config)
|
||||
|| in_array('web', LSconfig :: get('accessMethods', [], 'array', $config))
|
||||
)
|
||||
) {
|
||||
$LSview_actions[] = array (
|
||||
'label' => ((isset($config['label']))?__($config['label']):__($name)),
|
||||
'hideLabel' => ((isset($config['hideLabel']) && $config['hideLabel'])?$config['hideLabel']:False),
|
||||
|
@ -1369,6 +1379,15 @@ function handle_LSobject_customAction($request) {
|
|||
$config = LSconfig :: get("LSobjects.$LSobject.customActions.$customAction");
|
||||
$title = isset($config['label'])?__($config['label']):$customAction;
|
||||
|
||||
if (
|
||||
LSconfig :: get('accessMethods', [], 'array', $config)
|
||||
&& !in_array('web', LSconfig :: get('accessMethods', [], 'array', $config))
|
||||
) {
|
||||
LSerror :: addErrorCode('LSsession_28');
|
||||
LSsession :: displayTemplate();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check customAction function
|
||||
$function = LSconfig :: get('function', null, null, $config);
|
||||
if (!is_callable($function)) {
|
||||
|
@ -1556,6 +1575,235 @@ function get_LSobject_from_API_request($request, $instanciate=true, $check_acces
|
|||
return get_LSobject_from_request($request, $instanciate, $check_access, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle API global search request
|
||||
* @param LSurlRequest $request The request
|
||||
* @return void
|
||||
*/
|
||||
function handle_api_global_search($request) {
|
||||
// Check global search is enabled
|
||||
if (!LSsession :: globalSearch()) {
|
||||
LSurl :: error_404($request);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!LSsession :: loadLSclass('LSsearch')) {
|
||||
LSerror :: addErrorCode('LSsession_05','LSsearch');
|
||||
LSsession :: displayAjaxReturn();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!LSsession :: loadLSclass('LSform')) {
|
||||
LSerror :: addErrorCode('LSsession_05','LSform');
|
||||
LSsession :: displayAjaxReturn();
|
||||
return;
|
||||
}
|
||||
|
||||
$onlyLSobjects = (isset($_REQUEST['types'])?ensureIsArray($_REQUEST['types']):[]);
|
||||
$keepParamsBetweenSearches = (
|
||||
isset($_REQUEST['keepParamsBetweenSearches'])?
|
||||
boolval($_REQUEST['keepParamsBetweenSearches']):
|
||||
false
|
||||
);
|
||||
$all = isset($_REQUEST['all']);
|
||||
$page_nb = (isset($_REQUEST['page'])?(int)$_REQUEST['page']:1);
|
||||
$allowedParams = array(
|
||||
'pattern', 'approx', 'recursive', 'extraDisplayedColumns', 'nbObjectsByPage',
|
||||
'attributes', 'withoutCache', 'predefinedFilter', 'filter', 'basedn', 'subDn',
|
||||
'scope', 'attributes', 'displayFormat',
|
||||
);
|
||||
|
||||
// Handle JSON output
|
||||
$data = array(
|
||||
'success' => true,
|
||||
'objects' => array(),
|
||||
'total' => 0,
|
||||
'params' => array(
|
||||
'keepParamsBetweenSearches' => $keepParamsBetweenSearches,
|
||||
),
|
||||
);
|
||||
if (!$all) {
|
||||
$data['page'] = $page_nb;
|
||||
$data['nbPages'] = 1;
|
||||
}
|
||||
|
||||
foreach (LSsession :: getLSaccess() as $LSobject => $label) {
|
||||
if ( $LSobject == "SELF" || !LSsession :: loadLSobject($LSobject) )
|
||||
continue;
|
||||
if (!LSconfig::get("LSobjects.$LSobject.globalSearch", true, 'bool'))
|
||||
continue;
|
||||
if ($onlyLSobjects && !in_array($LSobject, $onlyLSobjects))
|
||||
continue;
|
||||
|
||||
$object = new $LSobject();
|
||||
|
||||
$search = new LSsearch(
|
||||
$LSobject,
|
||||
'api',
|
||||
null,
|
||||
!$keepParamsBetweenSearches
|
||||
);
|
||||
$search -> setParam(
|
||||
'extraDisplayedColumns',
|
||||
LSconfig::get("LSobjects.$LSobject.globalSearch_extraDisplayedColumns", true, 'bool')
|
||||
);
|
||||
$search -> setParam('onlyAccessible', True);
|
||||
$params = [];
|
||||
foreach($_REQUEST as $key => $value)
|
||||
if (in_array($key, $allowedParams))
|
||||
$params[$key] = $value;
|
||||
if (isset($_REQUEST['type_params']) && isset($_REQUEST['type_params'][$LSobject]))
|
||||
foreach(ensureIsArray($_REQUEST['type_params'][$LSobject]) as $key => $value)
|
||||
if (in_array($key, $allowedParams))
|
||||
$params[$key] = $value;
|
||||
|
||||
if (
|
||||
(!isset($params['pattern']) || !$params['pattern'])
|
||||
&& (!isset($params['filter']) || !$params['filter'])
|
||||
) {
|
||||
LSerror :: addErrorCode(
|
||||
false,
|
||||
_("No pattern or filter provided for $LSobject (required in global search).")
|
||||
);
|
||||
LSsession :: displayAjaxReturn();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$search -> setParamsFromRequest($params)) {
|
||||
LSerror :: addErrorCode(false, "Invalid search parameters for $LSobject.");
|
||||
LSsession :: displayAjaxReturn();
|
||||
return;
|
||||
}
|
||||
|
||||
// Run search
|
||||
if (!$search -> run())
|
||||
LSlog :: fatal("Fail to run search on $LSobject.");
|
||||
|
||||
if ($search -> total <= 0)
|
||||
continue;
|
||||
|
||||
$data['total'] += $search -> total;
|
||||
|
||||
if ($all) {
|
||||
$entries = $search -> listEntries();
|
||||
if (!is_array($entries))
|
||||
LSlog :: fatal("Fail to retrieve search result for $LSobject.");
|
||||
}
|
||||
else {
|
||||
// Retrieve page
|
||||
$page = $search -> getPage($page_nb);
|
||||
|
||||
/*
|
||||
* $page = array(
|
||||
* 'nb' => $page,
|
||||
* 'nbPages' => 1,
|
||||
* 'list' => array(),
|
||||
* 'total' => $this -> total
|
||||
* );
|
||||
*/
|
||||
|
||||
// Check page
|
||||
if (!is_array($page))
|
||||
LSlog :: fatal("Fail to retrieve page #$page_nb for $LSobject.");
|
||||
|
||||
if ($page['nb'] >= $data['page'])
|
||||
$data['page'] = $page['nb'];
|
||||
if ($page['nbPages'] >= $data['nbPages'])
|
||||
$data['nbPages'] = $page['nbPages'];
|
||||
}
|
||||
|
||||
// Export search parameters
|
||||
$exportedParams = array(
|
||||
'filter', 'pattern', 'predefinedFilter', 'basedn', 'scope', 'sizelimit', 'attronly',
|
||||
'approx', 'recursive', 'attributes', 'onlyAccessible', 'sortDirection', 'sortBy', 'sortlimit',
|
||||
'displayFormat', 'nbObjectsByPage', 'withoutCache', 'extraDisplayedColumns'
|
||||
);
|
||||
if (LSsession :: subDnIsEnabled())
|
||||
$exportedParams = array_merge($exportedParams, array('displaySubDn', 'subDn'));
|
||||
$data['params'][$LSobject] = [];
|
||||
foreach ($exportedParams as $param) {
|
||||
$data['params'][$LSobject][$param] = $search->getParam($param);
|
||||
if ($param == 'filter' && $data['params'][$LSobject][$param])
|
||||
$data['params'][$LSobject][$param] = $data['params'][$LSobject][$param] -> as_string();
|
||||
}
|
||||
|
||||
// Instanciate LSform export to handle custom requested attributes
|
||||
$object = new $LSobject();
|
||||
$export = new LSform($object, 'export');
|
||||
foreach ($search -> attributes as $attr) {
|
||||
if (array_key_exists($attr, $object -> attrs))
|
||||
$object -> attrs[$attr] -> addToExport($export);
|
||||
}
|
||||
|
||||
// Reset & increase time limit: allow one seconds by object to handle,
|
||||
// with a minimum of 30 seconds
|
||||
$timeout = count($all?$entries:$page['list']); // @phpstan-ignore-line
|
||||
set_time_limit($timeout>30?$timeout:30);
|
||||
|
||||
// Handle objects
|
||||
$data['objects'][$LSobject] = [];
|
||||
foreach(($all?$entries:$page['list']) as $obj) { // @phpstan-ignore-line
|
||||
$data['objects'][$LSobject][$obj -> dn] = array(
|
||||
'name' => $obj -> displayName,
|
||||
);
|
||||
// When as_list enabled, put object DN in object details (otherwise, it's the key)
|
||||
if (isset($_REQUEST['as_list']))
|
||||
$data['objects'][$LSobject][$obj -> dn]['dn'] = $obj -> dn;
|
||||
// When splited_result is disabled, put object type in object details (otherwise, present as key)
|
||||
if (!isset($_REQUEST['splited_result']))
|
||||
$data['objects'][$LSobject][$obj -> dn]['type'] = $LSobject;
|
||||
if ($search -> displaySubDn)
|
||||
$data['objects'][$LSobject][$obj -> dn][$search -> label_level] = $obj -> subDn;
|
||||
if ($search -> extraDisplayedColumns) {
|
||||
foreach ($search -> visibleExtraDisplayedColumns as $cid => $conf) {
|
||||
$data['objects'][$LSobject][$obj -> dn][$conf['label']] = $obj -> $cid;
|
||||
}
|
||||
}
|
||||
foreach ($search -> attributes as $attr) {
|
||||
if (!LSsession :: canAccess($LSobject, $obj -> dn, 'r', $attr))
|
||||
continue;
|
||||
$export -> elements[$attr] -> setValue(
|
||||
$object -> attrs[$attr] -> html -> refreshForm(
|
||||
$object -> attrs[$attr] -> getFormVal($obj -> $attr)
|
||||
)
|
||||
);
|
||||
$data['objects'][$LSobject][$obj -> dn][$attr] = $export -> elements[$attr] -> getApiValue(
|
||||
isset($_REQUEST['attributesDetails'])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$search -> afterUsingResult();
|
||||
}
|
||||
|
||||
if (!$all && $data['page'] > $data['nbPages']) {
|
||||
LSerror :: addErrorCode(
|
||||
false,
|
||||
"Requested page too hight ({$data['page']} > {$data['nbPages']})."
|
||||
);
|
||||
LSsession :: displayAjaxReturn();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle as_list parameter
|
||||
if (isset($_REQUEST['as_list']))
|
||||
foreach(array_keys($data['objects']) as $LSobject)
|
||||
$data['objects'][$LSobject] = array_values($data['objects'][$LSobject]);
|
||||
|
||||
// Handle splited_result parameter
|
||||
if (!isset($_REQUEST['splited_result'])) {
|
||||
$objects = [];
|
||||
foreach(array_keys($data['objects']) as $LSobject) {
|
||||
$objects = array_merge($objects, $data['objects'][$LSobject]);
|
||||
unset($data['objects'][$LSobject]);
|
||||
}
|
||||
$data['objects'] = $objects;
|
||||
}
|
||||
|
||||
LSsession :: displayAjaxReturn($data);
|
||||
}
|
||||
LSurl :: add_handler('#^api/1.0/search/?$#', 'handle_api_global_search', true, false, true);
|
||||
|
||||
/*
|
||||
* Handle API LSobject search
|
||||
*
|
||||
|
@ -1958,6 +2206,94 @@ function handle_api_LSobject_remove($request) {
|
|||
}
|
||||
LSurl :: add_handler('#^api/1.0/object/(?P<LSobject>[^/]+)/(?P<dn>[^/]+)/remove/?$#', 'handle_api_LSobject_remove', true, false, true);
|
||||
|
||||
/*
|
||||
* Handle API LSobject custom action request
|
||||
*
|
||||
* @param LSurlRequest $request The request
|
||||
*
|
||||
* @return void
|
||||
**/
|
||||
function handle_api_LSobject_customAction($request) {
|
||||
$object = get_LSobject_from_API_request($request);
|
||||
if (!$object)
|
||||
return;
|
||||
|
||||
$data = array(
|
||||
'dn' => $object -> getDn(),
|
||||
'type' => $object -> getType(),
|
||||
'name' => $object -> getDisplayName(),
|
||||
'success' => false,
|
||||
);
|
||||
|
||||
$customAction = $request -> customAction;
|
||||
|
||||
if ( !LSsession :: canExecuteCustomAction($data["dn"], $data["type"], $customAction) ) {
|
||||
LSerror :: addErrorCode('LSsession_11');
|
||||
LSsession :: displayAjaxReturn($data);
|
||||
return;
|
||||
}
|
||||
|
||||
$config = LSconfig :: get("LSobjects.{$data["type"]}.customActions.$customAction");
|
||||
$title = isset($config['label'])?__($config['label']):$customAction;
|
||||
$objectname = $object -> getDisplayName();
|
||||
|
||||
if (
|
||||
LSconfig :: get('accessMethods', [], 'array', $config)
|
||||
&& !in_array('api', LSconfig :: get('accessMethods', [], 'array', $config))
|
||||
) {
|
||||
LSerror :: addErrorCode('LSsession_28');
|
||||
LSsession :: displayAjaxReturn($data);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check customAction function
|
||||
$function = LSconfig :: get('function', null, null, $config);
|
||||
if (!is_callable($function)) {
|
||||
LSerror :: addErrorCode(
|
||||
'LSsession_13',
|
||||
array(
|
||||
'customAction' => $title,
|
||||
'function' => ($function?format_callable($function):_('undefined'))
|
||||
)
|
||||
);
|
||||
LSsession :: displayAjaxReturn($data);
|
||||
return;
|
||||
}
|
||||
|
||||
// Run customAction
|
||||
$result = call_user_func_array($function, array(&$object));
|
||||
|
||||
// Handle result: if its an array, merge it with returned data
|
||||
if (is_array($result))
|
||||
$data = array_merge($data, $result);
|
||||
|
||||
if ($result && (!is_array($result) || $data["success"])) {
|
||||
$data["success"] = true;
|
||||
if (!LSconfig :: get('disableOnSuccessMsg', false, 'bool', $config)) {
|
||||
$msg_format = LSconfig :: get('onSuccessMsgFormat', null, 'string', $config);
|
||||
if ($msg_format) {
|
||||
$msg = getFData(__($msg_format), $objectname);
|
||||
} else {
|
||||
$msg = getFData(
|
||||
_('The custom action %{customAction} have been successfully execute on %{objectname}.'),
|
||||
array('objectname' => $objectname, 'customAction' => $customAction)
|
||||
);
|
||||
}
|
||||
LSsession :: addInfo($msg);
|
||||
}
|
||||
}
|
||||
else {
|
||||
LSerror :: addErrorCode(
|
||||
'LSldapObject_31',
|
||||
array('objectname' => $objectname, 'customAction' => $customAction)
|
||||
);
|
||||
}
|
||||
LSsession :: displayAjaxReturn($data);
|
||||
}
|
||||
LSurl :: add_handler(
|
||||
'#^api/1.0/object/(?P<LSobject>[^/]+)/(?P<dn>[^/]+)/customAction/(?P<customAction>[^/]+)/?$#',
|
||||
'handle_api_LSobject_customAction', true, false, true);
|
||||
|
||||
/*
|
||||
* Handle API LSobject relation request
|
||||
*
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
@ -22,26 +22,37 @@ msgstr ""
|
|||
msgid "Password policy: An error occured writing a CSV row."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.ppolicy.php:169
|
||||
#: includes/addons/LSaddons.ppolicy.php:175
|
||||
#: includes/addons/LSaddons.ppolicy.php:171
|
||||
#: includes/addons/LSaddons.ppolicy.php:180
|
||||
msgid "Never"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.ppolicy.php:173
|
||||
#: includes/addons/LSaddons.ppolicy.php:176
|
||||
msgid "Unknown"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.ppolicy.php:180
|
||||
#: includes/addons/LSaddons.ppolicy.php:177
|
||||
#, php-format
|
||||
msgid "Last password changed: %s, no duration of validity configured."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.ppolicy.php:185
|
||||
#, php-format
|
||||
msgid "Expired (since %s)"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.ppolicy.php:190
|
||||
#: includes/addons/LSaddons.ppolicy.php:187
|
||||
#: includes/addons/LSaddons.ppolicy.php:199
|
||||
#, php-format
|
||||
msgid "Last password changed: %s, duration of validity: %s days"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.ppolicy.php:197
|
||||
#, php-format
|
||||
msgid "Expire on %s"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.ppolicy.php:260
|
||||
#: includes/addons/LSaddons.ppolicy.php:269
|
||||
msgid "Not set"
|
||||
msgstr ""
|
||||
|
||||
|
@ -159,27 +170,51 @@ msgid "ExportSearchResultAsCSV Error : An error occured writing a CSV row."
|
|||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:27
|
||||
msgid "MAIL Support : Pear::MAIL is missing."
|
||||
msgid "MAIL Support: Pear::MAIL is missing."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:30
|
||||
msgid "MAIL Support : Pear::MAIL_MIME is missing."
|
||||
msgid "MAIL Support: Pear::MAIL_MIME is missing."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:35
|
||||
msgid "MAIL Error : %{msg}"
|
||||
#: includes/addons/LSaddons.mail.php:33
|
||||
msgid "MAIL Support: Html2Text\\Html2Text is missing."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:39
|
||||
msgid "MAIL : Error sending your email"
|
||||
#: includes/addons/LSaddons.mail.php:38
|
||||
msgid "MAIL Error: %{msg}"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:125
|
||||
#: includes/addons/LSaddons.mail.php:41
|
||||
msgid "MAIL: Error sending your email"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:44
|
||||
msgid "MAIL: Unknown template %{name}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:47
|
||||
msgid "MAIL: Template %{name} is incomplete."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:50
|
||||
msgid "MAIL: No writable place to save your changes on this template."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:53
|
||||
msgid "MAIL: An error occured saving your changes on this template."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:158 includes/addons/LSaddons.mail.php:573
|
||||
msgid "Email templates"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:208
|
||||
#, php-format
|
||||
msgid "</hr><p><small>Mail initialy intended for %s.</small></p>"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:126
|
||||
#: includes/addons/LSaddons.mail.php:209
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
|
@ -188,18 +223,38 @@ msgid ""
|
|||
"Mail initialy intended for %s."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:156
|
||||
#: includes/addons/LSaddons.mail.php:238
|
||||
#, php-format
|
||||
msgid "<p><small>%s: %s</small></p>"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:157
|
||||
#: includes/addons/LSaddons.mail.php:239
|
||||
#, php-format
|
||||
msgid ""
|
||||
"\n"
|
||||
"%s: %s"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:463
|
||||
msgid "An exception occured forging message from email template '%{template}'"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:503
|
||||
msgid "Email template: %{name}"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:513 includes/addons/LSaddons.mail.php:529
|
||||
#: includes/addons/LSaddons.mail.php:547
|
||||
msgid "Your changes have been saved."
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.mail.php:565
|
||||
#: includes/addons/LSaddons.showSupportInfo.php:78
|
||||
#: includes/addons/LSaddons.accesslog.php:248
|
||||
#: includes/addons/LSaddons.showTechInfo.php:128
|
||||
msgid "Go back"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.phpldapadmin.php:27
|
||||
msgid "PhpLdapAdmin Support : The constant %{const} is not defined."
|
||||
msgstr ""
|
||||
|
@ -216,12 +271,6 @@ msgstr ""
|
|||
msgid "Download"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.showSupportInfo.php:78
|
||||
#: includes/addons/LSaddons.accesslog.php:248
|
||||
#: includes/addons/LSaddons.showTechInfo.php:117
|
||||
msgid "Go back"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.dyngroup.php:27
|
||||
msgid "Dynamic groups support: The constant %{const} is not defined."
|
||||
msgstr ""
|
||||
|
@ -317,8 +366,8 @@ msgstr ""
|
|||
#: includes/class/class.LSrelation.php:679 includes/class/class.LSform.php:346
|
||||
#: includes/class/class.LSformElement_select_object.php:75
|
||||
#: includes/class/class.LSformElement_select_object.php:91
|
||||
#: includes/class/class.LSsearchEntry.php:237 includes/routes.php:1068
|
||||
#: includes/routes.php:1212
|
||||
#: includes/class/class.LSsearchEntry.php:237 includes/routes.php:1072
|
||||
#: includes/routes.php:1222
|
||||
msgid "Delete"
|
||||
msgstr ""
|
||||
|
||||
|
@ -331,8 +380,8 @@ msgstr ""
|
|||
#: includes/class/class.LSrelation.php:736
|
||||
#: includes/class/class.LSformElement_select_object.php:74
|
||||
#: includes/class/class.LSformElement_supannLabeledValue.php:90
|
||||
#: includes/class/class.LSsearchEntry.php:221 includes/routes.php:1052
|
||||
#: includes/routes.php:1220 includes/routes.php:1305 includes/routes.php:1451
|
||||
#: includes/class/class.LSsearchEntry.php:221 includes/routes.php:1056
|
||||
#: includes/routes.php:1230 includes/routes.php:1315 includes/routes.php:1470
|
||||
msgid "Modify"
|
||||
msgstr ""
|
||||
|
||||
|
@ -340,7 +389,7 @@ msgstr ""
|
|||
msgid "Modify RDN"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.accesslog.php:35 includes/routes.php:517
|
||||
#: includes/addons/LSaddons.accesslog.php:35 includes/routes.php:518
|
||||
#: templates/default/select.tpl:28 templates/default/global_search.tpl:6
|
||||
msgid "Search"
|
||||
msgstr ""
|
||||
|
@ -368,7 +417,7 @@ msgstr ""
|
|||
|
||||
#: includes/addons/LSaddons.accesslog.php:243
|
||||
#: includes/class/class.LSsession.php:1875 includes/routes.php:157
|
||||
#: includes/routes.php:474 templates/default/select.tpl:29
|
||||
#: includes/routes.php:475 templates/default/select.tpl:29
|
||||
msgid "Refresh"
|
||||
msgstr ""
|
||||
|
||||
|
@ -584,7 +633,7 @@ msgstr ""
|
|||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: includes/addons/LSaddons.showTechInfo.php:113
|
||||
#: includes/addons/LSaddons.showTechInfo.php:124
|
||||
msgid "%{name}: Technical information"
|
||||
msgstr ""
|
||||
|
||||
|
@ -639,8 +688,10 @@ msgstr ""
|
|||
|
||||
#: includes/class/class.LSformRule.php:89
|
||||
#: includes/class/class.LSformRule.php:292
|
||||
#: includes/class/class.LSformElement_gpg_pub_key.php:101
|
||||
#: includes/class/class.LSattr_html_date.php:47
|
||||
#: includes/class/class.LSattr_html_select_list.php:63
|
||||
#: templates/default/LSformElement_gpg_pub_key_field.tpl:9
|
||||
msgid "Invalid value"
|
||||
msgstr ""
|
||||
|
||||
|
@ -768,7 +819,7 @@ msgstr ""
|
|||
|
||||
#: includes/class/class.LSconfirmBox.php:37
|
||||
#: includes/class/class.LSsmoothbox.php:39 includes/class/class.LSform.php:175
|
||||
#: includes/routes.php:638 includes/routes.php:1292 includes/routes.php:1438
|
||||
#: includes/routes.php:642 includes/routes.php:1302 includes/routes.php:1457
|
||||
#: templates/default/recoverpassword.tpl:21
|
||||
msgid "Validate"
|
||||
msgstr ""
|
||||
|
@ -870,6 +921,7 @@ msgid ""
|
|||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSformElement_ssh_key.php:83
|
||||
#: includes/class/class.LSformElement_gpg_pub_key.php:91
|
||||
msgid "Display the full key."
|
||||
msgstr ""
|
||||
|
||||
|
@ -1258,51 +1310,58 @@ msgid ""
|
|||
"LSattr_ldap :: password. It's not the case of the attribure %{attr}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:823
|
||||
msgid ""
|
||||
"LSattribute : Attribute %{attr} : LDAP or HTML types unknow (LDAP = %{ldap} "
|
||||
"& HTML = %{html})."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:826
|
||||
msgid ""
|
||||
"LSattribute : The function %{func} to display the attribute %{attr} is "
|
||||
"unknow."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:829
|
||||
msgid ""
|
||||
"LSattribute : The rule %{rule} to validate the attribute %{attr} is unknow."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:832
|
||||
msgid ""
|
||||
"LSattribute : Configuration data to verify the attribute %{attr} are "
|
||||
"incorrect."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:835
|
||||
msgid ""
|
||||
"LSattribute : The function %{func} to save the attribute %{attr} is unknow."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:838
|
||||
msgid "LSattribute : The value of the attribute %{attr} can't be generated."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:841
|
||||
msgid "LSattribute : Generation of the attribute %{attr} failed."
|
||||
msgid ""
|
||||
"LSattribute: Attribute %{attr} : LDAP or HTML types unknow (LDAP = %{ldap} & "
|
||||
"HTML = %{html})."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:844
|
||||
msgid ""
|
||||
"LSattribute : Generation of the attribute %{attr} did not return a correct "
|
||||
"value."
|
||||
"LSattribute: The function %{func} to display the attribute %{attr} is unknow."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:847
|
||||
msgid ""
|
||||
"LSattribute : The attr_%{type} of the attribute %{name} is not yet defined."
|
||||
"LSattribute: The rule %{rule} to validate the attribute %{attr} is unknow."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:850
|
||||
msgid ""
|
||||
"LSattribute: Configuration data to verify the attribute %{attr} are "
|
||||
"incorrect."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:853
|
||||
msgid ""
|
||||
"LSattribute: The function %{func} to save the attribute %{attr} is unknow."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:856
|
||||
msgid "LSattribute: The value of the attribute %{attr} can't be generated."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:859
|
||||
msgid "LSattribute: Generation of the attribute %{attr} failed."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:862
|
||||
msgid ""
|
||||
"LSattribute: Generation of the attribute %{attr} did not return a correct "
|
||||
"value."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:865
|
||||
msgid ""
|
||||
"LSattribute: The attr_%{type} of the attribute %{name} is not yet defined."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:868
|
||||
msgid "LSattribute: The default value of the attribute %{attr} is invalid."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattribute.php:871
|
||||
msgid "LSattribute: Fail to set attribute %{attr} value as default."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSformRule_callable.php:71
|
||||
|
@ -1493,209 +1552,218 @@ msgid ""
|
|||
"%{context}</pre>"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsession.php:3214
|
||||
msgid "LSsession : This custom action can not be executed by this way."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSformRule_mimetype.php:53
|
||||
#: includes/class/class.LSformRule_mimetype.php:57
|
||||
msgid "Invalid file type (%{type})."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:585
|
||||
#: includes/class/class.LSldapObject.php:603
|
||||
msgid "The attribute %{attr} is not valid."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3165
|
||||
#: includes/class/class.LSldapObject.php:3183
|
||||
msgid "LSldapObject : Object type unknown."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3168
|
||||
#: includes/class/class.LSldapObject.php:3186
|
||||
msgid "LSldapObject : Update form is not defined for the object %{obj}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3171
|
||||
#: includes/class/class.LSldapObject.php:3189
|
||||
msgid "LSldapObject : No form exists for the object %{obj}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3174
|
||||
#: includes/class/class.LSldapObject.php:3192
|
||||
msgid ""
|
||||
"LSldapObject : The function %{func} to validate the attribute %{attr} the "
|
||||
"object %{obj} is unknow."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3177
|
||||
#: includes/class/class.LSldapObject.php:3195
|
||||
msgid ""
|
||||
"LSldapObject : Configuration data are missing to validate the attribute "
|
||||
"%{attr} of the object %{obj}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3181
|
||||
#: includes/class/class.LSldapObject.php:3199
|
||||
msgid ""
|
||||
"LSldapObject : The function %{func} to be executed on the object event "
|
||||
"%{event} doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3184
|
||||
#: includes/class/class.LSldapObject.php:3202
|
||||
msgid ""
|
||||
"LSldapObject : The %{func} execution on the object event %{event} failed."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3188
|
||||
#: includes/class/class.LSldapObject.php:3206
|
||||
msgid ""
|
||||
"LSldapObject : Class %{class}, which method %{meth} to be executed on the "
|
||||
"object event %{event}, doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3191
|
||||
#: includes/class/class.LSldapObject.php:3209
|
||||
msgid ""
|
||||
"LSldapObject : Method %{meth} within %{class} class to be executed on object "
|
||||
"event %{event}, doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3194
|
||||
#: includes/class/class.LSldapObject.php:3212
|
||||
msgid ""
|
||||
"LSldapObject : Error during execute %{meth} method within %{class} class, to "
|
||||
"be executed on object event %{event}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3198
|
||||
#: includes/class/class.LSldapObject.php:3216
|
||||
msgid ""
|
||||
"LSldapObject : Some configuration data of the object type %{obj} are missing "
|
||||
"to generate the DN of the new object."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3201
|
||||
#: includes/class/class.LSldapObject.php:3219
|
||||
msgid ""
|
||||
"LSldapObject : The attibute %{attr} of the object is not yet defined. Can't "
|
||||
"generate DN."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3204
|
||||
#: includes/class/class.LSldapObject.php:3222
|
||||
msgid "LSldapObject : Without DN, the object could not be changed."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3207
|
||||
#: includes/class/class.LSldapObject.php:3225
|
||||
msgid ""
|
||||
"LSldapObject : The attribute %{attr_depend} depending on the attribute "
|
||||
"%{attr} doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3210
|
||||
#: includes/class/class.LSldapObject.php:3228
|
||||
msgid "LSldapObject : Error during deleting the object %{objectname}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3214
|
||||
#: includes/class/class.LSldapObject.php:3232
|
||||
msgid ""
|
||||
"LSldapObject : Error during actions to be executed before renaming the objet."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3217
|
||||
#: includes/class/class.LSldapObject.php:3235
|
||||
msgid ""
|
||||
"LSldapObject : Error during actions to be executed after renaming the objet."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3221
|
||||
#: includes/class/class.LSldapObject.php:3239
|
||||
msgid ""
|
||||
"LSldapObject : Error during actions to be executed before deleting the objet."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3224
|
||||
#: includes/class/class.LSldapObject.php:3242
|
||||
msgid ""
|
||||
"LSldapObject : Error during actions to be executed after deleting the objet."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3228
|
||||
#: includes/class/class.LSldapObject.php:3246
|
||||
msgid ""
|
||||
"LSldapObject : Error during the actions to be executed before creating the "
|
||||
"object."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3231
|
||||
#: includes/class/class.LSldapObject.php:3249
|
||||
msgid ""
|
||||
"LSldapObject : Error during the actions to be executed after creating the "
|
||||
"object. It was created anyway."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3235
|
||||
#: includes/class/class.LSldapObject.php:3253
|
||||
msgid ""
|
||||
"LSldapObject : The function %{func} to be executed before creating the "
|
||||
"object doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3238
|
||||
#: includes/class/class.LSldapObject.php:3256
|
||||
msgid ""
|
||||
"LSldapObject : Error executing the function %{func} to be execute after "
|
||||
"deleting the object."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3241
|
||||
#: includes/class/class.LSldapObject.php:3259
|
||||
msgid ""
|
||||
"LSldapObject : The function %{func} to be executed after deleting the object "
|
||||
"doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3244
|
||||
#: includes/class/class.LSldapObject.php:3262
|
||||
msgid ""
|
||||
"LSldapObject : Error executing the function %{func} to be execute after "
|
||||
"creating the object."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3248
|
||||
#: includes/class/class.LSldapObject.php:3266
|
||||
msgid ""
|
||||
"LSldapObject : %{func} function, to be executed on object event %{event}, "
|
||||
"doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3251
|
||||
#: includes/class/class.LSldapObject.php:3269
|
||||
msgid ""
|
||||
"LSldapObject : Error during the execution of %{func} function on object "
|
||||
"event %{event}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3255
|
||||
#: includes/class/class.LSldapObject.php:3273
|
||||
msgid ""
|
||||
"LSldapObject : %{meth} method, to be executed on object event %{event}, "
|
||||
"doesn't exist."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3258
|
||||
#: includes/class/class.LSldapObject.php:3276
|
||||
msgid ""
|
||||
"LSldapObject : Error during execution of %{meth} method on object event "
|
||||
"%{event}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3261
|
||||
#: includes/class/class.LSldapObject.php:3279
|
||||
msgid "LSldapObject : Error during generate LDAP filter for %{LSobject}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3265
|
||||
#: includes/class/class.LSldapObject.php:3283
|
||||
msgid ""
|
||||
"LSldapObject : Error during execution of the custom action %{customAction} "
|
||||
"on %{objectname}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3269
|
||||
#: includes/class/class.LSldapObject.php:3287
|
||||
msgid "LSldapObject : Fail to retrieve container DN."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3272
|
||||
#: includes/class/class.LSldapObject.php:3290
|
||||
msgid ""
|
||||
"LSldapObject : The function %{func} to generate container DN is not callable."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3275
|
||||
#: includes/class/class.LSldapObject.php:3293
|
||||
msgid "LSldapObject : Error during generating container DN : %{error}"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3278
|
||||
#: includes/class/class.LSldapObject.php:3296
|
||||
msgid ""
|
||||
"LSldapObject : An LDAP object with the same DN as generated for this new one "
|
||||
"already exists. Please verify your configuration."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSldapObject.php:3283
|
||||
#: includes/class/class.LSldapObject.php:3301
|
||||
msgid ""
|
||||
"LSrelation : Some parameters are missing in the call of methods to handle "
|
||||
"standard relations (Method : %{meth})."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSformElement_gpg_pub_key.php:113
|
||||
msgid ""
|
||||
"LSformElement_gpg_pub_key: PHP GnuPG extension is missing, can't parse value."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSformRule_password.php:58
|
||||
msgid "Password is too long (maximum: %{maxLength})."
|
||||
msgstr ""
|
||||
|
@ -1904,8 +1972,8 @@ msgstr ""
|
|||
msgid "No object."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSrelation.php:747 includes/routes.php:456
|
||||
#: includes/routes.php:997
|
||||
#: includes/class/class.LSrelation.php:747 includes/routes.php:457
|
||||
#: includes/routes.php:1001
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2102,11 +2170,11 @@ msgid ""
|
|||
"support."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSform.php:327 includes/routes.php:634
|
||||
#: includes/class/class.LSform.php:327 includes/routes.php:638
|
||||
msgid "Do you really want to execute custom action %{title} on this search ?"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSform.php:333 includes/routes.php:1432
|
||||
#: includes/class/class.LSform.php:333 includes/routes.php:1451
|
||||
msgid ""
|
||||
"Do you really want to execute custom action %{customAction} on "
|
||||
"%{objectname} ?"
|
||||
|
@ -2296,8 +2364,8 @@ msgstr ""
|
|||
msgid "Display RSS stack."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSattr_ldap_password.php:108 includes/routes.php:587
|
||||
#: includes/routes.php:1379
|
||||
#: includes/class/class.LSattr_ldap_password.php:108 includes/routes.php:591
|
||||
#: includes/routes.php:1398 includes/routes.php:2256
|
||||
msgid "undefined"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2405,88 +2473,88 @@ msgstr ""
|
|||
msgid "Pedagogical element"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1318
|
||||
#: includes/class/class.LSsearch.php:1321
|
||||
msgid "Actions"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1321
|
||||
#: includes/class/class.LSsearch.php:1324
|
||||
#: templates/default/global_search.tpl:16
|
||||
msgid "This search didn't get any result."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1963
|
||||
#: includes/class/class.LSsearch.php:1966
|
||||
msgid "LSsearch : Invalid filter : %{filter}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1966
|
||||
#: includes/class/class.LSsearch.php:1969
|
||||
msgid "LSsearch : Invalid basedn (%{basedn})."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1969
|
||||
#: includes/class/class.LSsearch.php:1972
|
||||
msgid "LSsearch : Invalid value for %{param} parameter."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1972
|
||||
#: includes/class/class.LSsearch.php:1975
|
||||
msgid ""
|
||||
"LSsearch : Invalid size limit. Must be an integer greater or equal to 0."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1975
|
||||
#: includes/class/class.LSsearch.php:1978
|
||||
msgid "LSsearch : Invalid parameter %{param}. Must be an boolean."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1978
|
||||
#: includes/class/class.LSsearch.php:1981
|
||||
msgid ""
|
||||
"LSsearch : Invalid parameter attributes. Must be an string or an array of "
|
||||
"strings."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1981
|
||||
#: includes/class/class.LSsearch.php:1984
|
||||
msgid "LSsearch : Can't build attributes list for make filter."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1984
|
||||
#: includes/class/class.LSsearch.php:1987
|
||||
msgid ""
|
||||
"LSsearch : Error building filter with attribute '%{attr}' and pattern "
|
||||
"'%{pattern}'"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1987
|
||||
#: includes/class/class.LSsearch.php:1990
|
||||
msgid "LSsearch : Error combining filters."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1990
|
||||
#: includes/class/class.LSsearch.php:1993
|
||||
msgid "LSsearch : Invalid pattern."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1993
|
||||
#: includes/class/class.LSsearch.php:1996
|
||||
msgid "LSsearch : Invalid attribute %{attr} in parameters."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1996
|
||||
#: includes/class/class.LSsearch.php:1999
|
||||
msgid "LSsearch : Error during the search."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:1999
|
||||
#: includes/class/class.LSsearch.php:2002
|
||||
msgid "LSsearch : Error sorting the search."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:2002
|
||||
#: includes/class/class.LSsearch.php:2005
|
||||
msgid ""
|
||||
"LSsearch : The function of the custum information %{name} is not callable."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:2005
|
||||
#: includes/class/class.LSsearch.php:2008
|
||||
msgid ""
|
||||
"LSsearch : Invalid predefinedFilter for LSobject type %{type} : %{label} "
|
||||
"(filter : %{filter})."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:2008
|
||||
#: includes/class/class.LSsearch.php:2011
|
||||
msgid "LSsearch : Error during execution of the custom action %{customAction}."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearch.php:2011
|
||||
#: includes/class/class.LSsearch.php:2014
|
||||
msgid "LSsearch : Invalid search pattern."
|
||||
msgstr ""
|
||||
|
||||
|
@ -2744,12 +2812,17 @@ msgstr ""
|
|||
msgid "Unknown error : %{error}"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearchEntry.php:213 includes/routes.php:1204
|
||||
#: includes/routes.php:1297 includes/routes.php:1443
|
||||
#: includes/class/class.LSformRule_gpg_pub_key.php:61
|
||||
msgid ""
|
||||
"LSformRule_gpg_pub_key: PHP GnuPG extension is missing, can't validate value."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearchEntry.php:213 includes/routes.php:1214
|
||||
#: includes/routes.php:1307 includes/routes.php:1462
|
||||
msgid "View"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class/class.LSsearchEntry.php:229 includes/routes.php:1060
|
||||
#: includes/class/class.LSsearchEntry.php:229 includes/routes.php:1064
|
||||
msgid "Copy"
|
||||
msgstr ""
|
||||
|
||||
|
@ -2775,64 +2848,64 @@ msgstr ""
|
|||
msgid "You must provide pattern for global search."
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:462 includes/routes.php:818
|
||||
#: includes/routes.php:463 includes/routes.php:822
|
||||
msgid "Import"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:467 includes/routes.php:884
|
||||
#: includes/routes.php:468 includes/routes.php:888
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:479
|
||||
#: includes/routes.php:480
|
||||
msgid "Reset"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:518 templates/default/select.tpl:31
|
||||
#: includes/routes.php:519 templates/default/select.tpl:31
|
||||
msgid "Approximative search"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:519 templates/default/select.tpl:32
|
||||
#: includes/routes.php:520 templates/default/select.tpl:32
|
||||
msgid "Recursive search"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:608
|
||||
#: includes/routes.php:612
|
||||
msgid ""
|
||||
"The custom action %{title} have been successfully execute on this search."
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:956
|
||||
#: includes/routes.php:960
|
||||
msgid "Data entry form"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:962 includes/routes.php:1736
|
||||
#: includes/routes.php:966 includes/routes.php:1984
|
||||
msgid "Object has been added."
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:1099
|
||||
#: includes/routes.php:1109
|
||||
msgid "My account"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:1162 includes/routes.php:1908
|
||||
#: includes/routes.php:1172 includes/routes.php:2156
|
||||
msgid "The object has been partially modified."
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:1165 includes/routes.php:1911
|
||||
#: includes/routes.php:1175 includes/routes.php:2159
|
||||
msgid "The object has been modified successfully."
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:1280 includes/routes.php:1951
|
||||
#: includes/routes.php:1290 includes/routes.php:2199
|
||||
msgid "%{objectname} has been successfully deleted."
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:1289
|
||||
#: includes/routes.php:1299
|
||||
msgid "Deleting : %{objectname}"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:1290
|
||||
#: includes/routes.php:1300
|
||||
msgid "Do you really want to delete <strong>%{displayName}</strong> ?"
|
||||
msgstr ""
|
||||
|
||||
#: includes/routes.php:1400
|
||||
#: includes/routes.php:1419 includes/routes.php:2278
|
||||
msgid ""
|
||||
"The custom action %{customAction} have been successfully execute on "
|
||||
"%{objectname}."
|
||||
|
@ -3079,6 +3152,10 @@ msgstr ""
|
|||
msgid "File"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/LSformElement_gpg_pub_key_field.tpl:3
|
||||
msgid "Fingerprint:"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/login.tpl:34
|
||||
msgid "Forgot your password ?"
|
||||
msgstr ""
|
||||
|
@ -3093,6 +3170,11 @@ msgstr ""
|
|||
msgid "Global search"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_templates.tpl:9
|
||||
#: templates/default/email_template.tpl:12
|
||||
msgid "HTML content"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/import.tpl:148
|
||||
msgid "Hook: %(name)"
|
||||
msgstr ""
|
||||
|
@ -3134,7 +3216,7 @@ msgstr ""
|
|||
msgid "Messages"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/viewSearch.tpl:113
|
||||
#: templates/default/viewSearch.tpl:128
|
||||
msgid "Nb / page :"
|
||||
msgstr ""
|
||||
|
||||
|
@ -3142,6 +3224,10 @@ msgstr ""
|
|||
msgid "No access log found for this object."
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_templates.tpl:23
|
||||
msgid "No existing email template."
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/LSform_view.tpl:34
|
||||
msgid "No field."
|
||||
msgstr ""
|
||||
|
@ -3154,6 +3240,20 @@ msgstr ""
|
|||
msgid "No value"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_template.tpl:29
|
||||
msgid ""
|
||||
"No writable path to save your changes on the HTML message of this template."
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_template.tpl:24
|
||||
msgid "No writable path to save your changes on the subject of this template."
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_template.tpl:34
|
||||
msgid ""
|
||||
"No writable path to save your changes on the text message of this template."
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/import.tpl:45
|
||||
msgid "Object %(idx)"
|
||||
msgstr ""
|
||||
|
@ -3235,14 +3335,28 @@ msgstr ""
|
|||
msgid "Right inherited from all connected users profile"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_template.tpl:39
|
||||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/base_connected.tpl:6
|
||||
msgid "Show/hide menu"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/LSmail.tpl:21
|
||||
#: templates/default/email_templates.tpl:8
|
||||
#: templates/default/email_template.tpl:9 templates/default/LSmail.tpl:21
|
||||
msgid "Subject"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_templates.tpl:7
|
||||
msgid "Template name"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/email_templates.tpl:10
|
||||
#: templates/default/email_template.tpl:15
|
||||
msgid "Text content"
|
||||
msgstr ""
|
||||
|
||||
#: templates/default/LSaccessRightsMatrixView.tpl:58
|
||||
msgid "Their relations with other objects"
|
||||
msgstr ""
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
{block name="content"}
|
||||
<div id='LSaccessRightsMatrixView'>
|
||||
<h1>{$pagetitle}</h1>
|
||||
<ul class="LSaccessRightsMatrixView_tabs">
|
||||
<ul class="LStabs">
|
||||
{foreach $LSobjects as $obj => $obj_conf}
|
||||
<li{if $LSobject==$obj} class="LSaccessRightsMatrixView_active_tab"{/if}><a href="addon/LSaccessRightsMatrixView/accessRightsMatrix?LSobject={$obj}">{$obj_conf.label}</a></li>
|
||||
<li{if $LSobject==$obj} class="LStabs_active"{/if}><a href="addon/LSaccessRightsMatrixView/accessRightsMatrix?LSobject={$obj}">{$obj_conf.label}</a></li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
|
||||
<div class='LSaccessRightsMatrixView_tab_content'>
|
||||
<div class='LStabs_content LStabs_content_active'>
|
||||
<h2>{$LSobjects[$LSobject]['label']}</h2>
|
||||
|
||||
<table class="table-header-rotated">
|
||||
|
|
7
src/templates/default/LSformElement_gpg_pub_key.tpl
Normal file
7
src/templates/default/LSformElement_gpg_pub_key.tpl
Normal file
|
@ -0,0 +1,7 @@
|
|||
<ul class='LSform{if $multiple && !$freeze} LSformElement_multiple'{/if}' id='{$attr_name|escape:"quotes"}'>
|
||||
{foreach from=$values_txt item=value}
|
||||
<li>{include file="ls:$fieldTemplate"}</li>
|
||||
{foreachelse}
|
||||
<li>{include file="ls:$fieldTemplate"}</li>
|
||||
{/foreach}
|
||||
</ul>
|
16
src/templates/default/LSformElement_gpg_pub_key_field.tpl
Normal file
16
src/templates/default/LSformElement_gpg_pub_key_field.tpl
Normal file
|
@ -0,0 +1,16 @@
|
|||
{if $freeze}
|
||||
{if $value.fingerprint}
|
||||
{tr msg="Fingerprint:"}
|
||||
<span class='LSformElement_gpg_pub_key_short_display' title='{$span_title|escape:"htmlall"}'>
|
||||
{$value.fingerprint|escape:"htmlall"}
|
||||
</span>
|
||||
<p class='LSformElement_gpg_pub_key_value'>{$value.value|escape:"htmlall"}</p>
|
||||
{elseif $value}
|
||||
<span class='LSformElement_gpg_pub_key_short_display'>{tr msg="Invalid value"}</span>
|
||||
<p class='LSformElement_gpg_pub_key_value'>{$value.value|escape:"htmlall"}</p>
|
||||
{else}
|
||||
{$noValueTxt|escape:"htmlall"}
|
||||
{/if}
|
||||
{else}
|
||||
<textarea name='{$attr_name|escape:"quotes"}[]' class='LSform LSformElement_gpg_pub_key'>{$value|escape:"htmlall"}</textarea>
|
||||
{/if}
|
43
src/templates/default/email_template.tpl
Normal file
43
src/templates/default/email_template.tpl
Normal file
|
@ -0,0 +1,43 @@
|
|||
{extends file='ls:base_connected.tpl'}
|
||||
{block name="content"}
|
||||
<h1>{$pagetitle}</h1>
|
||||
|
||||
{include file='ls:LSview_actions.tpl'}
|
||||
|
||||
<ul class="LStabs">
|
||||
<li{if $tab=="subject"} class="LStabs_active"{/if}>
|
||||
<a href="addon/mail/templates?name={$template.name}&tab=subject">{tr msg="Subject"}</a>
|
||||
</li>
|
||||
<li{if $tab=="html"} class="LStabs_active"{/if}>
|
||||
<a href="addon/mail/templates?name={$template.name}&tab=html">{tr msg="HTML content"}</a>
|
||||
</li>
|
||||
<li{if $tab=="txt"} class="LStabs_active"{/if}>
|
||||
<a href="addon/mail/templates?name={$template.name}&tab=txt">{tr msg="Text content"}</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class='LStabs_content LStabs_content_active'>
|
||||
<form action="addon/mail/templates?name={$template.name}&tab={$tab}" method="POST">
|
||||
{if $tab == "subject"}
|
||||
<input type="text" name="subject" value="{$template.subject|escape:"htmlall"}"
|
||||
{if !$writable}disabled="disabled" class="LStips"
|
||||
title="{tr msg="No writable path to save your changes on the subject of this template."}"
|
||||
{/if}
|
||||
/>
|
||||
{elseif $tab == "html"}
|
||||
<textarea name="html" {if !$writable}disabled="disabled"
|
||||
title="{tr msg="No writable path to save your changes on the HTML message of this template."}"
|
||||
{/if}
|
||||
>{$template.html}</textarea>
|
||||
{else}
|
||||
<textarea name="txt" {if !$writable}disabled="disabled" class="LStips"
|
||||
title="{tr msg="No writable path to save your changes on the text message of this template."}"
|
||||
{/if}
|
||||
>{$template.txt}</textarea>
|
||||
{/if}
|
||||
<div class="form-footer">
|
||||
<button type="submit">{tr msg="Save"}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/block}
|
28
src/templates/default/email_templates.tpl
Normal file
28
src/templates/default/email_templates.tpl
Normal file
|
@ -0,0 +1,28 @@
|
|||
{extends file='ls:base_connected.tpl'}
|
||||
{block name="content"}
|
||||
<h1>{$pagetitle}</h1>
|
||||
<table class="LStable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{tr msg="Template name"}</th>
|
||||
<th class="mail_subject">{tr msg="Subject"}</th>
|
||||
<th class="mail_content">{tr msg="HTML content"}</th>
|
||||
<th class="mail_content">{tr msg="Text content"}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{foreach $templates as $name => $tpl}
|
||||
<tr class="{cycle values=",bis"}">
|
||||
<td><a href="addon/mail/templates?name={$name|escape:"url"}">{$name}</td>
|
||||
<td class="mail_subject">{$tpl.subject|escape:"htmlall"}</td>
|
||||
<td class="mail_content">{$tpl.html|escape:"htmlall"}</td>
|
||||
<td class="mail_content">{$tpl.txt|escape:"htmlall"}</td>
|
||||
</tr>
|
||||
{foreachelse}
|
||||
<tr>
|
||||
<td colspan="4" class="center">{tr msg="No existing email template."}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
{/block}
|
|
@ -33,6 +33,11 @@
|
|||
|
||||
<table class='LSobject-list'>
|
||||
<tr class='LSobject-list'>
|
||||
{if $showSelectionBoxes}
|
||||
<th class='LSobject-list LSobject-list-selection'>
|
||||
<input type="checkbox" class="LSobject-list-selection" id="LSobject-list-select-all"/>
|
||||
</td>
|
||||
{/if}
|
||||
<th class='LSobject-list'>
|
||||
{if $LSsearch->sort}
|
||||
<a href='object/{$LSsearch->LSobject|escape:"url"}?sortBy=displayName&nocache={$smarty.now}'>
|
||||
|
@ -85,18 +90,28 @@
|
|||
</tr>
|
||||
{foreach from=$page.list item=object}
|
||||
<tr class='{cycle values="LSobject-list,LSobject-list LSobject-list-bis"}'>
|
||||
<td class='LSobject-list LSobject-list-names'><a href='object/{$LSsearch->LSobject|escape:"url"}/{$object->dn|escape:'url'}' class='LSobject-list'>{$object->displayName|escape:"htmlall"}</a> </td>
|
||||
{if $LSsearch->displaySubDn}<td class='LSobject-list'>{$object->subDn|escape:"htmlall"}</td>{/if}
|
||||
{if $LSsearch->extraDisplayedColumns}
|
||||
{foreach from=$LSsearch->visibleExtraDisplayedColumns item=conf key=cid}
|
||||
<td class='LSobject-list'{if isset($conf.cssStyle) && $conf.cssStyle} style='{$conf.cssStyle|escape:"htmlall"}'{/if}>{if !isset($conf.escape) || $conf.escape}{$object->$cid|escape:"htmlall"}{else}{$object->$cid}{/if}</td>
|
||||
{/foreach}
|
||||
{/if}
|
||||
<td class='LSobject-list LSobject-list-actions'>
|
||||
{foreach from=$object->actions item=item}
|
||||
<a href='{$item.url}' class='LSobject-list-actions'><img src='{img name=$item.action}' alt='{$item.label|escape:"htmlall"}' title='{$item.label|escape:"htmlall"}'/></a>
|
||||
{if $showSelectionBoxes}
|
||||
<td class='LSobject-list LSobject-list-selection'>
|
||||
<input type="checkbox" name="selected" value="{$object->dn|escape:'quotes'}"/>
|
||||
</td>
|
||||
{/if}
|
||||
<td class='LSobject-list LSobject-list-names'>
|
||||
<a href='object/{$LSsearch->LSobject|escape:"url"}/{$object->dn|escape:'url'}'
|
||||
class='LSobject-list'>
|
||||
{$object->displayName|escape:"htmlall"}
|
||||
</a>
|
||||
</td>
|
||||
{if $LSsearch->displaySubDn}<td class='LSobject-list'>{$object->subDn|escape:"htmlall"}</td>{/if}
|
||||
{if $LSsearch->extraDisplayedColumns}
|
||||
{foreach from=$LSsearch->visibleExtraDisplayedColumns item=conf key=cid}
|
||||
<td class='LSobject-list'{if isset($conf.cssStyle) && $conf.cssStyle} style='{$conf.cssStyle|escape:"htmlall"}'{/if}>{if !isset($conf.escape) || $conf.escape}{$object->$cid|escape:"htmlall"}{else}{$object->$cid}{/if}</td>
|
||||
{/foreach}
|
||||
</td>
|
||||
{/if}
|
||||
<td class='LSobject-list LSobject-list-actions'>
|
||||
{foreach from=$object->actions item=item}
|
||||
<a href='{$item.url}' class='LSobject-list-actions'><img src='{img name=$item.action}' alt='{$item.label|escape:"htmlall"}' title='{$item.label|escape:"htmlall"}'/></a>
|
||||
{/foreach}
|
||||
</td>
|
||||
</tr>
|
||||
{foreachelse}
|
||||
<tr class='LSobject-list'>
|
||||
|
|
2
src/tmp/.gitignore
vendored
2
src/tmp/.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
*.php
|
||||
*.tmp
|
||||
*.log
|
||||
*.kbx
|
||||
*.gpg
|
||||
|
|
Loading…
Reference in a new issue