31 public static function fetch ($dn)
35 $ldap = $config->get_ldap_link();
37 $attrs = $ldap->fetch(TRUE);
38 $attrs = static::fieldsFromLDAP($attrs);
39 list($depends, $errors) = static::attributesDependencies($attrs);
40 msg_dialog::displayChecks($errors);
41 $attrs = static::sortAttributes($attrs, $depends);
42 return [$attrs, $depends];
49 if (isset($template_attrs[
'fdTemplateField'])) {
50 unset($template_attrs[
'fdTemplateField'][
'count']);
51 sort($template_attrs[
'fdTemplateField']);
52 foreach ($template_attrs[
'fdTemplateField'] as $field) {
53 if (!preg_match(
'/^([^:]+):(.*)$/s', $field, $m)) {
56 if (isset($attrs[$m[1]])) {
57 $attrs[$m[1]][] = $m[2];
58 $attrs[$m[1]][
'count']++;
60 $attrs[$m[1]] = [$m[2]];
61 $attrs[$m[1]][
'count'] = 1;
69 public static function fieldsToLDAP (array $template_attrs, array $attrs)
72 unset($template_attrs[
'dn']);
73 unset($template_attrs[
'fdTemplateField'][
'count']);
74 unset($template_attrs[
'objectClass'][
'count']);
75 unset($template_attrs[
'cn'][
'count']);
76 if (isset($template_attrs[
'count'])) {
77 for ($i = 0; $i < $template_attrs[
'count']; ++$i) {
79 unset($template_attrs[$i]);
82 unset($template_attrs[
'count']);
85 foreach ($template_attrs[
'fdTemplateField'] as $key => $value) {
86 preg_match(
'/^([^:]+):(.*)$/s', $value, $m);
87 if (isset($attrs[$m[1]])) {
88 unset($template_attrs[
'fdTemplateField'][$key]);
92 foreach ($attrs as $key => $value) {
93 if (is_array($value)) {
94 foreach ($value as $v) {
98 $template_attrs[
'fdTemplateField'][] = $key.
':'.$v;
104 $template_attrs[
'fdTemplateField'][] = $key.
':'.$value;
107 sort($template_attrs[
'fdTemplateField']);
108 return $template_attrs;
118 list(, $errors) = static::attributesDependencies($attrs);
126 public static function parseMask (
string $mask, array $attrs)
132 if (preg_match(
'/^([^|]+)\|/', $mask, $m)) {
134 $mask = substr($mask, strlen($m[0]));
137 if (isset($attrs[$mask])) {
138 $result = $attrs[$mask];
139 if (is_array($result)) {
140 unset($result[
'count']);
141 if (empty($result)) {
148 } elseif (($mask !=
'') && !preg_match(
'/c/', $modifiers)) {
151 $len = strlen($modifiers);
152 for ($i = 0; $i < $len; ++$i) {
154 $modifier = $modifiers[$i];
155 if (preg_match(
'/^\[([^\]]+)\].*$/', substr($modifiers, $i + 1), $m)) {
157 $args = explode(
',', $m[1]);
158 $i += strlen($m[1]) + 2;
160 $result = static::applyModifier($modifier, $args, $result);
169 public static function neededAttrs (array &$attrs, array $flatdepends)
172 foreach ($flatdepends as $attr => $depends) {
173 if ((isset($depends[0])) && ($depends[0] ==
'askme')) {
175 unset($flatdepends[$attr]);
176 unset($attrs[$attr]);
179 $dependencies = array_unique(array_merge(...array_values($flatdepends)));
180 foreach ($dependencies as $attr) {
181 if (empty($flatdepends[$attr])) {
185 return array_unique($needed);
196 public static function parseArray (array $attrs, array $specialAttrs, $target = NULL)
198 foreach ($attrs as $name => &$attr) {
199 if (is_array($attr)) {
200 foreach ($attr as $key => &$string) {
201 if (!is_numeric($key)) {
204 $string = static::parseString($string, array_merge($attrs, $specialAttrs), NULL, $name, $target);
223 public static function parseString (
string $string, array $attrs, $escapeMethod = NULL,
string $unique = NULL,
string $target = NULL): string
227 if (preg_match(
'/^%%/', $string)) {
229 return preg_replace(
'/^%%/',
'', $string);
234 while (preg_match(
'/%([^%]+)%/', $string, $m, PREG_OFFSET_CAPTURE, $offset)) {
235 $replace = static::parseMask($m[1][0], $attrs);
236 $vars[] = [$m[0][1], strlen($m[0][0]), $replace];
237 $offset = $m[0][1] + strlen($m[0][0]);
240 $generator = static::iteratePossibleValues($string, $vars, $escapeMethod);
242 $string = $generator->current();
244 if (($unique !== NULL) && !empty($vars)) {
245 $ldap = $config->get_ldap_link();
246 $ldap->cd($config->current[
'BASE']);
248 foreach ($generator as $value) {
250 $filter = archivedObject::buildUniqueSearchFilter($unique, $value);
251 $ldap->search($filter, [
'dn']);
252 if ($ldap->count() > 0) {
256 $filter =
'('.ldap_escape_f($unique).
'='.ldap_escape_f($value).
')';
257 $ldap->search($filter, [
'dn']);
258 if ($ldap->count() == 0) {
261 if (($target !== NULL) && ($ldap->count() == 1)) {
262 $attrs = $ldap->fetch();
263 if ($attrs[
'dn'] == $target) {
282 if (!count($variables)) {
288 list($pos, $length, $val) = array_pop($variables);
291 foreach ($val as $possibility) {
292 if ($escapeMethod !== NULL) {
293 $possibility = $escapeMethod($possibility);
295 $nrule = mb_substr_replace($rule, $possibility, $pos, $length);
296 foreach (static::iteratePossibleValues($nrule, $variables, $escapeMethod) as $result) {
310 while (preg_match(
'/%([^%]+)%/', $string, $m, PREG_OFFSET_CAPTURE, $offset)) {
312 $offset = $m[0][1] + strlen($m[0][0]);
316 if (preg_match(
'/^([^|]+)\|/', $mask, $m)) {
317 $mask = substr($mask, strlen($m[0]));
324 private static function modifierRemoveAccents (array $args, $str)
327 if (count($args) >= 1) {
331 $str = htmlentities($str, ENT_NOQUOTES,
'UTF-8');
333 $str = preg_replace(
'#&([A-za-z])(?:acute|cedil|circ|grave|orn|ring|slash|th|tilde|uml);#',
'\1', $str);
335 $str = preg_replace(
'#&([A-za-z]{2})(?:lig);#',
'\1', $str);
337 $str = preg_replace(
'#&[^;]+;#',
'', $str);
339 if ($mode ===
'ascii') {
341 } elseif ($mode ===
'uid') {
343 $str = preg_replace(
'/[^a-z0-9_-]/',
'', mb_strtolower($str,
'UTF-8'));
345 $str = preg_replace(
'/[^a-zA-Z0-9 _.-]/',
'', $str);
353 private static function modifierTranslit (array $args, $str)
355 $localesaved = setlocale(LC_CTYPE, 0);
357 foreach ($args as $arg) {
358 setlocale(LC_CTYPE, [$arg,
"$arg.UTF8"]);
359 $ret[] = iconv(
'UTF8',
'ASCII//TRANSLIT', $str);
361 setlocale(LC_CTYPE, $localesaved);
362 return array_unique($ret);
365 private static function modifierPregReplace (array $args, $str)
369 if (count($args) >= 1) {
371 if (count($args) >= 2) {
376 return [preg_replace($pattern.
'u', $replace, $str)];
379 private static function modifierSubString (array $args, $str)
381 if (count($args) < 1) {
382 trigger_error(
"Missing 's' substr modifier parameter");
384 if (count($args) < 2) {
385 array_unshift($args, 0);
387 if (preg_match(
'/^(\d+)-(\d+)$/', $args[1], $m)) {
389 for ($i = $m[1];$i <= $m[2]; ++$i) {
390 $res[] = mb_substr($str, $args[0], $i);
392 return array_unique($res);
394 return [mb_substr($str, $args[0], $args[1])];
398 private static function modifierRandomString (array $args)
402 if (count($args) >= 2) {
403 $length = random_int($args[0], $args[1]);
404 if (count($args) >= 3) {
407 } elseif (count($args) >= 1) {
411 for ($i = 0; $i < $length; ++$i) {
415 $res .= (string)random_int(0, 9);
419 $nb = random_int(65, 116);
429 $nb = random_int(65, 126);
432 $nb = (string)($nb - 117);
448 private static function modifierDate (array $args)
450 if (count($args) < 1) {
453 if (count($args) < 2) {
456 $dateObject =
new DateTime($args[0],
new DateTimeZone(
'UTC'));
457 if ($args[1] ==
'epoch') {
459 return [floor($dateObject->format(
'U') / 86400)];
461 return [$dateObject->format($args[1])];
469 private static function modifierNumber (array $args)
471 if (count($args) < 1) {
474 if (count($args) < 2) {
477 if (count($args) < 3) {
480 $numberGenerator =
function ($mandatory, $start, $step)
492 return $numberGenerator($args[0], $args[1], $args[2]);
501 private static function modifierIncremental (array $args): array
505 if (count($args) < 1) {
508 if (count($args) < 2) {
511 if (count($args) < 3) {
514 $configDn =
CONFIGRDN.$config->current[
'BASE'];
517 $json = $tabObject->getBaseObject()->fdIncrementalModifierStates;
519 $modifierStates = [];
521 $modifierStates = json_decode($json, TRUE);
523 if (isset($modifierStates[$args[0]])) {
524 $value = $modifierStates[$args[0]][
'value'] + $args[2];
528 $modifierStates[$args[0]] = [
530 'date' => date(
'Y-m-d'),
532 $tabObject->getBaseObject()->fdIncrementalModifierStates = json_encode($modifierStates);
533 $errors = $tabObject->save();
535 if (!empty($errors)) {
542 private static function modifierTitleCase ($str)
544 return [mb_convert_case($str, MB_CASE_TITLE,
'UTF-8')];
557 mb_internal_encoding(
'UTF-8');
558 mb_regex_encoding(
'UTF-8');
559 if (is_array($str) && (!is_numeric($m)) && (strtolower($m) == $m)) {
561 if (count($str) == 0) {
570 $result = [reset($str)];
574 $result = [end($str)];
578 if (isset($args[0])) {
579 $result = [join($args[0], $str)];
581 $result = [join($str)];
586 $result = [count($str)];
590 if (count($args) < 1) {
591 trigger_error(
'Missing "M" match modifier parameter');
594 $result = array_filter(
596 function ($s) use ($args)
598 return preg_match($args[0], $s);
604 $result = array_filter($str,
'tests::is_ipv4');
608 $result = array_filter($str,
'tests::is_ipv6');
616 if (isset($args[0]) && ($args[0] ==
'd')) {
617 $result = [base64_decode($str)];
619 $result = [base64_encode($str)];
623 $result = [mb_strtoupper($str,
'UTF-8')];
627 $result = [mb_strtolower($str,
'UTF-8')];
631 $result = static::modifierRemoveAccents($args, $str);
635 $result = static::modifierTranslit($args, $str);
639 $result = static::modifierPregReplace($args, $str);
643 $result = static::modifierSubString($args, $str);
647 $result = static::modifierRandomString($args);
651 $result = static::modifierDate($args);
655 $result = static::modifierNumber($args);
659 $result = static::modifierTitleCase($str);
663 $result = static::modifierIncremental($args);
666 trigger_error(
"Unkown modifier '$m'");
674 protected static function flatDepends (&$cache, &$errors, $depends, $key, array $forbidden = [])
676 if (isset($cache[$key])) {
684 function ($a) use (&$cache, &$errors, $depends, $forbidden, $key)
686 if (in_array($a, $forbidden)) {
688 _(
'Recursive dependency in the template fields: "%1$s" cannot depend on "%2$s" as "%2$s" already depends on "%1$s"'),
694 $deps = static::flatDepends($cache, $errors, $depends, $a, $forbidden);
695 if (($askmeKey = array_search(
'askme', $deps)) !== FALSE) {
697 unset($deps[$askmeKey]);
703 $array[] = $depends[$key];
704 $cache[$key] = array_unique(array_merge_recursive(...$array));
713 foreach ($attrs as $key => $values) {
715 if (!is_array($values)) {
718 unset($values[
'count']);
719 foreach ($values as $value) {
721 while (preg_match(
'/%([^%\|]+\|)?([^%]+)%/', $value, $m, PREG_OFFSET_CAPTURE, $offset)) {
722 $offset = $m[0][1] + strlen($m[0][0]);
723 $depends[$key][] = $m[2][0];
724 if (!isset($attrs[$m[2][0]])) {
726 $attrs[$m[2][0]] = [];
727 $depends[$m[2][0]] = [];
735 foreach ($depends as $key => $value) {
736 static::flatDepends($flatdepends, $errors, $depends, $key);
738 return [$flatdepends, $errors];
744 uksort($attrs,
function ($k1, $k2) use ($flatdepends)
746 if (in_array($k1, $flatdepends[$k2])) {
748 } elseif (in_array($k2, $flatdepends[$k1])) {
752 $c1 = count($flatdepends[$k1]);
753 $c2 = count($flatdepends[$k2]);
757 return (($c1 < $c2) ? -1 : 1);
this class stores static methods used to parse templates LDAP data
static listFields($string)
Parse template masks in a single string and list the fields it needs.
static parseArray(array $attrs, array $specialAttrs, $target=NULL)
Parse template masks in an array.
const CONFIGRDN
FusionDirectory config object RDN.
static flatDepends(&$cache, &$errors, $depends, $key, array $forbidden=[])
Flattens dependencies (if a depends of b which depends of c then a depends of c)
static fetch($dn)
Fetch a template from LDAP and returns its attributes and dependencies information.
static addOrFail($object, string $user=NULL, int $retries=10)
Add a lock for object(s) or fail.
static open(string $dn, string $type)
Create the tab object for the given dn.
Parent class for all exceptions thrown in FusionDirectory.
static neededAttrs(array &$attrs, array $flatdepends)
Return attrs needed before applying template.
static deleteByObject($object)
Remove a lock for object(s)
static fieldsFromLDAP(array $template_attrs)
Translate template attrs into $attrs as if taken from LDAP.
static fieldsToLDAP(array $template_attrs, array $attrs)
Translate $attrs into template attrs.
strict_uid_mode()
Check if strict naming rules are configured.
static sortAttributes(array $attrs, array $flatdepends)
Sort attrs depending of dependencies.
static attributesDependencies(array $attrs)
Computes dependencies between attributes: which attributes must be filled in order to compute each at...
static parseMask(string $mask, array $attrs)
Parse a mask (without surrounding %) using $attrs attributes and apply modifiers. ...
static applyModifier(string $m, array $args, $str)
Apply a modifier.
static checkFields($attrs)
Check template fields.
static iteratePossibleValues(string $rule, array $variables, $escapeMethod=NULL)
Generator that yields possible template mask values.
static parseString(string $string, array $attrs, $escapeMethod=NULL, string $unique=NULL, string $target=NULL)
Parse template masks in a single string.
class_available($name)
Checks if a class is available.