mirror of
https://gitlab.easter-eggs.com/ee/ldapsaisie.git
synced 2024-11-22 09:59:06 +01:00
8920 lines
No EOL
1,011 KiB
HTML
8920 lines
No EOL
1,011 KiB
HTML
<!DOCTYPE html>
|
||
|
||
<html class="no-js" lang="fr"><head>
|
||
<meta charset="utf-8"/>
|
||
<meta content="width=device-width,initial-scale=1" name="viewport"/>
|
||
<meta content="Documentation" name="description"/>
|
||
<meta content="Benjamin Renard <brenard@easter-eggs.com / brenard@zionetrix.net>" name="author"/>
|
||
<link href="https://ldapsaisie.org/doc/print_page/" rel="canonical"/>
|
||
<link href="../assets/images/favicon.png" rel="icon"/>
|
||
<meta content="mkdocs-1.6.1, mkdocs-material-9.5.45" name="generator"/>
|
||
<title>Documentation - LdapSaisie</title>
|
||
<link href="data:text/css,%40charset%20%22UTF-8%22%3Bhtml%7B-webkit-text-size-adjust%3Anone%3B-moz-text-size-adjust%3Anone%3Btext-size-adjust%3Anone%3Bbox-sizing%3Aborder-box%7D%2A%2C%3Aafter%2C%3Abefore%7Bbox-sizing%3Ainherit%7D%40media%20%28prefers-reduced-motion%29%7B%2A%2C%3Aafter%2C%3Abefore%7Btransition%3Anone%21important%7D%7Dbody%7Bmargin%3A0%7Da%2Cbutton%2Cinput%2Clabel%7B-webkit-tap-highlight-color%3Atransparent%7Da%7Bcolor%3Ainherit%3Btext-decoration%3Anone%7Dhr%7Bborder%3A0%3Bbox-sizing%3Ainitial%3Bdisplay%3Ablock%3Bheight%3A.05rem%3Boverflow%3Avisible%3Bpadding%3A0%7Dsmall%7Bfont-size%3A80%25%7Dsub%2Csup%7Bline-height%3A1em%7Dimg%7Bborder-style%3Anone%7Dtable%7Bborder-collapse%3Ainitial%3Bborder-spacing%3A0%7Dtd%2Cth%7Bfont-weight%3A400%3Bvertical-align%3Atop%7Dbutton%7Bbackground%3A%230000%3Bborder%3A0%3Bfont-family%3Ainherit%3Bfont-size%3Ainherit%3Bmargin%3A0%3Bpadding%3A0%7Dinput%7Bborder%3A0%3Boutline%3Anone%7D%3Aroot%7B--md-primary-fg-color%3A%234051b5%3B--md-primary-fg-color--light%3A%235d6cc0%3B--md-primary-fg-color--dark%3A%23303fa1%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%3B--md-accent-fg-color%3A%23526cfe%3B--md-accent-fg-color--transparent%3A%23526cfe1a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-scheme%3Ddefault%5D%7Bcolor-scheme%3Alight%7D%5Bdata-md-color-scheme%3Ddefault%5D%20img%5Bsrc%24%3D%22%23gh-dark-mode-only%22%5D%2C%5Bdata-md-color-scheme%3Ddefault%5D%20img%5Bsrc%24%3D%22%23only-dark%22%5D%7Bdisplay%3Anone%7D%3Aroot%2C%5Bdata-md-color-scheme%3Ddefault%5D%7B--md-hue%3A225deg%3B--md-default-fg-color%3A%23000000de%3B--md-default-fg-color--light%3A%230000008a%3B--md-default-fg-color--lighter%3A%2300000052%3B--md-default-fg-color--lightest%3A%2300000012%3B--md-default-bg-color%3A%23fff%3B--md-default-bg-color--light%3A%23ffffffb3%3B--md-default-bg-color--lighter%3A%23ffffff4d%3B--md-default-bg-color--lightest%3A%23ffffff1f%3B--md-code-fg-color%3A%2336464e%3B--md-code-bg-color%3A%23f5f5f5%3B--md-code-hl-color%3A%234287ff%3B--md-code-hl-color--light%3A%234287ff1a%3B--md-code-hl-number-color%3A%23d52a2a%3B--md-code-hl-special-color%3A%23db1457%3B--md-code-hl-function-color%3A%23a846b9%3B--md-code-hl-constant-color%3A%236e59d9%3B--md-code-hl-keyword-color%3A%233f6ec6%3B--md-code-hl-string-color%3A%231c7d4d%3B--md-code-hl-name-color%3Avar%28--md-code-fg-color%29%3B--md-code-hl-operator-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-punctuation-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-comment-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-generic-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-variable-color%3Avar%28--md-default-fg-color--light%29%3B--md-typeset-color%3Avar%28--md-default-fg-color%29%3B--md-typeset-a-color%3Avar%28--md-primary-fg-color%29%3B--md-typeset-del-color%3A%23f5503d26%3B--md-typeset-ins-color%3A%230bd57026%3B--md-typeset-kbd-color%3A%23fafafa%3B--md-typeset-kbd-accent-color%3A%23fff%3B--md-typeset-kbd-border-color%3A%23b8b8b8%3B--md-typeset-mark-color%3A%23ffff0080%3B--md-typeset-table-color%3A%230000001f%3B--md-typeset-table-color--light%3Argba%280%2C0%2C0%2C.035%29%3B--md-admonition-fg-color%3Avar%28--md-default-fg-color%29%3B--md-admonition-bg-color%3Avar%28--md-default-bg-color%29%3B--md-warning-fg-color%3A%23000000de%3B--md-warning-bg-color%3A%23ff9%3B--md-footer-fg-color%3A%23fff%3B--md-footer-fg-color--light%3A%23ffffffb3%3B--md-footer-fg-color--lighter%3A%23ffffff73%3B--md-footer-bg-color%3A%23000000de%3B--md-footer-bg-color--dark%3A%2300000052%3B--md-shadow-z1%3A0%200.2rem%200.5rem%20%230000000d%2C0%200%200.05rem%20%230000001a%3B--md-shadow-z2%3A0%200.2rem%200.5rem%20%230000001a%2C0%200%200.05rem%20%2300000040%3B--md-shadow-z3%3A0%200.2rem%200.5rem%20%230003%2C0%200%200.05rem%20%2300000059%7D.md-icon%20svg%7Bfill%3Acurrentcolor%3Bdisplay%3Ablock%3Bheight%3A1.2rem%3Bwidth%3A1.2rem%7Dbody%7B-webkit-font-smoothing%3Aantialiased%3B-moz-osx-font-smoothing%3Agrayscale%3B--md-text-font-family%3Avar%28--md-text-font%2C_%29%2C-apple-system%2CBlinkMacSystemFont%2CHelvetica%2CArial%2Csans-serif%3B--md-code-font-family%3Avar%28--md-code-font%2C_%29%2CSFMono-Regular%2CConsolas%2CMenlo%2Cmonospace%7Daside%2Cbody%2Cinput%7Bfont-feature-settings%3A%22kern%22%2C%22liga%22%3Bcolor%3Avar%28--md-typeset-color%29%3Bfont-family%3Avar%28--md-text-font-family%29%7Dcode%2Ckbd%2Cpre%7Bfont-feature-settings%3A%22kern%22%3Bfont-family%3Avar%28--md-code-font-family%29%7D%3Aroot%7B--md-typeset-table-sort-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22m18%2021-4-4h3V7h-3l4-4%204%204h-3v10h3M2%2019v-2h10v2M2%2013v-2h7v2M2%207V5h4v2z%22/%3E%3C/svg%3E%27%29%3B--md-typeset-table-sort-icon--asc%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19%2017h3l-4%204-4-4h3V3h2M2%2017h10v2H2M6%205v2H2V5m0%206h7v2H2z%22/%3E%3C/svg%3E%27%29%3B--md-typeset-table-sort-icon--desc%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19%207h3l-4-4-4%204h3v14h2M2%2017h10v2H2M6%205v2H2V5m0%206h7v2H2z%22/%3E%3C/svg%3E%27%29%7D.md-typeset%7B-webkit-print-color-adjust%3Aexact%3Bcolor-adjust%3Aexact%3Bfont-size%3A.8rem%3Bline-height%3A1.6%7D%40media%20print%7B.md-typeset%7Bfont-size%3A.68rem%7D%7D.md-typeset%20blockquote%2C.md-typeset%20dl%2C.md-typeset%20figure%2C.md-typeset%20ol%2C.md-typeset%20pre%2C.md-typeset%20ul%7Bmargin-bottom%3A1em%3Bmargin-top%3A1em%7D.md-typeset%20h1%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bfont-size%3A2em%3Bline-height%3A1.3%3Bmargin%3A0%200%201.25em%7D.md-typeset%20h1%2C.md-typeset%20h2%7Bfont-weight%3A300%3Bletter-spacing%3A-.01em%7D.md-typeset%20h2%7Bfont-size%3A1.5625em%3Bline-height%3A1.4%3Bmargin%3A1.6em%200%20.64em%7D.md-typeset%20h3%7Bfont-size%3A1.25em%3Bfont-weight%3A400%3Bletter-spacing%3A-.01em%3Bline-height%3A1.5%3Bmargin%3A1.6em%200%20.8em%7D.md-typeset%20h2%2Bh3%7Bmargin-top%3A.8em%7D.md-typeset%20h4%7Bfont-weight%3A700%3Bletter-spacing%3A-.01em%3Bmargin%3A1em%200%7D.md-typeset%20h5%2C.md-typeset%20h6%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bfont-size%3A.8em%3Bfont-weight%3A700%3Bletter-spacing%3A-.01em%3Bmargin%3A1.25em%200%7D.md-typeset%20h5%7Btext-transform%3Auppercase%7D.md-typeset%20hr%7Bborder-bottom%3A.05rem%20solid%20var%28--md-default-fg-color--lightest%29%3Bdisplay%3Aflow-root%3Bmargin%3A1.5em%200%7D.md-typeset%20a%7Bcolor%3Avar%28--md-typeset-a-color%29%3Bword-break%3Abreak-word%7D.md-typeset%20a%2C.md-typeset%20a%3Abefore%7Btransition%3Acolor%20125ms%7D.md-typeset%20a%3Afocus%2C.md-typeset%20a%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20a%3Afocus%20code%2C.md-typeset%20a%3Ahover%20code%7Bbackground-color%3Avar%28--md-accent-fg-color--transparent%29%7D.md-typeset%20a%20code%7Bcolor%3Acurrentcolor%3Btransition%3Abackground-color%20125ms%7D.md-typeset%20a.focus-visible%7Boutline-color%3Avar%28--md-accent-fg-color%29%3Boutline-offset%3A.2rem%7D.md-typeset%20code%2C.md-typeset%20kbd%2C.md-typeset%20pre%7Bcolor%3Avar%28--md-code-fg-color%29%3Bdirection%3Altr%3Bfont-variant-ligatures%3Anone%7D%40media%20print%7B.md-typeset%20code%2C.md-typeset%20kbd%2C.md-typeset%20pre%7Bwhite-space%3Apre-wrap%7D%7D.md-typeset%20code%7Bbackground-color%3Avar%28--md-code-bg-color%29%3Bborder-radius%3A.1rem%3B-webkit-box-decoration-break%3Aclone%3Bbox-decoration-break%3Aclone%3Bfont-size%3A.85em%3Bpadding%3A0%20.2941176471em%3Bword-break%3Abreak-word%7D.md-typeset%20code%3Anot%28.focus-visible%29%7B-webkit-tap-highlight-color%3Atransparent%3Boutline%3Anone%7D.md-typeset%20pre%7Bdisplay%3Aflow-root%3Bline-height%3A1.4%3Bposition%3Arelative%7D.md-typeset%20pre%3Ecode%7B-webkit-box-decoration-break%3Aslice%3Bbox-decoration-break%3Aslice%3Bbox-shadow%3Anone%3Bdisplay%3Ablock%3Bmargin%3A0%3Boutline-color%3Avar%28--md-accent-fg-color%29%3Boverflow%3Aauto%3Bpadding%3A.7720588235em%201.1764705882em%3Bscrollbar-color%3Avar%28--md-default-fg-color--lighter%29%20%230000%3Bscrollbar-width%3Athin%3Btouch-action%3Aauto%3Bword-break%3Anormal%7D.md-typeset%20pre%3Ecode%3Ahover%7Bscrollbar-color%3Avar%28--md-accent-fg-color%29%20%230000%7D.md-typeset%20pre%3Ecode%3A%3A-webkit-scrollbar%7Bheight%3A.2rem%3Bwidth%3A.2rem%7D.md-typeset%20pre%3Ecode%3A%3A-webkit-scrollbar-thumb%7Bbackground-color%3Avar%28--md-default-fg-color--lighter%29%7D.md-typeset%20pre%3Ecode%3A%3A-webkit-scrollbar-thumb%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20kbd%7Bbackground-color%3Avar%28--md-typeset-kbd-color%29%3Bborder-radius%3A.1rem%3Bbox-shadow%3A0%20.1rem%200%20.05rem%20var%28--md-typeset-kbd-border-color%29%2C0%20.1rem%200%20var%28--md-typeset-kbd-border-color%29%2C0%20-.1rem%20.2rem%20var%28--md-typeset-kbd-accent-color%29%20inset%3Bcolor%3Avar%28--md-default-fg-color%29%3Bdisplay%3Ainline-block%3Bfont-size%3A.75em%3Bpadding%3A0%20.6666666667em%3Bvertical-align%3Atext-top%3Bword-break%3Abreak-word%7D.md-typeset%20mark%7Bbackground-color%3Avar%28--md-typeset-mark-color%29%3B-webkit-box-decoration-break%3Aclone%3Bbox-decoration-break%3Aclone%3Bcolor%3Ainherit%3Bword-break%3Abreak-word%7D.md-typeset%20abbr%7Bborder-bottom%3A.05rem%20dotted%20var%28--md-default-fg-color--light%29%3Bcursor%3Ahelp%3Btext-decoration%3Anone%7D.md-typeset%20small%7Bopacity%3A.75%7D%5Bdir%3Dltr%5D%20.md-typeset%20sub%2C%5Bdir%3Dltr%5D%20.md-typeset%20sup%7Bmargin-left%3A.078125em%7D%5Bdir%3Drtl%5D%20.md-typeset%20sub%2C%5Bdir%3Drtl%5D%20.md-typeset%20sup%7Bmargin-right%3A.078125em%7D%5Bdir%3Dltr%5D%20.md-typeset%20blockquote%7Bpadding-left%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20blockquote%7Bpadding-right%3A.6rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20blockquote%7Bborder-left%3A.2rem%20solid%20var%28--md-default-fg-color--lighter%29%7D%5Bdir%3Drtl%5D%20.md-typeset%20blockquote%7Bborder-right%3A.2rem%20solid%20var%28--md-default-fg-color--lighter%29%7D.md-typeset%20blockquote%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bmargin-left%3A0%3Bmargin-right%3A0%7D.md-typeset%20ul%7Blist-style-type%3Adisc%7D.md-typeset%20ul%5Btype%5D%7Blist-style-type%3Arevert-layer%7D%5Bdir%3Dltr%5D%20.md-typeset%20ol%2C%5Bdir%3Dltr%5D%20.md-typeset%20ul%7Bmargin-left%3A.625em%7D%5Bdir%3Drtl%5D%20.md-typeset%20ol%2C%5Bdir%3Drtl%5D%20.md-typeset%20ul%7Bmargin-right%3A.625em%7D.md-typeset%20ol%2C.md-typeset%20ul%7Bpadding%3A0%7D.md-typeset%20ol%3Anot%28%5Bhidden%5D%29%2C.md-typeset%20ul%3Anot%28%5Bhidden%5D%29%7Bdisplay%3Aflow-root%7D.md-typeset%20ol%20ol%2C.md-typeset%20ul%20ol%7Blist-style-type%3Alower-alpha%7D.md-typeset%20ol%20ol%20ol%2C.md-typeset%20ul%20ol%20ol%7Blist-style-type%3Alower-roman%7D.md-typeset%20ol%20ol%20ol%20ol%2C.md-typeset%20ul%20ol%20ol%20ol%7Blist-style-type%3Aupper-alpha%7D.md-typeset%20ol%20ol%20ol%20ol%20ol%2C.md-typeset%20ul%20ol%20ol%20ol%20ol%7Blist-style-type%3Aupper-roman%7D.md-typeset%20ol%5Btype%5D%2C.md-typeset%20ul%5Btype%5D%7Blist-style-type%3Arevert-layer%7D%5Bdir%3Dltr%5D%20.md-typeset%20ol%20li%2C%5Bdir%3Dltr%5D%20.md-typeset%20ul%20li%7Bmargin-left%3A1.25em%7D%5Bdir%3Drtl%5D%20.md-typeset%20ol%20li%2C%5Bdir%3Drtl%5D%20.md-typeset%20ul%20li%7Bmargin-right%3A1.25em%7D.md-typeset%20ol%20li%2C.md-typeset%20ul%20li%7Bmargin-bottom%3A.5em%7D.md-typeset%20ol%20li%20blockquote%2C.md-typeset%20ol%20li%20p%2C.md-typeset%20ul%20li%20blockquote%2C.md-typeset%20ul%20li%20p%7Bmargin%3A.5em%200%7D.md-typeset%20ol%20li%3Alast-child%2C.md-typeset%20ul%20li%3Alast-child%7Bmargin-bottom%3A0%7D%5Bdir%3Dltr%5D%20.md-typeset%20ol%20li%20ol%2C%5Bdir%3Dltr%5D%20.md-typeset%20ol%20li%20ul%2C%5Bdir%3Dltr%5D%20.md-typeset%20ul%20li%20ol%2C%5Bdir%3Dltr%5D%20.md-typeset%20ul%20li%20ul%7Bmargin-left%3A.625em%7D%5Bdir%3Drtl%5D%20.md-typeset%20ol%20li%20ol%2C%5Bdir%3Drtl%5D%20.md-typeset%20ol%20li%20ul%2C%5Bdir%3Drtl%5D%20.md-typeset%20ul%20li%20ol%2C%5Bdir%3Drtl%5D%20.md-typeset%20ul%20li%20ul%7Bmargin-right%3A.625em%7D.md-typeset%20ol%20li%20ol%2C.md-typeset%20ol%20li%20ul%2C.md-typeset%20ul%20li%20ol%2C.md-typeset%20ul%20li%20ul%7Bmargin-bottom%3A.5em%3Bmargin-top%3A.5em%7D%5Bdir%3Dltr%5D%20.md-typeset%20dd%7Bmargin-left%3A1.875em%7D%5Bdir%3Drtl%5D%20.md-typeset%20dd%7Bmargin-right%3A1.875em%7D.md-typeset%20dd%7Bmargin-bottom%3A1.5em%3Bmargin-top%3A1em%7D.md-typeset%20img%2C.md-typeset%20svg%2C.md-typeset%20video%7Bheight%3Aauto%3Bmax-width%3A100%25%7D.md-typeset%20img%5Balign%3Dleft%5D%7Bmargin%3A1em%201em%201em%200%7D.md-typeset%20img%5Balign%3Dright%5D%7Bmargin%3A1em%200%201em%201em%7D.md-typeset%20img%5Balign%5D%3Aonly-child%7Bmargin-top%3A0%7D.md-typeset%20figure%7Bdisplay%3Aflow-root%3Bmargin%3A1em%20auto%3Bmax-width%3A100%25%3Btext-align%3Acenter%3Bwidth%3A-moz-fit-content%3Bwidth%3Afit-content%7D.md-typeset%20figure%20img%7Bdisplay%3Ablock%3Bmargin%3A0%20auto%7D.md-typeset%20figcaption%7Bfont-style%3Aitalic%3Bmargin%3A1em%20auto%3Bmax-width%3A24rem%7D.md-typeset%20iframe%7Bmax-width%3A100%25%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder%3A.05rem%20solid%20var%28--md-typeset-table-color%29%3Bborder-radius%3A.1rem%3Bdisplay%3Ainline-block%3Bfont-size%3A.64rem%3Bmax-width%3A100%25%3Boverflow%3Aauto%3Btouch-action%3Aauto%7D%40media%20print%7B.md-typeset%20table%3Anot%28%5Bclass%5D%29%7Bdisplay%3Atable%7D%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%2B%2A%7Bmargin-top%3A1.5em%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20td%3E%3Afirst-child%2C.md-typeset%20table%3Anot%28%5Bclass%5D%29%20th%3E%3Afirst-child%7Bmargin-top%3A0%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20td%3E%3Alast-child%2C.md-typeset%20table%3Anot%28%5Bclass%5D%29%20th%3E%3Alast-child%7Bmargin-bottom%3A0%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20td%3Anot%28%5Balign%5D%29%2C.md-typeset%20table%3Anot%28%5Bclass%5D%29%20th%3Anot%28%5Balign%5D%29%7Btext-align%3Aleft%7D%5Bdir%3Drtl%5D%20.md-typeset%20table%3Anot%28%5Bclass%5D%29%20td%3Anot%28%5Balign%5D%29%2C%5Bdir%3Drtl%5D%20.md-typeset%20table%3Anot%28%5Bclass%5D%29%20th%3Anot%28%5Balign%5D%29%7Btext-align%3Aright%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20th%7Bfont-weight%3A700%3Bmin-width%3A5rem%3Bpadding%3A.9375em%201.25em%3Bvertical-align%3Atop%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20td%7Bborder-top%3A.05rem%20solid%20var%28--md-typeset-table-color%29%3Bpadding%3A.9375em%201.25em%3Bvertical-align%3Atop%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20tbody%20tr%7Btransition%3Abackground-color%20125ms%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20tbody%20tr%3Ahover%7Bbackground-color%3Avar%28--md-typeset-table-color--light%29%3Bbox-shadow%3A0%20.05rem%200%20var%28--md-default-bg-color%29%20inset%7D.md-typeset%20table%3Anot%28%5Bclass%5D%29%20a%7Bword-break%3Anormal%7D.md-typeset%20table%20th%5Brole%3Dcolumnheader%5D%7Bcursor%3Apointer%7D%5Bdir%3Dltr%5D%20.md-typeset%20table%20th%5Brole%3Dcolumnheader%5D%3Aafter%7Bmargin-left%3A.5em%7D%5Bdir%3Drtl%5D%20.md-typeset%20table%20th%5Brole%3Dcolumnheader%5D%3Aafter%7Bmargin-right%3A.5em%7D.md-typeset%20table%20th%5Brole%3Dcolumnheader%5D%3Aafter%7Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A1.2em%3B-webkit-mask-image%3Avar%28--md-typeset-table-sort-icon%29%3Bmask-image%3Avar%28--md-typeset-table-sort-icon%29%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Btransition%3Abackground-color%20125ms%3Bvertical-align%3Atext-bottom%3Bwidth%3A1.2em%7D.md-typeset%20table%20th%5Brole%3Dcolumnheader%5D%3Ahover%3Aafter%7Bbackground-color%3Avar%28--md-default-fg-color--lighter%29%7D.md-typeset%20table%20th%5Brole%3Dcolumnheader%5D%5Baria-sort%3Dascending%5D%3Aafter%7Bbackground-color%3Avar%28--md-default-fg-color--light%29%3B-webkit-mask-image%3Avar%28--md-typeset-table-sort-icon--asc%29%3Bmask-image%3Avar%28--md-typeset-table-sort-icon--asc%29%7D.md-typeset%20table%20th%5Brole%3Dcolumnheader%5D%5Baria-sort%3Ddescending%5D%3Aafter%7Bbackground-color%3Avar%28--md-default-fg-color--light%29%3B-webkit-mask-image%3Avar%28--md-typeset-table-sort-icon--desc%29%3Bmask-image%3Avar%28--md-typeset-table-sort-icon--desc%29%7D.md-typeset__scrollwrap%7Bmargin%3A1em%20-.8rem%3Boverflow-x%3Aauto%3Btouch-action%3Aauto%7D.md-typeset__table%7Bdisplay%3Ainline-block%3Bmargin-bottom%3A.5em%3Bpadding%3A0%20.8rem%7D%40media%20print%7B.md-typeset__table%7Bdisplay%3Ablock%7D%7Dhtml%20.md-typeset__table%20table%7Bdisplay%3Atable%3Bmargin%3A0%3Boverflow%3Ahidden%3Bwidth%3A100%25%7D%40media%20screen%20and%20%28max-width%3A44.984375em%29%7B.md-content__inner%3Epre%7Bmargin%3A1em%20-.8rem%7D.md-content__inner%3Epre%20code%7Bborder-radius%3A0%7D%7D.md-typeset%20.md-author%7Bborder-radius%3A100%25%3Bdisplay%3Ablock%3Bflex-shrink%3A0%3Bheight%3A1.6rem%3Boverflow%3Ahidden%3Bposition%3Arelative%3Btransition%3Acolor%20125ms%2Ctransform%20125ms%3Bwidth%3A1.6rem%7D.md-typeset%20.md-author%20img%7Bdisplay%3Ablock%7D.md-typeset%20.md-author--more%7Bbackground%3Avar%28--md-default-fg-color--lightest%29%3Bcolor%3Avar%28--md-default-fg-color--lighter%29%3Bfont-size%3A.6rem%3Bfont-weight%3A700%3Bline-height%3A1.6rem%3Btext-align%3Acenter%7D.md-typeset%20.md-author--long%7Bheight%3A2.4rem%3Bwidth%3A2.4rem%7D.md-typeset%20a.md-author%7Btransform%3Ascale%281%29%7D.md-typeset%20a.md-author%20img%7Bborder-radius%3A100%25%3Bfilter%3Agrayscale%28100%25%29%20opacity%2875%25%29%3Btransition%3Afilter%20125ms%7D.md-typeset%20a.md-author%3Afocus%2C.md-typeset%20a.md-author%3Ahover%7Btransform%3Ascale%281.1%29%3Bz-index%3A1%7D.md-typeset%20a.md-author%3Afocus%20img%2C.md-typeset%20a.md-author%3Ahover%20img%7Bfilter%3Agrayscale%280%29%7D.md-banner%7Bbackground-color%3Avar%28--md-footer-bg-color%29%3Bcolor%3Avar%28--md-footer-fg-color%29%3Boverflow%3Aauto%7D%40media%20print%7B.md-banner%7Bdisplay%3Anone%7D%7D.md-banner--warning%7Bbackground-color%3Avar%28--md-warning-bg-color%29%3Bcolor%3Avar%28--md-warning-fg-color%29%7D.md-banner__inner%7Bfont-size%3A.7rem%3Bmargin%3A.6rem%20auto%3Bpadding%3A0%20.8rem%7D%5Bdir%3Dltr%5D%20.md-banner__button%7Bfloat%3Aright%7D%5Bdir%3Drtl%5D%20.md-banner__button%7Bfloat%3Aleft%7D.md-banner__button%7Bcolor%3Ainherit%3Bcursor%3Apointer%3Btransition%3Aopacity%20.25s%7D.no-js%20.md-banner__button%7Bdisplay%3Anone%7D.md-banner__button%3Ahover%7Bopacity%3A.7%7Dhtml%7Bfont-size%3A125%25%3Bheight%3A100%25%3Boverflow-x%3Ahidden%7D%40media%20screen%20and%20%28min-width%3A100em%29%7Bhtml%7Bfont-size%3A137.5%25%7D%7D%40media%20screen%20and%20%28min-width%3A125em%29%7Bhtml%7Bfont-size%3A150%25%7D%7Dbody%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bdisplay%3Aflex%3Bflex-direction%3Acolumn%3Bfont-size%3A.5rem%3Bmin-height%3A100%25%3Bposition%3Arelative%3Bwidth%3A100%25%7D%40media%20print%7Bbody%7Bdisplay%3Ablock%7D%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7Bbody%5Bdata-md-scrolllock%5D%7Bposition%3Afixed%7D%7D.md-grid%7Bmargin-left%3Aauto%3Bmargin-right%3Aauto%3Bmax-width%3A61rem%7D.md-container%7Bdisplay%3Aflex%3Bflex-direction%3Acolumn%3Bflex-grow%3A1%7D%40media%20print%7B.md-container%7Bdisplay%3Ablock%7D%7D.md-main%7Bflex-grow%3A1%7D.md-main__inner%7Bdisplay%3Aflex%3Bheight%3A100%25%3Bmargin-top%3A1.5rem%7D.md-ellipsis%7Boverflow%3Ahidden%3Btext-overflow%3Aellipsis%7D.md-toggle%7Bdisplay%3Anone%7D.md-option%7Bheight%3A0%3Bopacity%3A0%3Bposition%3Aabsolute%3Bwidth%3A0%7D.md-option%3Achecked%2Blabel%3Anot%28%5Bhidden%5D%29%7Bdisplay%3Ablock%7D.md-option.focus-visible%2Blabel%7Boutline-color%3Avar%28--md-accent-fg-color%29%3Boutline-style%3Aauto%7D.md-skip%7Bbackground-color%3Avar%28--md-default-fg-color%29%3Bborder-radius%3A.1rem%3Bcolor%3Avar%28--md-default-bg-color%29%3Bfont-size%3A.64rem%3Bmargin%3A.5rem%3Bopacity%3A0%3Boutline-color%3Avar%28--md-accent-fg-color%29%3Bpadding%3A.3rem%20.5rem%3Bposition%3Afixed%3Btransform%3AtranslateY%28.4rem%29%3Bz-index%3A-1%7D.md-skip%3Afocus%7Bopacity%3A1%3Btransform%3AtranslateY%280%29%3Btransition%3Atransform%20.25s%20cubic-bezier%28.4%2C0%2C.2%2C1%29%2Copacity%20175ms%2075ms%3Bz-index%3A10%7D%40page%7Bmargin%3A25mm%7D%3Aroot%7B--md-clipboard-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19%2021H8V7h11m0-2H8a2%202%200%200%200-2%202v14a2%202%200%200%200%202%202h11a2%202%200%200%200%202-2V7a2%202%200%200%200-2-2m-3-4H4a2%202%200%200%200-2%202v14h2V3h12z%22/%3E%3C/svg%3E%27%29%7D.md-clipboard%7Bborder-radius%3A.1rem%3Bcolor%3Avar%28--md-default-fg-color--lightest%29%3Bcursor%3Apointer%3Bheight%3A1.5em%3Boutline-color%3Avar%28--md-accent-fg-color%29%3Boutline-offset%3A.1rem%3Bposition%3Aabsolute%3Bright%3A.5em%3Btop%3A.5em%3Btransition%3Acolor%20.25s%3Bwidth%3A1.5em%3Bz-index%3A1%7D%40media%20print%7B.md-clipboard%7Bdisplay%3Anone%7D%7D.md-clipboard%3Anot%28.focus-visible%29%7B-webkit-tap-highlight-color%3Atransparent%3Boutline%3Anone%7D%3Ahover%3E.md-clipboard%7Bcolor%3Avar%28--md-default-fg-color--light%29%7D.md-clipboard%3Afocus%2C.md-clipboard%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-clipboard%3Aafter%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ablock%3Bheight%3A1.125em%3Bmargin%3A0%20auto%3B-webkit-mask-image%3Avar%28--md-clipboard-icon%29%3Bmask-image%3Avar%28--md-clipboard-icon%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bwidth%3A1.125em%7D.md-clipboard--inline%7Bcursor%3Apointer%7D.md-clipboard--inline%20code%7Btransition%3Acolor%20.25s%2Cbackground-color%20.25s%7D.md-clipboard--inline%3Afocus%20code%2C.md-clipboard--inline%3Ahover%20code%7Bbackground-color%3Avar%28--md-accent-fg-color--transparent%29%3Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20.md-code__content%7Bdisplay%3Agrid%7D%40keyframes%20consent%7B0%25%7Bopacity%3A0%3Btransform%3AtranslateY%28100%25%29%7Dto%7Bopacity%3A1%3Btransform%3AtranslateY%280%29%7D%7D%40keyframes%20overlay%7B0%25%7Bopacity%3A0%7Dto%7Bopacity%3A1%7D%7D.md-consent__overlay%7Banimation%3Aoverlay%20.25s%20both%3B-webkit-backdrop-filter%3Ablur%28.1rem%29%3Bbackdrop-filter%3Ablur%28.1rem%29%3Bbackground-color%3A%230000008a%3Bheight%3A100%25%3Bopacity%3A1%3Bposition%3Afixed%3Btop%3A0%3Bwidth%3A100%25%3Bz-index%3A5%7D.md-consent__inner%7Banimation%3Aconsent%20.5s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%20both%3Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder%3A0%3Bborder-radius%3A.1rem%3Bbottom%3A0%3Bbox-shadow%3A0%200%20.2rem%20%230000001a%2C0%20.2rem%20.4rem%20%230003%3Bmax-height%3A100%25%3Boverflow%3Aauto%3Bpadding%3A0%3Bposition%3Afixed%3Bwidth%3A100%25%3Bz-index%3A5%7D.md-consent__form%7Bpadding%3A.8rem%7D.md-consent__settings%7Bdisplay%3Anone%3Bmargin%3A1em%200%7Dinput%3Achecked%2B.md-consent__settings%7Bdisplay%3Ablock%7D.md-consent__controls%7Bmargin-bottom%3A.8rem%7D.md-typeset%20.md-consent__controls%20.md-button%7Bdisplay%3Ainline%7D%40media%20screen%20and%20%28max-width%3A44.984375em%29%7B.md-typeset%20.md-consent__controls%20.md-button%7Bdisplay%3Ablock%3Bmargin-top%3A.4rem%3Btext-align%3Acenter%3Bwidth%3A100%25%7D%7D.md-consent%20label%7Bcursor%3Apointer%7D.md-content%7Bflex-grow%3A1%3Bmin-width%3A0%7D.md-content__inner%7Bmargin%3A0%20.8rem%201.2rem%3Bpadding-top%3A.6rem%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B%5Bdir%3Dltr%5D%20.md-sidebar--primary%3Anot%28%5Bhidden%5D%29~.md-content%3E.md-content__inner%7Bmargin-left%3A1.2rem%7D%5Bdir%3Dltr%5D%20.md-sidebar--secondary%3Anot%28%5Bhidden%5D%29~.md-content%3E.md-content__inner%2C%5Bdir%3Drtl%5D%20.md-sidebar--primary%3Anot%28%5Bhidden%5D%29~.md-content%3E.md-content__inner%7Bmargin-right%3A1.2rem%7D%5Bdir%3Drtl%5D%20.md-sidebar--secondary%3Anot%28%5Bhidden%5D%29~.md-content%3E.md-content__inner%7Bmargin-left%3A1.2rem%7D%7D.md-content__inner%3Abefore%7Bcontent%3A%22%22%3Bdisplay%3Ablock%3Bheight%3A.4rem%7D.md-content__inner%3E%3Alast-child%7Bmargin-bottom%3A0%7D%5Bdir%3Dltr%5D%20.md-content__button%7Bfloat%3Aright%7D%5Bdir%3Drtl%5D%20.md-content__button%7Bfloat%3Aleft%7D%5Bdir%3Dltr%5D%20.md-content__button%7Bmargin-left%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-content__button%7Bmargin-right%3A.4rem%7D.md-content__button%7Bmargin%3A.4rem%200%3Bpadding%3A0%7D%40media%20print%7B.md-content__button%7Bdisplay%3Anone%7D%7D.md-typeset%20.md-content__button%7Bcolor%3Avar%28--md-default-fg-color--lighter%29%7D.md-content__button%20svg%7Bdisplay%3Ainline%3Bvertical-align%3Atop%7D%5Bdir%3Drtl%5D%20.md-content__button%20svg%7Btransform%3AscaleX%28-1%29%7D%5Bdir%3Dltr%5D%20.md-dialog%7Bright%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-dialog%7Bleft%3A.8rem%7D.md-dialog%7Bbackground-color%3Avar%28--md-default-fg-color%29%3Bborder-radius%3A.1rem%3Bbottom%3A.8rem%3Bbox-shadow%3Avar%28--md-shadow-z3%29%3Bmin-width%3A11.1rem%3Bopacity%3A0%3Bpadding%3A.4rem%20.6rem%3Bpointer-events%3Anone%3Bposition%3Afixed%3Btransform%3AtranslateY%28100%25%29%3Btransition%3Atransform%200ms%20.4s%2Copacity%20.4s%3Bz-index%3A4%7D%40media%20print%7B.md-dialog%7Bdisplay%3Anone%7D%7D.md-dialog--active%7Bopacity%3A1%3Bpointer-events%3Aauto%3Btransform%3AtranslateY%280%29%3Btransition%3Atransform%20.4s%20cubic-bezier%28.075%2C.85%2C.175%2C1%29%2Copacity%20.4s%7D.md-dialog__inner%7Bcolor%3Avar%28--md-default-bg-color%29%3Bfont-size%3A.7rem%7D.md-feedback%7Bmargin%3A2em%200%201em%3Btext-align%3Acenter%7D.md-feedback%20fieldset%7Bborder%3Anone%3Bmargin%3A0%3Bpadding%3A0%7D.md-feedback__title%7Bfont-weight%3A700%3Bmargin%3A1em%20auto%7D.md-feedback__inner%7Bposition%3Arelative%7D.md-feedback__list%7Bdisplay%3Aflex%3Bflex-wrap%3Awrap%3Bplace-content%3Abaseline%20center%3Bposition%3Arelative%7D.md-feedback__list%3Ahover%20.md-icon%3Anot%28%3Adisabled%29%7Bcolor%3Avar%28--md-default-fg-color--lighter%29%7D%3Adisabled%20.md-feedback__list%7Bmin-height%3A1.8rem%7D.md-feedback__icon%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bcursor%3Apointer%3Bflex-shrink%3A0%3Bmargin%3A0%20.1rem%3Btransition%3Acolor%20125ms%7D.md-feedback__icon%3Anot%28%3Adisabled%29.md-icon%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-feedback__icon%3Adisabled%7Bcolor%3Avar%28--md-default-fg-color--lightest%29%3Bpointer-events%3Anone%7D.md-feedback__note%7Bopacity%3A0%3Bposition%3Arelative%3Btransform%3AtranslateY%28.4rem%29%3Btransition%3Atransform%20.4s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Copacity%20.15s%7D.md-feedback__note%3E%2A%7Bmargin%3A0%20auto%3Bmax-width%3A16rem%7D%3Adisabled%20.md-feedback__note%7Bopacity%3A1%3Btransform%3AtranslateY%280%29%7D%40media%20print%7B.md-feedback%7Bdisplay%3Anone%7D%7D.md-footer%7Bbackground-color%3Avar%28--md-footer-bg-color%29%3Bcolor%3Avar%28--md-footer-fg-color%29%7D%40media%20print%7B.md-footer%7Bdisplay%3Anone%7D%7D.md-footer__inner%7Bjustify-content%3Aspace-between%3Boverflow%3Aauto%3Bpadding%3A.2rem%7D.md-footer__inner%3Anot%28%5Bhidden%5D%29%7Bdisplay%3Aflex%7D.md-footer__link%7Balign-items%3Aend%3Bdisplay%3Aflex%3Bflex-grow%3A0.01%3Bmargin-bottom%3A.4rem%3Bmargin-top%3A1rem%3Bmax-width%3A100%25%3Boutline-color%3Avar%28--md-accent-fg-color%29%3Boverflow%3Ahidden%3Btransition%3Aopacity%20.25s%7D.md-footer__link%3Afocus%2C.md-footer__link%3Ahover%7Bopacity%3A.7%7D%5Bdir%3Drtl%5D%20.md-footer__link%20svg%7Btransform%3AscaleX%28-1%29%7D%40media%20screen%20and%20%28max-width%3A44.984375em%29%7B.md-footer__link--prev%7Bflex-shrink%3A0%7D.md-footer__link--prev%20.md-footer__title%7Bdisplay%3Anone%7D%7D%5Bdir%3Dltr%5D%20.md-footer__link--next%7Bmargin-left%3Aauto%7D%5Bdir%3Drtl%5D%20.md-footer__link--next%7Bmargin-right%3Aauto%7D.md-footer__link--next%7Btext-align%3Aright%7D%5Bdir%3Drtl%5D%20.md-footer__link--next%7Btext-align%3Aleft%7D.md-footer__title%7Bflex-grow%3A1%3Bfont-size%3A.9rem%3Bmargin-bottom%3A.7rem%3Bmax-width%3Acalc%28100%25%20-%202.4rem%29%3Bpadding%3A0%201rem%3Bwhite-space%3Anowrap%7D.md-footer__button%7Bmargin%3A.2rem%3Bpadding%3A.4rem%7D.md-footer__direction%7Bfont-size%3A.64rem%3Bopacity%3A.7%7D.md-footer-meta%7Bbackground-color%3Avar%28--md-footer-bg-color--dark%29%7D.md-footer-meta__inner%7Bdisplay%3Aflex%3Bflex-wrap%3Awrap%3Bjustify-content%3Aspace-between%3Bpadding%3A.2rem%7Dhtml%20.md-footer-meta.md-typeset%20a%7Bcolor%3Avar%28--md-footer-fg-color--light%29%7Dhtml%20.md-footer-meta.md-typeset%20a%3Afocus%2Chtml%20.md-footer-meta.md-typeset%20a%3Ahover%7Bcolor%3Avar%28--md-footer-fg-color%29%7D.md-copyright%7Bcolor%3Avar%28--md-footer-fg-color--lighter%29%3Bfont-size%3A.64rem%3Bmargin%3Aauto%20.6rem%3Bpadding%3A.4rem%200%3Bwidth%3A100%25%7D%40media%20screen%20and%20%28min-width%3A45em%29%7B.md-copyright%7Bwidth%3Aauto%7D%7D.md-copyright__highlight%7Bcolor%3Avar%28--md-footer-fg-color--light%29%7D.md-social%7Bdisplay%3Ainline-flex%3Bgap%3A.2rem%3Bmargin%3A0%20.4rem%3Bpadding%3A.2rem%200%20.6rem%7D%40media%20screen%20and%20%28min-width%3A45em%29%7B.md-social%7Bpadding%3A.6rem%200%7D%7D.md-social__link%7Bdisplay%3Ainline-block%3Bheight%3A1.6rem%3Btext-align%3Acenter%3Bwidth%3A1.6rem%7D.md-social__link%3Abefore%7Bline-height%3A1.9%7D.md-social__link%20svg%7Bfill%3Acurrentcolor%3Bmax-height%3A.8rem%3Bvertical-align%3A-25%25%7D.md-typeset%20.md-button%7Bborder%3A.1rem%20solid%3Bborder-radius%3A.1rem%3Bcolor%3Avar%28--md-primary-fg-color%29%3Bcursor%3Apointer%3Bdisplay%3Ainline-block%3Bfont-weight%3A700%3Bpadding%3A.625em%202em%3Btransition%3Acolor%20125ms%2Cbackground-color%20125ms%2Cborder-color%20125ms%7D.md-typeset%20.md-button--primary%7Bbackground-color%3Avar%28--md-primary-fg-color%29%3Bborder-color%3Avar%28--md-primary-fg-color%29%3Bcolor%3Avar%28--md-primary-bg-color%29%7D.md-typeset%20.md-button%3Afocus%2C.md-typeset%20.md-button%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color%29%3Bborder-color%3Avar%28--md-accent-fg-color%29%3Bcolor%3Avar%28--md-accent-bg-color%29%7D%5Bdir%3Dltr%5D%20.md-typeset%20.md-input%7Bborder-top-left-radius%3A.1rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20.md-input%2C%5Bdir%3Drtl%5D%20.md-typeset%20.md-input%7Bborder-top-right-radius%3A.1rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.md-input%7Bborder-top-left-radius%3A.1rem%7D.md-typeset%20.md-input%7Bborder-bottom%3A.1rem%20solid%20var%28--md-default-fg-color--lighter%29%3Bbox-shadow%3Avar%28--md-shadow-z1%29%3Bfont-size%3A.8rem%3Bheight%3A1.8rem%3Bpadding%3A0%20.6rem%3Btransition%3Aborder%20.25s%2Cbox-shadow%20.25s%7D.md-typeset%20.md-input%3Afocus%2C.md-typeset%20.md-input%3Ahover%7Bborder-bottom-color%3Avar%28--md-accent-fg-color%29%3Bbox-shadow%3Avar%28--md-shadow-z2%29%7D.md-typeset%20.md-input--stretch%7Bwidth%3A100%25%7D.md-header%7Bbackground-color%3Avar%28--md-primary-fg-color%29%3Bbox-shadow%3A0%200%20.2rem%20%230000%2C0%20.2rem%20.4rem%20%230000%3Bcolor%3Avar%28--md-primary-bg-color%29%3Bdisplay%3Ablock%3Bleft%3A0%3Bposition%3Asticky%3Bright%3A0%3Btop%3A0%3Bz-index%3A4%7D%40media%20print%7B.md-header%7Bdisplay%3Anone%7D%7D.md-header%5Bhidden%5D%7Btransform%3AtranslateY%28-100%25%29%3Btransition%3Atransform%20.25s%20cubic-bezier%28.8%2C0%2C.6%2C1%29%2Cbox-shadow%20.25s%7D.md-header--shadow%7Bbox-shadow%3A0%200%20.2rem%20%230000001a%2C0%20.2rem%20.4rem%20%230003%3Btransition%3Atransform%20.25s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Cbox-shadow%20.25s%7D.md-header__inner%7Balign-items%3Acenter%3Bdisplay%3Aflex%3Bpadding%3A0%20.2rem%7D.md-header__button%7Bcolor%3Acurrentcolor%3Bcursor%3Apointer%3Bmargin%3A.2rem%3Boutline-color%3Avar%28--md-accent-fg-color%29%3Bpadding%3A.4rem%3Bposition%3Arelative%3Btransition%3Aopacity%20.25s%3Bvertical-align%3Amiddle%3Bz-index%3A1%7D.md-header__button%3Ahover%7Bopacity%3A.7%7D.md-header__button%3Anot%28%5Bhidden%5D%29%7Bdisplay%3Ainline-block%7D.md-header__button%3Anot%28.focus-visible%29%7B-webkit-tap-highlight-color%3Atransparent%3Boutline%3Anone%7D.md-header__button.md-logo%7Bmargin%3A.2rem%3Bpadding%3A.4rem%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B.md-header__button.md-logo%7Bdisplay%3Anone%7D%7D.md-header__button.md-logo%20img%2C.md-header__button.md-logo%20svg%7Bfill%3Acurrentcolor%3Bdisplay%3Ablock%3Bheight%3A1.2rem%3Bwidth%3Aauto%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-header__button%5Bfor%3D__search%5D%7Bdisplay%3Anone%7D%7D.no-js%20.md-header__button%5Bfor%3D__search%5D%7Bdisplay%3Anone%7D%5Bdir%3Drtl%5D%20.md-header__button%5Bfor%3D__search%5D%20svg%7Btransform%3AscaleX%28-1%29%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B.md-header__button%5Bfor%3D__drawer%5D%7Bdisplay%3Anone%7D%7D.md-header__topic%7Bdisplay%3Aflex%3Bmax-width%3A100%25%3Bposition%3Aabsolute%3Btransition%3Atransform%20.4s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Copacity%20.15s%3Bwhite-space%3Anowrap%7D.md-header__topic%2B.md-header__topic%7Bopacity%3A0%3Bpointer-events%3Anone%3Btransform%3AtranslateX%281.25rem%29%3Btransition%3Atransform%20.4s%20cubic-bezier%281%2C.7%2C.1%2C.1%29%2Copacity%20.15s%3Bz-index%3A-1%7D%5Bdir%3Drtl%5D%20.md-header__topic%2B.md-header__topic%7Btransform%3AtranslateX%28-1.25rem%29%7D.md-header__topic%3Afirst-child%7Bfont-weight%3A700%7D%5Bdir%3Dltr%5D%20.md-header__title%7Bmargin-left%3A1rem%3Bmargin-right%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-header__title%7Bmargin-left%3A.4rem%3Bmargin-right%3A1rem%7D.md-header__title%7Bflex-grow%3A1%3Bfont-size%3A.9rem%3Bheight%3A2.4rem%3Bline-height%3A2.4rem%7D.md-header__title--active%20.md-header__topic%7Bopacity%3A0%3Bpointer-events%3Anone%3Btransform%3AtranslateX%28-1.25rem%29%3Btransition%3Atransform%20.4s%20cubic-bezier%281%2C.7%2C.1%2C.1%29%2Copacity%20.15s%3Bz-index%3A-1%7D%5Bdir%3Drtl%5D%20.md-header__title--active%20.md-header__topic%7Btransform%3AtranslateX%281.25rem%29%7D.md-header__title--active%20.md-header__topic%2B.md-header__topic%7Bopacity%3A1%3Bpointer-events%3Aauto%3Btransform%3AtranslateX%280%29%3Btransition%3Atransform%20.4s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Copacity%20.15s%3Bz-index%3A0%7D.md-header__title%3E.md-header__ellipsis%7Bheight%3A100%25%3Bposition%3Arelative%3Bwidth%3A100%25%7D.md-header__option%7Bdisplay%3Aflex%3Bflex-shrink%3A0%3Bmax-width%3A100%25%3Btransition%3Amax-width%200ms%20.25s%2Copacity%20.25s%20.25s%3Bwhite-space%3Anowrap%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-header__option%7Bmax-width%3A0%3Bopacity%3A0%3Btransition%3Amax-width%200ms%2Copacity%200ms%7D.md-header__option%3Einput%7Bbottom%3A0%7D.md-header__source%7Bdisplay%3Anone%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-header__source%7Bmargin-left%3A1rem%7D%5Bdir%3Drtl%5D%20.md-header__source%7Bmargin-right%3A1rem%7D.md-header__source%7Bdisplay%3Ablock%3Bmax-width%3A11.7rem%3Bwidth%3A11.7rem%7D%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B%5Bdir%3Dltr%5D%20.md-header__source%7Bmargin-left%3A1.4rem%7D%5Bdir%3Drtl%5D%20.md-header__source%7Bmargin-right%3A1.4rem%7D%7D.md-meta%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bfont-size%3A.7rem%3Bline-height%3A1.3%7D.md-meta__list%7Bdisplay%3Ainline-flex%3Bflex-wrap%3Awrap%3Blist-style%3Anone%3Bmargin%3A0%3Bpadding%3A0%7D.md-meta__item%3Anot%28%3Alast-child%29%3Aafter%7Bcontent%3A%22%C2%B7%22%3Bmargin-left%3A.2rem%3Bmargin-right%3A.2rem%7D.md-meta__link%7Bcolor%3Avar%28--md-typeset-a-color%29%7D.md-meta__link%3Afocus%2C.md-meta__link%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-draft%7Bbackground-color%3A%23ff1744%3Bborder-radius%3A.125em%3Bcolor%3A%23fff%3Bdisplay%3Ainline-block%3Bfont-weight%3A700%3Bpadding-left%3A.5714285714em%3Bpadding-right%3A.5714285714em%7D%3Aroot%7B--md-nav-icon--prev%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M20%2011v2H8l5.5%205.5-1.42%201.42L4.16%2012l7.92-7.92L13.5%205.5%208%2011z%22/%3E%3C/svg%3E%27%29%3B--md-nav-icon--next%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M8.59%2016.58%2013.17%2012%208.59%207.41%2010%206l6%206-6%206z%22/%3E%3C/svg%3E%27%29%3B--md-toc-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M3%209h14V7H3zm0%204h14v-2H3zm0%204h14v-2H3zm16%200h2v-2h-2zm0-10v2h2V7zm0%206h2v-2h-2z%22/%3E%3C/svg%3E%27%29%7D.md-nav%7Bfont-size%3A.7rem%3Bline-height%3A1.3%7D.md-nav__title%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bdisplay%3Ablock%3Bfont-weight%3A700%3Boverflow%3Ahidden%3Bpadding%3A0%20.6rem%3Btext-overflow%3Aellipsis%7D.md-nav__title%20.md-nav__button%7Bdisplay%3Anone%7D.md-nav__title%20.md-nav__button%20img%7Bheight%3A100%25%3Bwidth%3Aauto%7D.md-nav__title%20.md-nav__button.md-logo%20img%2C.md-nav__title%20.md-nav__button.md-logo%20svg%7Bfill%3Acurrentcolor%3Bdisplay%3Ablock%3Bheight%3A2.4rem%3Bmax-width%3A100%25%3Bobject-fit%3Acontain%3Bwidth%3Aauto%7D.md-nav__list%7Blist-style%3Anone%3Bmargin%3A0%3Bpadding%3A0%7D.md-nav__link%7Balign-items%3Aflex-start%3Bdisplay%3Aflex%3Bgap%3A.4rem%3Bmargin-top%3A.625em%3Bscroll-snap-align%3Astart%3Btransition%3Acolor%20125ms%7D.md-nav__link--passed%7Bcolor%3Avar%28--md-default-fg-color--light%29%7D.md-nav__item%20.md-nav__link--active%2C.md-nav__item%20.md-nav__link--active%20code%7Bcolor%3Avar%28--md-typeset-a-color%29%7D.md-nav__link%20.md-ellipsis%7Bposition%3Arelative%7D%5Bdir%3Dltr%5D%20.md-nav__link%20.md-icon%3Alast-child%7Bmargin-left%3Aauto%7D%5Bdir%3Drtl%5D%20.md-nav__link%20.md-icon%3Alast-child%7Bmargin-right%3Aauto%7D.md-nav__link%20svg%7Bfill%3Acurrentcolor%3Bflex-shrink%3A0%3Bheight%3A1.3em%3Bposition%3Arelative%7D.md-nav__link%5Bfor%5D%3Afocus%2C.md-nav__link%5Bfor%5D%3Ahover%2C.md-nav__link%5Bhref%5D%3Afocus%2C.md-nav__link%5Bhref%5D%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%3Bcursor%3Apointer%7D.md-nav__link.focus-visible%7Boutline-color%3Avar%28--md-accent-fg-color%29%3Boutline-offset%3A.2rem%7D.md-nav--primary%20.md-nav__link%5Bfor%3D__toc%5D%7Bdisplay%3Anone%7D.md-nav--primary%20.md-nav__link%5Bfor%3D__toc%5D%20.md-icon%3Aafter%7Bbackground-color%3Acurrentcolor%3Bdisplay%3Ablock%3Bheight%3A100%25%3B-webkit-mask-image%3Avar%28--md-toc-icon%29%3Bmask-image%3Avar%28--md-toc-icon%29%3Bwidth%3A100%25%7D.md-nav--primary%20.md-nav__link%5Bfor%3D__toc%5D~.md-nav%7Bdisplay%3Anone%7D.md-nav__container%3E.md-nav__link%7Bmargin-top%3A0%7D.md-nav__container%3E.md-nav__link%3Afirst-child%7Bflex-grow%3A1%3Bmin-width%3A0%7D.md-nav__icon%7Bflex-shrink%3A0%7D.md-nav__source%7Bdisplay%3Anone%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B.md-nav--primary%2C.md-nav--primary%20.md-nav%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bdisplay%3Aflex%3Bflex-direction%3Acolumn%3Bheight%3A100%25%3Bleft%3A0%3Bposition%3Aabsolute%3Bright%3A0%3Btop%3A0%3Bz-index%3A1%7D.md-nav--primary%20.md-nav__item%2C.md-nav--primary%20.md-nav__title%7Bfont-size%3A.8rem%3Bline-height%3A1.5%7D.md-nav--primary%20.md-nav__title%7Bbackground-color%3Avar%28--md-default-fg-color--lightest%29%3Bcolor%3Avar%28--md-default-fg-color--light%29%3Bcursor%3Apointer%3Bheight%3A5.6rem%3Bline-height%3A2.4rem%3Bpadding%3A3rem%20.8rem%20.2rem%3Bposition%3Arelative%3Bwhite-space%3Anowrap%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav__title%20.md-nav__icon%7Bleft%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav__title%20.md-nav__icon%7Bright%3A.4rem%7D.md-nav--primary%20.md-nav__title%20.md-nav__icon%7Bdisplay%3Ablock%3Bheight%3A1.2rem%3Bmargin%3A.2rem%3Bposition%3Aabsolute%3Btop%3A.4rem%3Bwidth%3A1.2rem%7D.md-nav--primary%20.md-nav__title%20.md-nav__icon%3Aafter%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ablock%3Bheight%3A100%25%3B-webkit-mask-image%3Avar%28--md-nav-icon--prev%29%3Bmask-image%3Avar%28--md-nav-icon--prev%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bwidth%3A100%25%7D.md-nav--primary%20.md-nav__title~.md-nav__list%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bbox-shadow%3A0%20.05rem%200%20var%28--md-default-fg-color--lightest%29%20inset%3Boverflow-y%3Aauto%3Bscroll-snap-type%3Ay%20mandatory%3Btouch-action%3Apan-y%7D.md-nav--primary%20.md-nav__title~.md-nav__list%3E%3Afirst-child%7Bborder-top%3A0%7D.md-nav--primary%20.md-nav__title%5Bfor%3D__drawer%5D%7Bbackground-color%3Avar%28--md-primary-fg-color%29%3Bcolor%3Avar%28--md-primary-bg-color%29%3Bfont-weight%3A700%7D.md-nav--primary%20.md-nav__title%20.md-logo%7Bdisplay%3Ablock%3Bleft%3A.2rem%3Bmargin%3A.2rem%3Bpadding%3A.4rem%3Bposition%3Aabsolute%3Bright%3A.2rem%3Btop%3A.2rem%7D.md-nav--primary%20.md-nav__list%7Bflex%3A1%7D.md-nav--primary%20.md-nav__item%7Bborder-top%3A.05rem%20solid%20var%28--md-default-fg-color--lightest%29%7D.md-nav--primary%20.md-nav__item--active%3E.md-nav__link%7Bcolor%3Avar%28--md-typeset-a-color%29%7D.md-nav--primary%20.md-nav__item--active%3E.md-nav__link%3Afocus%2C.md-nav--primary%20.md-nav__item--active%3E.md-nav__link%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-nav--primary%20.md-nav__link%7Bmargin-top%3A0%3Bpadding%3A.6rem%20.8rem%7D.md-nav--primary%20.md-nav__link%20svg%7Bmargin-top%3A.1em%7D.md-nav--primary%20.md-nav__link%3E.md-nav__link%7Bpadding%3A0%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav__link%20.md-nav__icon%7Bmargin-right%3A-.2rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav__link%20.md-nav__icon%7Bmargin-left%3A-.2rem%7D.md-nav--primary%20.md-nav__link%20.md-nav__icon%7Bfont-size%3A1.2rem%3Bheight%3A1.2rem%3Bwidth%3A1.2rem%7D.md-nav--primary%20.md-nav__link%20.md-nav__icon%3Aafter%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ablock%3Bheight%3A100%25%3B-webkit-mask-image%3Avar%28--md-nav-icon--next%29%3Bmask-image%3Avar%28--md-nav-icon--next%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bwidth%3A100%25%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav__icon%3Aafter%7Btransform%3Ascale%28-1%29%7D.md-nav--primary%20.md-nav--secondary%20.md-nav%7Bbackground-color%3Ainitial%3Bposition%3Astatic%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav__link%7Bpadding-left%3A1.4rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav__link%7Bpadding-right%3A1.4rem%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav%20.md-nav__link%7Bpadding-left%3A2rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav%20.md-nav__link%7Bpadding-right%3A2rem%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav%20.md-nav%20.md-nav__link%7Bpadding-left%3A2.6rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav%20.md-nav%20.md-nav__link%7Bpadding-right%3A2.6rem%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav%20.md-nav%20.md-nav%20.md-nav__link%7Bpadding-left%3A3.2rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav--secondary%20.md-nav%20.md-nav%20.md-nav%20.md-nav%20.md-nav__link%7Bpadding-right%3A3.2rem%7D.md-nav--secondary%7Bbackground-color%3Ainitial%7D.md-nav__toggle~.md-nav%7Bdisplay%3Aflex%3Bopacity%3A0%3Btransform%3AtranslateX%28100%25%29%3Btransition%3Atransform%20.25s%20cubic-bezier%28.8%2C0%2C.6%2C1%29%2Copacity%20125ms%2050ms%7D%5Bdir%3Drtl%5D%20.md-nav__toggle~.md-nav%7Btransform%3AtranslateX%28-100%25%29%7D.md-nav__toggle%3Achecked~.md-nav%7Bopacity%3A1%3Btransform%3AtranslateX%280%29%3Btransition%3Atransform%20.25s%20cubic-bezier%28.4%2C0%2C.2%2C1%29%2Copacity%20125ms%20125ms%7D.md-nav__toggle%3Achecked~.md-nav%3E.md-nav__list%7B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%7D%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B.md-nav--primary%20.md-nav__link%5Bfor%3D__toc%5D%7Bdisplay%3Aflex%7D.md-nav--primary%20.md-nav__link%5Bfor%3D__toc%5D%20.md-icon%3Aafter%7Bcontent%3A%22%22%7D.md-nav--primary%20.md-nav__link%5Bfor%3D__toc%5D%2B.md-nav__link%7Bdisplay%3Anone%7D.md-nav--primary%20.md-nav__link%5Bfor%3D__toc%5D~.md-nav%7Bdisplay%3Aflex%7D.md-nav__source%7Bbackground-color%3Avar%28--md-primary-fg-color--dark%29%3Bcolor%3Avar%28--md-primary-bg-color%29%3Bdisplay%3Ablock%3Bpadding%3A0%20.2rem%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%20and%20%28max-width%3A76.234375em%29%7B.md-nav--integrated%20.md-nav__link%5Bfor%3D__toc%5D%7Bdisplay%3Aflex%7D.md-nav--integrated%20.md-nav__link%5Bfor%3D__toc%5D%20.md-icon%3Aafter%7Bcontent%3A%22%22%7D.md-nav--integrated%20.md-nav__link%5Bfor%3D__toc%5D%2B.md-nav__link%7Bdisplay%3Anone%7D.md-nav--integrated%20.md-nav__link%5Bfor%3D__toc%5D~.md-nav%7Bdisplay%3Aflex%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-nav%7Bmargin-bottom%3A-.4rem%7D.md-nav--secondary%20.md-nav__title%7Bbackground%3Avar%28--md-default-bg-color%29%3Bbox-shadow%3A0%200%20.4rem%20.4rem%20var%28--md-default-bg-color%29%3Bposition%3Asticky%3Btop%3A0%3Bz-index%3A1%7D.md-nav--secondary%20.md-nav__title%5Bfor%3D__toc%5D%7Bscroll-snap-align%3Astart%7D.md-nav--secondary%20.md-nav__title%20.md-nav__icon%7Bdisplay%3Anone%7D%5Bdir%3Dltr%5D%20.md-nav--secondary%20.md-nav__list%7Bpadding-left%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-nav--secondary%20.md-nav__list%7Bpadding-right%3A.6rem%7D.md-nav--secondary%20.md-nav__list%7Bpadding-bottom%3A.4rem%7D%5Bdir%3Dltr%5D%20.md-nav--secondary%20.md-nav__item%3E.md-nav__link%7Bmargin-right%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-nav--secondary%20.md-nav__item%3E.md-nav__link%7Bmargin-left%3A.4rem%7D%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B.md-nav%7Bmargin-bottom%3A-.4rem%3Btransition%3Amax-height%20.25s%20cubic-bezier%28.86%2C0%2C.07%2C1%29%7D.md-nav--primary%20.md-nav__title%7Bbackground%3Avar%28--md-default-bg-color%29%3Bbox-shadow%3A0%200%20.4rem%20.4rem%20var%28--md-default-bg-color%29%3Bposition%3Asticky%3Btop%3A0%3Bz-index%3A1%7D.md-nav--primary%20.md-nav__title%5Bfor%3D__drawer%5D%7Bscroll-snap-align%3Astart%7D.md-nav--primary%20.md-nav__title%20.md-nav__icon%7Bdisplay%3Anone%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav__list%7Bpadding-left%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav__list%7Bpadding-right%3A.6rem%7D.md-nav--primary%20.md-nav__list%7Bpadding-bottom%3A.4rem%7D%5Bdir%3Dltr%5D%20.md-nav--primary%20.md-nav__item%3E.md-nav__link%7Bmargin-right%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-nav--primary%20.md-nav__item%3E.md-nav__link%7Bmargin-left%3A.4rem%7D.md-nav__toggle~.md-nav%7Bdisplay%3Agrid%3Bgrid-template-rows%3A0fr%3Bopacity%3A0%3Btransition%3Agrid-template-rows%20.25s%20cubic-bezier%28.86%2C0%2C.07%2C1%29%2Copacity%20.25s%2Cvisibility%200ms%20.25s%3Bvisibility%3Acollapse%7D.md-nav__toggle~.md-nav%3E.md-nav__list%7Boverflow%3Ahidden%7D.md-nav__toggle.md-toggle--indeterminate~.md-nav%2C.md-nav__toggle%3Achecked~.md-nav%7Bgrid-template-rows%3A1fr%3Bopacity%3A1%3Btransition%3Agrid-template-rows%20.25s%20cubic-bezier%28.86%2C0%2C.07%2C1%29%2Copacity%20.15s%20.1s%2Cvisibility%200ms%3Bvisibility%3Avisible%7D.md-nav__toggle.md-toggle--indeterminate~.md-nav%7Btransition%3Anone%7D.md-nav__item--nested%3E.md-nav%3E.md-nav__title%7Bdisplay%3Anone%7D.md-nav__item--section%7Bdisplay%3Ablock%3Bmargin%3A1.25em%200%7D.md-nav__item--section%3Alast-child%7Bmargin-bottom%3A0%7D.md-nav__item--section%3E.md-nav__link%7Bfont-weight%3A700%7D.md-nav__item--section%3E.md-nav__link%5Bfor%5D%7Bcolor%3Avar%28--md-default-fg-color--light%29%7D.md-nav__item--section%3E.md-nav__link%3Anot%28.md-nav__container%29%7Bpointer-events%3Anone%7D.md-nav__item--section%3E.md-nav__link%20.md-icon%2C.md-nav__item--section%3E.md-nav__link%3E%5Bfor%5D%7Bdisplay%3Anone%7D%5Bdir%3Dltr%5D%20.md-nav__item--section%3E.md-nav%7Bmargin-left%3A-.6rem%7D%5Bdir%3Drtl%5D%20.md-nav__item--section%3E.md-nav%7Bmargin-right%3A-.6rem%7D.md-nav__item--section%3E.md-nav%7Bdisplay%3Ablock%3Bopacity%3A1%3Bvisibility%3Avisible%7D.md-nav__item--section%3E.md-nav%3E.md-nav__list%3E.md-nav__item%7Bpadding%3A0%7D.md-nav__icon%7Bborder-radius%3A100%25%3Bheight%3A.9rem%3Btransition%3Abackground-color%20.25s%3Bwidth%3A.9rem%7D.md-nav__icon%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color--transparent%29%7D.md-nav__icon%3Aafter%7Bbackground-color%3Acurrentcolor%3Bborder-radius%3A100%25%3Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A100%25%3B-webkit-mask-image%3Avar%28--md-nav-icon--next%29%3Bmask-image%3Avar%28--md-nav-icon--next%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Btransition%3Atransform%20.25s%3Bvertical-align%3A-.1rem%3Bwidth%3A100%25%7D%5Bdir%3Drtl%5D%20.md-nav__icon%3Aafter%7Btransform%3Arotate%28180deg%29%7D.md-nav__item--nested%20.md-nav__toggle%3Achecked~.md-nav__link%20.md-nav__icon%3Aafter%2C.md-nav__item--nested%20.md-toggle--indeterminate~.md-nav__link%20.md-nav__icon%3Aafter%7Btransform%3Arotate%2890deg%29%7D.md-nav--lifted%3E.md-nav__list%3E.md-nav__item%2C.md-nav--lifted%3E.md-nav__title%7Bdisplay%3Anone%7D.md-nav--lifted%3E.md-nav__list%3E.md-nav__item--active%7Bdisplay%3Ablock%7D.md-nav--lifted%3E.md-nav__list%3E.md-nav__item--active%3E.md-nav__link%7Bbackground%3Avar%28--md-default-bg-color%29%3Bbox-shadow%3A0%200%20.4rem%20.4rem%20var%28--md-default-bg-color%29%3Bmargin-top%3A0%3Bposition%3Asticky%3Btop%3A0%3Bz-index%3A1%7D.md-nav--lifted%3E.md-nav__list%3E.md-nav__item--active%3E.md-nav__link%3Anot%28.md-nav__container%29%7Bpointer-events%3Anone%7D.md-nav--lifted%3E.md-nav__list%3E.md-nav__item--active.md-nav__item--section%7Bmargin%3A0%7D%5Bdir%3Dltr%5D%20.md-nav--lifted%3E.md-nav__list%3E.md-nav__item%3E.md-nav%3Anot%28.md-nav--secondary%29%7Bmargin-left%3A-.6rem%7D%5Bdir%3Drtl%5D%20.md-nav--lifted%3E.md-nav__list%3E.md-nav__item%3E.md-nav%3Anot%28.md-nav--secondary%29%7Bmargin-right%3A-.6rem%7D.md-nav--lifted%3E.md-nav__list%3E.md-nav__item%3E%5Bfor%5D%7Bcolor%3Avar%28--md-default-fg-color--light%29%7D.md-nav--lifted%20.md-nav%5Bdata-md-level%3D%221%22%5D%7Bgrid-template-rows%3A1fr%3Bopacity%3A1%3Bvisibility%3Avisible%7D%5Bdir%3Dltr%5D%20.md-nav--integrated%3E.md-nav__list%3E.md-nav__item--active%20.md-nav--secondary%7Bborder-left%3A.05rem%20solid%20var%28--md-primary-fg-color%29%7D%5Bdir%3Drtl%5D%20.md-nav--integrated%3E.md-nav__list%3E.md-nav__item--active%20.md-nav--secondary%7Bborder-right%3A.05rem%20solid%20var%28--md-primary-fg-color%29%7D.md-nav--integrated%3E.md-nav__list%3E.md-nav__item--active%20.md-nav--secondary%7Bdisplay%3Ablock%3Bmargin-bottom%3A1.25em%3Bopacity%3A1%3Bvisibility%3Avisible%7D.md-nav--integrated%3E.md-nav__list%3E.md-nav__item--active%20.md-nav--secondary%3E.md-nav__list%7Boverflow%3Avisible%3Bpadding-bottom%3A0%7D.md-nav--integrated%3E.md-nav__list%3E.md-nav__item--active%20.md-nav--secondary%3E.md-nav__title%7Bdisplay%3Anone%7D%7D.md-pagination%7Bfont-size%3A.8rem%3Bfont-weight%3A700%3Bgap%3A.4rem%7D.md-pagination%2C.md-pagination%3E%2A%7Balign-items%3Acenter%3Bdisplay%3Aflex%3Bjustify-content%3Acenter%7D.md-pagination%3E%2A%7Bborder-radius%3A.2rem%3Bheight%3A1.8rem%3Bmin-width%3A1.8rem%3Btext-align%3Acenter%7D.md-pagination__current%7Bbackground-color%3Avar%28--md-default-fg-color--lightest%29%3Bcolor%3Avar%28--md-default-fg-color--light%29%7D.md-pagination__link%7Btransition%3Acolor%20125ms%2Cbackground-color%20125ms%7D.md-pagination__link%3Afocus%2C.md-pagination__link%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color--transparent%29%3Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-pagination__link%3Afocus%20svg%2C.md-pagination__link%3Ahover%20svg%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-pagination__link.focus-visible%7Boutline-color%3Avar%28--md-accent-fg-color%29%3Boutline-offset%3A.2rem%7D.md-pagination__link%20svg%7Bfill%3Acurrentcolor%3Bcolor%3Avar%28--md-default-fg-color--lighter%29%3Bdisplay%3Ablock%3Bmax-height%3A100%25%3Bwidth%3A1.2rem%7D.md-post__back%7Bborder-bottom%3A.05rem%20solid%20var%28--md-default-fg-color--lightest%29%3Bmargin-bottom%3A1.2rem%3Bpadding-bottom%3A1.2rem%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B.md-post__back%7Bdisplay%3Anone%7D%7D%5Bdir%3Drtl%5D%20.md-post__back%20svg%7Btransform%3AscaleX%28-1%29%7D.md-post__authors%7Bdisplay%3Aflex%3Bflex-direction%3Acolumn%3Bgap%3A.6rem%3Bmargin%3A0%20.6rem%201.2rem%7D.md-post%20.md-post__meta%20a%7Btransition%3Acolor%20125ms%7D.md-post%20.md-post__meta%20a%3Afocus%2C.md-post%20.md-post__meta%20a%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-post__title%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bfont-weight%3A700%7D.md-post--excerpt%7Bmargin-bottom%3A3.2rem%7D.md-post--excerpt%20.md-post__header%7Balign-items%3Acenter%3Bdisplay%3Aflex%3Bgap%3A.6rem%3Bmin-height%3A1.6rem%7D.md-post--excerpt%20.md-post__authors%7Balign-items%3Acenter%3Bdisplay%3Ainline-flex%3Bflex-direction%3Arow%3Bgap%3A.2rem%3Bmargin%3A0%3Bmin-height%3A2.4rem%7D%5Bdir%3Dltr%5D%20.md-post--excerpt%20.md-post__meta%20.md-meta__list%7Bmargin-right%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-post--excerpt%20.md-post__meta%20.md-meta__list%7Bmargin-left%3A.4rem%7D.md-post--excerpt%20.md-post__content%3E%3Afirst-child%7B--md-scroll-margin%3A6rem%3Bmargin-top%3A0%7D.md-post%3E.md-nav--secondary%7Bmargin%3A1em%200%7D.md-profile%7Balign-items%3Acenter%3Bdisplay%3Aflex%3Bfont-size%3A.7rem%3Bgap%3A.6rem%3Bline-height%3A1.4%3Bwidth%3A100%25%7D.md-profile__description%7Bflex-grow%3A1%7D.md-content--post%7Bdisplay%3Aflex%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B.md-content--post%7Bflex-flow%3Acolumn-reverse%7D%7D.md-content--post%3E.md-content__inner%7Bmin-width%3A0%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B%5Bdir%3Dltr%5D%20.md-content--post%3E.md-content__inner%7Bmargin-left%3A1.2rem%7D%5Bdir%3Drtl%5D%20.md-content--post%3E.md-content__inner%7Bmargin-right%3A1.2rem%7D%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B.md-sidebar.md-sidebar--post%7Bpadding%3A0%3Bposition%3Astatic%3Bwidth%3A100%25%7D.md-sidebar.md-sidebar--post%20.md-sidebar__scrollwrap%7Boverflow%3Avisible%7D.md-sidebar.md-sidebar--post%20.md-sidebar__inner%7Bpadding%3A0%7D.md-sidebar.md-sidebar--post%20.md-post__meta%7Bmargin-left%3A.6rem%3Bmargin-right%3A.6rem%7D.md-sidebar.md-sidebar--post%20.md-nav__item%7Bborder%3Anone%3Bdisplay%3Ainline%7D.md-sidebar.md-sidebar--post%20.md-nav__list%7Bdisplay%3Ainline-flex%3Bflex-wrap%3Awrap%3Bgap%3A.6rem%3Bpadding-bottom%3A.6rem%3Bpadding-top%3A.6rem%7D.md-sidebar.md-sidebar--post%20.md-nav__link%7Bpadding%3A0%7D.md-sidebar.md-sidebar--post%20.md-nav%7Bheight%3Aauto%3Bmargin-bottom%3A0%3Bposition%3Astatic%7D%7D%3Aroot%7B--md-progress-value%3A0%3B--md-progress-delay%3A400ms%7D.md-progress%7Bbackground%3Avar%28--md-primary-bg-color%29%3Bheight%3A.075rem%3Bopacity%3Amin%28clamp%280%2Cvar%28--md-progress-value%29%2C1%29%2Cclamp%280%2C100%20-%20var%28--md-progress-value%29%2C1%29%29%3Bposition%3Afixed%3Btop%3A0%3Btransform%3AscaleX%28calc%28var%28--md-progress-value%29%2A1%25%29%29%3Btransform-origin%3Aleft%3Btransition%3Atransform%20.5s%20cubic-bezier%28.19%2C1%2C.22%2C1%29%2Copacity%20.25s%20var%28--md-progress-delay%29%3Bwidth%3A100%25%3Bz-index%3A4%7D%3Aroot%7B--md-search-result-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M14%202H6a2%202%200%200%200-2%202v16a2%202%200%200%200%202%202h7c-.41-.25-.8-.56-1.14-.9-.33-.33-.61-.7-.86-1.1H6V4h7v5h5v1.18c.71.16%201.39.43%202%20.82V8zm6.31%2016.9c1.33-2.11.69-4.9-1.4-6.22-2.11-1.33-4.91-.68-6.22%201.4-1.34%202.11-.69%204.89%201.4%206.22%201.46.93%203.32.93%204.79.02L22%2023.39%2023.39%2022zm-3.81.1a2.5%202.5%200%200%201-2.5-2.5%202.5%202.5%200%200%201%202.5-2.5%202.5%202.5%200%200%201%202.5%202.5%202.5%202.5%200%200%201-2.5%202.5%22/%3E%3C/svg%3E%27%29%7D.md-search%7Bposition%3Arelative%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-search%7Bpadding%3A.2rem%200%7D%7D.no-js%20.md-search%7Bdisplay%3Anone%7D.md-search__overlay%7Bopacity%3A0%3Bz-index%3A1%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B%5Bdir%3Dltr%5D%20.md-search__overlay%7Bleft%3A-2.2rem%7D%5Bdir%3Drtl%5D%20.md-search__overlay%7Bright%3A-2.2rem%7D.md-search__overlay%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder-radius%3A1rem%3Bheight%3A2rem%3Boverflow%3Ahidden%3Bpointer-events%3Anone%3Bposition%3Aabsolute%3Btop%3A-1rem%3Btransform-origin%3Acenter%3Btransition%3Atransform%20.3s%20.1s%2Copacity%20.2s%20.2s%3Bwidth%3A2rem%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__overlay%7Bopacity%3A1%3Btransition%3Atransform%20.4s%2Copacity%20.1s%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-search__overlay%7Bleft%3A0%7D%5Bdir%3Drtl%5D%20.md-search__overlay%7Bright%3A0%7D.md-search__overlay%7Bbackground-color%3A%230000008a%3Bcursor%3Apointer%3Bheight%3A0%3Bposition%3Afixed%3Btop%3A0%3Btransition%3Awidth%200ms%20.25s%2Cheight%200ms%20.25s%2Copacity%20.25s%3Bwidth%3A0%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__overlay%7Bheight%3A200vh%3Bopacity%3A1%3Btransition%3Awidth%200ms%2Cheight%200ms%2Copacity%20.25s%3Bwidth%3A100%25%7D%7D%40media%20screen%20and%20%28max-width%3A29.984375em%29%7B%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__overlay%7Btransform%3Ascale%2845%29%7D%7D%40media%20screen%20and%20%28min-width%3A30em%29%20and%20%28max-width%3A44.984375em%29%7B%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__overlay%7Btransform%3Ascale%2860%29%7D%7D%40media%20screen%20and%20%28min-width%3A45em%29%20and%20%28max-width%3A59.984375em%29%7B%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__overlay%7Btransform%3Ascale%2875%29%7D%7D.md-search__inner%7B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B%5Bdir%3Dltr%5D%20.md-search__inner%7Bleft%3A0%7D%5Bdir%3Drtl%5D%20.md-search__inner%7Bright%3A0%7D.md-search__inner%7Bheight%3A0%3Bopacity%3A0%3Boverflow%3Ahidden%3Bposition%3Afixed%3Btop%3A0%3Btransform%3AtranslateX%285%25%29%3Btransition%3Awidth%200ms%20.3s%2Cheight%200ms%20.3s%2Ctransform%20.15s%20cubic-bezier%28.4%2C0%2C.2%2C1%29%20.15s%2Copacity%20.15s%20.15s%3Bwidth%3A0%3Bz-index%3A2%7D%5Bdir%3Drtl%5D%20.md-search__inner%7Btransform%3AtranslateX%28-5%25%29%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__inner%7Bheight%3A100%25%3Bopacity%3A1%3Btransform%3AtranslateX%280%29%3Btransition%3Awidth%200ms%200ms%2Cheight%200ms%200ms%2Ctransform%20.15s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%20.15s%2Copacity%20.15s%20.15s%3Bwidth%3A100%25%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-search__inner%7Bfloat%3Aright%7D%5Bdir%3Drtl%5D%20.md-search__inner%7Bfloat%3Aleft%7D.md-search__inner%7Bpadding%3A.1rem%200%3Bposition%3Arelative%3Btransition%3Awidth%20.25s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%3Bwidth%3A11.7rem%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%20and%20%28max-width%3A76.234375em%29%7B%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__inner%7Bwidth%3A23.4rem%7D%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__inner%7Bwidth%3A34.4rem%7D%7D.md-search__form%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bbox-shadow%3A0%200%20.6rem%20%230000%3Bheight%3A2.4rem%3Bposition%3Arelative%3Btransition%3Acolor%20.25s%2Cbackground-color%20.25s%3Bz-index%3A2%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-search__form%7Bbackground-color%3A%2300000042%3Bborder-radius%3A.1rem%3Bheight%3A1.8rem%7D.md-search__form%3Ahover%7Bbackground-color%3A%23ffffff1f%7D%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__form%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder-radius%3A.1rem%20.1rem%200%200%3Bbox-shadow%3A0%200%20.6rem%20%2300000012%3Bcolor%3Avar%28--md-default-fg-color%29%7D%5Bdir%3Dltr%5D%20.md-search__input%7Bpadding-left%3A3.6rem%3Bpadding-right%3A2.2rem%7D%5Bdir%3Drtl%5D%20.md-search__input%7Bpadding-left%3A2.2rem%3Bpadding-right%3A3.6rem%7D.md-search__input%7Bbackground%3A%230000%3Bfont-size%3A.9rem%3Bheight%3A100%25%3Bposition%3Arelative%3Btext-overflow%3Aellipsis%3Bwidth%3A100%25%3Bz-index%3A2%7D.md-search__input%3A%3Aplaceholder%7Btransition%3Acolor%20.25s%7D.md-search__input%3A%3Aplaceholder%2C.md-search__input~.md-search__icon%7Bcolor%3Avar%28--md-default-fg-color--light%29%7D.md-search__input%3A%3A-ms-clear%7Bdisplay%3Anone%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B.md-search__input%7Bfont-size%3A.9rem%3Bheight%3A2.4rem%3Bwidth%3A100%25%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-search__input%7Bpadding-left%3A2.2rem%7D%5Bdir%3Drtl%5D%20.md-search__input%7Bpadding-right%3A2.2rem%7D.md-search__input%7Bcolor%3Ainherit%3Bfont-size%3A.8rem%7D.md-search__input%3A%3Aplaceholder%7Bcolor%3Avar%28--md-primary-bg-color--light%29%7D.md-search__input%2B.md-search__icon%7Bcolor%3Avar%28--md-primary-bg-color%29%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__input%7Btext-overflow%3Aclip%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__input%2B.md-search__icon%7Bcolor%3Avar%28--md-default-fg-color--light%29%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__input%3A%3Aplaceholder%7Bcolor%3A%230000%7D%7D.md-search__icon%7Bcursor%3Apointer%3Bdisplay%3Ainline-block%3Bheight%3A1.2rem%3Btransition%3Acolor%20.25s%2Copacity%20.25s%3Bwidth%3A1.2rem%7D.md-search__icon%3Ahover%7Bopacity%3A.7%7D%5Bdir%3Dltr%5D%20.md-search__icon%5Bfor%3D__search%5D%7Bleft%3A.5rem%7D%5Bdir%3Drtl%5D%20.md-search__icon%5Bfor%3D__search%5D%7Bright%3A.5rem%7D.md-search__icon%5Bfor%3D__search%5D%7Bposition%3Aabsolute%3Btop%3A.3rem%3Bz-index%3A2%7D%5Bdir%3Drtl%5D%20.md-search__icon%5Bfor%3D__search%5D%20svg%7Btransform%3AscaleX%28-1%29%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B%5Bdir%3Dltr%5D%20.md-search__icon%5Bfor%3D__search%5D%7Bleft%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-search__icon%5Bfor%3D__search%5D%7Bright%3A.8rem%7D.md-search__icon%5Bfor%3D__search%5D%7Btop%3A.6rem%7D.md-search__icon%5Bfor%3D__search%5D%20svg%3Afirst-child%7Bdisplay%3Anone%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-search__icon%5Bfor%3D__search%5D%7Bpointer-events%3Anone%7D.md-search__icon%5Bfor%3D__search%5D%20svg%3Alast-child%7Bdisplay%3Anone%7D%7D%5Bdir%3Dltr%5D%20.md-search__options%7Bright%3A.5rem%7D%5Bdir%3Drtl%5D%20.md-search__options%7Bleft%3A.5rem%7D.md-search__options%7Bpointer-events%3Anone%3Bposition%3Aabsolute%3Btop%3A.3rem%3Bz-index%3A2%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B%5Bdir%3Dltr%5D%20.md-search__options%7Bright%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-search__options%7Bleft%3A.8rem%7D.md-search__options%7Btop%3A.6rem%7D%7D%5Bdir%3Dltr%5D%20.md-search__options%3E.md-icon%7Bmargin-left%3A.2rem%7D%5Bdir%3Drtl%5D%20.md-search__options%3E.md-icon%7Bmargin-right%3A.2rem%7D.md-search__options%3E.md-icon%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bopacity%3A0%3Btransform%3Ascale%28.75%29%3Btransition%3Atransform%20.15s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Copacity%20.15s%7D.md-search__options%3E.md-icon%3Anot%28.focus-visible%29%7B-webkit-tap-highlight-color%3Atransparent%3Boutline%3Anone%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__input%3Avalid~.md-search__options%3E.md-icon%7Bopacity%3A1%3Bpointer-events%3Aauto%3Btransform%3Ascale%281%29%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__input%3Avalid~.md-search__options%3E.md-icon%3Ahover%7Bopacity%3A.7%7D%5Bdir%3Dltr%5D%20.md-search__suggest%7Bpadding-left%3A3.6rem%3Bpadding-right%3A2.2rem%7D%5Bdir%3Drtl%5D%20.md-search__suggest%7Bpadding-left%3A2.2rem%3Bpadding-right%3A3.6rem%7D.md-search__suggest%7Balign-items%3Acenter%3Bcolor%3Avar%28--md-default-fg-color--lighter%29%3Bdisplay%3Aflex%3Bfont-size%3A.9rem%3Bheight%3A100%25%3Bopacity%3A0%3Bposition%3Aabsolute%3Btop%3A0%3Btransition%3Aopacity%2050ms%3Bwhite-space%3Anowrap%3Bwidth%3A100%25%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-search__suggest%7Bpadding-left%3A2.2rem%7D%5Bdir%3Drtl%5D%20.md-search__suggest%7Bpadding-right%3A2.2rem%7D.md-search__suggest%7Bfont-size%3A.8rem%7D%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__suggest%7Bopacity%3A1%3Btransition%3Aopacity%20.3s%20.1s%7D%5Bdir%3Dltr%5D%20.md-search__output%7Bborder-bottom-left-radius%3A.1rem%7D%5Bdir%3Dltr%5D%20.md-search__output%2C%5Bdir%3Drtl%5D%20.md-search__output%7Bborder-bottom-right-radius%3A.1rem%7D%5Bdir%3Drtl%5D%20.md-search__output%7Bborder-bottom-left-radius%3A.1rem%7D.md-search__output%7Boverflow%3Ahidden%3Bposition%3Aabsolute%3Bwidth%3A100%25%3Bz-index%3A1%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B.md-search__output%7Bbottom%3A0%3Btop%3A2.4rem%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-search__output%7Bopacity%3A0%3Btop%3A1.9rem%3Btransition%3Aopacity%20.4s%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__output%7Bbox-shadow%3Avar%28--md-shadow-z3%29%3Bopacity%3A1%7D%7D.md-search__scrollwrap%7B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%3Bbackground-color%3Avar%28--md-default-bg-color%29%3Bheight%3A100%25%3Boverflow-y%3Aauto%3Btouch-action%3Apan-y%7D%40media%20%28-webkit-max-device-pixel-ratio%3A1%29%2C%28max-resolution%3A1dppx%29%7B.md-search__scrollwrap%7Btransform%3AtranslateZ%280%29%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%20and%20%28max-width%3A76.234375em%29%7B.md-search__scrollwrap%7Bwidth%3A23.4rem%7D%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B.md-search__scrollwrap%7Bwidth%3A34.4rem%7D%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-search__scrollwrap%7Bmax-height%3A0%3Bscrollbar-color%3Avar%28--md-default-fg-color--lighter%29%20%230000%3Bscrollbar-width%3Athin%7D%5Bdata-md-toggle%3Dsearch%5D%3Achecked~.md-header%20.md-search__scrollwrap%7Bmax-height%3A75vh%7D.md-search__scrollwrap%3Ahover%7Bscrollbar-color%3Avar%28--md-accent-fg-color%29%20%230000%7D.md-search__scrollwrap%3A%3A-webkit-scrollbar%7Bheight%3A.2rem%3Bwidth%3A.2rem%7D.md-search__scrollwrap%3A%3A-webkit-scrollbar-thumb%7Bbackground-color%3Avar%28--md-default-fg-color--lighter%29%7D.md-search__scrollwrap%3A%3A-webkit-scrollbar-thumb%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color%29%7D%7D.md-search-result%7Bcolor%3Avar%28--md-default-fg-color%29%3Bword-break%3Abreak-word%7D.md-search-result__meta%7Bbackground-color%3Avar%28--md-default-fg-color--lightest%29%3Bcolor%3Avar%28--md-default-fg-color--light%29%3Bfont-size%3A.64rem%3Bline-height%3A1.8rem%3Bpadding%3A0%20.8rem%3Bscroll-snap-align%3Astart%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-search-result__meta%7Bpadding-left%3A2.2rem%7D%5Bdir%3Drtl%5D%20.md-search-result__meta%7Bpadding-right%3A2.2rem%7D%7D.md-search-result__list%7Blist-style%3Anone%3Bmargin%3A0%3Bpadding%3A0%3B-webkit-user-select%3Anone%3Buser-select%3Anone%7D.md-search-result__item%7Bbox-shadow%3A0%20-.05rem%20var%28--md-default-fg-color--lightest%29%7D.md-search-result__item%3Afirst-child%7Bbox-shadow%3Anone%7D.md-search-result__link%7Bdisplay%3Ablock%3Boutline%3Anone%3Bscroll-snap-align%3Astart%3Btransition%3Abackground-color%20.25s%7D.md-search-result__link%3Afocus%2C.md-search-result__link%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color--transparent%29%7D.md-search-result__link%3Alast-child%20p%3Alast-child%7Bmargin-bottom%3A.6rem%7D.md-search-result__more%3Esummary%7Bcursor%3Apointer%3Bdisplay%3Ablock%3Boutline%3Anone%3Bposition%3Asticky%3Bscroll-snap-align%3Astart%3Btop%3A0%3Bz-index%3A1%7D.md-search-result__more%3Esummary%3A%3Amarker%7Bdisplay%3Anone%7D.md-search-result__more%3Esummary%3A%3A-webkit-details-marker%7Bdisplay%3Anone%7D.md-search-result__more%3Esummary%3Ediv%7Bcolor%3Avar%28--md-typeset-a-color%29%3Bfont-size%3A.64rem%3Bpadding%3A.75em%20.8rem%3Btransition%3Acolor%20.25s%2Cbackground-color%20.25s%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-search-result__more%3Esummary%3Ediv%7Bpadding-left%3A2.2rem%7D%5Bdir%3Drtl%5D%20.md-search-result__more%3Esummary%3Ediv%7Bpadding-right%3A2.2rem%7D%7D.md-search-result__more%3Esummary%3Afocus%3Ediv%2C.md-search-result__more%3Esummary%3Ahover%3Ediv%7Bbackground-color%3Avar%28--md-accent-fg-color--transparent%29%3Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-search-result__more%5Bopen%5D%3Esummary%7Bbackground-color%3Avar%28--md-default-bg-color%29%7D.md-search-result__article%7Boverflow%3Ahidden%3Bpadding%3A0%20.8rem%3Bposition%3Arelative%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdir%3Dltr%5D%20.md-search-result__article%7Bpadding-left%3A2.2rem%7D%5Bdir%3Drtl%5D%20.md-search-result__article%7Bpadding-right%3A2.2rem%7D%7D%5Bdir%3Dltr%5D%20.md-search-result__icon%7Bleft%3A0%7D%5Bdir%3Drtl%5D%20.md-search-result__icon%7Bright%3A0%7D.md-search-result__icon%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bheight%3A1.2rem%3Bmargin%3A.5rem%3Bposition%3Aabsolute%3Bwidth%3A1.2rem%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B.md-search-result__icon%7Bdisplay%3Anone%7D%7D.md-search-result__icon%3Aafter%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A100%25%3B-webkit-mask-image%3Avar%28--md-search-result-icon%29%3Bmask-image%3Avar%28--md-search-result-icon%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bwidth%3A100%25%7D%5Bdir%3Drtl%5D%20.md-search-result__icon%3Aafter%7Btransform%3AscaleX%28-1%29%7D.md-search-result%20.md-typeset%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bfont-size%3A.64rem%3Bline-height%3A1.6%7D.md-search-result%20.md-typeset%20h1%7Bcolor%3Avar%28--md-default-fg-color%29%3Bfont-size%3A.8rem%3Bfont-weight%3A400%3Bline-height%3A1.4%3Bmargin%3A.55rem%200%7D.md-search-result%20.md-typeset%20h1%20mark%7Btext-decoration%3Anone%7D.md-search-result%20.md-typeset%20h2%7Bcolor%3Avar%28--md-default-fg-color%29%3Bfont-size%3A.64rem%3Bfont-weight%3A700%3Bline-height%3A1.6%3Bmargin%3A.5em%200%7D.md-search-result%20.md-typeset%20h2%20mark%7Btext-decoration%3Anone%7D.md-search-result__terms%7Bcolor%3Avar%28--md-default-fg-color%29%3Bdisplay%3Ablock%3Bfont-size%3A.64rem%3Bfont-style%3Aitalic%3Bmargin%3A.5em%200%7D.md-search-result%20mark%7Bbackground-color%3Ainitial%3Bcolor%3Avar%28--md-accent-fg-color%29%3Btext-decoration%3Aunderline%7D.md-select%7Bposition%3Arelative%3Bz-index%3A1%7D.md-select__inner%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder-radius%3A.1rem%3Bbox-shadow%3Avar%28--md-shadow-z2%29%3Bcolor%3Avar%28--md-default-fg-color%29%3Bleft%3A50%25%3Bmargin-top%3A.2rem%3Bmax-height%3A0%3Bopacity%3A0%3Bposition%3Aabsolute%3Btop%3Acalc%28100%25%20-%20.2rem%29%3Btransform%3Atranslate3d%28-50%25%2C.3rem%2C0%29%3Btransition%3Atransform%20.25s%20375ms%2Copacity%20.25s%20.25s%2Cmax-height%200ms%20.5s%7D.md-select%3Afocus-within%20.md-select__inner%2C.md-select%3Ahover%20.md-select__inner%7Bmax-height%3A10rem%3Bopacity%3A1%3Btransform%3Atranslate3d%28-50%25%2C0%2C0%29%3Btransition%3Atransform%20.25s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Copacity%20.25s%2Cmax-height%200ms%7D.md-select__inner%3Aafter%7Bborder-bottom%3A.2rem%20solid%20%230000%3Bborder-bottom-color%3Avar%28--md-default-bg-color%29%3Bborder-left%3A.2rem%20solid%20%230000%3Bborder-right%3A.2rem%20solid%20%230000%3Bborder-top%3A0%3Bcontent%3A%22%22%3Bheight%3A0%3Bleft%3A50%25%3Bmargin-left%3A-.2rem%3Bmargin-top%3A-.2rem%3Bposition%3Aabsolute%3Btop%3A0%3Bwidth%3A0%7D.md-select__list%7Bborder-radius%3A.1rem%3Bfont-size%3A.8rem%3Blist-style-type%3Anone%3Bmargin%3A0%3Bmax-height%3Ainherit%3Boverflow%3Aauto%3Bpadding%3A0%7D.md-select__item%7Bline-height%3A1.8rem%7D%5Bdir%3Dltr%5D%20.md-select__link%7Bpadding-left%3A.6rem%3Bpadding-right%3A1.2rem%7D%5Bdir%3Drtl%5D%20.md-select__link%7Bpadding-left%3A1.2rem%3Bpadding-right%3A.6rem%7D.md-select__link%7Bcursor%3Apointer%3Bdisplay%3Ablock%3Boutline%3Anone%3Bscroll-snap-align%3Astart%3Btransition%3Abackground-color%20.25s%2Ccolor%20.25s%3Bwidth%3A100%25%7D.md-select__link%3Afocus%2C.md-select__link%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-select__link%3Afocus%7Bbackground-color%3Avar%28--md-default-fg-color--lightest%29%7D.md-sidebar%7Balign-self%3Aflex-start%3Bflex-shrink%3A0%3Bpadding%3A1.2rem%200%3Bposition%3Asticky%3Btop%3A2.4rem%3Bwidth%3A12.1rem%7D%40media%20print%7B.md-sidebar%7Bdisplay%3Anone%7D%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B%5Bdir%3Dltr%5D%20.md-sidebar--primary%7Bleft%3A-12.1rem%7D%5Bdir%3Drtl%5D%20.md-sidebar--primary%7Bright%3A-12.1rem%7D.md-sidebar--primary%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bdisplay%3Ablock%3Bheight%3A100%25%3Bposition%3Afixed%3Btop%3A0%3Btransform%3AtranslateX%280%29%3Btransition%3Atransform%20.25s%20cubic-bezier%28.4%2C0%2C.2%2C1%29%2Cbox-shadow%20.25s%3Bwidth%3A12.1rem%3Bz-index%3A5%7D%5Bdata-md-toggle%3Ddrawer%5D%3Achecked~.md-container%20.md-sidebar--primary%7Bbox-shadow%3Avar%28--md-shadow-z3%29%3Btransform%3AtranslateX%2812.1rem%29%7D%5Bdir%3Drtl%5D%20%5Bdata-md-toggle%3Ddrawer%5D%3Achecked~.md-container%20.md-sidebar--primary%7Btransform%3AtranslateX%28-12.1rem%29%7D.md-sidebar--primary%20.md-sidebar__scrollwrap%7Bbottom%3A0%3Bleft%3A0%3Bmargin%3A0%3Boverflow%3Ahidden%3Bposition%3Aabsolute%3Bright%3A0%3Bscroll-snap-type%3Anone%3Btop%3A0%7D%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B.md-sidebar%7Bheight%3A0%7D.no-js%20.md-sidebar%7Bheight%3Aauto%7D.md-header--lifted~.md-container%20.md-sidebar%7Btop%3A4.8rem%7D%7D.md-sidebar--secondary%7Bdisplay%3Anone%3Border%3A2%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B.md-sidebar--secondary%7Bheight%3A0%7D.no-js%20.md-sidebar--secondary%7Bheight%3Aauto%7D.md-sidebar--secondary%3Anot%28%5Bhidden%5D%29%7Bdisplay%3Ablock%7D.md-sidebar--secondary%20.md-sidebar__scrollwrap%7Btouch-action%3Apan-y%7D%7D.md-sidebar__scrollwrap%7Bscrollbar-gutter%3Astable%3B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%3Bmargin%3A0%20.2rem%3Boverflow-y%3Aauto%3Bscrollbar-color%3Avar%28--md-default-fg-color--lighter%29%20%230000%3Bscrollbar-width%3Athin%7D.md-sidebar__scrollwrap%3A%3A-webkit-scrollbar%7Bheight%3A.2rem%3Bwidth%3A.2rem%7D.md-sidebar__scrollwrap%3Afocus-within%2C.md-sidebar__scrollwrap%3Ahover%7Bscrollbar-color%3Avar%28--md-accent-fg-color%29%20%230000%7D.md-sidebar__scrollwrap%3Afocus-within%3A%3A-webkit-scrollbar-thumb%2C.md-sidebar__scrollwrap%3Ahover%3A%3A-webkit-scrollbar-thumb%7Bbackground-color%3Avar%28--md-default-fg-color--lighter%29%7D.md-sidebar__scrollwrap%3Afocus-within%3A%3A-webkit-scrollbar-thumb%3Ahover%2C.md-sidebar__scrollwrap%3Ahover%3A%3A-webkit-scrollbar-thumb%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color%29%7D%40supports%20selector%28%3A%3A-webkit-scrollbar%29%7B.md-sidebar__scrollwrap%7Bscrollbar-gutter%3Aauto%7D%5Bdir%3Dltr%5D%20.md-sidebar__inner%7Bpadding-right%3Acalc%28100%25%20-%2011.5rem%29%7D%5Bdir%3Drtl%5D%20.md-sidebar__inner%7Bpadding-left%3Acalc%28100%25%20-%2011.5rem%29%7D%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B.md-overlay%7Bbackground-color%3A%230000008a%3Bheight%3A0%3Bopacity%3A0%3Bposition%3Afixed%3Btop%3A0%3Btransition%3Awidth%200ms%20.25s%2Cheight%200ms%20.25s%2Copacity%20.25s%3Bwidth%3A0%3Bz-index%3A5%7D%5Bdata-md-toggle%3Ddrawer%5D%3Achecked~.md-overlay%7Bheight%3A100%25%3Bopacity%3A1%3Btransition%3Awidth%200ms%2Cheight%200ms%2Copacity%20.25s%3Bwidth%3A100%25%7D%7D%40keyframes%20facts%7B0%25%7Bheight%3A0%7Dto%7Bheight%3A.65rem%7D%7D%40keyframes%20fact%7B0%25%7Bopacity%3A0%3Btransform%3AtranslateY%28100%25%29%7D50%25%7Bopacity%3A0%7Dto%7Bopacity%3A1%3Btransform%3AtranslateY%280%29%7D%7D%3Aroot%7B--md-source-forks-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M5%205.372v.878c0%20.414.336.75.75.75h4.5a.75.75%200%200%200%20.75-.75v-.878a2.25%202.25%200%201%201%201.5%200v.878a2.25%202.25%200%200%201-2.25%202.25h-1.5v2.128a2.251%202.251%200%201%201-1.5%200V8.5h-1.5A2.25%202.25%200%200%201%203.5%206.25v-.878a2.25%202.25%200%201%201%201.5%200M5%203.25a.75.75%200%201%200-1.5%200%20.75.75%200%200%200%201.5%200m6.75.75a.75.75%200%201%200%200-1.5.75.75%200%200%200%200%201.5m-3%208.75a.75.75%200%201%200-1.5%200%20.75.75%200%200%200%201.5%200%22/%3E%3C/svg%3E%27%29%3B--md-source-repositories-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M2%202.5A2.5%202.5%200%200%201%204.5%200h8.75a.75.75%200%200%201%20.75.75v12.5a.75.75%200%200%201-.75.75h-2.5a.75.75%200%200%201%200-1.5h1.75v-2h-8a1%201%200%200%200-.714%201.7.75.75%200%201%201-1.072%201.05A2.5%202.5%200%200%201%202%2011.5Zm10.5-1h-8a1%201%200%200%200-1%201v6.708A2.5%202.5%200%200%201%204.5%209h8ZM5%2012.25a.25.25%200%200%201%20.25-.25h3.5a.25.25%200%200%201%20.25.25v3.25a.25.25%200%200%201-.4.2l-1.45-1.087a.25.25%200%200%200-.3%200L5.4%2015.7a.25.25%200%200%201-.4-.2Z%22/%3E%3C/svg%3E%27%29%3B--md-source-stars-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M8%20.25a.75.75%200%200%201%20.673.418l1.882%203.815%204.21.612a.75.75%200%200%201%20.416%201.279l-3.046%202.97.719%204.192a.751.751%200%200%201-1.088.791L8%2012.347l-3.766%201.98a.75.75%200%200%201-1.088-.79l.72-4.194L.818%206.374a.75.75%200%200%201%20.416-1.28l4.21-.611L7.327.668A.75.75%200%200%201%208%20.25m0%202.445L6.615%205.5a.75.75%200%200%201-.564.41l-3.097.45%202.24%202.184a.75.75%200%200%201%20.216.664l-.528%203.084%202.769-1.456a.75.75%200%200%201%20.698%200l2.77%201.456-.53-3.084a.75.75%200%200%201%20.216-.664l2.24-2.183-3.096-.45a.75.75%200%200%201-.564-.41z%22/%3E%3C/svg%3E%27%29%3B--md-source-version-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2016%2016%22%3E%3Cpath%20d%3D%22M1%207.775V2.75C1%201.784%201.784%201%202.75%201h5.025c.464%200%20.91.184%201.238.513l6.25%206.25a1.75%201.75%200%200%201%200%202.474l-5.026%205.026a1.75%201.75%200%200%201-2.474%200l-6.25-6.25A1.75%201.75%200%200%201%201%207.775m1.5%200c0%20.066.026.13.073.177l6.25%206.25a.25.25%200%200%200%20.354%200l5.025-5.025a.25.25%200%200%200%200-.354l-6.25-6.25a.25.25%200%200%200-.177-.073H2.75a.25.25%200%200%200-.25.25ZM6%205a1%201%200%201%201%200%202%201%201%200%200%201%200-2%22/%3E%3C/svg%3E%27%29%7D.md-source%7B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%3Bdisplay%3Ablock%3Bfont-size%3A.65rem%3Bline-height%3A1.2%3Boutline-color%3Avar%28--md-accent-fg-color%29%3Btransition%3Aopacity%20.25s%3Bwhite-space%3Anowrap%7D.md-source%3Ahover%7Bopacity%3A.7%7D.md-source__icon%7Bdisplay%3Ainline-block%3Bheight%3A2.4rem%3Bvertical-align%3Amiddle%3Bwidth%3A2rem%7D%5Bdir%3Dltr%5D%20.md-source__icon%20svg%7Bmargin-left%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-source__icon%20svg%7Bmargin-right%3A.6rem%7D.md-source__icon%20svg%7Bmargin-top%3A.6rem%7D%5Bdir%3Dltr%5D%20.md-source__icon%2B.md-source__repository%7Bpadding-left%3A2rem%7D%5Bdir%3Drtl%5D%20.md-source__icon%2B.md-source__repository%7Bpadding-right%3A2rem%7D%5Bdir%3Dltr%5D%20.md-source__icon%2B.md-source__repository%7Bmargin-left%3A-2rem%7D%5Bdir%3Drtl%5D%20.md-source__icon%2B.md-source__repository%7Bmargin-right%3A-2rem%7D%5Bdir%3Dltr%5D%20.md-source__repository%7Bmargin-left%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-source__repository%7Bmargin-right%3A.6rem%7D.md-source__repository%7Bdisplay%3Ainline-block%3Bmax-width%3Acalc%28100%25%20-%201.2rem%29%3Boverflow%3Ahidden%3Btext-overflow%3Aellipsis%3Bvertical-align%3Amiddle%7D.md-source__facts%7Bdisplay%3Aflex%3Bfont-size%3A.55rem%3Bgap%3A.4rem%3Blist-style-type%3Anone%3Bmargin%3A.1rem%200%200%3Bopacity%3A.75%3Boverflow%3Ahidden%3Bpadding%3A0%3Bwidth%3A100%25%7D.md-source__repository--active%20.md-source__facts%7Banimation%3Afacts%20.25s%20ease-in%7D.md-source__fact%7Boverflow%3Ahidden%3Btext-overflow%3Aellipsis%7D.md-source__repository--active%20.md-source__fact%7Banimation%3Afact%20.4s%20ease-out%7D%5Bdir%3Dltr%5D%20.md-source__fact%3Abefore%7Bmargin-right%3A.1rem%7D%5Bdir%3Drtl%5D%20.md-source__fact%3Abefore%7Bmargin-left%3A.1rem%7D.md-source__fact%3Abefore%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A.6rem%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bvertical-align%3Atext-top%3Bwidth%3A.6rem%7D.md-source__fact%3Anth-child%281n%2B2%29%7Bflex-shrink%3A0%7D.md-source__fact--version%3Abefore%7B-webkit-mask-image%3Avar%28--md-source-version-icon%29%3Bmask-image%3Avar%28--md-source-version-icon%29%7D.md-source__fact--stars%3Abefore%7B-webkit-mask-image%3Avar%28--md-source-stars-icon%29%3Bmask-image%3Avar%28--md-source-stars-icon%29%7D.md-source__fact--forks%3Abefore%7B-webkit-mask-image%3Avar%28--md-source-forks-icon%29%3Bmask-image%3Avar%28--md-source-forks-icon%29%7D.md-source__fact--repositories%3Abefore%7B-webkit-mask-image%3Avar%28--md-source-repositories-icon%29%3Bmask-image%3Avar%28--md-source-repositories-icon%29%7D.md-source-file%7Bmargin%3A1em%200%7D%5Bdir%3Dltr%5D%20.md-source-file__fact%7Bmargin-right%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-source-file__fact%7Bmargin-left%3A.6rem%7D.md-source-file__fact%7Balign-items%3Acenter%3Bcolor%3Avar%28--md-default-fg-color--light%29%3Bdisplay%3Ainline-flex%3Bfont-size%3A.68rem%3Bgap%3A.3rem%7D.md-source-file__fact%20.md-icon%7Bflex-shrink%3A0%3Bmargin-bottom%3A.05rem%7D%5Bdir%3Dltr%5D%20.md-source-file__fact%20.md-author%7Bfloat%3Aleft%7D%5Bdir%3Drtl%5D%20.md-source-file__fact%20.md-author%7Bfloat%3Aright%7D.md-source-file__fact%20.md-author%7Bmargin-right%3A.2rem%7D.md-source-file__fact%20svg%7Bwidth%3A.9rem%7D%3Aroot%7B--md-status%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M11%209h2V7h-2m1%2013c-4.41%200-8-3.59-8-8s3.59-8%208-8%208%203.59%208%208-3.59%208-8%208m0-18A10%2010%200%200%200%202%2012a10%2010%200%200%200%2010%2010%2010%2010%200%200%200%2010-10A10%2010%200%200%200%2012%202m-1%2015h2v-6h-2z%22/%3E%3C/svg%3E%27%29%3B--md-status--new%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22m23%2012-2.44-2.78.34-3.68-3.61-.82-1.89-3.18L12%203%208.6%201.54%206.71%204.72l-3.61.81.34%203.68L1%2012l2.44%202.78-.34%203.69%203.61.82%201.89%203.18L12%2021l3.4%201.46%201.89-3.18%203.61-.82-.34-3.68zm-10%205h-2v-2h2zm0-4h-2V7h2z%22/%3E%3C/svg%3E%27%29%3B--md-status--deprecated%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M9%203v1H4v2h1v13a2%202%200%200%200%202%202h10a2%202%200%200%200%202-2V6h1V4h-5V3zm0%205h2v9H9zm4%200h2v9h-2z%22/%3E%3C/svg%3E%27%29%3B--md-status--encrypted%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%201%203%205v6c0%205.55%203.84%2010.74%209%2012%205.16-1.26%209-6.45%209-12V5zm0%206c1.4%200%202.8%201.1%202.8%202.5V11c.6%200%201.2.6%201.2%201.3v3.5c0%20.6-.6%201.2-1.3%201.2H9.2c-.6%200-1.2-.6-1.2-1.3v-3.5c0-.6.6-1.2%201.2-1.2V9.5C9.2%208.1%2010.6%207%2012%207m0%201.2c-.8%200-1.5.5-1.5%201.3V11h3V9.5c0-.8-.7-1.3-1.5-1.3%22/%3E%3C/svg%3E%27%29%7D.md-status%3Aafter%7Bbackground-color%3Avar%28--md-default-fg-color--light%29%3Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A1.125em%3B-webkit-mask-image%3Avar%28--md-status%29%3Bmask-image%3Avar%28--md-status%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bvertical-align%3Atext-bottom%3Bwidth%3A1.125em%7D.md-status%3Ahover%3Aafter%7Bbackground-color%3Acurrentcolor%7D.md-status--new%3Aafter%7B-webkit-mask-image%3Avar%28--md-status--new%29%3Bmask-image%3Avar%28--md-status--new%29%7D.md-status--deprecated%3Aafter%7B-webkit-mask-image%3Avar%28--md-status--deprecated%29%3Bmask-image%3Avar%28--md-status--deprecated%29%7D.md-status--encrypted%3Aafter%7B-webkit-mask-image%3Avar%28--md-status--encrypted%29%3Bmask-image%3Avar%28--md-status--encrypted%29%7D.md-tabs%7Bbackground-color%3Avar%28--md-primary-fg-color%29%3Bcolor%3Avar%28--md-primary-bg-color%29%3Bdisplay%3Ablock%3Bline-height%3A1.3%3Boverflow%3Aauto%3Bwidth%3A100%25%3Bz-index%3A3%7D%40media%20print%7B.md-tabs%7Bdisplay%3Anone%7D%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7B.md-tabs%7Bdisplay%3Anone%7D%7D.md-tabs%5Bhidden%5D%7Bpointer-events%3Anone%7D%5Bdir%3Dltr%5D%20.md-tabs__list%7Bmargin-left%3A.2rem%7D%5Bdir%3Drtl%5D%20.md-tabs__list%7Bmargin-right%3A.2rem%7D.md-tabs__list%7Bcontain%3Acontent%3Bdisplay%3Aflex%3Blist-style%3Anone%3Bmargin%3A0%3Boverflow%3Aauto%3Bpadding%3A0%3Bscrollbar-width%3Anone%3Bwhite-space%3Anowrap%7D.md-tabs__list%3A%3A-webkit-scrollbar%7Bdisplay%3Anone%7D.md-tabs__item%7Bheight%3A2.4rem%3Bpadding-left%3A.6rem%3Bpadding-right%3A.6rem%7D.md-tabs__item--active%20.md-tabs__link%7Bcolor%3Ainherit%3Bopacity%3A1%7D.md-tabs__link%7B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%3Bdisplay%3Aflex%3Bfont-size%3A.7rem%3Bmargin-top%3A.8rem%3Bopacity%3A.7%3Boutline-color%3Avar%28--md-accent-fg-color%29%3Boutline-offset%3A.2rem%3Btransition%3Atransform%20.4s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Copacity%20.25s%7D.md-tabs__link%3Afocus%2C.md-tabs__link%3Ahover%7Bcolor%3Ainherit%3Bopacity%3A1%7D%5Bdir%3Dltr%5D%20.md-tabs__link%20svg%7Bmargin-right%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-tabs__link%20svg%7Bmargin-left%3A.4rem%7D.md-tabs__link%20svg%7Bfill%3Acurrentcolor%3Bheight%3A1.3em%7D.md-tabs__item%3Anth-child%282%29%20.md-tabs__link%7Btransition-delay%3A20ms%7D.md-tabs__item%3Anth-child%283%29%20.md-tabs__link%7Btransition-delay%3A40ms%7D.md-tabs__item%3Anth-child%284%29%20.md-tabs__link%7Btransition-delay%3A60ms%7D.md-tabs__item%3Anth-child%285%29%20.md-tabs__link%7Btransition-delay%3A80ms%7D.md-tabs__item%3Anth-child%286%29%20.md-tabs__link%7Btransition-delay%3A.1s%7D.md-tabs__item%3Anth-child%287%29%20.md-tabs__link%7Btransition-delay%3A.12s%7D.md-tabs__item%3Anth-child%288%29%20.md-tabs__link%7Btransition-delay%3A.14s%7D.md-tabs__item%3Anth-child%289%29%20.md-tabs__link%7Btransition-delay%3A.16s%7D.md-tabs__item%3Anth-child%2810%29%20.md-tabs__link%7Btransition-delay%3A.18s%7D.md-tabs__item%3Anth-child%2811%29%20.md-tabs__link%7Btransition-delay%3A.2s%7D.md-tabs__item%3Anth-child%2812%29%20.md-tabs__link%7Btransition-delay%3A.22s%7D.md-tabs__item%3Anth-child%2813%29%20.md-tabs__link%7Btransition-delay%3A.24s%7D.md-tabs__item%3Anth-child%2814%29%20.md-tabs__link%7Btransition-delay%3A.26s%7D.md-tabs__item%3Anth-child%2815%29%20.md-tabs__link%7Btransition-delay%3A.28s%7D.md-tabs__item%3Anth-child%2816%29%20.md-tabs__link%7Btransition-delay%3A.3s%7D.md-tabs%5Bhidden%5D%20.md-tabs__link%7Bopacity%3A0%3Btransform%3AtranslateY%2850%25%29%3Btransition%3Atransform%200ms%20.1s%2Copacity%20.1s%7D%3Aroot%7B--md-tag-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22m5.41%2021%20.71-4h-4l.35-2h4l1.06-6h-4l.35-2h4l.71-4h2l-.71%204h6l.71-4h2l-.71%204h4l-.35%202h-4l-1.06%206h4l-.35%202h-4l-.71%204h-2l.71-4h-6l-.71%204zM9.53%209l-1.06%206h6l1.06-6z%22/%3E%3C/svg%3E%27%29%7D.md-typeset%20.md-tags%3Anot%28%5Bhidden%5D%29%7Bdisplay%3Ainline-flex%3Bflex-wrap%3Awrap%3Bgap%3A.5em%3Bmargin-bottom%3A.75em%3Bmargin-top%3A-.125em%7D.md-typeset%20.md-tag%7Balign-items%3Acenter%3Bbackground%3Avar%28--md-default-fg-color--lightest%29%3Bborder-radius%3A2.4rem%3Bdisplay%3Ainline-flex%3Bfont-size%3A.64rem%3Bfont-size%3Amin%28.8em%2C.64rem%29%3Bfont-weight%3A700%3Bgap%3A.5em%3Bletter-spacing%3Anormal%3Bline-height%3A1.6%3Bpadding%3A.3125em%20.78125em%7D.md-typeset%20.md-tag%5Bhref%5D%7B-webkit-tap-highlight-color%3Atransparent%3Bcolor%3Ainherit%3Boutline%3Anone%3Btransition%3Acolor%20125ms%2Cbackground-color%20125ms%7D.md-typeset%20.md-tag%5Bhref%5D%3Afocus%2C.md-typeset%20.md-tag%5Bhref%5D%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color%29%3Bcolor%3Avar%28--md-accent-bg-color%29%7D%5Bid%5D%3E.md-typeset%20.md-tag%7Bvertical-align%3Atext-top%7D.md-typeset%20.md-tag-icon%3Abefore%7Bbackground-color%3Avar%28--md-default-fg-color--lighter%29%3Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A1.2em%3B-webkit-mask-image%3Avar%28--md-tag-icon%29%3Bmask-image%3Avar%28--md-tag-icon%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Btransition%3Abackground-color%20125ms%3Bvertical-align%3Atext-bottom%3Bwidth%3A1.2em%7D.md-typeset%20.md-tag-icon%5Bhref%5D%3Afocus%3Abefore%2C.md-typeset%20.md-tag-icon%5Bhref%5D%3Ahover%3Abefore%7Bbackground-color%3Avar%28--md-accent-bg-color%29%7D%40keyframes%20pulse%7B0%25%7Btransform%3Ascale%28.95%29%7D75%25%7Btransform%3Ascale%281%29%7Dto%7Btransform%3Ascale%28.95%29%7D%7D%3Aroot%7B--md-annotation-bg-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%202A10%2010%200%200%200%202%2012a10%2010%200%200%200%2010%2010%2010%2010%200%200%200%2010-10A10%2010%200%200%200%2012%202%22/%3E%3C/svg%3E%27%29%3B--md-annotation-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M17%2013h-4v4h-2v-4H7v-2h4V7h2v4h4m-5-9A10%2010%200%200%200%202%2012a10%2010%200%200%200%2010%2010%2010%2010%200%200%200%2010-10A10%2010%200%200%200%2012%202%22/%3E%3C/svg%3E%27%29%7D.md-tooltip%7B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%3Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder-radius%3A.1rem%3Bbox-shadow%3Avar%28--md-shadow-z2%29%3Bcolor%3Avar%28--md-default-fg-color%29%3Bfont-family%3Avar%28--md-text-font-family%29%3Bleft%3Aclamp%28var%28--md-tooltip-0%2C0rem%29%20%2B%20.8rem%2Cvar%28--md-tooltip-x%29%2C100vw%20%2B%20var%28--md-tooltip-0%2C0rem%29%20%2B%20.8rem%20-%20var%28--md-tooltip-width%29%20-%202%20%2A%20.8rem%29%3Bmax-width%3Acalc%28100vw%20-%201.6rem%29%3Bopacity%3A0%3Bposition%3Aabsolute%3Btop%3Avar%28--md-tooltip-y%29%3Btransform%3AtranslateY%28-.4rem%29%3Btransition%3Atransform%200ms%20.25s%2Copacity%20.25s%2Cz-index%20.25s%3Bwidth%3Avar%28--md-tooltip-width%29%3Bz-index%3A0%7D.md-tooltip--active%7Bopacity%3A1%3Btransform%3AtranslateY%280%29%3Btransition%3Atransform%20.25s%20cubic-bezier%28.1%2C.7%2C.1%2C1%29%2Copacity%20.25s%2Cz-index%200ms%3Bz-index%3A2%7D.md-tooltip--inline%7Bfont-weight%3A700%3B-webkit-user-select%3Anone%3Buser-select%3Anone%3Bwidth%3Aauto%7D.md-tooltip--inline%3Anot%28.md-tooltip--active%29%7Btransform%3AtranslateY%28.2rem%29%20scale%28.9%29%7D.md-tooltip--inline%20.md-tooltip__inner%7Bfont-size%3A.5rem%3Bpadding%3A.2rem%20.4rem%7D%5Bhidden%5D%2B.md-tooltip--inline%7Bdisplay%3Anone%7D.focus-visible%3E.md-tooltip%2C.md-tooltip%3Atarget%7Boutline%3Avar%28--md-accent-fg-color%29%20auto%7D.md-tooltip__inner%7Bfont-size%3A.64rem%3Bpadding%3A.8rem%7D.md-tooltip__inner.md-typeset%3E%3Afirst-child%7Bmargin-top%3A0%7D.md-tooltip__inner.md-typeset%3E%3Alast-child%7Bmargin-bottom%3A0%7D.md-annotation%7Bfont-style%3Anormal%3Bfont-weight%3A400%3Boutline%3Anone%3Btext-align%3Ainitial%3Bvertical-align%3Atext-bottom%3Bwhite-space%3Anormal%7D%5Bdir%3Drtl%5D%20.md-annotation%7Bdirection%3Artl%7Dcode%20.md-annotation%7Bfont-family%3Avar%28--md-code-font-family%29%3Bfont-size%3Ainherit%7D.md-annotation%3Anot%28%5Bhidden%5D%29%7Bdisplay%3Ainline-block%3Bline-height%3A1.25%7D.md-annotation__index%7Bborder-radius%3A.01px%3Bcursor%3Apointer%3Bdisplay%3Ainline-block%3Bmargin-left%3A.4ch%3Bmargin-right%3A.4ch%3Boutline%3Anone%3Boverflow%3Ahidden%3Bposition%3Arelative%3B-webkit-user-select%3Anone%3Buser-select%3Anone%3Bvertical-align%3Atext-top%3Bz-index%3A0%7D.md-annotation%20.md-annotation__index%7Btransition%3Az-index%20.25s%7D%40media%20screen%7B.md-annotation__index%7Bwidth%3A2.2ch%7D%5Bdata-md-visible%5D%3E.md-annotation__index%7Banimation%3Apulse%202s%20infinite%7D.md-annotation__index%3Abefore%7Bbackground%3Avar%28--md-default-bg-color%29%3B-webkit-mask-image%3Avar%28--md-annotation-bg-icon%29%3Bmask-image%3Avar%28--md-annotation-bg-icon%29%7D.md-annotation__index%3Aafter%2C.md-annotation__index%3Abefore%7Bcontent%3A%22%22%3Bheight%3A2.2ch%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bposition%3Aabsolute%3Btop%3A-.1ch%3Bwidth%3A2.2ch%3Bz-index%3A-1%7D.md-annotation__index%3Aafter%7Bbackground-color%3Avar%28--md-default-fg-color--lighter%29%3B-webkit-mask-image%3Avar%28--md-annotation-icon%29%3Bmask-image%3Avar%28--md-annotation-icon%29%3Btransform%3Ascale%281.0001%29%3Btransition%3Abackground-color%20.25s%2Ctransform%20.25s%7D.md-tooltip--active%2B.md-annotation__index%3Aafter%7Btransform%3Arotate%2845deg%29%7D.md-tooltip--active%2B.md-annotation__index%3Aafter%2C%3Ahover%3E.md-annotation__index%3Aafter%7Bbackground-color%3Avar%28--md-accent-fg-color%29%7D%7D.md-tooltip--active%2B.md-annotation__index%7Banimation-play-state%3Apaused%3Btransition-duration%3A0ms%3Bz-index%3A2%7D.md-annotation__index%20%5Bdata-md-annotation-id%5D%7Bdisplay%3Ainline-block%7D%40media%20print%7B.md-annotation__index%20%5Bdata-md-annotation-id%5D%7Bbackground%3Avar%28--md-default-fg-color--lighter%29%3Bborder-radius%3A2ch%3Bcolor%3Avar%28--md-default-bg-color%29%3Bfont-weight%3A700%3Bpadding%3A0%20.6ch%3Bwhite-space%3Anowrap%7D.md-annotation__index%20%5Bdata-md-annotation-id%5D%3Aafter%7Bcontent%3Aattr%28data-md-annotation-id%29%7D%7D.md-typeset%20.md-annotation-list%7Bcounter-reset%3Axxx%3Blist-style%3Anone%7D.md-typeset%20.md-annotation-list%20li%7Bposition%3Arelative%7D%5Bdir%3Dltr%5D%20.md-typeset%20.md-annotation-list%20li%3Abefore%7Bleft%3A-2.125em%7D%5Bdir%3Drtl%5D%20.md-typeset%20.md-annotation-list%20li%3Abefore%7Bright%3A-2.125em%7D.md-typeset%20.md-annotation-list%20li%3Abefore%7Bbackground%3Avar%28--md-default-fg-color--lighter%29%3Bborder-radius%3A2ch%3Bcolor%3Avar%28--md-default-bg-color%29%3Bcontent%3Acounter%28xxx%29%3Bcounter-increment%3Axxx%3Bfont-size%3A.8875em%3Bfont-weight%3A700%3Bheight%3A2ch%3Bline-height%3A1.25%3Bmin-width%3A2ch%3Bpadding%3A0%20.6ch%3Bposition%3Aabsolute%3Btext-align%3Acenter%3Btop%3A.25em%7D%3Aroot%7B--md-tooltip-width%3A20rem%3B--md-tooltip-tail%3A0.3rem%7D.md-tooltip2%7B-webkit-backface-visibility%3Ahidden%3Bbackface-visibility%3Ahidden%3Bcolor%3Avar%28--md-default-fg-color%29%3Bfont-family%3Avar%28--md-text-font-family%29%3Bopacity%3A0%3Bpointer-events%3Anone%3Bposition%3Aabsolute%3Btop%3Acalc%28var%28--md-tooltip-host-y%29%20%2B%20var%28--md-tooltip-y%29%29%3Btransform%3AtranslateY%28-.4rem%29%3Btransform-origin%3Acalc%28var%28--md-tooltip-host-x%29%20%2B%20var%28--md-tooltip-x%29%29%200%3Btransition%3Atransform%200ms%20.25s%2Copacity%20.25s%2Cz-index%20.25s%3Bwidth%3A100%25%3Bz-index%3A0%7D.md-tooltip2%3Abefore%7Bborder-left%3Avar%28--md-tooltip-tail%29%20solid%20%230000%3Bborder-right%3Avar%28--md-tooltip-tail%29%20solid%20%230000%3Bcontent%3A%22%22%3Bdisplay%3Ablock%3Bleft%3Aclamp%281.5%20%2A%20.8rem%2Cvar%28--md-tooltip-host-x%29%20%2B%20var%28--md-tooltip-x%29%20-%20var%28--md-tooltip-tail%29%2C100vw%20-%202%20%2A%20var%28--md-tooltip-tail%29%20-%201.5%20%2A%20.8rem%29%3Bposition%3Aabsolute%3Bz-index%3A1%7D.md-tooltip2--top%3Abefore%7Bborder-top%3Avar%28--md-tooltip-tail%29%20solid%20var%28--md-default-bg-color%29%3Bbottom%3Acalc%28var%28--md-tooltip-tail%29%2A-1%20%2B%20.025rem%29%3Bfilter%3Adrop-shadow%280%201px%200%20hsla%280%2C0%25%2C0%25%2C.05%29%29%7D.md-tooltip2--bottom%3Abefore%7Bborder-bottom%3Avar%28--md-tooltip-tail%29%20solid%20var%28--md-default-bg-color%29%3Bfilter%3Adrop-shadow%280%20-1px%200%20hsla%280%2C0%25%2C0%25%2C.05%29%29%3Btop%3Acalc%28var%28--md-tooltip-tail%29%2A-1%20%2B%20.025rem%29%7D.md-tooltip2--active%7Bopacity%3A1%3Btransform%3AtranslateY%280%29%3Btransition%3Atransform%20.4s%20cubic-bezier%280%2C1%2C.5%2C1%29%2Copacity%20.25s%2Cz-index%200ms%3Bz-index%3A2%7D.md-tooltip2__inner%7Bscrollbar-gutter%3Astable%3Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder-radius%3A.1rem%3Bbox-shadow%3Avar%28--md-shadow-z2%29%3Bleft%3Aclamp%28.8rem%2Cvar%28--md-tooltip-host-x%29%20-%20.8rem%2C100vw%20-%20var%28--md-tooltip-width%29%20-%20.8rem%29%3Bmax-height%3A40vh%3Bmax-width%3Acalc%28100vw%20-%201.6rem%29%3Bposition%3Arelative%3Bscrollbar-width%3Athin%7D.md-tooltip2__inner%3A%3A-webkit-scrollbar%7Bheight%3A.2rem%3Bwidth%3A.2rem%7D.md-tooltip2__inner%3A%3A-webkit-scrollbar-thumb%7Bbackground-color%3Avar%28--md-default-fg-color--lighter%29%7D.md-tooltip2__inner%3A%3A-webkit-scrollbar-thumb%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color%29%7D%5Brole%3Dtooltip%5D%3E.md-tooltip2__inner%7Bfont-size%3A.5rem%3Bfont-weight%3A700%3Bleft%3Aclamp%28.8rem%2Cvar%28--md-tooltip-host-x%29%20%2B%20var%28--md-tooltip-x%29%20-%20var%28--md-tooltip-width%29/2%2C100vw%20-%20var%28--md-tooltip-width%29%20-%20.8rem%29%3Bmax-width%3Amin%28100vw%20-%202%20%2A%20.8rem%2C400px%29%3Bpadding%3A.2rem%20.4rem%3B-webkit-user-select%3Anone%3Buser-select%3Anone%3Bwidth%3A-moz-fit-content%3Bwidth%3Afit-content%7D.md-tooltip2__inner.md-typeset%3E%3Afirst-child%7Bmargin-top%3A0%7D.md-tooltip2__inner.md-typeset%3E%3Alast-child%7Bmargin-bottom%3A0%7D%5Bdir%3Dltr%5D%20.md-top%7Bmargin-left%3A50%25%7D%5Bdir%3Drtl%5D%20.md-top%7Bmargin-right%3A50%25%7D.md-top%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder-radius%3A1.6rem%3Bbox-shadow%3Avar%28--md-shadow-z2%29%3Bcolor%3Avar%28--md-default-fg-color--light%29%3Bcursor%3Apointer%3Bdisplay%3Ablock%3Bfont-size%3A.7rem%3Boutline%3Anone%3Bpadding%3A.4rem%20.8rem%3Bposition%3Afixed%3Btop%3A3.2rem%3Btransform%3Atranslate%28-50%25%29%3Btransition%3Acolor%20125ms%2Cbackground-color%20125ms%2Ctransform%20125ms%20cubic-bezier%28.4%2C0%2C.2%2C1%29%2Copacity%20125ms%3Bz-index%3A2%7D%40media%20print%7B.md-top%7Bdisplay%3Anone%7D%7D%5Bdir%3Drtl%5D%20.md-top%7Btransform%3Atranslate%2850%25%29%7D.md-top%5Bhidden%5D%7Bopacity%3A0%3Bpointer-events%3Anone%3Btransform%3Atranslate%28-50%25%2C.2rem%29%3Btransition-duration%3A0ms%7D%5Bdir%3Drtl%5D%20.md-top%5Bhidden%5D%7Btransform%3Atranslate%2850%25%2C.2rem%29%7D.md-top%3Afocus%2C.md-top%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color%29%3Bcolor%3Avar%28--md-accent-bg-color%29%7D.md-top%20svg%7Bdisplay%3Ainline-block%3Bvertical-align%3A-.5em%7D%40keyframes%20hoverfix%7B0%25%7Bpointer-events%3Anone%7D%7D%3Aroot%7B--md-version-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%20320%20512%22%3E%3C%21--%21%20Font%20Awesome%20Free%206.6.0%20by%20%40fontawesome%20-%20https%3A//fontawesome.com%20License%20-%20https%3A//fontawesome.com/license/free%20%28Icons%3A%20CC%20BY%204.0%2C%20Fonts%3A%20SIL%20OFL%201.1%2C%20Code%3A%20MIT%20License%29%20Copyright%202024%20Fonticons%2C%20Inc.--%3E%3Cpath%20d%3D%22M137.4%20374.6c12.5%2012.5%2032.8%2012.5%2045.3%200l128-128c9.2-9.2%2011.9-22.9%206.9-34.9S301%20191.9%20288%20191.9L32%20192c-12.9%200-24.6%207.8-29.6%2019.8s-2.2%2025.7%206.9%2034.9l128%20128z%22/%3E%3C/svg%3E%27%29%7D.md-version%7Bflex-shrink%3A0%3Bfont-size%3A.8rem%3Bheight%3A2.4rem%7D%5Bdir%3Dltr%5D%20.md-version__current%7Bmargin-left%3A1.4rem%3Bmargin-right%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-version__current%7Bmargin-left%3A.4rem%3Bmargin-right%3A1.4rem%7D.md-version__current%7Bcolor%3Ainherit%3Bcursor%3Apointer%3Boutline%3Anone%3Bposition%3Arelative%3Btop%3A.05rem%7D%5Bdir%3Dltr%5D%20.md-version__current%3Aafter%7Bmargin-left%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-version__current%3Aafter%7Bmargin-right%3A.4rem%7D.md-version__current%3Aafter%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A.6rem%3B-webkit-mask-image%3Avar%28--md-version-icon%29%3Bmask-image%3Avar%28--md-version-icon%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bwidth%3A.4rem%7D.md-version__alias%7Bmargin-left%3A.3rem%3Bopacity%3A.7%7D.md-version__list%7Bbackground-color%3Avar%28--md-default-bg-color%29%3Bborder-radius%3A.1rem%3Bbox-shadow%3Avar%28--md-shadow-z2%29%3Bcolor%3Avar%28--md-default-fg-color%29%3Blist-style-type%3Anone%3Bmargin%3A.2rem%20.8rem%3Bmax-height%3A0%3Bopacity%3A0%3Boverflow%3Aauto%3Bpadding%3A0%3Bposition%3Aabsolute%3Bscroll-snap-type%3Ay%20mandatory%3Btop%3A.15rem%3Btransition%3Amax-height%200ms%20.5s%2Copacity%20.25s%20.25s%3Bz-index%3A3%7D.md-version%3Afocus-within%20.md-version__list%2C.md-version%3Ahover%20.md-version__list%7Bmax-height%3A10rem%3Bopacity%3A1%3Btransition%3Amax-height%200ms%2Copacity%20.25s%7D%40media%20%28hover%3Anone%29%2C%28pointer%3Acoarse%29%7B.md-version%3Ahover%20.md-version__list%7Banimation%3Ahoverfix%20.25s%20forwards%7D.md-version%3Afocus-within%20.md-version__list%7Banimation%3Anone%7D%7D.md-version__item%7Bline-height%3A1.8rem%7D%5Bdir%3Dltr%5D%20.md-version__link%7Bpadding-left%3A.6rem%3Bpadding-right%3A1.2rem%7D%5Bdir%3Drtl%5D%20.md-version__link%7Bpadding-left%3A1.2rem%3Bpadding-right%3A.6rem%7D.md-version__link%7Bcursor%3Apointer%3Bdisplay%3Ablock%3Boutline%3Anone%3Bscroll-snap-align%3Astart%3Btransition%3Acolor%20.25s%2Cbackground-color%20.25s%3Bwhite-space%3Anowrap%3Bwidth%3A100%25%7D.md-version__link%3Afocus%2C.md-version__link%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-version__link%3Afocus%7Bbackground-color%3Avar%28--md-default-fg-color--lightest%29%7D%3Aroot%7B--md-admonition-icon--note%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M12%202C6.47%202%202%206.47%202%2012s4.47%2010%2010%2010%2010-4.47%2010-10S17.53%202%2012%202m3.1%205.07c.14%200%20.28.05.4.16l1.27%201.27c.23.22.23.57%200%20.78l-1%201-2.05-2.05%201-1c.1-.11.24-.16.38-.16m-1.97%201.74%202.06%202.06-6.06%206.06H7.07v-2.06z%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--abstract%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M17%209H7V7h10m0%206H7v-2h10m-3%206H7v-2h7M12%203a1%201%200%200%201%201%201%201%201%200%200%201-1%201%201%201%200%200%201-1-1%201%201%200%200%201%201-1m7%200h-4.18C14.4%201.84%2013.3%201%2012%201s-2.4.84-2.82%202H5a2%202%200%200%200-2%202v14a2%202%200%200%200%202%202h14a2%202%200%200%200%202-2V5a2%202%200%200%200-2-2%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--info%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M13%209h-2V7h2m0%2010h-2v-6h2m-1-9A10%2010%200%200%200%202%2012a10%2010%200%200%200%2010%2010%2010%2010%200%200%200%2010-10A10%2010%200%200%200%2012%202%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--tip%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M17.66%2011.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33%207.26%2013%204.85%2013.95%203c-.95.23-1.78.75-2.49%201.32-2.59%202.08-3.61%205.75-2.39%208.9.04.1.08.2.08.33%200%20.22-.15.42-.35.5-.23.1-.47.04-.66-.12a.6.6%200%200%201-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78%2010%204.87%2012.3%205%2014.47c.06.5.12%201%20.29%201.5.14.6.41%201.2.71%201.73%201.08%201.73%202.95%202.97%204.96%203.22%202.14.27%204.43-.12%206.07-1.6%201.83-1.66%202.47-4.32%201.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16%206.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82%201.19-.28%201.9-1.16%202.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63%201.06.77%201%201.98%201.44%202.24%202.8.04.14.06.28.06.43.03.82-.33%201.72-.93%202.27%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--success%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M21%207%209%2019l-5.5-5.5%201.41-1.41L9%2016.17%2019.59%205.59z%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--question%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22m15.07%2011.25-.9.92C13.45%2012.89%2013%2013.5%2013%2015h-2v-.5c0-1.11.45-2.11%201.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2%202%200%200%200-2-2%202%202%200%200%200-2%202H8a4%204%200%200%201%204-4%204%204%200%200%201%204%204%203.2%203.2%200%200%201-.93%202.25M13%2019h-2v-2h2M12%202A10%2010%200%200%200%202%2012a10%2010%200%200%200%2010%2010%2010%2010%200%200%200%2010-10c0-5.53-4.5-10-10-10%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--warning%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M13%2014h-2V9h2m0%209h-2v-2h2M1%2021h22L12%202z%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--failure%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19%206.41%2017.59%205%2012%2010.59%206.41%205%205%206.41%2010.59%2012%205%2017.59%206.41%2019%2012%2013.41%2017.59%2019%2019%2017.59%2013.41%2012z%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--danger%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22m11.5%2020%204.86-9.73H13V4l-5%209.73h3.5zM12%202c2.75%200%205.1%201%207.05%202.95S22%209.25%2022%2012s-1%205.1-2.95%207.05S14.75%2022%2012%2022s-5.1-1-7.05-2.95S2%2014.75%202%2012s1-5.1%202.95-7.05S9.25%202%2012%202%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--bug%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M11%2013h2v1h-2zm10-8v6c0%205.5-3.8%2010.7-9%2012-5.2-1.3-9-6.5-9-12V5l9-4zm-4%205h-2.2c-.2-.6-.6-1.1-1.1-1.5l1.2-1.2-.7-.7L12.8%208H12c-.2%200-.5%200-.7.1L9.9%206.6l-.8.8%201.2%201.2c-.5.3-.9.8-1.1%201.4H7v1h2v1H7v1h2v1H7v1h2.2c.4%201.2%201.5%202%202.8%202s2.4-.8%202.8-2H17v-1h-2v-1h2v-1h-2v-1h2zm-6%202h2v-1h-2z%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--example%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M7%202v2h1v14a4%204%200%200%200%204%204%204%204%200%200%200%204-4V4h1V2zm4%2014c-.6%200-1-.4-1-1s.4-1%201-1%201%20.4%201%201-.4%201-1%201m2-4c-.6%200-1-.4-1-1s.4-1%201-1%201%20.4%201%201-.4%201-1%201m1-5h-4V4h4z%22/%3E%3C/svg%3E%27%29%3B--md-admonition-icon--quote%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M14%2017h3l2-4V7h-6v6h3M6%2017h3l2-4V7H5v6h3z%22/%3E%3C/svg%3E%27%29%7D.md-typeset%20.admonition%2C.md-typeset%20details%7Bbackground-color%3Avar%28--md-admonition-bg-color%29%3Bborder%3A.075rem%20solid%20%23448aff%3Bborder-radius%3A.2rem%3Bbox-shadow%3Avar%28--md-shadow-z1%29%3Bcolor%3Avar%28--md-admonition-fg-color%29%3Bdisplay%3Aflow-root%3Bfont-size%3A.64rem%3Bmargin%3A1.5625em%200%3Bpadding%3A0%20.6rem%3Bpage-break-inside%3Aavoid%3Btransition%3Abox-shadow%20125ms%7D%40media%20print%7B.md-typeset%20.admonition%2C.md-typeset%20details%7Bbox-shadow%3Anone%7D%7D.md-typeset%20.admonition%3Afocus-within%2C.md-typeset%20details%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%23448aff1a%7D.md-typeset%20.admonition%3E%2A%2C.md-typeset%20details%3E%2A%7Bbox-sizing%3Aborder-box%7D.md-typeset%20.admonition%20.admonition%2C.md-typeset%20.admonition%20details%2C.md-typeset%20details%20.admonition%2C.md-typeset%20details%20details%7Bmargin-bottom%3A1em%3Bmargin-top%3A1em%7D.md-typeset%20.admonition%20.md-typeset__scrollwrap%2C.md-typeset%20details%20.md-typeset__scrollwrap%7Bmargin%3A1em%20-.6rem%7D.md-typeset%20.admonition%20.md-typeset__table%2C.md-typeset%20details%20.md-typeset__table%7Bpadding%3A0%20.6rem%7D.md-typeset%20.admonition%3E.tabbed-set%3Aonly-child%2C.md-typeset%20details%3E.tabbed-set%3Aonly-child%7Bmargin-top%3A0%7Dhtml%20.md-typeset%20.admonition%3E%3Alast-child%2Chtml%20.md-typeset%20details%3E%3Alast-child%7Bmargin-bottom%3A.6rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Dltr%5D%20.md-typeset%20summary%7Bpadding-left%3A2rem%3Bpadding-right%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Drtl%5D%20.md-typeset%20summary%7Bpadding-left%3A.6rem%3Bpadding-right%3A2rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Dltr%5D%20.md-typeset%20summary%7Bborder-left-width%3A.2rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Drtl%5D%20.md-typeset%20summary%7Bborder-right-width%3A.2rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Dltr%5D%20.md-typeset%20summary%7Bborder-top-left-radius%3A.1rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Dltr%5D%20.md-typeset%20summary%2C%5Bdir%3Drtl%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Drtl%5D%20.md-typeset%20summary%7Bborder-top-right-radius%3A.1rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.admonition-title%2C%5Bdir%3Drtl%5D%20.md-typeset%20summary%7Bborder-top-left-radius%3A.1rem%7D.md-typeset%20.admonition-title%2C.md-typeset%20summary%7Bbackground-color%3A%23448aff1a%3Bborder%3Anone%3Bfont-weight%3A700%3Bmargin%3A0%20-.6rem%3Bpadding-bottom%3A.4rem%3Bpadding-top%3A.4rem%3Bposition%3Arelative%7Dhtml%20.md-typeset%20.admonition-title%3Alast-child%2Chtml%20.md-typeset%20summary%3Alast-child%7Bmargin-bottom%3A0%7D%5Bdir%3Dltr%5D%20.md-typeset%20.admonition-title%3Abefore%2C%5Bdir%3Dltr%5D%20.md-typeset%20summary%3Abefore%7Bleft%3A.6rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.admonition-title%3Abefore%2C%5Bdir%3Drtl%5D%20.md-typeset%20summary%3Abefore%7Bright%3A.6rem%7D.md-typeset%20.admonition-title%3Abefore%2C.md-typeset%20summary%3Abefore%7Bbackground-color%3A%23448aff%3Bcontent%3A%22%22%3Bheight%3A1rem%3B-webkit-mask-image%3Avar%28--md-admonition-icon--note%29%3Bmask-image%3Avar%28--md-admonition-icon--note%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bposition%3Aabsolute%3Btop%3A.625em%3Bwidth%3A1rem%7D.md-typeset%20.admonition-title%20code%2C.md-typeset%20summary%20code%7Bbox-shadow%3A0%200%200%20.05rem%20var%28--md-default-fg-color--lightest%29%7D.md-typeset%20.admonition.note%2C.md-typeset%20details.note%7Bborder-color%3A%23448aff%7D.md-typeset%20.admonition.note%3Afocus-within%2C.md-typeset%20details.note%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%23448aff1a%7D.md-typeset%20.note%3E.admonition-title%2C.md-typeset%20.note%3Esummary%7Bbackground-color%3A%23448aff1a%7D.md-typeset%20.note%3E.admonition-title%3Abefore%2C.md-typeset%20.note%3Esummary%3Abefore%7Bbackground-color%3A%23448aff%3B-webkit-mask-image%3Avar%28--md-admonition-icon--note%29%3Bmask-image%3Avar%28--md-admonition-icon--note%29%7D.md-typeset%20.note%3E.admonition-title%3Aafter%2C.md-typeset%20.note%3Esummary%3Aafter%7Bcolor%3A%23448aff%7D.md-typeset%20.admonition.abstract%2C.md-typeset%20details.abstract%7Bborder-color%3A%2300b0ff%7D.md-typeset%20.admonition.abstract%3Afocus-within%2C.md-typeset%20details.abstract%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%2300b0ff1a%7D.md-typeset%20.abstract%3E.admonition-title%2C.md-typeset%20.abstract%3Esummary%7Bbackground-color%3A%2300b0ff1a%7D.md-typeset%20.abstract%3E.admonition-title%3Abefore%2C.md-typeset%20.abstract%3Esummary%3Abefore%7Bbackground-color%3A%2300b0ff%3B-webkit-mask-image%3Avar%28--md-admonition-icon--abstract%29%3Bmask-image%3Avar%28--md-admonition-icon--abstract%29%7D.md-typeset%20.abstract%3E.admonition-title%3Aafter%2C.md-typeset%20.abstract%3Esummary%3Aafter%7Bcolor%3A%2300b0ff%7D.md-typeset%20.admonition.info%2C.md-typeset%20details.info%7Bborder-color%3A%2300b8d4%7D.md-typeset%20.admonition.info%3Afocus-within%2C.md-typeset%20details.info%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%2300b8d41a%7D.md-typeset%20.info%3E.admonition-title%2C.md-typeset%20.info%3Esummary%7Bbackground-color%3A%2300b8d41a%7D.md-typeset%20.info%3E.admonition-title%3Abefore%2C.md-typeset%20.info%3Esummary%3Abefore%7Bbackground-color%3A%2300b8d4%3B-webkit-mask-image%3Avar%28--md-admonition-icon--info%29%3Bmask-image%3Avar%28--md-admonition-icon--info%29%7D.md-typeset%20.info%3E.admonition-title%3Aafter%2C.md-typeset%20.info%3Esummary%3Aafter%7Bcolor%3A%2300b8d4%7D.md-typeset%20.admonition.tip%2C.md-typeset%20details.tip%7Bborder-color%3A%2300bfa5%7D.md-typeset%20.admonition.tip%3Afocus-within%2C.md-typeset%20details.tip%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%2300bfa51a%7D.md-typeset%20.tip%3E.admonition-title%2C.md-typeset%20.tip%3Esummary%7Bbackground-color%3A%2300bfa51a%7D.md-typeset%20.tip%3E.admonition-title%3Abefore%2C.md-typeset%20.tip%3Esummary%3Abefore%7Bbackground-color%3A%2300bfa5%3B-webkit-mask-image%3Avar%28--md-admonition-icon--tip%29%3Bmask-image%3Avar%28--md-admonition-icon--tip%29%7D.md-typeset%20.tip%3E.admonition-title%3Aafter%2C.md-typeset%20.tip%3Esummary%3Aafter%7Bcolor%3A%2300bfa5%7D.md-typeset%20.admonition.success%2C.md-typeset%20details.success%7Bborder-color%3A%2300c853%7D.md-typeset%20.admonition.success%3Afocus-within%2C.md-typeset%20details.success%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%2300c8531a%7D.md-typeset%20.success%3E.admonition-title%2C.md-typeset%20.success%3Esummary%7Bbackground-color%3A%2300c8531a%7D.md-typeset%20.success%3E.admonition-title%3Abefore%2C.md-typeset%20.success%3Esummary%3Abefore%7Bbackground-color%3A%2300c853%3B-webkit-mask-image%3Avar%28--md-admonition-icon--success%29%3Bmask-image%3Avar%28--md-admonition-icon--success%29%7D.md-typeset%20.success%3E.admonition-title%3Aafter%2C.md-typeset%20.success%3Esummary%3Aafter%7Bcolor%3A%2300c853%7D.md-typeset%20.admonition.question%2C.md-typeset%20details.question%7Bborder-color%3A%2364dd17%7D.md-typeset%20.admonition.question%3Afocus-within%2C.md-typeset%20details.question%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%2364dd171a%7D.md-typeset%20.question%3E.admonition-title%2C.md-typeset%20.question%3Esummary%7Bbackground-color%3A%2364dd171a%7D.md-typeset%20.question%3E.admonition-title%3Abefore%2C.md-typeset%20.question%3Esummary%3Abefore%7Bbackground-color%3A%2364dd17%3B-webkit-mask-image%3Avar%28--md-admonition-icon--question%29%3Bmask-image%3Avar%28--md-admonition-icon--question%29%7D.md-typeset%20.question%3E.admonition-title%3Aafter%2C.md-typeset%20.question%3Esummary%3Aafter%7Bcolor%3A%2364dd17%7D.md-typeset%20.admonition.warning%2C.md-typeset%20details.warning%7Bborder-color%3A%23ff9100%7D.md-typeset%20.admonition.warning%3Afocus-within%2C.md-typeset%20details.warning%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%23ff91001a%7D.md-typeset%20.warning%3E.admonition-title%2C.md-typeset%20.warning%3Esummary%7Bbackground-color%3A%23ff91001a%7D.md-typeset%20.warning%3E.admonition-title%3Abefore%2C.md-typeset%20.warning%3Esummary%3Abefore%7Bbackground-color%3A%23ff9100%3B-webkit-mask-image%3Avar%28--md-admonition-icon--warning%29%3Bmask-image%3Avar%28--md-admonition-icon--warning%29%7D.md-typeset%20.warning%3E.admonition-title%3Aafter%2C.md-typeset%20.warning%3Esummary%3Aafter%7Bcolor%3A%23ff9100%7D.md-typeset%20.admonition.failure%2C.md-typeset%20details.failure%7Bborder-color%3A%23ff5252%7D.md-typeset%20.admonition.failure%3Afocus-within%2C.md-typeset%20details.failure%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%23ff52521a%7D.md-typeset%20.failure%3E.admonition-title%2C.md-typeset%20.failure%3Esummary%7Bbackground-color%3A%23ff52521a%7D.md-typeset%20.failure%3E.admonition-title%3Abefore%2C.md-typeset%20.failure%3Esummary%3Abefore%7Bbackground-color%3A%23ff5252%3B-webkit-mask-image%3Avar%28--md-admonition-icon--failure%29%3Bmask-image%3Avar%28--md-admonition-icon--failure%29%7D.md-typeset%20.failure%3E.admonition-title%3Aafter%2C.md-typeset%20.failure%3Esummary%3Aafter%7Bcolor%3A%23ff5252%7D.md-typeset%20.admonition.danger%2C.md-typeset%20details.danger%7Bborder-color%3A%23ff1744%7D.md-typeset%20.admonition.danger%3Afocus-within%2C.md-typeset%20details.danger%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%23ff17441a%7D.md-typeset%20.danger%3E.admonition-title%2C.md-typeset%20.danger%3Esummary%7Bbackground-color%3A%23ff17441a%7D.md-typeset%20.danger%3E.admonition-title%3Abefore%2C.md-typeset%20.danger%3Esummary%3Abefore%7Bbackground-color%3A%23ff1744%3B-webkit-mask-image%3Avar%28--md-admonition-icon--danger%29%3Bmask-image%3Avar%28--md-admonition-icon--danger%29%7D.md-typeset%20.danger%3E.admonition-title%3Aafter%2C.md-typeset%20.danger%3Esummary%3Aafter%7Bcolor%3A%23ff1744%7D.md-typeset%20.admonition.bug%2C.md-typeset%20details.bug%7Bborder-color%3A%23f50057%7D.md-typeset%20.admonition.bug%3Afocus-within%2C.md-typeset%20details.bug%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%23f500571a%7D.md-typeset%20.bug%3E.admonition-title%2C.md-typeset%20.bug%3Esummary%7Bbackground-color%3A%23f500571a%7D.md-typeset%20.bug%3E.admonition-title%3Abefore%2C.md-typeset%20.bug%3Esummary%3Abefore%7Bbackground-color%3A%23f50057%3B-webkit-mask-image%3Avar%28--md-admonition-icon--bug%29%3Bmask-image%3Avar%28--md-admonition-icon--bug%29%7D.md-typeset%20.bug%3E.admonition-title%3Aafter%2C.md-typeset%20.bug%3Esummary%3Aafter%7Bcolor%3A%23f50057%7D.md-typeset%20.admonition.example%2C.md-typeset%20details.example%7Bborder-color%3A%237c4dff%7D.md-typeset%20.admonition.example%3Afocus-within%2C.md-typeset%20details.example%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%237c4dff1a%7D.md-typeset%20.example%3E.admonition-title%2C.md-typeset%20.example%3Esummary%7Bbackground-color%3A%237c4dff1a%7D.md-typeset%20.example%3E.admonition-title%3Abefore%2C.md-typeset%20.example%3Esummary%3Abefore%7Bbackground-color%3A%237c4dff%3B-webkit-mask-image%3Avar%28--md-admonition-icon--example%29%3Bmask-image%3Avar%28--md-admonition-icon--example%29%7D.md-typeset%20.example%3E.admonition-title%3Aafter%2C.md-typeset%20.example%3Esummary%3Aafter%7Bcolor%3A%237c4dff%7D.md-typeset%20.admonition.quote%2C.md-typeset%20details.quote%7Bborder-color%3A%239e9e9e%7D.md-typeset%20.admonition.quote%3Afocus-within%2C.md-typeset%20details.quote%3Afocus-within%7Bbox-shadow%3A0%200%200%20.2rem%20%239e9e9e1a%7D.md-typeset%20.quote%3E.admonition-title%2C.md-typeset%20.quote%3Esummary%7Bbackground-color%3A%239e9e9e1a%7D.md-typeset%20.quote%3E.admonition-title%3Abefore%2C.md-typeset%20.quote%3Esummary%3Abefore%7Bbackground-color%3A%239e9e9e%3B-webkit-mask-image%3Avar%28--md-admonition-icon--quote%29%3Bmask-image%3Avar%28--md-admonition-icon--quote%29%7D.md-typeset%20.quote%3E.admonition-title%3Aafter%2C.md-typeset%20.quote%3Esummary%3Aafter%7Bcolor%3A%239e9e9e%7D%3Aroot%7B--md-footnotes-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M19%207v4H5.83l3.58-3.59L8%206l-6%206%206%206%201.41-1.42L5.83%2013H21V7z%22/%3E%3C/svg%3E%27%29%7D.md-typeset%20.footnote%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bfont-size%3A.64rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20.footnote%3Eol%7Bmargin-left%3A0%7D%5Bdir%3Drtl%5D%20.md-typeset%20.footnote%3Eol%7Bmargin-right%3A0%7D.md-typeset%20.footnote%3Eol%3Eli%7Btransition%3Acolor%20125ms%7D.md-typeset%20.footnote%3Eol%3Eli%3Atarget%7Bcolor%3Avar%28--md-default-fg-color%29%7D.md-typeset%20.footnote%3Eol%3Eli%3Afocus-within%20.footnote-backref%7Bopacity%3A1%3Btransform%3AtranslateX%280%29%3Btransition%3Anone%7D.md-typeset%20.footnote%3Eol%3Eli%3Ahover%20.footnote-backref%2C.md-typeset%20.footnote%3Eol%3Eli%3Atarget%20.footnote-backref%7Bopacity%3A1%3Btransform%3AtranslateX%280%29%7D.md-typeset%20.footnote%3Eol%3Eli%3E%3Afirst-child%7Bmargin-top%3A0%7D.md-typeset%20.footnote-ref%7Bfont-size%3A.75em%3Bfont-weight%3A700%7Dhtml%20.md-typeset%20.footnote-ref%7Boutline-offset%3A.1rem%7D.md-typeset%20%5Bid%5E%3D%22fnref%3A%22%5D%3Atarget%3E.footnote-ref%7Boutline%3Aauto%7D.md-typeset%20.footnote-backref%7Bcolor%3Avar%28--md-typeset-a-color%29%3Bdisplay%3Ainline-block%3Bfont-size%3A0%3Bopacity%3A0%3Btransform%3AtranslateX%28.25rem%29%3Btransition%3Acolor%20.25s%2Ctransform%20.25s%20.25s%2Copacity%20125ms%20.25s%3Bvertical-align%3Atext-bottom%7D%40media%20print%7B.md-typeset%20.footnote-backref%7Bcolor%3Avar%28--md-typeset-a-color%29%3Bopacity%3A1%3Btransform%3AtranslateX%280%29%7D%7D%5Bdir%3Drtl%5D%20.md-typeset%20.footnote-backref%7Btransform%3AtranslateX%28-.25rem%29%7D.md-typeset%20.footnote-backref%3Ahover%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20.footnote-backref%3Abefore%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ainline-block%3Bheight%3A.8rem%3B-webkit-mask-image%3Avar%28--md-footnotes-icon%29%3Bmask-image%3Avar%28--md-footnotes-icon%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bwidth%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.footnote-backref%3Abefore%20svg%7Btransform%3AscaleX%28-1%29%7D%5Bdir%3Dltr%5D%20.md-typeset%20.headerlink%7Bmargin-left%3A.5rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.headerlink%7Bmargin-right%3A.5rem%7D.md-typeset%20.headerlink%7Bcolor%3Avar%28--md-default-fg-color--lighter%29%3Bdisplay%3Ainline-block%3Bopacity%3A0%3Btransition%3Acolor%20.25s%2Copacity%20125ms%7D%40media%20print%7B.md-typeset%20.headerlink%7Bdisplay%3Anone%7D%7D.md-typeset%20.headerlink%3Afocus%2C.md-typeset%20%3Ahover%3E.headerlink%2C.md-typeset%20%3Atarget%3E.headerlink%7Bopacity%3A1%3Btransition%3Acolor%20.25s%2Copacity%20125ms%7D.md-typeset%20.headerlink%3Afocus%2C.md-typeset%20.headerlink%3Ahover%2C.md-typeset%20%3Atarget%3E.headerlink%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20%3Atarget%7B--md-scroll-margin%3A3.6rem%3B--md-scroll-offset%3A0rem%3Bscroll-margin-top%3Acalc%28var%28--md-scroll-margin%29%20-%20var%28--md-scroll-offset%29%29%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B.md-header--lifted~.md-container%20.md-typeset%20%3Atarget%7B--md-scroll-margin%3A6rem%7D%7D.md-typeset%20h1%3Atarget%2C.md-typeset%20h2%3Atarget%2C.md-typeset%20h3%3Atarget%7B--md-scroll-offset%3A0.2rem%7D.md-typeset%20h4%3Atarget%7B--md-scroll-offset%3A0.15rem%7D.md-typeset%20div.arithmatex%7Boverflow%3Aauto%7D%40media%20screen%20and%20%28max-width%3A44.984375em%29%7B.md-typeset%20div.arithmatex%7Bmargin%3A0%20-.8rem%7D.md-typeset%20div.arithmatex%3E%2A%7Bwidth%3Amin-content%7D%7D.md-typeset%20div.arithmatex%3E%2A%7Bmargin-left%3Aauto%21important%3Bmargin-right%3Aauto%21important%3Bpadding%3A0%20.8rem%3Btouch-action%3Aauto%7D.md-typeset%20div.arithmatex%3E%2A%20mjx-container%7Bmargin%3A0%21important%7D.md-typeset%20div.arithmatex%20mjx-assistive-mml%7Bheight%3A0%7D.md-typeset%20del.critic%7Bbackground-color%3Avar%28--md-typeset-del-color%29%7D.md-typeset%20del.critic%2C.md-typeset%20ins.critic%7B-webkit-box-decoration-break%3Aclone%3Bbox-decoration-break%3Aclone%7D.md-typeset%20ins.critic%7Bbackground-color%3Avar%28--md-typeset-ins-color%29%7D.md-typeset%20.critic.comment%7B-webkit-box-decoration-break%3Aclone%3Bbox-decoration-break%3Aclone%3Bcolor%3Avar%28--md-code-hl-comment-color%29%7D.md-typeset%20.critic.comment%3Abefore%7Bcontent%3A%22/%2A%20%22%7D.md-typeset%20.critic.comment%3Aafter%7Bcontent%3A%22%20%2A/%22%7D.md-typeset%20.critic.block%7Bbox-shadow%3Anone%3Bdisplay%3Ablock%3Bmargin%3A1em%200%3Boverflow%3Aauto%3Bpadding-left%3A.8rem%3Bpadding-right%3A.8rem%7D.md-typeset%20.critic.block%3E%3Afirst-child%7Bmargin-top%3A.5em%7D.md-typeset%20.critic.block%3E%3Alast-child%7Bmargin-bottom%3A.5em%7D%3Aroot%7B--md-details-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M8.59%2016.58%2013.17%2012%208.59%207.41%2010%206l6%206-6%206z%22/%3E%3C/svg%3E%27%29%7D.md-typeset%20details%7Bdisplay%3Aflow-root%3Boverflow%3Avisible%3Bpadding-top%3A0%7D.md-typeset%20details%5Bopen%5D%3Esummary%3Aafter%7Btransform%3Arotate%2890deg%29%7D.md-typeset%20details%3Anot%28%5Bopen%5D%29%7Bbox-shadow%3Anone%3Bpadding-bottom%3A0%7D.md-typeset%20details%3Anot%28%5Bopen%5D%29%3Esummary%7Bborder-radius%3A.1rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20summary%7Bpadding-right%3A1.8rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20summary%7Bpadding-left%3A1.8rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20summary%7Bborder-top-left-radius%3A.1rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20summary%2C%5Bdir%3Drtl%5D%20.md-typeset%20summary%7Bborder-top-right-radius%3A.1rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20summary%7Bborder-top-left-radius%3A.1rem%7D.md-typeset%20summary%7Bcursor%3Apointer%3Bdisplay%3Ablock%3Bmin-height%3A1rem%3Boverflow%3Ahidden%7D.md-typeset%20summary.focus-visible%7Boutline-color%3Avar%28--md-accent-fg-color%29%3Boutline-offset%3A.2rem%7D.md-typeset%20summary%3Anot%28.focus-visible%29%7B-webkit-tap-highlight-color%3Atransparent%3Boutline%3Anone%7D%5Bdir%3Dltr%5D%20.md-typeset%20summary%3Aafter%7Bright%3A.4rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20summary%3Aafter%7Bleft%3A.4rem%7D.md-typeset%20summary%3Aafter%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bheight%3A1rem%3B-webkit-mask-image%3Avar%28--md-details-icon%29%3Bmask-image%3Avar%28--md-details-icon%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bposition%3Aabsolute%3Btop%3A.625em%3Btransform%3Arotate%280deg%29%3Btransition%3Atransform%20.25s%3Bwidth%3A1rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20summary%3Aafter%7Btransform%3Arotate%28180deg%29%7D.md-typeset%20summary%3A%3Amarker%7Bdisplay%3Anone%7D.md-typeset%20summary%3A%3A-webkit-details-marker%7Bdisplay%3Anone%7D.md-typeset%20.emojione%2C.md-typeset%20.gemoji%2C.md-typeset%20.twemoji%7B--md-icon-size%3A1.125em%3Bdisplay%3Ainline-flex%3Bheight%3Avar%28--md-icon-size%29%3Bvertical-align%3Atext-top%7D.md-typeset%20.emojione%20svg%2C.md-typeset%20.gemoji%20svg%2C.md-typeset%20.twemoji%20svg%7Bfill%3Acurrentcolor%3Bmax-height%3A100%25%3Bwidth%3Avar%28--md-icon-size%29%7D.md-typeset%20.lg%2C.md-typeset%20.xl%2C.md-typeset%20.xxl%2C.md-typeset%20.xxxl%7Bvertical-align%3Atext-bottom%7D.md-typeset%20.middle%7Bvertical-align%3Amiddle%7D.md-typeset%20.lg%7B--md-icon-size%3A1.5em%7D.md-typeset%20.xl%7B--md-icon-size%3A2.25em%7D.md-typeset%20.xxl%7B--md-icon-size%3A3em%7D.md-typeset%20.xxxl%7B--md-icon-size%3A4em%7D.highlight%20.o%2C.highlight%20.ow%7Bcolor%3Avar%28--md-code-hl-operator-color%29%7D.highlight%20.p%7Bcolor%3Avar%28--md-code-hl-punctuation-color%29%7D.highlight%20.cpf%2C.highlight%20.l%2C.highlight%20.s%2C.highlight%20.s1%2C.highlight%20.s2%2C.highlight%20.sb%2C.highlight%20.sc%2C.highlight%20.si%2C.highlight%20.ss%7Bcolor%3Avar%28--md-code-hl-string-color%29%7D.highlight%20.cp%2C.highlight%20.se%2C.highlight%20.sh%2C.highlight%20.sr%2C.highlight%20.sx%7Bcolor%3Avar%28--md-code-hl-special-color%29%7D.highlight%20.il%2C.highlight%20.m%2C.highlight%20.mb%2C.highlight%20.mf%2C.highlight%20.mh%2C.highlight%20.mi%2C.highlight%20.mo%7Bcolor%3Avar%28--md-code-hl-number-color%29%7D.highlight%20.k%2C.highlight%20.kd%2C.highlight%20.kn%2C.highlight%20.kp%2C.highlight%20.kr%2C.highlight%20.kt%7Bcolor%3Avar%28--md-code-hl-keyword-color%29%7D.highlight%20.kc%2C.highlight%20.n%7Bcolor%3Avar%28--md-code-hl-name-color%29%7D.highlight%20.bp%2C.highlight%20.nb%2C.highlight%20.no%7Bcolor%3Avar%28--md-code-hl-constant-color%29%7D.highlight%20.nc%2C.highlight%20.ne%2C.highlight%20.nf%2C.highlight%20.nn%7Bcolor%3Avar%28--md-code-hl-function-color%29%7D.highlight%20.nd%2C.highlight%20.ni%2C.highlight%20.nl%2C.highlight%20.nt%7Bcolor%3Avar%28--md-code-hl-keyword-color%29%7D.highlight%20.c%2C.highlight%20.c1%2C.highlight%20.ch%2C.highlight%20.cm%2C.highlight%20.cs%2C.highlight%20.sd%7Bcolor%3Avar%28--md-code-hl-comment-color%29%7D.highlight%20.na%2C.highlight%20.nv%2C.highlight%20.vc%2C.highlight%20.vg%2C.highlight%20.vi%7Bcolor%3Avar%28--md-code-hl-variable-color%29%7D.highlight%20.ge%2C.highlight%20.gh%2C.highlight%20.go%2C.highlight%20.gp%2C.highlight%20.gr%2C.highlight%20.gs%2C.highlight%20.gt%2C.highlight%20.gu%7Bcolor%3Avar%28--md-code-hl-generic-color%29%7D.highlight%20.gd%2C.highlight%20.gi%7Bborder-radius%3A.1rem%3Bmargin%3A0%20-.125em%3Bpadding%3A0%20.125em%7D.highlight%20.gd%7Bbackground-color%3Avar%28--md-typeset-del-color%29%7D.highlight%20.gi%7Bbackground-color%3Avar%28--md-typeset-ins-color%29%7D.highlight%20.hll%7Bbackground-color%3Avar%28--md-code-hl-color--light%29%3Bbox-shadow%3A2px%200%200%200%20var%28--md-code-hl-color%29%20inset%3Bdisplay%3Ablock%3Bmargin%3A0%20-1.1764705882em%3Bpadding%3A0%201.1764705882em%7D.highlight%20span.filename%7Bbackground-color%3Avar%28--md-code-bg-color%29%3Bborder-bottom%3A.05rem%20solid%20var%28--md-default-fg-color--lightest%29%3Bborder-top-left-radius%3A.1rem%3Bborder-top-right-radius%3A.1rem%3Bdisplay%3Aflow-root%3Bfont-size%3A.85em%3Bfont-weight%3A700%3Bmargin-top%3A1em%3Bpadding%3A.6617647059em%201.1764705882em%3Bposition%3Arelative%7D.highlight%20span.filename%2Bpre%7Bmargin-top%3A0%7D.highlight%20span.filename%2Bpre%3Ecode%7Bborder-top-left-radius%3A0%3Bborder-top-right-radius%3A0%7D.highlight%20%5Bdata-linenos%5D%3Abefore%7Bbackground-color%3Avar%28--md-code-bg-color%29%3Bbox-shadow%3A-.05rem%200%20var%28--md-default-fg-color--lightest%29%20inset%3Bcolor%3Avar%28--md-default-fg-color--light%29%3Bcontent%3Aattr%28data-linenos%29%3Bfloat%3Aleft%3Bleft%3A-1.1764705882em%3Bmargin-left%3A-1.1764705882em%3Bmargin-right%3A1.1764705882em%3Bpadding-left%3A1.1764705882em%3Bposition%3Asticky%3B-webkit-user-select%3Anone%3Buser-select%3Anone%3Bz-index%3A3%7D.highlight%20code%20a%5Bid%5D%7Bposition%3Aabsolute%3Bvisibility%3Ahidden%7D.highlight%20code%5Bdata-md-copying%5D%7Bdisplay%3Ainitial%7D.highlight%20code%5Bdata-md-copying%5D%20.hll%7Bdisplay%3Acontents%7D.highlight%20code%5Bdata-md-copying%5D%20.md-annotation%7Bdisplay%3Anone%7D.highlighttable%7Bdisplay%3Aflow-root%7D.highlighttable%20tbody%2C.highlighttable%20td%7Bdisplay%3Ablock%3Bpadding%3A0%7D.highlighttable%20tr%7Bdisplay%3Aflex%7D.highlighttable%20pre%7Bmargin%3A0%7D.highlighttable%20th.filename%7Bflex-grow%3A1%3Bpadding%3A0%3Btext-align%3Aleft%7D.highlighttable%20th.filename%20span.filename%7Bmargin-top%3A0%7D.highlighttable%20.linenos%7Bbackground-color%3Avar%28--md-code-bg-color%29%3Bborder-bottom-left-radius%3A.1rem%3Bborder-top-left-radius%3A.1rem%3Bfont-size%3A.85em%3Bpadding%3A.7720588235em%200%20.7720588235em%201.1764705882em%3B-webkit-user-select%3Anone%3Buser-select%3Anone%7D.highlighttable%20.linenodiv%7Bbox-shadow%3A-.05rem%200%20var%28--md-default-fg-color--lightest%29%20inset%3Bpadding-right%3A.5882352941em%7D.highlighttable%20.linenodiv%20pre%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Btext-align%3Aright%7D.highlighttable%20.code%7Bflex%3A1%3Bmin-width%3A0%7D.linenodiv%20a%7Bcolor%3Ainherit%7D.md-typeset%20.highlighttable%7Bdirection%3Altr%3Bmargin%3A1em%200%7D.md-typeset%20.highlighttable%3Etbody%3Etr%3E.code%3Ediv%3Epre%3Ecode%7Bborder-bottom-left-radius%3A0%3Bborder-top-left-radius%3A0%7D.md-typeset%20.highlight%2B.result%7Bborder%3A.05rem%20solid%20var%28--md-code-bg-color%29%3Bborder-bottom-left-radius%3A.1rem%3Bborder-bottom-right-radius%3A.1rem%3Bborder-top-width%3A.1rem%3Bmargin-top%3A-1.125em%3Boverflow%3Avisible%3Bpadding%3A0%201em%7D.md-typeset%20.highlight%2B.result%3Aafter%7Bclear%3Aboth%3Bcontent%3A%22%22%3Bdisplay%3Ablock%7D%40media%20screen%20and%20%28max-width%3A44.984375em%29%7B.md-content__inner%3E.highlight%7Bmargin%3A1em%20-.8rem%7D.md-content__inner%3E.highlight%3E.filename%2C.md-content__inner%3E.highlight%3E.highlighttable%3Etbody%3Etr%3E.code%3Ediv%3Epre%3Ecode%2C.md-content__inner%3E.highlight%3E.highlighttable%3Etbody%3Etr%3E.filename%20span.filename%2C.md-content__inner%3E.highlight%3E.highlighttable%3Etbody%3Etr%3E.linenos%2C.md-content__inner%3E.highlight%3Epre%3Ecode%7Bborder-radius%3A0%7D.md-content__inner%3E.highlight%2B.result%7Bborder-left-width%3A0%3Bborder-radius%3A0%3Bborder-right-width%3A0%3Bmargin-left%3A-.8rem%3Bmargin-right%3A-.8rem%7D%7D.md-typeset%20.keys%20kbd%3Aafter%2C.md-typeset%20.keys%20kbd%3Abefore%7B-moz-osx-font-smoothing%3Ainitial%3B-webkit-font-smoothing%3Ainitial%3Bcolor%3Ainherit%3Bmargin%3A0%3Bposition%3Arelative%7D.md-typeset%20.keys%20span%7Bcolor%3Avar%28--md-default-fg-color--light%29%3Bpadding%3A0%20.2em%7D.md-typeset%20.keys%20.key-alt%3Abefore%2C.md-typeset%20.keys%20.key-left-alt%3Abefore%2C.md-typeset%20.keys%20.key-right-alt%3Abefore%7Bcontent%3A%22%E2%8E%87%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-command%3Abefore%2C.md-typeset%20.keys%20.key-left-command%3Abefore%2C.md-typeset%20.keys%20.key-right-command%3Abefore%7Bcontent%3A%22%E2%8C%98%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-control%3Abefore%2C.md-typeset%20.keys%20.key-left-control%3Abefore%2C.md-typeset%20.keys%20.key-right-control%3Abefore%7Bcontent%3A%22%E2%8C%83%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-left-meta%3Abefore%2C.md-typeset%20.keys%20.key-meta%3Abefore%2C.md-typeset%20.keys%20.key-right-meta%3Abefore%7Bcontent%3A%22%E2%97%86%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-left-option%3Abefore%2C.md-typeset%20.keys%20.key-option%3Abefore%2C.md-typeset%20.keys%20.key-right-option%3Abefore%7Bcontent%3A%22%E2%8C%A5%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-left-shift%3Abefore%2C.md-typeset%20.keys%20.key-right-shift%3Abefore%2C.md-typeset%20.keys%20.key-shift%3Abefore%7Bcontent%3A%22%E2%87%A7%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-left-super%3Abefore%2C.md-typeset%20.keys%20.key-right-super%3Abefore%2C.md-typeset%20.keys%20.key-super%3Abefore%7Bcontent%3A%22%E2%9D%96%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-left-windows%3Abefore%2C.md-typeset%20.keys%20.key-right-windows%3Abefore%2C.md-typeset%20.keys%20.key-windows%3Abefore%7Bcontent%3A%22%E2%8A%9E%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-arrow-down%3Abefore%7Bcontent%3A%22%E2%86%93%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-arrow-left%3Abefore%7Bcontent%3A%22%E2%86%90%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-arrow-right%3Abefore%7Bcontent%3A%22%E2%86%92%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-arrow-up%3Abefore%7Bcontent%3A%22%E2%86%91%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-backspace%3Abefore%7Bcontent%3A%22%E2%8C%AB%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-backtab%3Abefore%7Bcontent%3A%22%E2%87%A4%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-caps-lock%3Abefore%7Bcontent%3A%22%E2%87%AA%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-clear%3Abefore%7Bcontent%3A%22%E2%8C%A7%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-context-menu%3Abefore%7Bcontent%3A%22%E2%98%B0%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-delete%3Abefore%7Bcontent%3A%22%E2%8C%A6%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-eject%3Abefore%7Bcontent%3A%22%E2%8F%8F%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-end%3Abefore%7Bcontent%3A%22%E2%A4%93%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-escape%3Abefore%7Bcontent%3A%22%E2%8E%8B%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-home%3Abefore%7Bcontent%3A%22%E2%A4%92%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-insert%3Abefore%7Bcontent%3A%22%E2%8E%80%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-page-down%3Abefore%7Bcontent%3A%22%E2%87%9F%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-page-up%3Abefore%7Bcontent%3A%22%E2%87%9E%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-print-screen%3Abefore%7Bcontent%3A%22%E2%8E%99%22%3Bpadding-right%3A.4em%7D.md-typeset%20.keys%20.key-tab%3Aafter%7Bcontent%3A%22%E2%87%A5%22%3Bpadding-left%3A.4em%7D.md-typeset%20.keys%20.key-num-enter%3Aafter%7Bcontent%3A%22%E2%8C%A4%22%3Bpadding-left%3A.4em%7D.md-typeset%20.keys%20.key-enter%3Aafter%7Bcontent%3A%22%E2%8F%8E%22%3Bpadding-left%3A.4em%7D%3Aroot%7B--md-tabbed-icon--prev%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M15.41%2016.58%2010.83%2012l4.58-4.59L14%206l-6%206%206%206z%22/%3E%3C/svg%3E%27%29%3B--md-tabbed-icon--next%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M8.59%2016.58%2013.17%2012%208.59%207.41%2010%206l6%206-6%206z%22/%3E%3C/svg%3E%27%29%7D.md-typeset%20.tabbed-set%7Bborder-radius%3A.1rem%3Bdisplay%3Aflex%3Bflex-flow%3Acolumn%20wrap%3Bmargin%3A1em%200%3Bposition%3Arelative%7D.md-typeset%20.tabbed-set%3Einput%7Bheight%3A0%3Bopacity%3A0%3Bposition%3Aabsolute%3Bwidth%3A0%7D.md-typeset%20.tabbed-set%3Einput%3Atarget%7B--md-scroll-offset%3A0.625em%7D.md-typeset%20.tabbed-set%3Einput.focus-visible~.tabbed-labels%3Abefore%7Bbackground-color%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20.tabbed-labels%7B-ms-overflow-style%3Anone%3Bbox-shadow%3A0%20-.05rem%20var%28--md-default-fg-color--lightest%29%20inset%3Bdisplay%3Aflex%3Bmax-width%3A100%25%3Boverflow%3Aauto%3Bscrollbar-width%3Anone%7D%40media%20print%7B.md-typeset%20.tabbed-labels%7Bdisplay%3Acontents%7D%7D%40media%20screen%7B.js%20.md-typeset%20.tabbed-labels%7Bposition%3Arelative%7D.js%20.md-typeset%20.tabbed-labels%3Abefore%7Bbackground%3Avar%28--md-default-fg-color%29%3Bbottom%3A0%3Bcontent%3A%22%22%3Bdisplay%3Ablock%3Bheight%3A2px%3Bleft%3A0%3Bposition%3Aabsolute%3Btransform%3AtranslateX%28var%28--md-indicator-x%29%29%3Btransition%3Awidth%20225ms%2Cbackground-color%20.25s%2Ctransform%20.25s%3Btransition-timing-function%3Acubic-bezier%28.4%2C0%2C.2%2C1%29%3Bwidth%3Avar%28--md-indicator-width%29%7D%7D.md-typeset%20.tabbed-labels%3A%3A-webkit-scrollbar%7Bdisplay%3Anone%7D.md-typeset%20.tabbed-labels%3Elabel%7Bborder-bottom%3A.1rem%20solid%20%230000%3Bborder-radius%3A.1rem%20.1rem%200%200%3Bcolor%3Avar%28--md-default-fg-color--light%29%3Bcursor%3Apointer%3Bflex-shrink%3A0%3Bfont-size%3A.64rem%3Bfont-weight%3A700%3Bpadding%3A.78125em%201.25em%20.625em%3Bscroll-margin-inline-start%3A1rem%3Btransition%3Abackground-color%20.25s%2Ccolor%20.25s%3Bwhite-space%3Anowrap%3Bwidth%3Aauto%7D%40media%20print%7B.md-typeset%20.tabbed-labels%3Elabel%3Afirst-child%7Border%3A1%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%282%29%7Border%3A2%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%283%29%7Border%3A3%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%284%29%7Border%3A4%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%285%29%7Border%3A5%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%286%29%7Border%3A6%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%287%29%7Border%3A7%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%288%29%7Border%3A8%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%289%29%7Border%3A9%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2810%29%7Border%3A10%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2811%29%7Border%3A11%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2812%29%7Border%3A12%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2813%29%7Border%3A13%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2814%29%7Border%3A14%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2815%29%7Border%3A15%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2816%29%7Border%3A16%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2817%29%7Border%3A17%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2818%29%7Border%3A18%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2819%29%7Border%3A19%7D.md-typeset%20.tabbed-labels%3Elabel%3Anth-child%2820%29%7Border%3A20%7D%7D.md-typeset%20.tabbed-labels%3Elabel%3Ahover%7Bcolor%3Avar%28--md-default-fg-color%29%7D.md-typeset%20.tabbed-labels%3Elabel%3E%5Bhref%5D%3Afirst-child%7Bcolor%3Ainherit%7D.md-typeset%20.tabbed-labels--linked%3Elabel%7Bpadding%3A0%7D.md-typeset%20.tabbed-labels--linked%3Elabel%3Ea%7Bdisplay%3Ablock%3Bpadding%3A.78125em%201.25em%20.625em%7D.md-typeset%20.tabbed-content%7Bwidth%3A100%25%7D%40media%20print%7B.md-typeset%20.tabbed-content%7Bdisplay%3Acontents%7D%7D.md-typeset%20.tabbed-block%7Bdisplay%3Anone%7D%40media%20print%7B.md-typeset%20.tabbed-block%7Bdisplay%3Ablock%7D.md-typeset%20.tabbed-block%3Afirst-child%7Border%3A1%7D.md-typeset%20.tabbed-block%3Anth-child%282%29%7Border%3A2%7D.md-typeset%20.tabbed-block%3Anth-child%283%29%7Border%3A3%7D.md-typeset%20.tabbed-block%3Anth-child%284%29%7Border%3A4%7D.md-typeset%20.tabbed-block%3Anth-child%285%29%7Border%3A5%7D.md-typeset%20.tabbed-block%3Anth-child%286%29%7Border%3A6%7D.md-typeset%20.tabbed-block%3Anth-child%287%29%7Border%3A7%7D.md-typeset%20.tabbed-block%3Anth-child%288%29%7Border%3A8%7D.md-typeset%20.tabbed-block%3Anth-child%289%29%7Border%3A9%7D.md-typeset%20.tabbed-block%3Anth-child%2810%29%7Border%3A10%7D.md-typeset%20.tabbed-block%3Anth-child%2811%29%7Border%3A11%7D.md-typeset%20.tabbed-block%3Anth-child%2812%29%7Border%3A12%7D.md-typeset%20.tabbed-block%3Anth-child%2813%29%7Border%3A13%7D.md-typeset%20.tabbed-block%3Anth-child%2814%29%7Border%3A14%7D.md-typeset%20.tabbed-block%3Anth-child%2815%29%7Border%3A15%7D.md-typeset%20.tabbed-block%3Anth-child%2816%29%7Border%3A16%7D.md-typeset%20.tabbed-block%3Anth-child%2817%29%7Border%3A17%7D.md-typeset%20.tabbed-block%3Anth-child%2818%29%7Border%3A18%7D.md-typeset%20.tabbed-block%3Anth-child%2819%29%7Border%3A19%7D.md-typeset%20.tabbed-block%3Anth-child%2820%29%7Border%3A20%7D%7D.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%3Epre%2C.md-typeset%20.tabbed-block%3Epre%3Afirst-child%7Bmargin%3A0%7D.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%3Epre%3Ecode%2C.md-typeset%20.tabbed-block%3Epre%3Afirst-child%3Ecode%7Bborder-top-left-radius%3A0%3Bborder-top-right-radius%3A0%7D.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%3E.filename%7Bborder-top-left-radius%3A0%3Bborder-top-right-radius%3A0%3Bmargin%3A0%7D.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%3E.highlighttable%7Bmargin%3A0%7D.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%3E.highlighttable%3Etbody%3Etr%3E.filename%20span.filename%2C.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%3E.highlighttable%3Etbody%3Etr%3E.linenos%7Bborder-top-left-radius%3A0%3Bborder-top-right-radius%3A0%3Bmargin%3A0%7D.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%3E.highlighttable%3Etbody%3Etr%3E.code%3Ediv%3Epre%3Ecode%7Bborder-top-left-radius%3A0%3Bborder-top-right-radius%3A0%7D.md-typeset%20.tabbed-block%3E.highlight%3Afirst-child%2B.result%7Bmargin-top%3A-.125em%7D.md-typeset%20.tabbed-block%3E.tabbed-set%7Bmargin%3A0%7D.md-typeset%20.tabbed-button%7Balign-self%3Acenter%3Bborder-radius%3A100%25%3Bcolor%3Avar%28--md-default-fg-color--light%29%3Bcursor%3Apointer%3Bdisplay%3Ablock%3Bheight%3A.9rem%3Bmargin-top%3A.1rem%3Bpointer-events%3Aauto%3Btransition%3Abackground-color%20.25s%3Bwidth%3A.9rem%7D.md-typeset%20.tabbed-button%3Ahover%7Bbackground-color%3Avar%28--md-accent-fg-color--transparent%29%3Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20.tabbed-button%3Aafter%7Bbackground-color%3Acurrentcolor%3Bcontent%3A%22%22%3Bdisplay%3Ablock%3Bheight%3A100%25%3B-webkit-mask-image%3Avar%28--md-tabbed-icon--prev%29%3Bmask-image%3Avar%28--md-tabbed-icon--prev%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Btransition%3Abackground-color%20.25s%2Ctransform%20.25s%3Bwidth%3A100%25%7D.md-typeset%20.tabbed-control%7Bbackground%3Alinear-gradient%28to%20right%2Cvar%28--md-default-bg-color%29%2060%25%2C%230000%29%3Bdisplay%3Aflex%3Bheight%3A1.9rem%3Bjustify-content%3Astart%3Bpointer-events%3Anone%3Bposition%3Aabsolute%3Btransition%3Aopacity%20125ms%3Bwidth%3A1.2rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.tabbed-control%7Btransform%3Arotate%28180deg%29%7D.md-typeset%20.tabbed-control%5Bhidden%5D%7Bopacity%3A0%7D.md-typeset%20.tabbed-control--next%7Bbackground%3Alinear-gradient%28to%20left%2Cvar%28--md-default-bg-color%29%2060%25%2C%230000%29%3Bjustify-content%3Aend%3Bright%3A0%7D.md-typeset%20.tabbed-control--next%20.tabbed-button%3Aafter%7B-webkit-mask-image%3Avar%28--md-tabbed-icon--next%29%3Bmask-image%3Avar%28--md-tabbed-icon--next%29%7D%40media%20screen%20and%20%28max-width%3A44.984375em%29%7B%5Bdir%3Dltr%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels%7Bpadding-left%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels%7Bpadding-right%3A.8rem%7D.md-content__inner%3E.tabbed-set%20.tabbed-labels%7Bmargin%3A0%20-.8rem%3Bmax-width%3A100vw%3Bscroll-padding-inline-start%3A.8rem%7D%5Bdir%3Dltr%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels%3Aafter%7Bpadding-right%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels%3Aafter%7Bpadding-left%3A.8rem%7D.md-content__inner%3E.tabbed-set%20.tabbed-labels%3Aafter%7Bcontent%3A%22%22%7D%5Bdir%3Dltr%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--prev%7Bpadding-left%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--prev%7Bpadding-right%3A.8rem%7D%5Bdir%3Dltr%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--prev%7Bmargin-left%3A-.8rem%7D%5Bdir%3Drtl%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--prev%7Bmargin-right%3A-.8rem%7D.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--prev%7Bwidth%3A2rem%7D%5Bdir%3Dltr%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--next%7Bpadding-right%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--next%7Bpadding-left%3A.8rem%7D%5Bdir%3Dltr%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--next%7Bmargin-right%3A-.8rem%7D%5Bdir%3Drtl%5D%20.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--next%7Bmargin-left%3A-.8rem%7D.md-content__inner%3E.tabbed-set%20.tabbed-labels~.tabbed-control--next%7Bwidth%3A2rem%7D%7D%40media%20screen%7B.md-typeset%20.tabbed-set%3Einput%3Afirst-child%3Achecked~.tabbed-labels%3E%3Afirst-child%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2810%29%3Achecked~.tabbed-labels%3E%3Anth-child%2810%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2811%29%3Achecked~.tabbed-labels%3E%3Anth-child%2811%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2812%29%3Achecked~.tabbed-labels%3E%3Anth-child%2812%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2813%29%3Achecked~.tabbed-labels%3E%3Anth-child%2813%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2814%29%3Achecked~.tabbed-labels%3E%3Anth-child%2814%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2815%29%3Achecked~.tabbed-labels%3E%3Anth-child%2815%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2816%29%3Achecked~.tabbed-labels%3E%3Anth-child%2816%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2817%29%3Achecked~.tabbed-labels%3E%3Anth-child%2817%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2818%29%3Achecked~.tabbed-labels%3E%3Anth-child%2818%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2819%29%3Achecked~.tabbed-labels%3E%3Anth-child%2819%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%282%29%3Achecked~.tabbed-labels%3E%3Anth-child%282%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2820%29%3Achecked~.tabbed-labels%3E%3Anth-child%2820%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%283%29%3Achecked~.tabbed-labels%3E%3Anth-child%283%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%284%29%3Achecked~.tabbed-labels%3E%3Anth-child%284%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%285%29%3Achecked~.tabbed-labels%3E%3Anth-child%285%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%286%29%3Achecked~.tabbed-labels%3E%3Anth-child%286%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%287%29%3Achecked~.tabbed-labels%3E%3Anth-child%287%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%288%29%3Achecked~.tabbed-labels%3E%3Anth-child%288%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%289%29%3Achecked~.tabbed-labels%3E%3Anth-child%289%29%7Bcolor%3Avar%28--md-default-fg-color%29%7D.md-typeset%20.no-js%20.tabbed-set%3Einput%3Afirst-child%3Achecked~.tabbed-labels%3E%3Afirst-child%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2810%29%3Achecked~.tabbed-labels%3E%3Anth-child%2810%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2811%29%3Achecked~.tabbed-labels%3E%3Anth-child%2811%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2812%29%3Achecked~.tabbed-labels%3E%3Anth-child%2812%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2813%29%3Achecked~.tabbed-labels%3E%3Anth-child%2813%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2814%29%3Achecked~.tabbed-labels%3E%3Anth-child%2814%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2815%29%3Achecked~.tabbed-labels%3E%3Anth-child%2815%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2816%29%3Achecked~.tabbed-labels%3E%3Anth-child%2816%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2817%29%3Achecked~.tabbed-labels%3E%3Anth-child%2817%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2818%29%3Achecked~.tabbed-labels%3E%3Anth-child%2818%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2819%29%3Achecked~.tabbed-labels%3E%3Anth-child%2819%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%282%29%3Achecked~.tabbed-labels%3E%3Anth-child%282%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%2820%29%3Achecked~.tabbed-labels%3E%3Anth-child%2820%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%283%29%3Achecked~.tabbed-labels%3E%3Anth-child%283%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%284%29%3Achecked~.tabbed-labels%3E%3Anth-child%284%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%285%29%3Achecked~.tabbed-labels%3E%3Anth-child%285%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%286%29%3Achecked~.tabbed-labels%3E%3Anth-child%286%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%287%29%3Achecked~.tabbed-labels%3E%3Anth-child%287%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%288%29%3Achecked~.tabbed-labels%3E%3Anth-child%288%29%2C.md-typeset%20.no-js%20.tabbed-set%3Einput%3Anth-child%289%29%3Achecked~.tabbed-labels%3E%3Anth-child%289%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Afirst-child%3Achecked~.tabbed-labels%3E%3Afirst-child%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2810%29%3Achecked~.tabbed-labels%3E%3Anth-child%2810%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2811%29%3Achecked~.tabbed-labels%3E%3Anth-child%2811%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2812%29%3Achecked~.tabbed-labels%3E%3Anth-child%2812%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2813%29%3Achecked~.tabbed-labels%3E%3Anth-child%2813%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2814%29%3Achecked~.tabbed-labels%3E%3Anth-child%2814%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2815%29%3Achecked~.tabbed-labels%3E%3Anth-child%2815%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2816%29%3Achecked~.tabbed-labels%3E%3Anth-child%2816%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2817%29%3Achecked~.tabbed-labels%3E%3Anth-child%2817%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2818%29%3Achecked~.tabbed-labels%3E%3Anth-child%2818%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2819%29%3Achecked~.tabbed-labels%3E%3Anth-child%2819%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%282%29%3Achecked~.tabbed-labels%3E%3Anth-child%282%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%2820%29%3Achecked~.tabbed-labels%3E%3Anth-child%2820%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%283%29%3Achecked~.tabbed-labels%3E%3Anth-child%283%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%284%29%3Achecked~.tabbed-labels%3E%3Anth-child%284%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%285%29%3Achecked~.tabbed-labels%3E%3Anth-child%285%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%286%29%3Achecked~.tabbed-labels%3E%3Anth-child%286%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%287%29%3Achecked~.tabbed-labels%3E%3Anth-child%287%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%288%29%3Achecked~.tabbed-labels%3E%3Anth-child%288%29%2C.no-js%20.md-typeset%20.tabbed-set%3Einput%3Anth-child%289%29%3Achecked~.tabbed-labels%3E%3Anth-child%289%29%7Bborder-color%3Avar%28--md-default-fg-color%29%7D%7D.md-typeset%20.tabbed-set%3Einput%3Afirst-child.focus-visible~.tabbed-labels%3E%3Afirst-child%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2810%29.focus-visible~.tabbed-labels%3E%3Anth-child%2810%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2811%29.focus-visible~.tabbed-labels%3E%3Anth-child%2811%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2812%29.focus-visible~.tabbed-labels%3E%3Anth-child%2812%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2813%29.focus-visible~.tabbed-labels%3E%3Anth-child%2813%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2814%29.focus-visible~.tabbed-labels%3E%3Anth-child%2814%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2815%29.focus-visible~.tabbed-labels%3E%3Anth-child%2815%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2816%29.focus-visible~.tabbed-labels%3E%3Anth-child%2816%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2817%29.focus-visible~.tabbed-labels%3E%3Anth-child%2817%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2818%29.focus-visible~.tabbed-labels%3E%3Anth-child%2818%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2819%29.focus-visible~.tabbed-labels%3E%3Anth-child%2819%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%282%29.focus-visible~.tabbed-labels%3E%3Anth-child%282%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2820%29.focus-visible~.tabbed-labels%3E%3Anth-child%2820%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%283%29.focus-visible~.tabbed-labels%3E%3Anth-child%283%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%284%29.focus-visible~.tabbed-labels%3E%3Anth-child%284%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%285%29.focus-visible~.tabbed-labels%3E%3Anth-child%285%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%286%29.focus-visible~.tabbed-labels%3E%3Anth-child%286%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%287%29.focus-visible~.tabbed-labels%3E%3Anth-child%287%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%288%29.focus-visible~.tabbed-labels%3E%3Anth-child%288%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%289%29.focus-visible~.tabbed-labels%3E%3Anth-child%289%29%7Bcolor%3Avar%28--md-accent-fg-color%29%7D.md-typeset%20.tabbed-set%3Einput%3Afirst-child%3Achecked~.tabbed-content%3E%3Afirst-child%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2810%29%3Achecked~.tabbed-content%3E%3Anth-child%2810%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2811%29%3Achecked~.tabbed-content%3E%3Anth-child%2811%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2812%29%3Achecked~.tabbed-content%3E%3Anth-child%2812%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2813%29%3Achecked~.tabbed-content%3E%3Anth-child%2813%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2814%29%3Achecked~.tabbed-content%3E%3Anth-child%2814%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2815%29%3Achecked~.tabbed-content%3E%3Anth-child%2815%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2816%29%3Achecked~.tabbed-content%3E%3Anth-child%2816%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2817%29%3Achecked~.tabbed-content%3E%3Anth-child%2817%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2818%29%3Achecked~.tabbed-content%3E%3Anth-child%2818%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2819%29%3Achecked~.tabbed-content%3E%3Anth-child%2819%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%282%29%3Achecked~.tabbed-content%3E%3Anth-child%282%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%2820%29%3Achecked~.tabbed-content%3E%3Anth-child%2820%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%283%29%3Achecked~.tabbed-content%3E%3Anth-child%283%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%284%29%3Achecked~.tabbed-content%3E%3Anth-child%284%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%285%29%3Achecked~.tabbed-content%3E%3Anth-child%285%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%286%29%3Achecked~.tabbed-content%3E%3Anth-child%286%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%287%29%3Achecked~.tabbed-content%3E%3Anth-child%287%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%288%29%3Achecked~.tabbed-content%3E%3Anth-child%288%29%2C.md-typeset%20.tabbed-set%3Einput%3Anth-child%289%29%3Achecked~.tabbed-content%3E%3Anth-child%289%29%7Bdisplay%3Ablock%7D%3Aroot%7B--md-tasklist-icon%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M1%2012C1%205.925%205.925%201%2012%201s11%204.925%2011%2011-4.925%2011-11%2011S1%2018.075%201%2012m16.28-2.72a.75.75%200%200%200-.018-1.042.75.75%200%200%200-1.042-.018l-5.97%205.97-2.47-2.47a.75.75%200%200%200-1.042.018.75.75%200%200%200-.018%201.042l3%203a.75.75%200%200%200%201.06%200Z%22/%3E%3C/svg%3E%27%29%3B--md-tasklist-icon--checked%3Aurl%28%27data%3Aimage/svg%2Bxml%3Bcharset%3Dutf-8%2C%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20viewBox%3D%220%200%2024%2024%22%3E%3Cpath%20d%3D%22M1%2012C1%205.925%205.925%201%2012%201s11%204.925%2011%2011-4.925%2011-11%2011S1%2018.075%201%2012m16.28-2.72a.75.75%200%200%200-.018-1.042.75.75%200%200%200-1.042-.018l-5.97%205.97-2.47-2.47a.75.75%200%200%200-1.042.018.75.75%200%200%200-.018%201.042l3%203a.75.75%200%200%200%201.06%200Z%22/%3E%3C/svg%3E%27%29%7D.md-typeset%20.task-list-item%7Blist-style-type%3Anone%3Bposition%3Arelative%7D%5Bdir%3Dltr%5D%20.md-typeset%20.task-list-item%20%5Btype%3Dcheckbox%5D%7Bleft%3A-2em%7D%5Bdir%3Drtl%5D%20.md-typeset%20.task-list-item%20%5Btype%3Dcheckbox%5D%7Bright%3A-2em%7D.md-typeset%20.task-list-item%20%5Btype%3Dcheckbox%5D%7Bposition%3Aabsolute%3Btop%3A.45em%7D.md-typeset%20.task-list-control%20%5Btype%3Dcheckbox%5D%7Bopacity%3A0%3Bz-index%3A-1%7D%5Bdir%3Dltr%5D%20.md-typeset%20.task-list-indicator%3Abefore%7Bleft%3A-1.5em%7D%5Bdir%3Drtl%5D%20.md-typeset%20.task-list-indicator%3Abefore%7Bright%3A-1.5em%7D.md-typeset%20.task-list-indicator%3Abefore%7Bbackground-color%3Avar%28--md-default-fg-color--lightest%29%3Bcontent%3A%22%22%3Bheight%3A1.25em%3B-webkit-mask-image%3Avar%28--md-tasklist-icon%29%3Bmask-image%3Avar%28--md-tasklist-icon%29%3B-webkit-mask-position%3Acenter%3Bmask-position%3Acenter%3B-webkit-mask-repeat%3Ano-repeat%3Bmask-repeat%3Ano-repeat%3B-webkit-mask-size%3Acontain%3Bmask-size%3Acontain%3Bposition%3Aabsolute%3Btop%3A.15em%3Bwidth%3A1.25em%7D.md-typeset%20%5Btype%3Dcheckbox%5D%3Achecked%2B.task-list-indicator%3Abefore%7Bbackground-color%3A%2300e676%3B-webkit-mask-image%3Avar%28--md-tasklist-icon--checked%29%3Bmask-image%3Avar%28--md-tasklist-icon--checked%29%7D%40media%20print%7B.giscus%2C%5Bid%3D__comments%5D%7Bdisplay%3Anone%7D%7D%3Aroot%3E%2A%7B--md-mermaid-font-family%3Avar%28--md-text-font-family%29%2Csans-serif%3B--md-mermaid-edge-color%3Avar%28--md-code-fg-color%29%3B--md-mermaid-node-bg-color%3Avar%28--md-accent-fg-color--transparent%29%3B--md-mermaid-node-fg-color%3Avar%28--md-accent-fg-color%29%3B--md-mermaid-label-bg-color%3Avar%28--md-default-bg-color%29%3B--md-mermaid-label-fg-color%3Avar%28--md-code-fg-color%29%3B--md-mermaid-sequence-actor-bg-color%3Avar%28--md-mermaid-label-bg-color%29%3B--md-mermaid-sequence-actor-fg-color%3Avar%28--md-mermaid-label-fg-color%29%3B--md-mermaid-sequence-actor-border-color%3Avar%28--md-mermaid-node-fg-color%29%3B--md-mermaid-sequence-actor-line-color%3Avar%28--md-default-fg-color--lighter%29%3B--md-mermaid-sequence-actorman-bg-color%3Avar%28--md-mermaid-label-bg-color%29%3B--md-mermaid-sequence-actorman-line-color%3Avar%28--md-mermaid-node-fg-color%29%3B--md-mermaid-sequence-box-bg-color%3Avar%28--md-mermaid-node-bg-color%29%3B--md-mermaid-sequence-box-fg-color%3Avar%28--md-mermaid-edge-color%29%3B--md-mermaid-sequence-label-bg-color%3Avar%28--md-mermaid-node-bg-color%29%3B--md-mermaid-sequence-label-fg-color%3Avar%28--md-mermaid-node-fg-color%29%3B--md-mermaid-sequence-loop-bg-color%3Avar%28--md-mermaid-node-bg-color%29%3B--md-mermaid-sequence-loop-fg-color%3Avar%28--md-mermaid-edge-color%29%3B--md-mermaid-sequence-loop-border-color%3Avar%28--md-mermaid-node-fg-color%29%3B--md-mermaid-sequence-message-fg-color%3Avar%28--md-mermaid-edge-color%29%3B--md-mermaid-sequence-message-line-color%3Avar%28--md-mermaid-edge-color%29%3B--md-mermaid-sequence-note-bg-color%3Avar%28--md-mermaid-label-bg-color%29%3B--md-mermaid-sequence-note-fg-color%3Avar%28--md-mermaid-edge-color%29%3B--md-mermaid-sequence-note-border-color%3Avar%28--md-mermaid-label-fg-color%29%3B--md-mermaid-sequence-number-bg-color%3Avar%28--md-mermaid-node-fg-color%29%3B--md-mermaid-sequence-number-fg-color%3Avar%28--md-accent-bg-color%29%7D.mermaid%7Bline-height%3Anormal%3Bmargin%3A1em%200%7D.md-typeset%20.grid%7Bgrid-gap%3A.4rem%3Bdisplay%3Agrid%3Bgrid-template-columns%3Arepeat%28auto-fit%2Cminmax%28min%28100%25%2C16rem%29%2C1fr%29%29%3Bmargin%3A1em%200%7D.md-typeset%20.grid.cards%3Eol%2C.md-typeset%20.grid.cards%3Eul%7Bdisplay%3Acontents%7D.md-typeset%20.grid.cards%3Eol%3Eli%2C.md-typeset%20.grid.cards%3Eul%3Eli%2C.md-typeset%20.grid%3E.card%7Bborder%3A.05rem%20solid%20var%28--md-default-fg-color--lightest%29%3Bborder-radius%3A.1rem%3Bdisplay%3Ablock%3Bmargin%3A0%3Bpadding%3A.8rem%3Btransition%3Aborder%20.25s%2Cbox-shadow%20.25s%7D.md-typeset%20.grid.cards%3Eol%3Eli%3Afocus-within%2C.md-typeset%20.grid.cards%3Eol%3Eli%3Ahover%2C.md-typeset%20.grid.cards%3Eul%3Eli%3Afocus-within%2C.md-typeset%20.grid.cards%3Eul%3Eli%3Ahover%2C.md-typeset%20.grid%3E.card%3Afocus-within%2C.md-typeset%20.grid%3E.card%3Ahover%7Bborder-color%3A%230000%3Bbox-shadow%3Avar%28--md-shadow-z2%29%7D.md-typeset%20.grid.cards%3Eol%3Eli%3Ehr%2C.md-typeset%20.grid.cards%3Eul%3Eli%3Ehr%2C.md-typeset%20.grid%3E.card%3Ehr%7Bmargin-bottom%3A1em%3Bmargin-top%3A1em%7D.md-typeset%20.grid.cards%3Eol%3Eli%3E%3Afirst-child%2C.md-typeset%20.grid.cards%3Eul%3Eli%3E%3Afirst-child%2C.md-typeset%20.grid%3E.card%3E%3Afirst-child%7Bmargin-top%3A0%7D.md-typeset%20.grid.cards%3Eol%3Eli%3E%3Alast-child%2C.md-typeset%20.grid.cards%3Eul%3Eli%3E%3Alast-child%2C.md-typeset%20.grid%3E.card%3E%3Alast-child%7Bmargin-bottom%3A0%7D.md-typeset%20.grid%3E%2A%2C.md-typeset%20.grid%3E.admonition%2C.md-typeset%20.grid%3E.highlight%3E%2A%2C.md-typeset%20.grid%3E.highlighttable%2C.md-typeset%20.grid%3E.md-typeset%20details%2C.md-typeset%20.grid%3Edetails%2C.md-typeset%20.grid%3Epre%7Bmargin-bottom%3A0%3Bmargin-top%3A0%7D.md-typeset%20.grid%3E.highlight%3Epre%3Aonly-child%2C.md-typeset%20.grid%3E.highlight%3Epre%3Ecode%2C.md-typeset%20.grid%3E.highlighttable%2C.md-typeset%20.grid%3E.highlighttable%3Etbody%2C.md-typeset%20.grid%3E.highlighttable%3Etbody%3Etr%2C.md-typeset%20.grid%3E.highlighttable%3Etbody%3Etr%3E.code%2C.md-typeset%20.grid%3E.highlighttable%3Etbody%3Etr%3E.code%3E.highlight%2C.md-typeset%20.grid%3E.highlighttable%3Etbody%3Etr%3E.code%3E.highlight%3Epre%2C.md-typeset%20.grid%3E.highlighttable%3Etbody%3Etr%3E.code%3E.highlight%3Epre%3Ecode%7Bheight%3A100%25%7D.md-typeset%20.grid%3E.tabbed-set%7Bmargin-bottom%3A0%3Bmargin-top%3A0%7D%40media%20screen%20and%20%28min-width%3A45em%29%7B%5Bdir%3Dltr%5D%20.md-typeset%20.inline%7Bfloat%3Aleft%7D%5Bdir%3Drtl%5D%20.md-typeset%20.inline%7Bfloat%3Aright%7D%5Bdir%3Dltr%5D%20.md-typeset%20.inline%7Bmargin-right%3A.8rem%7D%5Bdir%3Drtl%5D%20.md-typeset%20.inline%7Bmargin-left%3A.8rem%7D.md-typeset%20.inline%7Bmargin-bottom%3A.8rem%3Bmargin-top%3A0%3Bwidth%3A11.7rem%7D%5Bdir%3Dltr%5D%20.md-typeset%20.inline.end%7Bfloat%3Aright%7D%5Bdir%3Drtl%5D%20.md-typeset%20.inline.end%7Bfloat%3Aleft%7D%5Bdir%3Dltr%5D%20.md-typeset%20.inline.end%7Bmargin-left%3A.8rem%3Bmargin-right%3A0%7D%5Bdir%3Drtl%5D%20.md-typeset%20.inline.end%7Bmargin-left%3A0%3Bmargin-right%3A.8rem%7D%7D" rel="stylesheet"/><!--URL:../assets/stylesheets/main.0253249f.min.css-->
|
||
<link href="data:text/css,%40media%20screen%7B%5Bdata-md-color-scheme%3Dslate%5D%7B--md-default-fg-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C90%25%2C0.82%29%3B--md-default-fg-color--light%3Ahsla%28var%28--md-hue%29%2C15%25%2C90%25%2C0.56%29%3B--md-default-fg-color--lighter%3Ahsla%28var%28--md-hue%29%2C15%25%2C90%25%2C0.32%29%3B--md-default-fg-color--lightest%3Ahsla%28var%28--md-hue%29%2C15%25%2C90%25%2C0.12%29%3B--md-default-bg-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C14%25%2C1%29%3B--md-default-bg-color--light%3Ahsla%28var%28--md-hue%29%2C15%25%2C14%25%2C0.54%29%3B--md-default-bg-color--lighter%3Ahsla%28var%28--md-hue%29%2C15%25%2C14%25%2C0.26%29%3B--md-default-bg-color--lightest%3Ahsla%28var%28--md-hue%29%2C15%25%2C14%25%2C0.07%29%3B--md-code-fg-color%3Ahsla%28var%28--md-hue%29%2C18%25%2C86%25%2C0.82%29%3B--md-code-bg-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C18%25%2C1%29%3B--md-code-hl-color%3A%232977ff%3B--md-code-hl-color--light%3A%232977ff1a%3B--md-code-hl-number-color%3A%23e6695b%3B--md-code-hl-special-color%3A%23f06090%3B--md-code-hl-function-color%3A%23c973d9%3B--md-code-hl-constant-color%3A%239383e2%3B--md-code-hl-keyword-color%3A%236791e0%3B--md-code-hl-string-color%3A%232fb170%3B--md-code-hl-name-color%3Avar%28--md-code-fg-color%29%3B--md-code-hl-operator-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-punctuation-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-comment-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-generic-color%3Avar%28--md-default-fg-color--light%29%3B--md-code-hl-variable-color%3Avar%28--md-default-fg-color--light%29%3B--md-typeset-color%3Avar%28--md-default-fg-color%29%3B--md-typeset-a-color%3Avar%28--md-primary-fg-color%29%3B--md-typeset-kbd-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C90%25%2C0.12%29%3B--md-typeset-kbd-accent-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C90%25%2C0.2%29%3B--md-typeset-kbd-border-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C14%25%2C1%29%3B--md-typeset-mark-color%3A%234287ff4d%3B--md-typeset-table-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C95%25%2C0.12%29%3B--md-typeset-table-color--light%3Ahsla%28var%28--md-hue%29%2C15%25%2C95%25%2C0.035%29%3B--md-admonition-fg-color%3Avar%28--md-default-fg-color%29%3B--md-admonition-bg-color%3Avar%28--md-default-bg-color%29%3B--md-footer-bg-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C10%25%2C0.87%29%3B--md-footer-bg-color--dark%3Ahsla%28var%28--md-hue%29%2C15%25%2C8%25%2C1%29%3B--md-shadow-z1%3A0%200.2rem%200.5rem%20%230000000d%2C0%200%200.05rem%20%230000001a%3B--md-shadow-z2%3A0%200.2rem%200.5rem%20%2300000040%2C0%200%200.05rem%20%2300000040%3B--md-shadow-z3%3A0%200.2rem%200.5rem%20%230006%2C0%200%200.05rem%20%2300000059%3Bcolor-scheme%3Adark%7D%5Bdata-md-color-scheme%3Dslate%5D%20img%5Bsrc%24%3D%22%23gh-light-mode-only%22%5D%2C%5Bdata-md-color-scheme%3Dslate%5D%20img%5Bsrc%24%3D%22%23only-light%22%5D%7Bdisplay%3Anone%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dpink%5D%7B--md-typeset-a-color%3A%23ed5487%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dpurple%5D%7B--md-typeset-a-color%3A%23c46fd3%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Ddeep-purple%5D%7B--md-typeset-a-color%3A%23a47bea%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dindigo%5D%7B--md-typeset-a-color%3A%235488e8%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dteal%5D%7B--md-typeset-a-color%3A%2300ccb8%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dgreen%5D%7B--md-typeset-a-color%3A%2371c174%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Ddeep-orange%5D%7B--md-typeset-a-color%3A%23ff764d%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dbrown%5D%7B--md-typeset-a-color%3A%23c1775c%7D%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dblack%5D%2C%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dblue-grey%5D%2C%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dgrey%5D%2C%5Bdata-md-color-scheme%3Dslate%5D%5Bdata-md-color-primary%3Dwhite%5D%7B--md-typeset-a-color%3A%235e8bde%7D%5Bdata-md-color-switching%5D%20%2A%2C%5Bdata-md-color-switching%5D%20%3Aafter%2C%5Bdata-md-color-switching%5D%20%3Abefore%7Btransition-duration%3A0ms%21important%7D%7D%5Bdata-md-color-accent%3Dred%5D%7B--md-accent-fg-color%3A%23ff1947%3B--md-accent-fg-color--transparent%3A%23ff19471a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dpink%5D%7B--md-accent-fg-color%3A%23f50056%3B--md-accent-fg-color--transparent%3A%23f500561a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dpurple%5D%7B--md-accent-fg-color%3A%23df41fb%3B--md-accent-fg-color--transparent%3A%23df41fb1a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Ddeep-purple%5D%7B--md-accent-fg-color%3A%237c4dff%3B--md-accent-fg-color--transparent%3A%237c4dff1a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dindigo%5D%7B--md-accent-fg-color%3A%23526cfe%3B--md-accent-fg-color--transparent%3A%23526cfe1a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dblue%5D%7B--md-accent-fg-color%3A%234287ff%3B--md-accent-fg-color--transparent%3A%234287ff1a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dlight-blue%5D%7B--md-accent-fg-color%3A%230091eb%3B--md-accent-fg-color--transparent%3A%230091eb1a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dcyan%5D%7B--md-accent-fg-color%3A%2300bad6%3B--md-accent-fg-color--transparent%3A%2300bad61a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dteal%5D%7B--md-accent-fg-color%3A%2300bda4%3B--md-accent-fg-color--transparent%3A%2300bda41a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dgreen%5D%7B--md-accent-fg-color%3A%2300c753%3B--md-accent-fg-color--transparent%3A%2300c7531a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dlight-green%5D%7B--md-accent-fg-color%3A%2363de17%3B--md-accent-fg-color--transparent%3A%2363de171a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-accent%3Dlime%5D%7B--md-accent-fg-color%3A%23b0eb00%3B--md-accent-fg-color--transparent%3A%23b0eb001a%3B--md-accent-bg-color%3A%23000000de%3B--md-accent-bg-color--light%3A%230000008a%7D%5Bdata-md-color-accent%3Dyellow%5D%7B--md-accent-fg-color%3A%23ffd500%3B--md-accent-fg-color--transparent%3A%23ffd5001a%3B--md-accent-bg-color%3A%23000000de%3B--md-accent-bg-color--light%3A%230000008a%7D%5Bdata-md-color-accent%3Damber%5D%7B--md-accent-fg-color%3A%23fa0%3B--md-accent-fg-color--transparent%3A%23ffaa001a%3B--md-accent-bg-color%3A%23000000de%3B--md-accent-bg-color--light%3A%230000008a%7D%5Bdata-md-color-accent%3Dorange%5D%7B--md-accent-fg-color%3A%23ff9100%3B--md-accent-fg-color--transparent%3A%23ff91001a%3B--md-accent-bg-color%3A%23000000de%3B--md-accent-bg-color--light%3A%230000008a%7D%5Bdata-md-color-accent%3Ddeep-orange%5D%7B--md-accent-fg-color%3A%23ff6e42%3B--md-accent-fg-color--transparent%3A%23ff6e421a%3B--md-accent-bg-color%3A%23fff%3B--md-accent-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dred%5D%7B--md-primary-fg-color%3A%23ef5552%3B--md-primary-fg-color--light%3A%23e57171%3B--md-primary-fg-color--dark%3A%23e53734%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dpink%5D%7B--md-primary-fg-color%3A%23e92063%3B--md-primary-fg-color--light%3A%23ec417a%3B--md-primary-fg-color--dark%3A%23c3185d%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dpurple%5D%7B--md-primary-fg-color%3A%23ab47bd%3B--md-primary-fg-color--light%3A%23bb69c9%3B--md-primary-fg-color--dark%3A%238c24a8%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Ddeep-purple%5D%7B--md-primary-fg-color%3A%237e56c2%3B--md-primary-fg-color--light%3A%239574cd%3B--md-primary-fg-color--dark%3A%23673ab6%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dindigo%5D%7B--md-primary-fg-color%3A%234051b5%3B--md-primary-fg-color--light%3A%235d6cc0%3B--md-primary-fg-color--dark%3A%23303fa1%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dblue%5D%7B--md-primary-fg-color%3A%232094f3%3B--md-primary-fg-color--light%3A%2342a5f5%3B--md-primary-fg-color--dark%3A%231975d2%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dlight-blue%5D%7B--md-primary-fg-color%3A%2302a6f2%3B--md-primary-fg-color--light%3A%2328b5f6%3B--md-primary-fg-color--dark%3A%230287cf%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dcyan%5D%7B--md-primary-fg-color%3A%2300bdd6%3B--md-primary-fg-color--light%3A%2325c5da%3B--md-primary-fg-color--dark%3A%230097a8%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dteal%5D%7B--md-primary-fg-color%3A%23009485%3B--md-primary-fg-color--light%3A%2326a699%3B--md-primary-fg-color--dark%3A%23007a6c%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dgreen%5D%7B--md-primary-fg-color%3A%234cae4f%3B--md-primary-fg-color--light%3A%2368bb6c%3B--md-primary-fg-color--dark%3A%23398e3d%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dlight-green%5D%7B--md-primary-fg-color%3A%238bc34b%3B--md-primary-fg-color--light%3A%239ccc66%3B--md-primary-fg-color--dark%3A%23689f38%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dlime%5D%7B--md-primary-fg-color%3A%23cbdc38%3B--md-primary-fg-color--light%3A%23d3e156%3B--md-primary-fg-color--dark%3A%23b0b52c%3B--md-primary-bg-color%3A%23000000de%3B--md-primary-bg-color--light%3A%230000008a%7D%5Bdata-md-color-primary%3Dyellow%5D%7B--md-primary-fg-color%3A%23ffec3d%3B--md-primary-fg-color--light%3A%23ffee57%3B--md-primary-fg-color--dark%3A%23fbc02d%3B--md-primary-bg-color%3A%23000000de%3B--md-primary-bg-color--light%3A%230000008a%7D%5Bdata-md-color-primary%3Damber%5D%7B--md-primary-fg-color%3A%23ffc105%3B--md-primary-fg-color--light%3A%23ffc929%3B--md-primary-fg-color--dark%3A%23ffa200%3B--md-primary-bg-color%3A%23000000de%3B--md-primary-bg-color--light%3A%230000008a%7D%5Bdata-md-color-primary%3Dorange%5D%7B--md-primary-fg-color%3A%23ffa724%3B--md-primary-fg-color--light%3A%23ffa724%3B--md-primary-fg-color--dark%3A%23fa8900%3B--md-primary-bg-color%3A%23000000de%3B--md-primary-bg-color--light%3A%230000008a%7D%5Bdata-md-color-primary%3Ddeep-orange%5D%7B--md-primary-fg-color%3A%23ff6e42%3B--md-primary-fg-color--light%3A%23ff8a66%3B--md-primary-fg-color--dark%3A%23f4511f%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dbrown%5D%7B--md-primary-fg-color%3A%23795649%3B--md-primary-fg-color--light%3A%238d6e62%3B--md-primary-fg-color--dark%3A%235d4037%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%7D%5Bdata-md-color-primary%3Dgrey%5D%7B--md-primary-fg-color%3A%23757575%3B--md-primary-fg-color--light%3A%239e9e9e%3B--md-primary-fg-color--dark%3A%23616161%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%3B--md-typeset-a-color%3A%234051b5%7D%5Bdata-md-color-primary%3Dblue-grey%5D%7B--md-primary-fg-color%3A%23546d78%3B--md-primary-fg-color--light%3A%23607c8a%3B--md-primary-fg-color--dark%3A%23455a63%3B--md-primary-bg-color%3A%23fff%3B--md-primary-bg-color--light%3A%23ffffffb3%3B--md-typeset-a-color%3A%234051b5%7D%5Bdata-md-color-primary%3Dlight-green%5D%3Anot%28%5Bdata-md-color-scheme%3Dslate%5D%29%7B--md-typeset-a-color%3A%2372ad2e%7D%5Bdata-md-color-primary%3Dlime%5D%3Anot%28%5Bdata-md-color-scheme%3Dslate%5D%29%7B--md-typeset-a-color%3A%238b990a%7D%5Bdata-md-color-primary%3Dyellow%5D%3Anot%28%5Bdata-md-color-scheme%3Dslate%5D%29%7B--md-typeset-a-color%3A%23b8a500%7D%5Bdata-md-color-primary%3Damber%5D%3Anot%28%5Bdata-md-color-scheme%3Dslate%5D%29%7B--md-typeset-a-color%3A%23d19d00%7D%5Bdata-md-color-primary%3Dorange%5D%3Anot%28%5Bdata-md-color-scheme%3Dslate%5D%29%7B--md-typeset-a-color%3A%23e68a00%7D%5Bdata-md-color-primary%3Dwhite%5D%7B--md-primary-fg-color%3Ahsla%28var%28--md-hue%29%2C0%25%2C100%25%2C1%29%3B--md-primary-fg-color--light%3Ahsla%28var%28--md-hue%29%2C0%25%2C100%25%2C0.7%29%3B--md-primary-fg-color--dark%3Ahsla%28var%28--md-hue%29%2C0%25%2C0%25%2C0.07%29%3B--md-primary-bg-color%3Ahsla%28var%28--md-hue%29%2C0%25%2C0%25%2C0.87%29%3B--md-primary-bg-color--light%3Ahsla%28var%28--md-hue%29%2C0%25%2C0%25%2C0.54%29%3B--md-typeset-a-color%3A%234051b5%7D%5Bdata-md-color-primary%3Dwhite%5D%20.md-button%7Bcolor%3Avar%28--md-typeset-a-color%29%7D%5Bdata-md-color-primary%3Dwhite%5D%20.md-button--primary%7Bbackground-color%3Avar%28--md-typeset-a-color%29%3Bborder-color%3Avar%28--md-typeset-a-color%29%3Bcolor%3Ahsla%28var%28--md-hue%29%2C0%25%2C100%25%2C1%29%7D%40media%20screen%20and%20%28min-width%3A60em%29%7B%5Bdata-md-color-primary%3Dwhite%5D%20.md-search__form%7Bbackground-color%3Ahsla%28var%28--md-hue%29%2C0%25%2C0%25%2C.07%29%7D%5Bdata-md-color-primary%3Dwhite%5D%20.md-search__form%3Ahover%7Bbackground-color%3Ahsla%28var%28--md-hue%29%2C0%25%2C0%25%2C.32%29%7D%5Bdata-md-color-primary%3Dwhite%5D%20.md-search__input%2B.md-search__icon%7Bcolor%3Ahsla%28var%28--md-hue%29%2C0%25%2C0%25%2C.87%29%7D%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B%5Bdata-md-color-primary%3Dwhite%5D%20.md-tabs%7Bborder-bottom%3A.05rem%20solid%20%2300000012%7D%7D%5Bdata-md-color-primary%3Dblack%5D%7B--md-primary-fg-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C9%25%2C1%29%3B--md-primary-fg-color--light%3Ahsla%28var%28--md-hue%29%2C15%25%2C9%25%2C0.54%29%3B--md-primary-fg-color--dark%3Ahsla%28var%28--md-hue%29%2C15%25%2C9%25%2C1%29%3B--md-primary-bg-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C100%25%2C1%29%3B--md-primary-bg-color--light%3Ahsla%28var%28--md-hue%29%2C15%25%2C100%25%2C0.7%29%3B--md-typeset-a-color%3A%234051b5%7D%5Bdata-md-color-primary%3Dblack%5D%20.md-button%7Bcolor%3Avar%28--md-typeset-a-color%29%7D%5Bdata-md-color-primary%3Dblack%5D%20.md-button--primary%7Bbackground-color%3Avar%28--md-typeset-a-color%29%3Bborder-color%3Avar%28--md-typeset-a-color%29%3Bcolor%3Ahsla%28var%28--md-hue%29%2C0%25%2C100%25%2C1%29%7D%5Bdata-md-color-primary%3Dblack%5D%20.md-header%7Bbackground-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C9%25%2C1%29%7D%40media%20screen%20and%20%28max-width%3A59.984375em%29%7B%5Bdata-md-color-primary%3Dblack%5D%20.md-nav__source%7Bbackground-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C11%25%2C.87%29%7D%7D%40media%20screen%20and%20%28max-width%3A76.234375em%29%7Bhtml%20%5Bdata-md-color-primary%3Dblack%5D%20.md-nav--primary%20.md-nav__title%5Bfor%3D__drawer%5D%7Bbackground-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C9%25%2C1%29%7D%7D%40media%20screen%20and%20%28min-width%3A76.25em%29%7B%5Bdata-md-color-primary%3Dblack%5D%20.md-tabs%7Bbackground-color%3Ahsla%28var%28--md-hue%29%2C15%25%2C9%25%2C1%29%7D%7D" rel="stylesheet"/><!--URL:../assets/stylesheets/palette.06af60db.min.css-->
|
||
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect"/>
|
||
<link href="data:text/css; charset=utf-8;base64,QGZvbnQtZmFjZSB7CiAgZm9udC1mYW1pbHk6ICdSb2JvdG8nOwogIGZvbnQtc3R5bGU6IGl0YWxpYzsKICBmb250LXdlaWdodDogMzAwOwogIGZvbnQtZGlzcGxheTogZmFsbGJhY2s7CiAgc3JjOiB1cmwoaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbS9zL3JvYm90by92MzIvS0ZPakNucUV1OTJGcjFNdTUxVGpBU2M2Q3NFLnR0ZikgZm9ybWF0KCd0cnVldHlwZScpOwp9CkBmb250LWZhY2UgewogIGZvbnQtZmFtaWx5OiAnUm9ib3RvJzsKICBmb250LXN0eWxlOiBpdGFsaWM7CiAgZm9udC13ZWlnaHQ6IDQwMDsKICBmb250LWRpc3BsYXk6IGZhbGxiYWNrOwogIHNyYzogdXJsKGh0dHBzOi8vZm9udHMuZ3N0YXRpYy5jb20vcy9yb2JvdG8vdjMyL0tGT2tDbnFFdTkyRnIxTXU1MXhJSXpjLnR0ZikgZm9ybWF0KCd0cnVldHlwZScpOwp9CkBmb250LWZhY2UgewogIGZvbnQtZmFtaWx5OiAnUm9ib3RvJzsKICBmb250LXN0eWxlOiBpdGFsaWM7CiAgZm9udC13ZWlnaHQ6IDcwMDsKICBmb250LWRpc3BsYXk6IGZhbGxiYWNrOwogIHNyYzogdXJsKGh0dHBzOi8vZm9udHMuZ3N0YXRpYy5jb20vcy9yb2JvdG8vdjMyL0tGT2pDbnFFdTkyRnIxTXU1MVR6QmljNkNzRS50dGYpIGZvcm1hdCgndHJ1ZXR5cGUnKTsKfQpAZm9udC1mYWNlIHsKICBmb250LWZhbWlseTogJ1JvYm90byc7CiAgZm9udC1zdHlsZTogbm9ybWFsOwogIGZvbnQtd2VpZ2h0OiAzMDA7CiAgZm9udC1kaXNwbGF5OiBmYWxsYmFjazsKICBzcmM6IHVybChodHRwczovL2ZvbnRzLmdzdGF0aWMuY29tL3Mvcm9ib3RvL3YzMi9LRk9sQ25xRXU5MkZyMU1tU1U1ZkJCYzkudHRmKSBmb3JtYXQoJ3RydWV0eXBlJyk7Cn0KQGZvbnQtZmFjZSB7CiAgZm9udC1mYW1pbHk6ICdSb2JvdG8nOwogIGZvbnQtc3R5bGU6IG5vcm1hbDsKICBmb250LXdlaWdodDogNDAwOwogIGZvbnQtZGlzcGxheTogZmFsbGJhY2s7CiAgc3JjOiB1cmwoaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbS9zL3JvYm90by92MzIvS0ZPbUNucUV1OTJGcjFNdTRteFAudHRmKSBmb3JtYXQoJ3RydWV0eXBlJyk7Cn0KQGZvbnQtZmFjZSB7CiAgZm9udC1mYW1pbHk6ICdSb2JvdG8nOwogIGZvbnQtc3R5bGU6IG5vcm1hbDsKICBmb250LXdlaWdodDogNzAwOwogIGZvbnQtZGlzcGxheTogZmFsbGJhY2s7CiAgc3JjOiB1cmwoaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbS9zL3JvYm90by92MzIvS0ZPbENucUV1OTJGcjFNbVdVbGZCQmM5LnR0ZikgZm9ybWF0KCd0cnVldHlwZScpOwp9CkBmb250LWZhY2UgewogIGZvbnQtZmFtaWx5OiAnUm9ib3RvIE1vbm8nOwogIGZvbnQtc3R5bGU6IGl0YWxpYzsKICBmb250LXdlaWdodDogNDAwOwogIGZvbnQtZGlzcGxheTogZmFsbGJhY2s7CiAgc3JjOiB1cmwoaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbS9zL3JvYm90b21vbm8vdjIzL0wweG9ERjR4bFZNRi1CZlI4YlhNSWpoT3NYRy1xMm9ldUZvcUZybG5BTlc2Q3B3LnR0ZikgZm9ybWF0KCd0cnVldHlwZScpOwp9CkBmb250LWZhY2UgewogIGZvbnQtZmFtaWx5OiAnUm9ib3RvIE1vbm8nOwogIGZvbnQtc3R5bGU6IGl0YWxpYzsKICBmb250LXdlaWdodDogNzAwOwogIGZvbnQtZGlzcGxheTogZmFsbGJhY2s7CiAgc3JjOiB1cmwoaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbS9zL3JvYm90b21vbm8vdjIzL0wweG9ERjR4bFZNRi1CZlI4YlhNSWpoT3NYRy1xMm9ldUZvcUZybUFCOVc2Q3B3LnR0ZikgZm9ybWF0KCd0cnVldHlwZScpOwp9CkBmb250LWZhY2UgewogIGZvbnQtZmFtaWx5OiAnUm9ib3RvIE1vbm8nOwogIGZvbnQtc3R5bGU6IG5vcm1hbDsKICBmb250LXdlaWdodDogNDAwOwogIGZvbnQtZGlzcGxheTogZmFsbGJhY2s7CiAgc3JjOiB1cmwoaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbS9zL3JvYm90b21vbm8vdjIzL0wweHVERjR4bFZNRi1CZlI4YlhNSWhKSGc0NW13Z0dFRmwwXzN2cV9ST1c5LnR0ZikgZm9ybWF0KCd0cnVldHlwZScpOwp9CkBmb250LWZhY2UgewogIGZvbnQtZmFtaWx5OiAnUm9ib3RvIE1vbm8nOwogIGZvbnQtc3R5bGU6IG5vcm1hbDsKICBmb250LXdlaWdodDogNzAwOwogIGZvbnQtZGlzcGxheTogZmFsbGJhY2s7CiAgc3JjOiB1cmwoaHR0cHM6Ly9mb250cy5nc3RhdGljLmNvbS9zL3JvYm90b21vbm8vdjIzL0wweHVERjR4bFZNRi1CZlI4YlhNSWhKSGc0NW13Z0dFRmwwX09mMl9ST1c5LnR0ZikgZm9ybWF0KCd0cnVldHlwZScpOwp9Cg==" rel="stylesheet"/><!--URL:https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback-->
|
||
<style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
|
||
<link href="data:text/css,%0A/%2A%20%0AThe%20print-site%20banner%0A%2A/%0A%23print-site-banner%20%7B%0A%20%20%20%20border%3A2px%3B%20%0A%20%20%20%20border-style%3Asolid%3B%20%0A%20%20%20%20border-color%3A%23000000%3B%20%0A%20%20%20%20padding%3A%200em%201em%200em%201em%3B%20%0A%20%20%20%20margin-bottom%3A%202em%3B%0A%7D%0A%23print-site-banner%20h3%20%7B%0A%20%20%20%20margin-top%3A%201rem%3B%0A%7D%0A%0A%0A/%2A%20%0AEnumerate%20headings%0A%0AOnly%20displayed%20when%20set%20in%20mkdocs.yml%0A%0Aprint-site%3A%0A%20%20%20%20-%20print-site-enumerate_headings%3A%20true%0A%2A/%0A%0A/%2A%20Ensure%20that%20when%20adding%20enumeration%20to%20headings%2C%20this%20happens%20inline%20%2A/%0A.print-site-enumerate-headings%20h1%3Abefore%2C%0A.print-site-enumerate-headings%20h2%3Abefore%2C%0A.print-site-enumerate-headings%20h3%3Abefore%2C%0A.print-site-enumerate-headings%20h4%3Abefore%2C%0A.print-site-enumerate-headings%20h5%3Abefore%2C%0A.print-site-enumerate-headings%20h6%3Abefore%20%7B%0A%20%20%20%20display%3A%20inline%20%21important%3B%0A%7D%0A%0A/%2A%20Reset%20all%20enumeration%20at%20start%20of%20page%20%2A/%0Abody%20%7Bcounter-reset%3A%20chapter%20sec-top%20toc-chapter%20toc-sec-chapter%20figurecounter%3B%7D%0A%0A/%2A%20Enumerate%20headings%20of%20CHAPTERS%2C%0Athat%20are%20part%20of%20an%20original%20included%20page%20%2A/%0A.print-site-enumerate-headings%20.print-page%20h1%20%7Bcounter-reset%3A%20section%20sub-section%20composite%20detail%20last%3B%20%7D%0A.print-site-enumerate-headings%20.print-page%20h2%20%7Bcounter-reset%3A%20sub-section%20composite%20detail%20last%3B%20%7D%0A.print-site-enumerate-headings%20.print-page%20h3%20%7Bcounter-reset%3A%20composite%20detail%20last%3B%20%7D%0A.print-site-enumerate-headings%20.print-page%20h4%20%7Bcounter-reset%3A%20detail%20last%3B%20%7D%0A.print-site-enumerate-headings%20.print-page%20h5%20%7Bcounter-reset%3A%20last%3B%20%7D%0A.print-site-enumerate-headings%20.print-page%20h1%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20chapter%3B%0A%20%20%20%20content%3A%20counter%28chapter%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20h1.print-page-toc-title%3Abefore%2C%0A%23print-site-cover-page%20h1%3Abefore%2C%0A%23print-site-cover-page%20h2%3Abefore%2C%0A%23print-site-cover-page%20h3%3Abefore%2C%0A%23print-site-cover-page%20h4%3Abefore%2C%0A%23print-site-cover-page%20h5%3Abefore%2C%0A%23print-site-cover-page%20h6%3Abefore%20%7B%0A%20%20%20%20content%3A%20none%20%21important%3B%0A%20%20%20%20counter-increment%3A%20none%3B%0A%7D%0A.print-site-enumerate-headings%20.print-page%20h2%3Abefore%20%7B%0A%20%20counter-increment%3A%20section%3B%0A%20%20content%3A%20counter%28chapter%29%20%22.%22%20counter%28section%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20.print-page%20h3%3Abefore%20%7B%0A%20%20counter-increment%3A%20sub-section%3B%0A%20%20content%3A%20counter%28chapter%29%20%22.%22%20counter%28section%29%20%22.%22%20counter%28sub-section%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20.print-page%20h4%3Abefore%20%7B%0A%20%20counter-increment%3A%20composite%3B%0A%20%20content%3A%20counter%28chapter%29%20%22.%22%20counter%28section%29%20%22.%22%20counter%28sub-section%29%20%22.%22%20counter%28composite%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20.print-page%20h5%3Abefore%20%7B%0A%20%20counter-increment%3A%20detail%3B%0A%20%20content%3A%20counter%28chapter%29%20%22.%22%20counter%28section%29%20%22.%22%20counter%28sub-section%29%20%22.%22%20counter%28composite%29%20%22.%22%20counter%28detail%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20.print-page%20h6%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20last%3B%0A%20%20%20%20content%3A%20counter%28chapter%29%20%22.%22%20counter%28section%29%20%22.%22%20counter%28sub-section%29%20%22.%22%20counter%28composite%29%20%22.%22%20counter%28detail%29%20%22.%22%20counter%28last%29%20%21important%3B%0A%7D%0A%0A/%2A%20Enumerate%20headings%20of%20SECTIONS%2C%0Athat%20are%20part%20of%20an%20original%20included%20page%20%2A/%0A.print-site-enumerate-headings%20h1%20%7Bcounter-reset%3A%20sec-section%20sec-sub-section%20sec-composite%20sec-detail%20sec-last%3B%20%7D%0A.print-site-enumerate-headings%20h2.nav-section-title%20%7Bcounter-reset%3A%20sec-sub-section%20sec-composite%20sec-detail%20sec-last%3B%20%7D%0A.print-site-enumerate-headings%20h3.nav-section-title%20%7Bcounter-reset%3A%20sec-composite%20sec-detail%20sec-last%3B%20%7D%0A.print-site-enumerate-headings%20h4.nav-section-title%20%7Bcounter-reset%3A%20sec-detail%20sec-last%3B%20%7D%0A.print-site-enumerate-headings%20h5.nav-section-title%20%7Bcounter-reset%3A%20sec-last%3B%20%7D%0A.print-site-enumerate-headings%20h1.nav-section-title%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20sec-top%3B%0A%20%20%20%20content%3A%20counter%28sec-top%2C%20upper-roman%29%20%22.%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20h2.nav-section-title%3Abefore%20%7B%0A%20%20counter-increment%3A%20sec-section%3B%0A%20%20content%3A%20counter%28sec-top%2C%20upper-roman%29%20%22.%22%20counter%28sec-section%2C%20upper-roman%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20h3.nav-section-title%3Abefore%20%7B%0A%20%20counter-increment%3A%20sec-sub-section%3B%0A%20%20content%3A%20counter%28sec-top%2C%20upper-roman%29%20%22.%22%20counter%28sec-section%2C%20upper-roman%29%20%22.%22%20counter%28sec-sub-section%2C%20upper-roman%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20h4.nav-section-title%3Abefore%20%7B%0A%20%20counter-increment%3A%20sec-composite%3B%0A%20%20content%3A%20counter%28sec-top%2C%20upper-roman%29%20%22.%22%20counter%28sec-section%2C%20upper-roman%29%20%22.%22%20counter%28sec-sub-section%2C%20upper-roman%29%20%22.%22%20counter%28sec-composite%2C%20upper-roman%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20h5.nav-section-title%3Abefore%20%7B%0A%20%20counter-increment%3A%20sec-detail%3B%0A%20%20content%3A%20counter%28sec-top%2C%20upper-roman%29%20%22.%22%20counter%28sec-section%2C%20upper-roman%29%20%22.%22%20counter%28sec-sub-section%2C%20upper-roman%29%20%22.%22%20counter%28sec-composite%2C%20upper-roman%29%20%22.%22%20counter%28sec-detail%2C%20upper-roman%29%20%22%20%22%20%21important%3B%0A%7D%0A.print-site-enumerate-headings%20h6.nav-section-title%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20sec-last%3B%0A%20%20%20%20content%3A%20counter%28sec-top%2C%20upper-roman%29%20%22.%22%20counter%28sec-section%2C%20upper-roman%29%20%22.%22%20counter%28sec-sub-section%2C%20upper-roman%29%20%22.%22%20counter%28sec-composite%2C%20upper-roman%29%20%22.%22%20counter%28sec-detail%2C%20upper-roman%29%20%22.%22%20counter%28sec-last%2C%20upper-roman%29%20%21important%3B%0A%7D%0A%0A%0A/%2A%20Enumerate%20CHAPTERS%20in%20table%20of%20contents%20also%20%2A/%0A.print-site-enumerate-headings%20.print-site-toc-level-1%20%3E%20ul%20%7B%20counter-reset%3A%20toc-section%3B%20%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-2%20%3E%20ul%20%7B%20counter-reset%3A%20toc-sub-section%3B%20%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-3%20%3E%20ul%20%7B%20counter-reset%3A%20toc-composite%3B%20%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-4%20%3E%20ul%20%7B%20counter-reset%3A%20toc-detail%3B%20%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-5%20%3E%20ul%20%7B%20counter-reset%3A%20toc-last%3B%20%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-1%20%3E%20li%20a%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-chapter%3B%0A%20%20%20%20content%3A%20counter%28toc-chapter%29%20%22%20%22%3B%20%0A%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-2%20%3E%20li%20a%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-section%3B%20%0A%20%20%20%20content%3A%20counter%28toc-chapter%29%20%22.%22%20counter%28toc-section%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-3%20%3E%20li%20a%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-sub-section%3B%0A%20%20%20%20content%3A%20counter%28toc-chapter%29%20%22.%22%20counter%28toc-section%29%20%22.%22%20counter%28toc-sub-section%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-4%20%3E%20li%20a%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-composite%3B%0A%20%20%20%20content%3A%20counter%28toc-chapter%29%20%22.%22%20counter%28toc-section%29%20%22.%22%20counter%28toc-sub-section%29%20%22.%22%20counter%28toc-composite%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-5%20%3E%20li%20a%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-detail%3B%0A%20%20%20%20content%3A%20counter%28toc-chapter%29%20%22.%22%20counter%28toc-section%29%20%22.%22%20counter%28toc-sub-section%29%20%22.%22%20counter%28toc-composite%29%20%22.%22%20counter%28toc-detail%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20.print-site-toc-level-6%20%3E%20li%20a%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-last%3B%0A%20%20%20%20content%3A%20counter%28toc-chapter%29%20%22.%22%20counter%28toc-section%29%20%22.%22%20counter%28toc-sub-section%29%20%22.%22%20counter%28toc-composite%29%20%22.%22%20counter%28toc-detail%29%20%22.%22%20counter%28toc-last%29%3B%0A%7D%0A%0A/%2A%20Enumerate%20SECTIONS%20in%20table%20of%20contents%20also%20%2A/%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-1%20%7B%20counter-reset%3A%20toc-sec-section%3B%20%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-2%20%7B%20counter-reset%3A%20toc-sec-sub-section%3B%20%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-3%20%7B%20counter-reset%3A%20toc-sec-composite%3B%20%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-4%20%7B%20counter-reset%3A%20toc-sec-detail%3B%20%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-5%20%7B%20counter-reset%3A%20toc-sec-last%3B%20%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-1%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-sec-chapter%3B%0A%20%20%20%20content%3A%20counter%28toc-sec-chapter%2C%20upper-roman%29%20%22%20%22%3B%20%0A%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-2%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-sec-section%3B%20%0A%20%20%20%20content%3A%20counter%28toc-sec-chapter%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-section%2C%20upper-roman%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-3%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-sec-sub-section%3B%0A%20%20%20%20content%3A%20counter%28toc-sec-chapter%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-section%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-sub-section%2C%20upper-roman%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-4before%20%7B%0A%20%20%20%20counter-increment%3A%20toc-sec-composite%3B%0A%20%20%20%20content%3A%20counter%28toc-sec-chapter%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-section%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-sub-section%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-composite%2C%20upper-roman%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-5%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-detail%3B%0A%20%20%20%20content%3A%20counter%28toc-sec-chapter%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-section%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-sub-section%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-composite%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-detail%2C%20upper-roman%29%20%22%20%22%3B%0A%7D%0A.print-site-enumerate-headings%20li.toc-nav-section-title-level-6%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20toc-sec-last%3B%0A%20%20%20%20content%3A%20counter%28toc-sec-chapter%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-section%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-sub-section%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-composite%2C%20upper-roman%29%20%22.%22%20counter%28toc-sec-detail%2C%20upper-roman%29%20%22.%22%20counter%28toc-last%2C%20upper-roman%29%3B%0A%7D%0A%0A%23print-page-toc%20li%20a.headerlink%3Abefore%20%7B%0A%20%20%20%20content%3A%20none%20%21important%3B%0A%20%20%20%20counter-increment%3A%20none%3B%0A%7D%0A%0A%0A/%2A%20Enumerate%20figures%20%2A/%0A.print-site-enumerate-figures%20figcaption%3Abefore%20%7B%0A%20%20%20%20counter-increment%3A%20figurecounter%3B%0A%20%20%20%20content%3A%20%22Figure%20%22%20counter%28figurecounter%29%20%22%3A%20%22%3B%0A%7D%0A%0A%0A/%2A%20Print%20URLS%3A%20%0AChange%20a%20%27link%27%20to%20%27link%20%28target%29%27%20%2A/%0Adiv.print-site-add-full-url%20section.print-page%20a%5Bhref%5E%3D%22http%22%5D%3A%3Aafter%7B%0A%20%20%20%20content%3A%20%22%20%28%22%20attr%28href%29%20%22%29%20%22%3B%0A%7D%0A%0A%0A/%2A%20%0APrint%20site%20table%20of%20contents%20styling%0A%20%2A/%0A.print-page-toc-nav%20%7B%0A%20%20%20%20padding-bottom%3A%202em%3B%0A%7D%0A%0A%23print-site-page%20h1%3Atarget%2C%20%0A%23print-site-page%20h2%3Atarget%2C%20%0A%23print-site-page%20h3%3Atarget%2C%20%0A%23print-site-page%20h4%3Atarget%2C%20%0A%23print-site-page%20h5%3Atarget%2C%20%0A%23print-site-page%20h6%3Atarget%20%7B%0A%20%20%20%20animation%3A%20highlight%201s%20ease%3B%0A%7D%0A%40keyframes%20highlight%20%7B%0A%20%20%20%20from%20%7B%20background%3A%20yellow%3B%20%7D%0A%20%20%20%20to%20%7B%20background%3A%20white%3B%20%7D%0A%7D%0A%0A%23print-page-toc%20ul%20%7B%0A%20%20%20%20/%2A%20margin-left%3A%201.6em%3B%20%2A/%0A%20%20%20%20margin-top%3A%200%3B%0A%20%20%20%20margin-bottom%3A%200%3B%0A%20%20%20%20padding-left%3A%200%3B%0A%20%20%20%20list-style-position%3A%20inside%3B%0A%7D%0A%23print-page-toc%20ul.print-site-toc-level-2%2C%0A%23print-page-toc%20ul.print-site-toc-level-3%2C%0A%23print-page-toc%20ul.print-site-toc-level-4%2C%0A%23print-page-toc%20ul.print-site-toc-level-5%2C%0A%23print-page-toc%20ul.print-site-toc-level-6%20%7B%0A%20%20%20%20margin-left%3A%201.6em%3B%0A%7D%0A%23print-page-toc%20ul%20li%20%7B%0A%20%20%20%20margin-left%3A%200%3B%0A%20%20%20%20margin-bottom%3A%200.2em%3B%0A%7D%0Aul.print-site-toc-level-1%20%7B%0A%20%20%20%20list-style-type%3A%20none%3B%0A%7D%0Aul.print-site-toc-level-1%20li%20a%20%7B%0A%20%20%20%20font-weight%3A%20bold%3B%0A%20%20%20%20font-size%3A%20120%25%3B%0A%7D%0Aul.print-site-toc-level-2%20li%20a%20%7B%0A%20%20%20%20font-weight%3A%20normal%3B%0A%20%20%20%20font-size%3A%20100%25%3B%0A%20%20%20%20margin-bottom%3A%200em%3B%0A%7D%0A%23print-site-page%20ul%20li.toc-nav-section-title%20%7B%0A%20%20%20%20padding-top%3A%201em%3B%0A%20%20%20%20padding-bottom%3A%200em%3B%0A%20%20%20%20font-size%3A%20110%25%3B%0A%20%20%20%20letter-spacing%3A%201px%3B%0A%7D%0A%23print-site-page%20ul.toc-section-line-border%20%7B%20%0A%20%20%20%20border-left%3A%205px%20solid%20grey%3B%0A%20%20%20%20padding-left%3A%201.5em%3B%0A%20%20%20%20margin-top%3A%200.5em%3B%0A%20%20%20%20margin-bottom%3A%201em%3B%0A%7D%0A%0A%0A%23print-site-page%20ul%20%7B%0A%20%20%20%20margin-left%3A%200em%3B%0A%7D%0A%0A%0A%0A/%2A%20Don%27t%20display%20cover%20page%20when%20not%20in%20print%20mode%20%2A/%0A%23print-site-cover-page%20%7B%20display%3A%20none%3B%20%7D%0A%0A/%2A%20Don%27t%20display%20the%20section%20headings%20that%20we%20added%0AFor%20now%2C%20we%20added%20them%20for%20use%20only%20in%20the%20table%20of%20contents%20%2A/%0A%23print-site-page%20h1.nav-section-title%2C%0A%23print-site-page%20h2.nav-section-title%2C%0A%23print-site-page%20h3.nav-section-title%2C%0A%23print-site-page%20h4.nav-section-title%2C%0A%23print-site-page%20h5.nav-section-title%2C%0A%23print-site-page%20h6.nav-section-title%20%7B%20%0A%20%20%20%20padding-top%3A%201.5em%3B%0A%20%20%20%20padding-bottom%3A%201em%3B%0A%20%20%20%20padding-left%3A%201em%3B%0A%20%20%20%20font-size%3A%202.2em%3B%0A%20%20%20%20font-weight%3A%20300%3B%0A%20%20%20%20line-height%3A%201.3%3B%0A%20%20%20%20color%3A%20var%28--md-default-fg-color--light%29%3B%0A%7D%0A%0A%23print-site-page%20h1.nav-section-title-end%2C%0A%23print-site-page%20h2.nav-section-title-end%2C%0A%23print-site-page%20h3.nav-section-title-end%2C%0A%23print-site-page%20h4.nav-section-title-end%2C%0A%23print-site-page%20h5.nav-section-title-end%2C%0A%23print-site-page%20h6.nav-section-title-end%20%7B%20display%3A%20none%3B%20%7D%0A%0A/%2A%20In%20the%20TOC%2C%20we%20want%20lines%20that%20are%20children%20of%20a%20section%20to%20be%20displayed%20with%20a%20left%20margin%20%2A/%0A%23print-site-page%20ul%20li.toc-nav-section-child%20%7B%20padding-left%3A%201em%3B%20%7D%0A%0A/%2A%20Be%20able%20to%20not%20print%20certain%20elements%20%2A/%0A%23print-site-page%20.print-site-plugin-ignore%20%7B%20display%3A%20none%3B%7D%0A%0A%0A%0A%40media%20print%20%7B%20%20%20%20%0A%0A%20%20%20%20/%2A%20included%20bookmarks%20on%20h1%20and%20h2%0A%20%20%20%20Doesn%27t%20work%2C%20but%20included%20In%20case%20Chrome%20gets%20support%20%0A%20%20%20%20for%20these%20experimental%20CSS%20features%20that%20define%20PDF%20bookmarks%20%2A/%0A%20%20%20%20/%2A%20%23print-site-page%20h1%20%7B%0A%20%20%20%20%20%20%20%20bookmark-level%3A%201%3B%0A%20%20%20%20%20%20%20%20bookmark-label%3A%20content%28%29%3B%20%0A%20%20%20%20%20%20%20%20-ah-bookmark-level%3A%201%3B%0A%20%20%20%20%20%20%20%20-ro-pdf-bookmark-level%3A%201%3B%0A%20%20%20%20%7D%0A%20%20%20%20%23print-site-page%20h2%20%7B%0A%20%20%20%20%20%20%20%20bookmark-level%3A%202%3B%0A%20%20%20%20%20%20%20%20bookmark-label%3A%20content%28%29%3B%20%0A%20%20%20%20%20%20%20%20-ah-bookmark-level%3A%202%3B%0A%20%20%20%20%20%20%20%20-ro-pdf-bookmark-level%3A%202%3B%0A%20%20%20%20%7D%20%2A/%0A%0A%20%20%20%20/%2A%20Be%20able%20to%20not%20print%20certain%20elements%20%2A/%0A%20%20%20%20.print-site-plugin-ignore%20%7B%20display%3A%20none%3B%20%7D%0A%0A%20%20%20%20/%2A%20Remove%20print%20site%20banner%20%2A/%0A%20%20%20%20%23print-site-banner%20%7B%20display%3A%20none%3B%20%7D%0A%0A%20%20%20%20/%2A%20Ensure%20all%20tabbed%20content%20is%20displayed%20and%20printed%0A%20%20%20%20https%3A//squidfunk.github.io/mkdocs-material/reference/content-tabs/%20%2A/%0A%20%20%20%20/%2A%20%23print-site-page%20div.tabbed-content%20%7B%20display%3A%20block%20%21important%3B%20%7D%20%2A/%0A%0A%20%20%20%20/%2A%20PDF%20page%20breaks%20on%20each%20MkDocs%20page%2C%20except%20the%20first%20one%20%2A/%0A%20%20%20%20%23print-site-page%20section.print-page%20%7B%0A%20%20%20%20%20%20%20%20page-break-before%3A%20always%3B%0A%20%20%20%20%7D%0A%20%20%20%20%23print-site-page%20section.print-page%3Afirst-of-type%20%7B%0A%20%20%20%20%20%20%20%20page-break-before%3A%20avoid%3B%0A%20%20%20%20%7D%0A%20%20%20%20/%2A%20PDF%20page%20breaks%20-%20separate%20title%20page%20for%20each%20section%20%2A/%0A%20%20%20%20%23print-site-page%20.nav-section-title%20%7B%0A%20%20%20%20%20%20%20%20page-break-before%3A%20always%3B%0A%20%20%20%20%20%20%20%20page-break-after%3A%20always%3B%0A%20%20%20%20%20%20%20%20align-content%3A%20center%3B%0A%20%20%20%20%20%20%20%20text-align%3A%20center%3B%0A%20%20%20%20%20%20%20%20vertical-align%3A%20middle%3B%0A%20%20%20%20%20%20%20%20padding-top%3A%20150px%20%21important%3B%0A%20%20%20%20%20%20%20%20padding-bottom%3A%200em%3B%0A%20%20%20%20%20%20%20%20padding-left%3A%200em%3B%0A%20%20%20%20%20%20%20%20font-size%3A%202.5em%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%23print-site-page%20p%2C%20%0A%20%20%20%20%23print-site-page%20pre%2C%20%0A%20%20%20%20%23print-site-page%20blockquote%2C%20%0A%20%20%20%20%23print-site-page%20.tabbed-set%20%7B%0A%20%20%20%20%20%20%20%20page-break-inside%3A%20avoid%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20/%2A%20Avoid%20a%20page%20break%20immediately%20after%20a%20heading%20%2A/%0A%20%20%20%20/%2A%20Credits%20https%3A//stackoverflow.com/a/9238898/5525118%20%2A/%0A%20%20%20%20%23print-site-page%20h1%20%7B%0A%20%20%20%20%20%20%20%20page-break-inside%3A%20avoid%3B%0A%20%20%20%20%7D%0A%20%20%20%20%23print-site-page%20h1%3A%3Aafter%20%7B%0A%20%20%20%20%20%20%20%20content%3A%20%22%22%3B%0A%20%20%20%20%20%20%20%20display%3A%20block%3B%0A%20%20%20%20%20%20%20%20height%3A%20100px%3B%0A%20%20%20%20%20%20%20%20margin-bottom%3A%20-100px%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%23print-site-page%20footer%20%7B%20display%20%3A%20none%3B%20%7D%0A%0A%0A%20%20%20%20%0A%20%20%20%20%23print-site-cover-page%20%7B%0A%20%20%20%20%20%20%20%20display%3A%20block%3B%0A%20%20%20%20%20%20%20%20width%3A100%25%3B%20%0A%20%20%20%20%20%20%20%20text-align%3A%20center%3B%0A%20%20%20%20%7D%0A%20%20%20%20%23print-site-cover-page%20h1%20%7B%0A%20%20%20%20%20%20%20%20font-size%3A%20300%25%3B%0A%20%20%20%20%7D%0A%0A%7D%0A%0A%0A/%2A%20%40page%20%7B%20%2A/%0A%0A%20%20%20%20/%2A%20%0A%20%20%20%20%20%20%20%20Note%20this%20CSS%20file%20is%20added%20to%20all%20MkDocs%20pages%0A%20%20%20%20%20%20%20%20So%20this%20%40page%20logic%20will%20affect%20print%20of%20all%20pages%0A%20%20%20%20%2A/%0A%0A%20%20%20%20/%2A%20Prevent%20image%20page%20overflow%20%2A/%0A%20%20%20%20/%2A%20img%20%7B%20max-width%3A500px%20%21important%3B%20%7D%20%2A/%0A%0A/%2A%20%7D%20%2A/" rel="stylesheet"/><!--URL:../css/print-site.css-->
|
||
<link href="data:text/css,/%2A%20print%20styles%20for%20mkdocs%20material%20theme%20%0Ahttps%3A//github.com/squidfunk/mkdocs-material%20%2A/%0A%0A%0A/%2A%20Table%20of%20Contents%20styling%20%2A/%0A.print-page-toc-title%20%7B%0A%20%20%20%20padding-bottom%3A%200em%3B%0A%20%20%20%20margin-bottom%3A%200%3B%0A%7D%0A%0A%23print-site-page%20ul.toc-section-line-border%20%7B%20%0A%20%20%20%20border-left%3A%205px%20solid%20var%28--md-default-fg-color--lightest%29%3B%0A%7D%0A%0A%0A/%2A%20Box%20shadows%20don%27t%20do%20well%20in%20PDFs%20%2A/%0A%23print-site-page%20table%20%7B%0A%20%20%20%20border%3A%201px%20solid%20hsla%28200%2C%2018%25%2C%2026%25%2C%201%29%3B%20/%2A%20%23EFEFEF%20%2A/%0A%20%20%20%20box-shadow%3A%20none%20%21important%3B%0A%7D%0A%0A%40media%20print%20%7B%0A%20%20%20%20%23print-site-page%20td%20%7B%0A%20%20%20%20%20%20%20%20word-wrap%3A%20break-word%3B%0A%20%20%20%20%7D%0A%7D%0A%0A%40page%20%7B%0A%0A%20%20%20%20/%2A%20%0A%20%20%20%20%20%20%20%20Note%20this%20CSS%20file%20is%20added%20to%20all%20MkDocs%20pages%0A%20%20%20%20%20%20%20%20So%20this%20%40page%20logic%20will%20affect%20print%20of%20all%20pages%0A%20%20%20%20%2A/%0A%0A%20%20%20%20size%3A%20a4%20portrait%3B%0A%20%20%20%20margin%3A%2015mm%2010mm%2025mm%2010mm%3B%0A%20%20%20%20counter-increment%3A%20page%3B%0A%0A%20%20%20%20%40bottom-center%20%7B%0A%20%20%20%20%20%20%20%20content%3A%20string%28chapter%29%3B%0A%20%20%20%20%7D%0A%20%20%20%20%40bottom-right%20%7B%0A%20%20%20%20%20%20%20%20content%3A%20%27Page%20%27%20counter%28page%29%3B%0A%20%20%20%20%7D%0A%0A%7D" rel="stylesheet"/><!--URL:../css/print-site-material.css-->
|
||
<script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
|
||
<script type="text/javascript">
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
generate_toc();
|
||
})
|
||
</script>
|
||
</head>
|
||
<body data-md-color-accent="blue" data-md-color-primary="light-blue" data-md-color-scheme="default" dir="ltr">
|
||
<input autocomplete="off" class="md-toggle" data-md-toggle="drawer" id="__drawer" type="checkbox"/>
|
||
<input autocomplete="off" class="md-toggle" data-md-toggle="search" id="__search" type="checkbox"/>
|
||
<label class="md-overlay" for="__drawer"></label>
|
||
<div data-md-component="skip">
|
||
</div>
|
||
<div data-md-component="announce">
|
||
</div>
|
||
<div data-md-color-scheme="default" data-md-component="outdated" hidden="">
|
||
</div>
|
||
<header class="md-header md-header--shadow" data-md-component="header">
|
||
<nav aria-label="En-tête" class="md-header__inner md-grid">
|
||
<a aria-label="LdapSaisie" class="md-header__button md-logo" data-md-component="logo" href="javascript:window.scrollTo(0,0)" title="LdapSaisie">
|
||
<img alt="logo" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAAAuCAYAAABtRVYBAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAZ5QAAGeUBblTa3gAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAABQqSURBVHic7Z17lBTVncc/35oZBnkjKKKODyDGB2bjK0GjCRKdh2KMm+DqbqIeo8H1GM1MDyHqbpATjQGZIWsSs2qymA3HqLhRI8r0EAMmisFoYqLGSEBFBZG3g8hrpn/7x62eru6p6tf0gOB8z7mnq6pv/X63u+t37+95W2ZGL3rRi3B4e3oAvejFhxnle3oApYCks4C5/umzZvaFPTmeUkJTWg8k0TEK84ZgrEW73mXryLV250m79sh4Yi2Xgb4PgNkca669vud4xacC9f7p962p5gc9xSsKJRMQSb8FRvmnzWZ2e6lo54FPAyP84zd3I98egRoWVqPEjcBJQH/wQLhGBQxYn1As/mewRcAiPO9Ju616624aXX+S37XnDephZgM7eTm+ux0lERBJ/YDPkVLZdvdDemLg+E+7mXfJoG8tGE2Hdw/i9BxdPeAk0ElAIwn7OnB3z4/wo4dSrSD/RLo9s7sf0qCA/Hk38y4JNHl+Pwb0eQjs+MDl9cB8sJWY1iCNwGw0YjRwClCx+wfKDoz3ALDEBz3MbBvYe/7Jjp7lFTGCUnixJF0N/Ng/3WBmw7tNNH/e+wMb/NOdwAAz2yP6eXegWHwOcJl/ahhTGFz5Y5s2fnto/ymtB5LgErCvAc3WVNO7gvQASrWCnBA43t0zeJD3S3ulcEx+voIBXJy6oFusqbop2z12W/VaYBYwS1Na94h+/lFAqQSkR1UcSQOB4bjVqS0L74JUO0mDgaHAGjMLnamLgSThxlthZqtz3jBo3TEkVJkiwP8Uwq9QA13XPzaUHX2H4m1rY+DzG23atEQh9xcDTX6+gv02jaTS2tm1eZM1T9rWo/ymT/dYd/pQ+u0cgpVtYeV7G+yBSR0F0+muiiWpAngf6ONfutjM7usWUUd3EHAd8G/AxwNvLQOagLvNzCT9ErjIf+9qM/tJFnpnAecCnwUOAfYLdFkL/BH4rpktzWN89wAH+adXmtlbkmqByUAdkHzgN+EEt8HM/hpKK9byFdAv/NOd1lRTGdavGGj64r60bZ+AdB7GBFAVWPBzb8VsKehnvN12f66HSLHWiWDX+KePWlPNjyP7NracgmkqcCruuwraqdtBL0AijiX+z5rPebHL/Q2tlyJzK6vZPdZcm/O5UqxlEugSYALQL/DWFlALZrOsuebZXHSSKMUKchwp4YASrCCSaoD/BQ4Mefso4E7gTElfwblCkwhdQSRVASvIbtQeiBOecyX9l5l9M8v4BgBfxf3gO4EtkubihDkTQ4HPA0slXWVmPw/pszFw3Eex1iprqn4ry1jzR9uOF0Fj6JwHu0yI/ZEmABOoGnSVGuf/s82auD6aoB0O1AAgrYjqpVj8Z6DLs4ysL9g40DjkjQG+0pWIfSzFy/t9FlqoYf4heBXzQKdGdBkINgkxSbF4M801jWZdv4xMlEJAgjbA+8A/ukNM0iTgXlJjWw/8zm+VOHfyObhV40VgjN+vAwidoXFqWFI4XgFeBlYCbwNDfBpfBJK6/HWSnjazeRH0gl675cD9QDXQDjwLLAS24YT3y7gIRl/gDkmtZvZOGrUEf0vPabCbgK9F8C4UydVoM7AU9AYkViJ1YByB8RnEJ/w+Z2AVv9KF884sRh1JQrGW6zOEYwniNyRYhzDQIZgdivgscHixfDr5NTwxCvX5HWaH+JcM+A3G35C9ibzRYKdhfNJ/v4H6eBnURE6CSZRaQP5iZkXrs5KOBeaQGtcvgUvMrD3QbaakK4G7gO/ih8+AV8wsSq8dDtwK3GtmL0XwHgzMA872LzX652EIfuZj/fYyUGtmb2fQrQEexglIP+AG4Btp1H5Qu5KG+J9I2VOXKxY/GmwG5TsX2YwvbIkYRz74PaKFRNuDYXq/hKiPX4z0U1/1OoOqwZdCYXZQJ73p0z0Yd4N/2oF0kc2qfjC0rxCNrWeSsIOL4eX4zeuDBj2AU5kBXiJhX7fZtc904dXQ8g3QTKAScZ2mxBfabTWPZaNfCgEpiYEuqQ/wIKlZ/E6cTdFF4MzsbkkX4HT9JCINdDP7WS7+ZvaepAtxK1YZcKwkWbiRdmLG+TPAuWa2KYRuXNJdwLX+pYlkCIgZpoaOy1DZc6TU1dNAj9Be2a6G+PNISxHPws54dhUog39TTZjal8Ybau5VQ7wy5RywqylSQGg7ZQwwwD9bEiUcKd7Vvy2KTye/QZeSUrM3kqDaZte+k9nN8aq9XQ3xIYjpACS4AcgqIN1KVpTk4dSNJLoTILwcOMY//jsRwhHATzPOu237mNlmnBMA3I8cFc8JCshaoC5MOAIICmiV79hI5+2M1Fqsi4pajvg02LWYzcUq1igW/50aW+s1eX6/TDrFwppr5uAcCgAn6Nu/GVwcIY0MnJXM2ZAF13YeGY02u6aLcKRhcOVMINnnNE1dcGi27t3N5g3OFlDkQ+qvHjcELt2ah6q2POO8VNH7oFB0iRRLqsSpVEncZNYZ7Y1C0JgtA44I62RNNYsYXPkJxFSw5wixqP37z8CsmQEVf1FD/IwcvAuAkjacx65dx2TtGoVyezVw9inn9eoZ+A/32M4L3q5Hc93jB15TXsr2ss9k699dFSs4k+7E6eHFoAao8o/fwBnpufB+4NjIIZy+5+l8nMtxLHAAMIiunq0D/Nd3zSwsvjA2cM9W4BchfdJgZlslbcfZIQCRwu//gDOBmZq68GDaE+cC4zBORhxPyuYCGIN4Ug2t51tzddaHQ42PHw5ll2M2GnQwTmcflEFvSOqGsoG5Plfo+Gees0aN8WcwfG+S/Vqx+GOYPUyFxW1G3dvZKRSAXd5pgdGvpKN8gOpbBmS5w8FTYJVJjIru2H0BKVUUOzjL3JthlEfhqMDxcjMLNWR9wbgRtxQXopJECXvwMy8ws/cj+gXHcBgp4QBYk88AbMbZq3FJiHcD6JtPjKBsVx3oRlLeO4HdoWsXPGm312UGUd0s2+7NgLILgfJ0eciCRNp4C0OCK/F4EmOYGx8TkSbSLhSLrwAWYDxGe2KR3V5XfI6Vx8jAGns4nl4vnIiypkWVcgXpjopzduD4b3neE1QBouIfhwCtpKtEbcBTONthPU7vTs7odbggYiRN0j/zMxF9MnFc4HhzxMqUE/aDz78L3KPpi++jbcdc4EsAiEMp967EBVA7oemL+9LuPUx6rGg1ZkuQtwGzDXhKTSxml5D+vRYFa655WVNaj8VocmNMC0yOBq5BXEOF964aW+ptVu0vi2OkIeFaaEFEsiZ8lnIFKdb+ECn1CvIXkOBD3+VhllQOPBLo93dgCrDQzEJnLUlBQY0SkOBnfiXPsY4NHC/O855I2LTx21W/+Aq8HWcC+wPgpWUBO2zZ2URKOFYj+xeaap+OCpApFq+jBAICnbliX9Xk+ZPpX3E2ogY4Ezg60G0EpnsVix9jTTXfKZxLYktgRXwWz6YWTKJDWVW+ogXEj04PC1wq1os0PGMcmcZ3GO9BuABcEmEPczDK/gow3szWZqF5IC4ImcTzIX3KSPfaRdLLwL8GjlvyvCcrbPb4zYq1PAeqdhd0bNdOdl7q2Dvfms5+jllZyR6V9d0iYHdO/AA3UT0CvsrXUXYBZo3AYX63G9Tw+LywdJPsxLUmoDEeZrfVLi7JoAPojhcrqGokgL8USacs43xYaK90XE3QoAwXzosCx3OyCYePSYGxbCE8I+Bo0vO3chqykuqgM4K7FfhVrnvyh4J2V5+0d65/bCiplXmzNZ/9XFZK9YuHkMot6zHYjLq3bVb1D9mVOJ7UZFiGV35WwcTUEfxMBzlHRGnRHQEJqhqvmllRxTNmtgb34CTxsWz9Je1Hqk4ZYKWZbQjpGqST/eFwtspNgUsvRAQIT8g4H52Nro9vB45/ZGbr8rgnX6QmKSNdVWgvC6ittpFcKNt5VclGlQd8h8KvA1cKXr2s6ZxluJQh/4J3TXTv4lAqAeluDOK1wPEVUZ38GMQDpCcxRql2QU9YVUSfpK1yL+nxj3wMdEhXncJo30TK6F8L3Bbar77lVMXil+jCeZmraTTthtZLgSNTFywjIu2toNOC1RG65onIlVnXPDEMK0J/D6OlfN1kQPA7T9hrWfplYxhwTKhe9Qs/Gd0589bcYy2VivWSpL4FtEy+gZmEL0v6csb7SOqPSwvIDDxFPcxBle/bvrs3k+bxuKDRZzPeysdAB5jg54Vl0vUk3QFM8y91ABdFrHRQxkjg51QNelWx1htV33JEBH80pbW/GuPXIbsrcPk9PG9usJ9fI5IMUHpUtt+pyc938dhoSutYKtufIl1lLR6x+LWKxR9SY2udy8sKh2ILxpH0wrkrfyiK386OuxAv+GdleIm4Yi2XZXv49a0Fo9XQcisN8SdzkS/KSJc0HAiG6G/1W744FQh+ITNxdRTDcUI7T9IDOHes4dLFx+N+xBeB7biabIh+mO/B2RXgPDPL/BqOFTjj8ARcgLIP8BDOTkjOyGFeMZEuID8B/h24S9J5wCJc8HI8rhYhqM/HzGxRxDiDGA12M55uViz+OtJSsFUkaMPTCEhUYTodl0KfRAKzq+y2mhAbS/8BnbU5X2LA+lcUa5kLLMcYieediNsiqR/iBYwNuO+6eCQoR3wRsy/SNu4tFzTUCmSvkeADYKTL4vXOIfn8mT3I7NqnaC6cnd1et0P1LRfg6WngYOBA0Bzq4/WKsRS0DNgIdgToSKfKeacgFJLW0wVpAiLpIOA7OMkWroDo+pBCn0xVoxC0k2HQm1mbpCtwe1slZ/oL/RbEYuBinJAkESogZva4pDtxggcwEsjcw8lwtfTTgKRtsI1w9+2RQDI/6Q2cy/hknKCe57dMbAO+kTNZ0rw1wCroTNd2/MycwAowIyTItwbjKmuufSSUbFP1/YrFq3F5bgCjQdPSaQLoRdq98ylv/xFWiIaUE1UYVWDumw4n3cLgvl/NpzYjCja79g3Vx0/G4z6S2oBL4f9Eepwkg4XoEljNRKeASDoSWIJLtUjqwnXA6ZLONbOnAvcNBnIuTxFYGZaWbmaPSDoZuAMYRyrqbf647sYVUe1PKsrd1qW2Ip3mVZKWALeQvuJ9ADwK/NDMnpZ0HK7eBGCZmYXVQqRlLfvpI+Nxxv0VpM/q63Gr0s1mlnMLJGuqXgIcqvqFn8SzcyFRB/o4dEaig/gA+BPG/fQp+4V9/6yseWDWVPM1NbQ+jLgF7FiCXkM3g85lcJ+ZNm38djXEX8S50EGEq4PSKiz529uyLu+3J+6m3FvuirBsAs7zl6mpbET2NDDTZtU+1YVG5/jsdeT5vBIrI/sBfpLi5xRrOQc0GScomWrjDpxR/zjSQwx85qlkPVYUOktuJc3HCUSY3rgOGBHh2Sk5fBsl6YVaHZVGUiDNobjinI3AO4WmxUj6HqkV6Dtm9t3Ae+W45X0YboeVVRFCVtiYp8/rw5b+I6F8uNtup30LA//4VrE15K4ufN0oyq2M7X3etR99PlwISggJEZs/jETFCKwsQXnizd2xyZ2mT/f44LSD2LVrGGXlxrayd4r5vDKzpHdoM0Tm32zG1Tss6c6g92ZIWgDU+qfnmdn8PTmeXuweJFeLAUC2GdVID5B9FBFUsV6I7NWLfQpJ3XAjLl09W7/IAv19HZJ87wgA6zLLavdW+KrhEL8NzfO1Ejp3ChZuklWO5uFc3ZtxKujGPF43dad8O8tn7lvIFk/lAP72ObOBqXRNnzDgD2b2RslGufdhr1o9/JjRobiaj7A2EvfA566d2HNISHoPZ/++ArwUaK92o7TivyXNMLO8Ek07vQtmdotft3AxzoOUlPpyoK+k/sWmae8D2JM7R6bBr748ElcPUkW4IOQql03g0v5fx83qm/y2OeM17Hg7btJMtkTGeZdmZgk/0XN/nCNjGC7mNSykBa/vjxPko3DFbknskrQMJywvkxKcFXmsOuXAEklfMsvMPgjv3AkzmyypGbc/VD9cHORm4Azgcd/dm7NAaB9EJakyzcU9zUxSX1ye15iQdhjZMyC24urqV+G2NVoVcrymJ9SXbPC9eutIxZvygu99PBpXMjAWV1uTfD0uo/s2ScnV5q+40obMGF4Cpyq2SJpsZnOy8s/lufW3w2nBxSb+iNs58SNrj5QKvhoUJgBjcKtAWFjNgNW4LNjluIDlqkB7O4/6+H0CfjbH2JCWuXq+iUtRehSX7fBn0mtSbgH+MyqEkdfWo/7euL/GpVFsxW2jeVfWm3qRrFuJEoKREbclcLP9P0gJQrKtyLL3Vy8AScmNHD6F04ROITXZbCPcG3sfcFlYIV3ee/P6OuRUXOS4Ard74A1mljWVfF+HpANw6tAougrBARG3deAiupkCsBx4LarisReFQ9IInKBM9FtUie0S4HwzS9tzrODNqyWdiMuZSpZmPobb+mafFBR/YqjCCUFYiyqa2oVTgZbTdTV4Y2/8m4a9GZJOwtmR2UoK2oBPm9nfO+8rJnvE96Rchku9OMK//BLOVmkBfm9m2eIqHyrI/YXcKMIF4HCiZ52tuFqW13BxohWkhGBlKdJNetF9SDoVN5EPzdUX5627wMyehCIFJMC4HLfL+TehcwNkcA/Ob/EFxqzIYpgSIqAKhbVspabvkBKAtFcze7cnx9yL0kDSGbgtbTv/CjXjVbg9wvbHGfU7cc+tleQv2PxBHIrLVarF/Q9H0JuwHOevXo3ztqwOHpvlURLalV8/XHT7gJDXzGvDSO35m4kdOFUouAokj18vtpS4F/sGSiYgaUTdynIqTliSmxZkKzTYjhOYdpyOmKtVkLFJQQ5swvcC0XU1WLW7YwK92HvQIwLShYn7o83DcP79g/2WeXwA0ULUkdHacVHddbha73XZjntXgV4Ui90iIPnA3/F8PzKEoXd278WexIdGQHrRiw8j/h+c20IoEFD+pgAAAABJRU5ErkJggg=="/><!--URL:../assets/images/logo.png-->
|
||
</a>
|
||
<label class="md-header__button md-icon" for="__drawer">
|
||
<svg viewbox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"></path></svg>
|
||
</label>
|
||
<div class="md-header__title" data-md-component="header-title">
|
||
<div class="md-header__ellipsis">
|
||
<div class="md-header__topic">
|
||
<span class="md-ellipsis">
|
||
LdapSaisie
|
||
</span>
|
||
</div>
|
||
<div class="md-header__topic" data-md-component="header-topic">
|
||
<span class="md-ellipsis">
|
||
|
||
Documentation
|
||
|
||
</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
|
||
|
||
</nav>
|
||
</header>
|
||
<div class="md-container" data-md-component="container">
|
||
<main class="md-main" data-md-component="main">
|
||
<div class="md-main__inner md-grid">
|
||
|
||
|
||
<div class="md-content" data-md-component="content">
|
||
<article class="md-content__inner md-typeset">
|
||
<div class="print-site-enumerate-headings print-site-enumerate-figures" id="print-site-page">
|
||
<section id="print-site-cover-page">
|
||
<div style="padding-bottom: 3em">
|
||
<h1>LdapSaisie</h1>
|
||
<h2>Documentation</h2>
|
||
</div>
|
||
<p>
|
||
<small>
|
||
Auteur: Benjamin Renard
|
||
(<a href="mailto:brenard@easter-eggs.com">brenard@easter-eggs.com</a> /
|
||
<a href="mailto:brenard@zionetrix.net">brenard@zionetrix.net</a>)
|
||
</small><br/>
|
||
<small>Site web: <a href="https://ldapsaisie.org/doc/">https://ldapsaisie.org/doc/</a></small><br/>
|
||
<small>Repo: <a href="https://gitlab.easter-eggs.com/ee/ldapsaisie">https://gitlab.easter-eggs.com/ee/ldapsaisie</a></small><br/>
|
||
<small>Easter-eggs</small><br/>
|
||
</p>
|
||
</section>
|
||
|
||
<section class="print-page">
|
||
<div data-toc-depth="6" id="print-page-toc">
|
||
<nav class="print-page-toc-nav" role="navigation">
|
||
<h1 class="print-page-toc-title">Table des matières</h1>
|
||
</nav>
|
||
</div>
|
||
</section>
|
||
<section class="print-page" id="index"><h1 id="index-introduction">Introduction</h1>
|
||
<p>LdapSaisie est une application web d'administration d'annuaire LDAP développée en PHP/Javascript.
|
||
Cette application a pour but d'abstraire la complexité d'un annuaire par l'intermédiraire d'une
|
||
interface d'administration simple et intuitive. L'application a été concue avec pour objectif
|
||
premier une modularité maximum, ce qui permet l'extention ou l'adaptation facile de l'application
|
||
par l'intermédiaire de modules, d'extentions et de greffons. Cette application peut être utilisée
|
||
pour administrer le système d'information basé sur l'annuaire LDAP et également en paralèlle pour
|
||
permettre aux utilisateurs d'avoir accès aux données les concernants et éventuellement de les
|
||
modifier.</p>
|
||
<h2 id="index-fonctionnalites">Fonctionnalités</h2>
|
||
<p>De part sa modularité, LdapSaisie est facilement extensible. Cependant, voici une liste
|
||
non-exhaustive de ses fonctionnalités :</p>
|
||
<ul>
|
||
<li>Gestion d'annuaire simple et multi-branches</li>
|
||
<li>Gestion d'un nombre illimité de types d'objets</li>
|
||
<li>Gestion d'un nombre illimité de populations se connectant à l'interface</li>
|
||
<li>Gestion fine des droits des utilisateurs, permettant la maitrise des droits d'accès sur les objets
|
||
de l'annuaire et leurs atributs, tout en permettant la délégation de droits.</li>
|
||
<li>
|
||
<p>Gestion d'un grand nombre de types d'attributs :</p>
|
||
<ul>
|
||
<li>Texte (court ou long)</li>
|
||
<li>Date (format paramétrable)</li>
|
||
<li>Booléen (valeurs paramétrables)</li>
|
||
<li>Image/Photo</li>
|
||
<li>Mot de passe (génération de mot passe avec gestion d'une politique fine)</li>
|
||
<li>Adresse mail</li>
|
||
<li>Flux RSS</li>
|
||
<li>Lien web (URL)</li>
|
||
<li>Adresse XMPP</li>
|
||
<li>Maildir</li>
|
||
<li>Quota de mails</li>
|
||
<li>Clef publique SSH</li>
|
||
<li>Liste déroulante à choix simple ou multiple</li>
|
||
<li>
|
||
<p>Relation à d'autres objets de l'annuaire/ Exemple : membres d'un groupe, parrain d'un
|
||
utilisateur, ... (valeur clé paramétrable)</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Chaque type d'attribut à des fonctionnalités qui lui sont propres et qui rendent plus facile
|
||
et agréable l'utilisation de l'interface (génération automatique de mot de passe, génération
|
||
des valeurs d'un champ à partir d'autres, ...).</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Gestion d'un grand nombre de règles de vérification des valeurs des attributs :<ul>
|
||
<li>Alpha-numérique</li>
|
||
<li>Lettres uniquement</li>
|
||
<li>Longeur maximale/minimale d'une chaine de caractères</li>
|
||
<li>Valeur différente de zéro</li>
|
||
<li>Pas de signe de ponctuation</li>
|
||
<li>Valeur numérique</li>
|
||
<li>Comparaison de valeur</li>
|
||
<li>Date</li>
|
||
<li>Adresse mail</li>
|
||
<li>Poids d'une image</li>
|
||
<li>Taille d'une image</li>
|
||
<li>Type de fichiers images</li>
|
||
<li>Politique de mot de passe (longueur/caractères autorisés/caractères obligatoires)</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Gestion simplifiée des relations entre les objets de l'annuaire</li>
|
||
<li>Interface facilement personnalisable grâce à l'utilisation d'un système de template.</li>
|
||
<li>Possibilité de postionner des déclencheurs permettant d'exécuter vos propres scripts, fonctions ou
|
||
méthodes au moments précis ou l'utilisateur créé, modifie ou supprime un objet ou un de ses
|
||
attributs. Ces déclencheurs, en fonction de leur positionnement, peuvent influencer le
|
||
comportement de l'application en empêchant par exemple, la validation des données d'un formulaire.</li>
|
||
<li>Gestion fine de l'affichage des attributs en fonction de l'écran (=vue) sur lequel se trouve
|
||
l'utilisateur.</li>
|
||
<li>Gestion des dépendances entre attributs, permettant par exemple de regénérer automatiquement la
|
||
valeur d'un attribut caché lors de la modification d'un autre.</li>
|
||
<li>Possibilité de gérer des attributs entièrement cachés, dont les valeurs seront modifiées lors de
|
||
la modification d'attribut en dépendance.</li>
|
||
</ul></section><h1 class="nav-section-title">Installation</h1><section class="print-page" id="install-requirements"><h1 id="install-requirements-pre-requis">Pré-requis</h1>
|
||
<ul>
|
||
<li>Le service Apache HTTP avec le module mod_rewrite d'activé. Les règles de réécriture d'URL sont
|
||
définies dans le fichier <code>.htaccess</code> fourni avec l'application et il est donc nécessaire
|
||
d'autoriser une telle configuration à ce niveau via la directive <code>AllowOverride</code> devant inclure à
|
||
minima <code>FileInfo</code>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>L'utisateur exécutant le serveur web doit avoir les droits d'écriture sur le dossier <code>tmp</code>. En cas
|
||
d'installation à partir du paquet Debian, ce dossier est remplacé par un lien symbolique vers
|
||
le dossier <code>/var/cache/ldapsaisie/</code>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>PHP 5.6 (ou supérieur) avec <code>magic_quotes_gpc</code> et <code>register_globals</code> à <code>off</code>. L'outil CLI de PHP
|
||
est par ailleurs nécessaire pour l'utilisation des outils CLI fournis avec l'application (fourni
|
||
par le paquet <code>php-cli</code> dans Debian).</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le support LDAP dans PHP (paquet <code>php-ldap</code> dans Debian)</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le support mhash dans PHP (paquet <code>php5-mhash</code> dans Debian Lenny, intégré à <code>php-common</code> dans les
|
||
versions supérieurs)</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le support json dans PHP (<code>pear install pecl/json</code> sur RedHat, intégré au paquet <code>php5-common</code>
|
||
précédement)</li>
|
||
</ul>
|
||
<ul>
|
||
<li><a href="http://pear.php.net/package/Net_LDAP2">Net_LDAP2</a> (paquet <code>php-net-ldap2</code> dans Debian ou
|
||
<code>pear install net_ldap2</code>)</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le support mbstring dans PHP (paquet <code>php-mbstring</code> depuis Debian Stretch, intégré au paquet
|
||
<code>php-common</code> dans Debian)</li>
|
||
</ul>
|
||
<ul>
|
||
<li><a href="http://www.smarty.net/">Smarty</a> (paquet <code>smarty3</code> dans Debian)</li>
|
||
</ul>
|
||
<ul>
|
||
<li>La librairie <a href="https://pear.php.net/package/Console_Table">Console_Table</a> (nécessaire pour le
|
||
fonctionnement de l'outil CLI, paquet <code>php-console-table</code> dans Debian)</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Les librairies <a href="https://pear.php.net/package/Mail">Mail</a> et
|
||
<a href="https://pear.php.net/package/Mail_Mime">PEAR_Mail_Mime</a> (nécessaire pour l'envoi de courriels,
|
||
paquets <code>php-mail</code> et <code>php-mail-mime</code> dans Debian)</li>
|
||
</ul>
|
||
<ul>
|
||
<li>L'<a href="https://www.php.net/manual/fr/intro.ftp.php">extension PHP <code>ftp</code></a> (nécessaire pour le
|
||
fonctionnement du <a href="#conf-configuration-des-lsaddons">LSaddon</a> FTP, paquet <code>php-ftp</code>
|
||
dans Debian)</li>
|
||
</ul>
|
||
<ul>
|
||
<li>La librairie <a href="https://github.com/phpseclib/phpseclib">PhpSecLib</a> (nécessaire pour le
|
||
fonctionnement du <a href="#conf-configuration-des-lsaddons">LSaddon</a> SSH, paquet
|
||
<code>php-phpseclib</code> dans Debian)</li>
|
||
</ul>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>La librairie <a href="http://pear.php.net/package/Net_LDAP2">Net_LDAP2</a> oblige le fait que la racine DSE
|
||
de l'annuaire soit lisible en anonyme sinon la connexion à l'annuaire échouera systématiquement.</p>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette documentation est écrite à l'aide du langage Markdown et est mis en forme pour une
|
||
consultation en ligne à l'aide de <a href="https://www.mkdocs.org/">mkdocs</a> et son thème
|
||
<a href="https://squidfunk.github.io/mkdocs-material/">mkdocs-material</a>. Le dépendances pour construire
|
||
cette documentation sont listées dans le fichier <code>doc/requirements.txt</code> et sont installables à
|
||
l'aide de la commande <code>pip install -r doc/requirements.txt</code>.</p>
|
||
</div></section><section class="print-page" id="install-download"><h1 id="install-download-telechargement">Téléchargement</h1>
|
||
<h2 id="install-download-a-partir-du-paquet-debian">À partir du paquet Debian</h2>
|
||
<p>L'installation à partir du paquet Debian peut être réalisée soit en téléchargeant manuellement le
|
||
paquet, soit en déclarant le dépôt APT suivant dans votre fichier <code>/etc/apt/sources.list</code> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#install-download-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>deb http://ldapsaisie.org/debian stable main
|
||
</code></pre></div>
|
||
<p>Il ne vous restera ensuite plus qu'a installer le paquet <code>ldapsaisie</code> avec la commande suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#install-download-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>apt-get install ldapsaisie
|
||
</code></pre></div>
|
||
<p>Le fichier <code>/etc/ldapsaisie/apache.conf</code> est un example de configuration du serveur web Apache. La
|
||
configuration du logiciel ce fera ensuite dans le dossier <code>/etc/ldapsaisie/local/</code>.</p>
|
||
<h2 id="install-download-a-partir-de-git">À partir de Git</h2>
|
||
<p>Le dépôt Git peut être récupéré anonymement en utilisant la commande suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#install-download-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>git clone https://gitlab.easter-eggs.com/ee/ldapsaisie.git
|
||
</code></pre></div>
|
||
<p>La racine web de l'application se trouvera alors dans le dossier <code>/ldapsaisie/src/public_html/</code>.</p>
|
||
<h2 id="install-download-a-partir-des-snapshot">À partir des snapshot</h2>
|
||
<p>Toutes les nuits, un snapshot de l'arbre Git est réalisé et est téléchargeable au format <em>tar.gz</em> à
|
||
l'adresse suivante :</p>
|
||
<p><a href="http://ldapsaisie.org/download/ldapsaisie-snapshoot.tar.gz">http://ldapsaisie.org/download/ldapsaisie-snapshoot.tar.gz</a></p></section><section class="print-page" id="install-arbo"><h1 id="install-arbo-arborescence-du-projet">Arborescence du projet</h1>
|
||
<ul>
|
||
<li>
|
||
<p><code>doc/</code></p>
|
||
<p>Les fichiers sources de la documentation (Markdown & configuration Mkdocs).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>lsexample/</code></p>
|
||
<p>Les fichiers relatifs à l'annuaire d'exemple.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>src/</code></p>
|
||
<p>Les sources de l'application.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>public_html/</code></p>
|
||
<p>La racine web de l'application : celle-ci ne contient que les fichiers <code>.htaccess</code> et
|
||
<code>index.php</code> qui configure et déclenche la réécriture d'URL.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>conf/</code></p>
|
||
<p>Contient les fichiers de configuration.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSobjects/</code></p>
|
||
<p>Configuration des <a href="#conf-configuration-lsobject">LSobjects</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSaddons/</code></p>
|
||
<p>Configuration des <a href="#conf-configuration-des-lsaddons">LSaddons</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSauth/</code></p>
|
||
<p>Configuration des <a href="#conf-configuration-des-lsauthmethods">LSauthMethod</a>.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>includes/</code></p>
|
||
<p>Contient les fichiers des ressources.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>addons/</code></p>
|
||
<p>Les addons au projet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>class/</code></p>
|
||
<p>Les fichiers de définition des classes PHP.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>js/</code></p>
|
||
<p>Les fichiers Javascript.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>libs/</code></p>
|
||
<p>Les librairies utilisées.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>lang/</code></p>
|
||
<p>Les fichiers d'internationalisation.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>templates/</code></p>
|
||
<p>Les fichiers <em>template</em> de l'interface. Il y a un sous-dossier par template.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>css/</code></p>
|
||
<p>Les fichiers css de l'interface. Il y a un sous-dossier par template CSS.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>images/</code></p>
|
||
<p>Les images de l'interface. Il y a un sous-dossier par template d'image.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>local/</code></p>
|
||
<p>Les fichiers personnalisés de l'installation.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>tmp/</code></p>
|
||
<p>Les fichiers temporaires (y compris le cache des templates).</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul></section><section class="print-page" id="install-howto"><h1 id="install-howto-tutoriel-dinstallation">Tutoriel d'installation</h1>
|
||
<p>Cette section décrit les différentes étapes de l'installation de LdapSaisie. Deux méthodes
|
||
d'installation sont présentées ici, l'une à partir des sources du projet et l'autre à partir du
|
||
paquet Debian.</p>
|
||
<p>Dans ce tutoriel, nous partirons du principe que vous avez pleinement la main sur votre serveur
|
||
(installation de nouveau paquet et configuration de votre serveur web). Nous partons également du
|
||
principe que votre annuaire LDAP est déjà en place. Nous utiliserons pour cette exemple de mise en
|
||
oeuvre l'annuaire correspondant au schéma et à la configuration présente dans les sources du projet
|
||
dans le dossier <code>lsexample</code>.</p>
|
||
<p>La première étape consiste à installer le locigiel en tant que tel. Pour cela, référez vous au
|
||
chapitre <a href="#install-howto-telechargement">Téléchargement</a>.</p>
|
||
<p>En cas d'installation à partir du paquet Debian, la configuration du logiciel se fera dans le
|
||
dossier <code>/etc/ldapsaisie/local/</code>. Les fichiers placés dans ce dossier prévaleront toujours aux
|
||
fichiers fournis par le paquet Debian, vous permettant facilement de modifier un composant existant
|
||
ou dans écrire de nouveaux. Ainsi, pour modifier un fichier CSS par exemple, il vous suffira de le
|
||
placer dans le dossier <code>/etc/ldapsaisie/local/css/</code>.</p>
|
||
<p>Pour une installation à partir du code source, il vous faut cloner le dépôt Git du projet dans le
|
||
dossier <code>/var/www/ldapsaisie</code>. Pour cela il vous faut avoir installés les outils de Git contenu,
|
||
dans Debian, dans le paquet <code>git-core</code>. Le dépôt Git doit ensuite être récupéré anonymement en
|
||
utilisant la commande suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#install-howto-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>git clone https://gitlab.easter-eggs.com/ee/ldapsaisie.git /var/www/ldapsaisie
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour que cette commande se déroule correctement, vous devez avoir accès au port TCP 443 du
|
||
serveur <code>gitlab.easter-eggs.com</code>. En cas de problème vérifiez votre parefeu.</p>
|
||
</div>
|
||
<p>La suite des opérations se déroulera donc maintenant dans le dossier <code>/var/www/ldapsaisie</code>. Pour
|
||
avoir plus de détails sur les élements qu'on retrouve dans ce dossier, vous pouvez consulter
|
||
<a href="#install-howto-arborescence-du-projet">la section concernée</a>. Nous allons nous instérésser plus particulièrement :</p>
|
||
<ul>
|
||
<li>au script <code>upgradeFromGit.sh</code> permettant la mise à jour de votre repos tout en concervant les
|
||
adaptations que nous ferons pour l'usage d'LdapSaisie adapté à notre annuaire ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>au dossier <code>config.local</code> dans lequel seront stockés vos fichiers et vos adaptations de
|
||
l'application ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>au dossier <code>src/public_html</code> qui correspond à la futur racine du site web de l'application.</li>
|
||
</ul>
|
||
<p>Le principe de l'adaptation est ici de mettre vos fichiers personnalisés dans le dossier
|
||
<code>config.local</code>, de les déclarer dans votre fichier <code>config.local/local.sh</code> contenant la liste des
|
||
fichiers devant être installés. Le fichier <code>local.sh</code> est la source de configuration du script
|
||
<code>upgradeFromGit.sh</code>. Il faut donc dans un premier temps créer votre fichier <code>local.sh</code> en copiant le
|
||
fichier d'example <code>local.sh.example</code>. Ce fichier est un script bash déclarant les variables de
|
||
configurations suivantes :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>LOCAL_FILES</code></p>
|
||
<p>La liste des chemins des fichiers à installer dans l'arboressence du site. Cette élément doivent
|
||
être séparés par des espaces ou des retour à la liste. Exemple :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#install-howto-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>conf/config.inc.php
|
||
<a href="#install-howto-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a>lang/fr_FR.UTF8/lang.php
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LOG_FILE</code></p>
|
||
<p>Nom du fichier de log des mises à jour.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>THEME</code></p>
|
||
<p>Le nom du theme à installer (facultatif et non traité dans ce tutoriel).</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Il est possible d'utiliser dans ce fichier de configuration la variable bash <code>$ROOT_DIR</code>
|
||
correspondant au chemin du dossier d'installation, c'est à dire dans notre exemple
|
||
<code>/var/www/ldapsaisie</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<p>La deuxième étape concerne la configuration globale de l'application : Cette partie est
|
||
principalement contenue dans le fichier <code>src/conf/config.inc.php</code> (ou
|
||
<code>/etc/ldapsaisie/local/conf/config.inc.php</code> en cas d'installation à partir du paquet Debian). En cas
|
||
d'installation à partir du code source, il faut donc dans un premier temps copier ce fichier dans le
|
||
dossier <code>config.local</code> et le déclarer dans la liste des fichiers à déployer lors des mises à jour
|
||
(variable <code>LOCAL_FILES</code> dans le fichier <code>local.sh</code>). Il s'agit en particulier dans ce fichier de
|
||
configurer la connexion à votre annuaire. Vous pouvez vous inspirer du fichier d'exemple fourni et
|
||
pour plus de détails, reportez-vous à <a href="#install-howto-configuration-globale">la section concernée</a>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Notez qu'il est possible de passer l'application en mode <em>debug</em> ce qui peut être utile par la
|
||
suite.</p>
|
||
</div>
|
||
<p>La troisième étape concerne la configuration des types de
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a> : Chaque type d'objet manipulé par
|
||
LdapSaisie doit correspondre avec un type de LSobject.</p>
|
||
<ol>
|
||
<li>
|
||
<p>Création du fichier de classe <em>(optionnel)</em> : Ce fichier contient la déclaration de la classe PHP
|
||
correspondant au type de LSobject. Cette classe étend la classe <code>LSldapObject</code> qui contient pour
|
||
ainsi dire toute les méthodes et proprités nécessaires pour les types de LSobject simples. Si
|
||
votre type de LSobject nécessite des méthodes ou propriétés particulières, vous pouvez implémenter
|
||
cette classe. À défaut, une classe vierge d'adaptation sera automatiquement déclarée.</p>
|
||
<p>Les fichiers des classes sont contenus dans le dossier <code>/includes/class/</code> et portent les noms
|
||
composés de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#install-howto-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>class.LSobjects.[nom du type d'LSobject].php
|
||
</code></pre></div>
|
||
</li>
|
||
<li>
|
||
<p>Configurer vos LSobject : Cette partie est certainement la plus longue et consiste à déclarer
|
||
l'ensemble des informations relatives aux types des objets LDAP manipulés. Les fichiers d'exemples
|
||
fournis vous seront alors d'une aide précieuse. Basez vous sur l'un de pour créer le votre. Pour
|
||
cela le fichier de configuration du type d'LSobjet <code>LSpeople</code> est le plus complet et est un bon
|
||
point de départ. Pour plus de détails sur les élements de configuration de ce fichier,
|
||
reportez-vous à <a href="#conf-lsobject-configuration-lsobject">la section concernée</a>.</p>
|
||
</li>
|
||
<li>
|
||
<p>Configurer si nécessaire les relations entre les objets appelés <a href="#install-howto-lsrelation">LSrelations</a>. Les
|
||
relations les plus simples (via un attribut de liaison) pourront être implémentées à l'aide d'un
|
||
simple paramètrage. Pour des relations, plus complexes, il sera possible d'implémenter des
|
||
méthodes personnalisées pour les gérer. Pour plus de détails, reportez-vous à
|
||
<a href="#conf-lsrelation">la section concernée</a>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour avoir un exemple de fichier de classe PHP implémentant des methodes de gestion de
|
||
<a href="#install-howto-lsrelation">LSrelations</a> complexes, vous pouvez consulter le fichier de classe <code>LSgroup</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ol>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>En cas d'installation à partir du code source, pensez à déclarer les fichiers que vous venez de
|
||
créer dans la variable <code>LOCAL_FILES</code> du fichier <code>local.sh</code>. Exemple pour le type d'LSobjet
|
||
portant comme nom <code>LSexample</code> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#install-howto-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a>src/conf/LSobjects/config.LSobjects.LSexample.php
|
||
<a href="#install-howto-__codelineno-3-2" id="__codelineno-3-2" name="__codelineno-3-2"></a>src/includes/class/class.LSobjects.LSexample.php
|
||
</code></pre></div>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Vous pouvez également personnaliser l'interface : Il est possible de personnaliser à votre goût
|
||
l'interface en écrivant votre template ou en modifiant simplement les fichiers CSS. Une partie
|
||
de cette documentation concernera bientôt cette problématique. Patience...</p>
|
||
</div>
|
||
<p>En cas d'installation à partir du code source, une dernière étape à ce niveau consiste à lancer le
|
||
script <code>upgradeFromGit.sh</code> pour qu'il installe les fichiers que vous venez de créer. Ce script est
|
||
conçu pour dire tout ce qu'il fait donc en cas de problème vous devriez rapidement comprendre où
|
||
cela coince. Dans tout les cas, n'hésitez pas à poser vos questions à la communauté sur la liste
|
||
<a href="mailto:ldapsaisie-users@lists.ldapsaisie.org">ldapsaisie-users@lists.ldapsaisie.org</a>.</p></section><h1 class="nav-section-title-end">Ended: Installation</h1><h1 class="nav-section-title">Mise à jour</h1><section class="print-page" id="upgrade"><h1 id="upgrade-mise-a-jour">Mise à jour</h1>
|
||
<p>Cette section de la documentation détaille la procédure de mise à jour d'une installation existante
|
||
et regroupe des informations pratiques et utiles pour des montées de versions spécifiques entraînant
|
||
par exemple une perte de rétrocompatibilité de la configuration.</p></section><section class="print-page" id="upgrade-method"><h1 id="upgrade-method-procedure-de-mise-a-jour">Procédure de mise à jour</h1>
|
||
<h2 id="upgrade-method-installation-via-paquet-debian">Installation via paquet Debian</h2>
|
||
<p>Lors d’une installation par paquet Debian, la mise à jour est grandement facilité par le packaging :
|
||
Il vous suffit de mettre à jour le paquet <code>ldapsaisie</code> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-method-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>apt<span class="w"> </span>update
|
||
<a href="#upgrade-method-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>apt<span class="w"> </span>install<span class="w"> </span>ldapsaisie
|
||
</code></pre></div>
|
||
<p>Une fois l’application mise à jour, prêté attention aux nouveautés et point de vigilances décrite
|
||
dans la section suivante.</p>
|
||
<h2 id="upgrade-method-installation-a-partir-des-sources">Installation à partir des sources</h2>
|
||
<p>Lors d’une installation par à partir des sources, le script <code>upgradeFromGit.sh</code> permet d’automatiser
|
||
la mise à jour, à condition que vous ayez suivi la procédure d’installation à ce sujet.</p>
|
||
<p>Ce script s’occupera alors de :</p>
|
||
<ul>
|
||
<li>Nettoyer <code>working-tree</code> Git des liens symboliques des fichiers locaux (et éventuellement du
|
||
thème) mis en place lors d’une précédente exécution ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Vider le cache des templates ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Mettre à jour le <code>working-tree</code> Git via un <code>git pull</code> de la mise à jour ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Installer des liens symboliques pour les fichiers locaux. En cas de fichier remplacant un fichier
|
||
livré avec l’application, le script vous notifiera en cas de changement intervenu dans le fichier
|
||
fourni avec l’application et vous permettra de le mettre à jour simplement votre fichier local
|
||
(via un <code>vim -d</code>) ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Détecter des changements dans les fichiers <code>MO</code> (traduction) et de déclencher dans ce cas un
|
||
rechargement du serveur web pour prise en compte ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Option : de compiler une version locale à jour de la documentation ;</li>
|
||
</ul>
|
||
<p>Une fois l’application mise à jour, prêté attention aux nouveautés et point de vigilances décrite
|
||
dans la section suivante.</p></section><section class="print-page" id="upgrade-2_4_1-to-3_0_0"><h1 id="upgrade-2_4_1-to-3_0_0-mise-a-jour-241-300">Mise à jour 2.4.1 -> 3.0.0</h1>
|
||
<p>Cette mise à jour majeure apporte de nombreuses nouveautés auxquelles il est important de prêter
|
||
attention. Cette section ne parlera pas particulièrement de ces nouveautés, mais vous pouvez
|
||
consulter le fichier
|
||
<a href="https://gitlab.easter-eggs.com/ee/ldapsaisie/-/raw/master/debian/ldapsaisie.NEWS">debian/ldapsaisie.NEWS</a>
|
||
pour cela. Cette section listera en outre les points de vigilances à avoir et les adaptations à
|
||
apporter sur votre configuration et votre code personnalisé.</p>
|
||
<h2 id="upgrade-2_4_1-to-3_0_0-fichier-configincphp">Fichier config.inc.php</h2>
|
||
<ul>
|
||
<li>ajout du paramètre <code>ConsoleTable</code> avec pour valeur par défaut sous Debian
|
||
<code>/usr/share/php/Console/Table.php</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>ajout du paramètre <code>public_root_url</code> avec pour valeur par défaut sous Debian <code>/ldapsaisie</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>paramètre <code>$GLOBALS['defaultCSSfiles']</code> : il est nécessaire de modifier les URLs des fichiers
|
||
listés : seul le nom du fichier doit rester, sa localisation sera détectée automatiquement. Par
|
||
exemple, <code>$GLOBALS['defaultCSSfiles'] = array('../light-blue.css');</code> devient
|
||
<code>$GLOBALS['defaultCSSfiles'] = array('light-blue.css');</code>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>les paramètres <code>authObjectType</code>, <code>authObjectFilter</code> et <code>authObjectTypeAttrPwd</code> sont remplacés par
|
||
le tablau <code>LSobjects</code> dans le paramètre <code>LSauth</code>.</p>
|
||
<p>Par exemple:</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'authObjectType' => 'LSpeople',
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>'authObjectFilter' => '(|(uid=%{user})(mail=%{user}))',
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>'authObjectTypeAttrPwd' => 'userPassword',
|
||
</code></pre></div>
|
||
<p>Devient:</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>'LSauth' => array (
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> 'LSobjects' => array(
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> 'LSpeople' => array(
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> 'filter' => '(|(uid=%{user})(mail=%{user}))',
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> 'password_attribute' => 'userPassword',
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> ),
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> ),
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a> [...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a>),
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Une erreur de frappe historique a été corrigé dans le nom de la variable
|
||
<code>$GLOBALS['defaultJSscripts']</code>, à savoir un <em>"R"</em> manquant.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Les fichiers Javascript utilisés par défaut par l'application ne sont désormais plus listés dans
|
||
la variable <code>$GLOBALS['defaultJSscripts']</code>. Seul doit y demeurer vos propres fichiers. Voici la
|
||
liste des fichiers concernés et qui n'ont plus à être inclus via ce paramètre :<p>- <code>mootools-core.js</code>
|
||
- <code>mootools-more.js</code>
|
||
- <code>functions.js</code>
|
||
- <code>LSdefault.js</code>
|
||
- <code>LSinfosBox.js</code></p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="upgrade-2_4_1-to-3_0_0-fichiers-css">Fichiers CSS</h2>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Les fichiers <code>light-*.css</code> ont été retravaillés pour tous <em>hériter</em> du fichier <code>light-blue.css</code>
|
||
qui défini les couleurs de l'interface au travers des variables. Ainsi, il est très simple
|
||
d'ajuster ce thème à vos couleurs. Si cela vous intéresse, vous pouvez prendre exemple sur les
|
||
autres fichiers <code>light-*.css</code>.</p>
|
||
<p>Au passage, ce thème a été retravaillé pour prendre en compte la mise en forme d'un maximum de
|
||
composants de l'application tout en profitant du côté responsive de l'interface apporter par
|
||
cette mise à jour. Si vous avez un thème personnalisé, il est conseillé de regarder si celui-ci
|
||
ne pourrait pas tirer partie du fichier <code>light-blue.css</code> en le surchargeant. À minima, vous
|
||
pouvez analyser les évolutions de ce fichier pour identifier les modifications intéressantes à
|
||
reporter sur votre thème personnel.</p>
|
||
</div>
|
||
<ul>
|
||
<li>Si vous utilisez un des fichiers <code>light-*.css</code> autre que le fichier <code>light-blue.css</code>, vous devez
|
||
désormais également charger ce dernier en premier.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>corriger les URL des images : <code>url(../../images/default/find.png)</code> devient <code>url(../image/find)</code>.
|
||
Pour identifier les fichiers CSS concernés, vous pouvez utiliser les commandes suivantes :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'url\(.*images'</span><span class="w"> </span>/etc/ldapsaisie/local/css
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-2-2" id="__codelineno-2-2" name="__codelineno-2-2"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'url\(.*\.(png|gif|jpg)'</span><span class="w"> </span>/etc/ldapsaisie/local/css
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>modification CSS page <code>fatal_error</code> (fichier <code>base.css</code>) : <code>#fatal_error</code> devient <code>#error</code></li>
|
||
</ul>
|
||
<h2 id="upgrade-2_4_1-to-3_0_0-fichiers-php">Fichiers PHP</h2>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSsession :: redirect()</code> devient <code>LSurl :: redirect()</code>. Pour identifier les fichiers CSS
|
||
concernés, vous pouvez utiliser la commande suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'LSsession *:: *redirect *\('</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Les méthodes de gestion des Javascript et CSS additionels ont été migrées de la classe <code>LSsession</code>
|
||
vers la classe <code>LStemplate</code> :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSsession :: addJSscript()</code> devient <code>LStemplate :: addJSscript()</code>.</p>
|
||
<p>Par ailleurs le paramètre <code>$path</code> disparait et la méthode <code>addLibJSscript</code> a été ajoutée pour
|
||
permettre spécifiquement l'inclusion des fichiers Javascript des librairies. Voici quelques
|
||
exemples d'utilisation et leur équivalent à présent:</p>
|
||
<ul>
|
||
<li><code>LSsession :: addJSscript('../../local/includes/js/LSformElement_eetelephone.js');</code>
|
||
devient <code>LStemplate :: addJSscript('LSformElement_eetelephone.js');</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LSsession :: addJSscript('../../local/includes/js/LSformElement_eetelephone.js');</code>
|
||
devient <code>LStemplate :: addJSscript('LSformElement_eetelephone.js');</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LSsession :: addJSscript('click-to-dial_view.js', 'local/includes/js/');</code> devient
|
||
<code>LStemplate :: addJSscript('click-to-dial_view.js');</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LSsession :: addJSscript('Picker.js',LS_LIB_DIR.'arian-mootools-datepicker/');</code>
|
||
devient <code>LStemplate :: addLibJSscript('arian-mootools-datepicker/Picker.js');</code></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LSsession :: addJSconfigParam()</code> devient <code>LStemplate :: addJSconfigParam()</code>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LSsession :: addHelpInfos()</code> devient <code>LStemplate :: addHelpInfo()</code>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSsession :: addCssFile()</code> devient <code>LStemplate :: addCssFile()</code>.</p>
|
||
<p>Par ailleurs le paramètre <code>$path</code> disparait et la méthode <code>addLibCssFile</code> à été ajoutée pour
|
||
permettre spécifiquement l'inclusion des fichiers CSS des librairies. Voici quelques exemples
|
||
d'utilisation et leur équivalent à présent:</p>
|
||
<ul>
|
||
<li><code>LSsession :: addCssFile('test.css', '../../local/css/');</code> devient
|
||
<code>LStemplate :: addCssFile('test.css');</code>. Doit donc être conservé, que le nom du fichier CSS,
|
||
pas de chemin vers celui-ci.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LSsession :: addCssFile('datepicker_vista.css',LS_LIB_DIR.'arian-mootools-datepicker/datepicker_vista/');</code>
|
||
devient
|
||
<code>LStemplate :: addLibCssFile('arian-mootools-datepicker/datepicker_vista/datepicker_vista.css');</code></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>Pour identifier les fichiers concernés, vous pouvez utiliser les commandes suivantes :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-4-1" id="__codelineno-4-1" name="__codelineno-4-1"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'LSsession *:: *(addJSscript|addLibJSscript|addJSconfigParam|addHelpInfos|addCssFile|addLibCssFile) *\('</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-4-2" id="__codelineno-4-2" name="__codelineno-4-2"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'(LSsession|LStemplate) *:: *addJSscript\(.*local'</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-4-3" id="__codelineno-4-3" name="__codelineno-4-3"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'(LSsession|LStemplate) *:: *addJSscript\(.*\.\.\/'</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-4-4" id="__codelineno-4-4" name="__codelineno-4-4"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'(LSsession|LStemplate) *:: *addCssFile\(.*local'</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-4-5" id="__codelineno-4-5" name="__codelineno-4-5"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'(LSsession|LStemplate) *:: *addCssFile\(.*\.\.\/'</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSlog</code> vs <code>LSdebug</code> : L’utilisation de <code>LSdebug</code> est dépriorisée en faveur de <code>LSlog</code>. Ce dernier
|
||
ajoute désormais la notion de <em>logger</em>, permettant d’identifier la source des logs. Ce mécanisme
|
||
permet la configuration d’un niveau de log spécifique pour un <em>logger</em> donné, ainsi que la mise en
|
||
place de filtres au niveau des <em>handers</em> pour ne logger par exemple que certains <em>loggers</em>, ou à
|
||
l’inverse en exclure d’autres.</p>
|
||
<ul>
|
||
<li>Pour vos classes personnalisées : si celles-ci héritent d’une classe standard, il est fort
|
||
probable qu’il soit possible d’utiliser des méthodes fournies par cette classe pour logguer
|
||
au travers un <em>logger</em> dédié (voir les méthodes <code>log_debug</code>, <code>log_info</code>, …). À défaut, il est
|
||
possible d’utiliser la classe <code>LSlog_staticLoggerClass</code> qui facilite l’implémentation.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Pour vos <a href="#conf-configuration-des-lsaddons">LSaddons</a> : il est conseillé d’utiliser un
|
||
<em>logger</em> <code>LSaddon_[addon]</code> dédié. Le <em>logger</em> peut facilement être récupéré de la manière
|
||
suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-5-1" id="__codelineno-5-1" name="__codelineno-5-1"></a><span class="x">LSlog :: get_logger("LSaddon_[addon]")</span>
|
||
</code></pre></div>
|
||
<p>Cette méthode retourne une référence au <em>logger</em> et il est possible d’appeler directement une
|
||
méthode de log, par exemple :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-6-1" id="__codelineno-6-1" name="__codelineno-6-1"></a><span class="x">LSlog :: get_logger("LSaddon_[addon]") -> debug("message");</span>
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h2 id="upgrade-2_4_1-to-3_0_0-fichiers-templates">Fichiers templates :</h2>
|
||
<h3 id="upgrade-2_4_1-to-3_0_0-changement-de-linclusion-des-templates">Changement de l’inclusion des templates</h3>
|
||
<ul>
|
||
<li>
|
||
<p>Le cas des fichiers <code>top.tpl</code> et <code>bottom.tpl</code></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-7-1" id="__codelineno-7-1" name="__codelineno-7-1"></a>{include file='ls:top.tpl'}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-7-2" id="__codelineno-7-2" name="__codelineno-7-2"></a>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-7-3" id="__codelineno-7-3" name="__codelineno-7-3"></a>[...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-7-4" id="__codelineno-7-4" name="__codelineno-7-4"></a>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-7-5" id="__codelineno-7-5" name="__codelineno-7-5"></a>{include file='ls:bottom.tpl'}
|
||
</code></pre></div>
|
||
<p>devient :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-8-1" id="__codelineno-8-1" name="__codelineno-8-1"></a>{extends file='ls:base_connected.tpl'}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-8-2" id="__codelineno-8-2" name="__codelineno-8-2"></a>{block name="content"}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-8-3" id="__codelineno-8-3" name="__codelineno-8-3"></a>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-8-4" id="__codelineno-8-4" name="__codelineno-8-4"></a>[...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-8-5" id="__codelineno-8-5" name="__codelineno-8-5"></a>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-8-6" id="__codelineno-8-6" name="__codelineno-8-6"></a>{/block}
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pages à l’état connecté uniquement (incluant le menu, l’entête…).</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Fichiers avec entête HTML :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-1" id="__codelineno-9-1" name="__codelineno-9-1"></a><span class="p"><</span><span class="nt">html</span><span class="p">></span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-2" id="__codelineno-9-2" name="__codelineno-9-2"></a> <span class="p"><</span><span class="nt">head</span><span class="p">></span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-3" id="__codelineno-9-3" name="__codelineno-9-3"></a> [...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-4" id="__codelineno-9-4" name="__codelineno-9-4"></a> <span class="p"></</span><span class="nt">head</span><span class="p">></span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-5" id="__codelineno-9-5" name="__codelineno-9-5"></a> <span class="p"><</span><span class="nt">body</span><span class="p">></span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-6" id="__codelineno-9-6" name="__codelineno-9-6"></a> [...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-7" id="__codelineno-9-7" name="__codelineno-9-7"></a> <span class="p"></</span><span class="nt">body</span><span class="p">></span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-9-8" id="__codelineno-9-8" name="__codelineno-9-8"></a><span class="p"></</span><span class="nt">html</span><span class="p">></span>
|
||
</code></pre></div>
|
||
<p>devient :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-10-1" id="__codelineno-10-1" name="__codelineno-10-1"></a>{extends file='ls:base.tpl'}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-10-2" id="__codelineno-10-2" name="__codelineno-10-2"></a>{block name="body"}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-10-3" id="__codelineno-10-3" name="__codelineno-10-3"></a>[...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-10-4" id="__codelineno-10-4" name="__codelineno-10-4"></a>{/block}
|
||
</code></pre></div>
|
||
<p>Au besoin, si vous avez besoin :</p>
|
||
<ul>
|
||
<li>
|
||
<p>de remplacer les fichiers CSS chargés par défaut (<code>base.css</code> par exemple) : ajouter le block
|
||
<code>css</code> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-11-1" id="__codelineno-11-1" name="__codelineno-11-1"></a>{block name="css"}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-11-2" id="__codelineno-11-2" name="__codelineno-11-2"></a> <link rel="stylesheet" type="text/css" href="{css name='custom.css'}" media="screen" title="Normal" />
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-11-3" id="__codelineno-11-3" name="__codelineno-11-3"></a> {include file='ls:css.tpl'}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-11-4" id="__codelineno-11-4" name="__codelineno-11-4"></a>{/block}
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Ce block contient tous les CSS, y compris ceux gérés par <code>LSsession :: addCssFile()</code>.
|
||
Pensez à ajouter <code>{include file='ls:css.tpl'}</code> pour conserver ces derniers.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>d’ajouter des infos dans <code><head></code> : ajouter le block <code>head</code> (vide par défaut) :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-12-1" id="__codelineno-12-1" name="__codelineno-12-1"></a>{block name="head"}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-12-2" id="__codelineno-12-2" name="__codelineno-12-2"></a>[...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-12-3" id="__codelineno-12-3" name="__codelineno-12-3"></a>{/block}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>d’ajouter des fichiers Javascript personnalisés : ajouter le block <code>js</code> (vide par défaut):</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-13-1" id="__codelineno-13-1" name="__codelineno-13-1"></a>{block name="js"}
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-13-2" id="__codelineno-13-2" name="__codelineno-13-2"></a>[...]
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-13-3" id="__codelineno-13-3" name="__codelineno-13-3"></a>{/block}
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Ce block sera ajouté <em>APRÈS</em> les autres fichiers Javascript chargés (ceux par défaut et ceux
|
||
ajoutés via <code>LSsession :: addJSscript()</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Autres fichiers remplacés :</p>
|
||
<ul>
|
||
<li><code>blank.tpl</code> remplacé par <code>base.tpl</code></li>
|
||
<li><code>empty.tpl</code> remplacé par <code>base_connected.tpl</code></li>
|
||
<li><code>accueil.tpl</code> remplacé par <code>homepage.tpl</code></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>Pour identifier les fichiers concernés, vous pouvez utiliser la commande suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-14-1" id="__codelineno-14-1" name="__codelineno-14-1"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'(accueil|blank|empty|top|bottom)\.tpl'</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
</code></pre></div>
|
||
<h3 id="upgrade-2_4_1-to-3_0_0-fichiers-templates-fournis-par-defaut">Fichiers templates fournis par défaut :</h3>
|
||
<p>Vérifier les modifications des fichiers templates fourni avec l’application et que vous auriez
|
||
personnalisé. Pour cela, vous pouvez utiliser la commande suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-15-1" id="__codelineno-15-1" name="__codelineno-15-1"></a><span class="k">for</span><span class="w"> </span>i<span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">$(</span><span class="w"> </span>ls<span class="w"> </span>/etc/ldapsaisie/local/templates/*<span class="w"> </span><span class="k">)</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-15-2" id="__codelineno-15-2" name="__codelineno-15-2"></a><span class="k">do</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-15-3" id="__codelineno-15-3" name="__codelineno-15-3"></a><span class="w"> </span><span class="nv">default_file</span><span class="o">=</span><span class="s2">"/usr/share/ldapsaisie/templates/default/</span><span class="k">$(</span><span class="w"> </span>basename<span class="w"> </span><span class="s2">"</span><span class="nv">$i</span><span class="s2">"</span><span class="w"> </span><span class="k">)</span><span class="s2">"</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-15-4" id="__codelineno-15-4" name="__codelineno-15-4"></a><span class="w"> </span><span class="o">[</span><span class="w"> </span>!<span class="w"> </span>-e<span class="w"> </span><span class="s2">"</span><span class="nv">$default_file</span><span class="s2">"</span><span class="w"> </span><span class="o">]</span><span class="w"> </span><span class="o">&&</span><span class="w"> </span><span class="k">continue</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-15-5" id="__codelineno-15-5" name="__codelineno-15-5"></a><span class="w"> </span>vi<span class="w"> </span>-d<span class="w"> </span><span class="nv">$default_file</span><span class="w"> </span><span class="nv">$i</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-15-6" id="__codelineno-15-6" name="__codelineno-15-6"></a><span class="k">done</span>
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Une attention particulière doit être porté aux fichiers <code>login.tpl</code> et <code>recoverpassword.tpl</code> qui
|
||
ont particulièrement changés.</p>
|
||
</div>
|
||
<h3 id="upgrade-2_4_1-to-3_0_0-corriger-les-url-des-images">Corriger les URL des images :</h3>
|
||
<p><code>../../images/default/find.png</code> devient <code>../image/find</code></p>
|
||
<p>Pour identifier les fichiers concernés, vous pouvez utiliser les commandes suivantes :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-16-1" id="__codelineno-16-1" name="__codelineno-16-1"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'images'</span><span class="w"> </span>/etc/ldapsaisie/local/templates
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-16-2" id="__codelineno-16-2" name="__codelineno-16-2"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'\.(png|gif|jpg)'</span><span class="w"> </span>/etc/ldapsaisie/local/templates
|
||
</code></pre></div>
|
||
<h3 id="upgrade-2_4_1-to-3_0_0-le-cas-de-variable-de-template-lssession_css-et-lssession_js">Le cas de variable de template <code>{$LSsession_css}</code> et <code>{$LSsession_js}</code> :</h3>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Ceci est déjà géré si vous étendez bien vos templates du fichier <code>base.tpl</code> (pour les pages
|
||
non-connectées) ou <code>base_connected.tpl</code> (pour les pages connectées).</p>
|
||
</div>
|
||
<ul>
|
||
<li><code>{$LSsession_css}</code> doit être remplacé par <code>{include file='ls:css.tpl'}</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>{$LSsession_js}</code> doit être remplacé par <code>{include file='ls:js.tpl'}</code></li>
|
||
</ul>
|
||
<h2 id="upgrade-2_4_1-to-3_0_0-tous-les-fichiers-modification-des-urls">Tous les fichiers : Modification des URLs</h2>
|
||
<ul>
|
||
<li>
|
||
<p><code>view.php</code> :</p>
|
||
<ul>
|
||
<li>page recherche : <code>view.php?LSobject=LSpeople</code> devient <code>object/LSpeople</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>page d'un objet : <code>view.php?LSobject=LSpeople&dn=$dn</code> devient <code>object/LSpeople/$dn</code></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>addon_view.php</code> : <code>addon_view.php?LSaddon=ee&view=copyContract</code> devient <code>addon/ee/copyContract</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>index_ajax.php</code> :</p>
|
||
<ul>
|
||
<li>
|
||
<p>Pour les méthodes Ajax de classes :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-17-1" id="__codelineno-17-1" name="__codelineno-17-1"></a><span class="kd">var</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-17-2" id="__codelineno-17-2" name="__codelineno-17-2"></a><span class="w"> </span><span class="nx">template</span><span class="o">:</span><span class="w"> </span><span class="s1">'LSformElement_eetelephone'</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-17-3" id="__codelineno-17-3" name="__codelineno-17-3"></a><span class="w"> </span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="s1">'make_call'</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-17-4" id="__codelineno-17-4" name="__codelineno-17-4"></a><span class="w"> </span><span class="nx">telephoneNumber</span><span class="o">:</span><span class="w"> </span><span class="nx">tel</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-17-5" id="__codelineno-17-5" name="__codelineno-17-5"></a><span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="nx">name</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-17-6" id="__codelineno-17-6" name="__codelineno-17-6"></a><span class="p">};</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-17-7" id="__codelineno-17-7" name="__codelineno-17-7"></a><span class="ow">new</span><span class="w"> </span><span class="nx">Request</span><span class="p">({</span><span class="nx">url</span><span class="o">:</span><span class="w"> </span><span class="s1">'index_ajax.php'</span><span class="p">,</span><span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="nx">onSuccess</span><span class="o">:</span><span class="w"> </span><span class="p">...});</span>
|
||
</code></pre></div>
|
||
<p>Devient :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-18-1" id="__codelineno-18-1" name="__codelineno-18-1"></a>var data = {
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-18-2" id="__codelineno-18-2" name="__codelineno-18-2"></a> telephoneNumber: tel,
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-18-3" id="__codelineno-18-3" name="__codelineno-18-3"></a> name: name,
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-18-4" id="__codelineno-18-4" name="__codelineno-18-4"></a>};
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-18-5" id="__codelineno-18-5" name="__codelineno-18-5"></a>new Request({url: 'ajax/class/LSformElement_eetelephone/make_call', data: data, onSuccess: ...});
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Pour les méthodes Ajax d'addon :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-1" id="__codelineno-19-1" name="__codelineno-19-1"></a><span class="kd">var</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-2" id="__codelineno-19-2" name="__codelineno-19-2"></a><span class="w"> </span><span class="nx">addon</span><span class="o">:</span><span class="w"> </span><span class="s1">'asterisk'</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-3" id="__codelineno-19-3" name="__codelineno-19-3"></a><span class="w"> </span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="s1">'LSasterisk_make_call'</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-4" id="__codelineno-19-4" name="__codelineno-19-4"></a><span class="w"> </span><span class="nx">telephoneNumber</span><span class="o">:</span><span class="w"> </span><span class="nx">tel</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-5" id="__codelineno-19-5" name="__codelineno-19-5"></a><span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="nx">name</span><span class="p">,</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-6" id="__codelineno-19-6" name="__codelineno-19-6"></a><span class="w"> </span><span class="nx">nocache</span><span class="o">:</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">()</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-7" id="__codelineno-19-7" name="__codelineno-19-7"></a><span class="p">};</span>
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-19-8" id="__codelineno-19-8" name="__codelineno-19-8"></a><span class="ow">new</span><span class="w"> </span><span class="nx">Request</span><span class="p">({</span><span class="nx">url</span><span class="o">:</span><span class="w"> </span><span class="s1">'index_ajax.php'</span><span class="p">,</span><span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="nx">onSuccess</span><span class="o">:</span><span class="w"> </span><span class="p">...});</span>
|
||
</code></pre></div>
|
||
<p>Devient :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-20-1" id="__codelineno-20-1" name="__codelineno-20-1"></a>var data = {
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-20-2" id="__codelineno-20-2" name="__codelineno-20-2"></a> telephoneNumber: tel,
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-20-3" id="__codelineno-20-3" name="__codelineno-20-3"></a> name: name,
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-20-4" id="__codelineno-20-4" name="__codelineno-20-4"></a> nocache: new Date().getTime()
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-20-5" id="__codelineno-20-5" name="__codelineno-20-5"></a>};
|
||
<a href="#upgrade-2_4_1-to-3_0_0-__codelineno-20-6" id="__codelineno-20-6" name="__codelineno-20-6"></a>new Request({url: 'ajax/addon/asterisk/LSasterisk_make_call', data: data, onSuccess: ...});
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>global_search.php</code> : <code>global_search.php?refresh</code> devient <code>search?refresh</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>index.php</code> : <code>index.php?LSsession_recoverPassword</code> devient <code>index?LSsession_recoverPassword</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>create.php</code> : <code>create.php?LSobject=LSpeople</code> devient <code>object/LSpeople/create</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>modify.php</code> : <code>modify.php?LSobject=LSpeople&dn=$dn</code> devient <code>object/LSpeople/$dn/modify</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>import.php</code> : <code>import.php?LSobject=LSpeople</code> devient <code>object/LSpeople/import</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>remove.php</code> : <code>remove.php?LSobject=LSpeople&dn=$dn</code> devient <code>object/LSpeople/$dn/remove</code></p>
|
||
<p>Avec validation : <code>remove.php?LSobject=LSpeople&dn=$dn&valid</code> devient
|
||
<code>object/LSpeople/$dn/remove?valid</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>select.php</code> : <code>select.php?LSobject=LSpeople</code> devient <code>object/LSpeople/select</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>custom_action.php</code> :
|
||
<code>custom_action.php?LSobject=LSpeople&dn=$dn&customAction=$customAction</code>
|
||
devient <code>object/LSpeople/$dn/customAction/$customAction</code></p>
|
||
<p>Avec validation :
|
||
<code>custom_action.php?LSobject=LSpeople&dn=$dn&customAction=$customAction&valid</code>
|
||
devient <code>object/LSpeople/$dn/customAction/$customAction?valid</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>custom_search_action.php</code> :
|
||
<code>custom_search_action.php?LSobject=LSpeople&customAction=$customAction</code>
|
||
devient <code>object/LSpeople/customAction/$customAction</code></p>
|
||
<p>Avec validation :
|
||
<code>custom_search_action.php?LSobject=LSpeople&customAction=$customAction&valid</code>
|
||
devient <code>object/LSpeople/customAction/$customAction?valid</code></p>
|
||
</li>
|
||
</ul>
|
||
<p>Pour identifier les fichiers concernés, vous pouvez utiliser la commande suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#upgrade-2_4_1-to-3_0_0-__codelineno-21-1" id="__codelineno-21-1" name="__codelineno-21-1"></a>grep<span class="w"> </span>-Er<span class="w"> </span><span class="s1">'(index|global_search|view|select|create|modify|import|remove|index_ajax|custom_action|custom_search_action|addon_view)\.php'</span><span class="w"> </span>/etc/ldapsaisie/local/
|
||
</code></pre></div></section><h1 class="nav-section-title-end">Ended: Mise à jour</h1><h1 class="nav-section-title">Configuration</h1><section class="print-page" id="conf"><h1 id="conf-configuration">Configuration</h1>
|
||
<p>La configuration du projet est située principalement dans le dossier <code>conf/</code>. Les exceptions seront
|
||
détaillées par la suite.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Toute la configuration du projet se fait par l'intermédiaire de fichiers définissant des
|
||
variables PHP dont les valeurs sont utilisées par le programme. Ceci signifie que la syntaxe de
|
||
ces fichiers doit être valide avec l'interpréteur PHP utilisé.</p>
|
||
</div></section><h2 class="nav-section-title">Configuration globale</h2><section class="print-page" id="conf-global"><h1 id="conf-global-configuration-globale">Configuration globale</h1>
|
||
<p>La plus grande partie de la configuration globale se trouve dans le fichier <code>config.inc.php</code>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>// Variables globales
|
||
<a href="#conf-global-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>$GLOBALS['LSconfig'] = array(
|
||
<a href="#conf-global-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> // Variables globales
|
||
<a href="#conf-global-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>);
|
||
<a href="#conf-global-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>
|
||
<a href="#conf-global-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>// Variables et constantes indépendantes
|
||
<a href="#conf-global-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a>$var1 = 'val1'
|
||
<a href="#conf-global-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a>$var2 = 'val2'
|
||
<a href="#conf-global-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>...
|
||
<a href="#conf-global-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a>define('CONST1','val1')
|
||
<a href="#conf-global-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a>define('CONST2','val2')
|
||
<a href="#conf-global-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a>...
|
||
</code></pre></div>
|
||
<h2 id="conf-global-variables-globales">Variables globales</h2>
|
||
<ul>
|
||
<li>
|
||
<p><code>NetLDAP2</code></p>
|
||
<p>Chemin vers la librairie <a href="http://pear.php.net/">PEAR</a>
|
||
<a href="http://pear.php.net/package/Net_LDAP2">Net_LDAP2</a>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>/usr/share/php/Net/LDAP2.php
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>Smarty</code></p>
|
||
<p>Chemin vers le moteur de template <a href="http://www.smarty.net/">Smarty</a>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>/usr/share/php/smarty/libs/Smarty.class.php
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>public_root_url</code></p>
|
||
<p>URL publique de la racine web de l'application. Il peut s'agir d'une URL relative bien qu'une URL
|
||
absolue soit préférable, notament pour éviter l'auto-détection de celle-ci lorsque nécessaire
|
||
(lien dans un e-mail par exemple. Par défaut : <code>/</code>.)</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Il est indispensable que ce paramètre soit configuré en adéquation avec votre environement
|
||
pour que l'application fonctionne correctement (notament en cas en cas de déploiement dans un
|
||
sous-dossier ou encore dans le cadre d'un accès à l'application au travers un
|
||
<em>reverse-proxy</em>).</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>lang</code></p>
|
||
<p>Paramètre utilisé pour l'internationalisation : code de la langue (<code>fr_FR</code> ou <code>en_US</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>encoding</code></p>
|
||
<p>Encodage de caractère (<code>UTF8</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ldap_servers</code></p>
|
||
<p>Configuration des serveurs LDAP.
|
||
<a href="#conf-global-ldap-configuration-des-serveurs-ldap">Voir section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<h3 id="conf-global-preferences-globales">Préférences globales</h3>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Les variables globales suivantes ont une action globale, mais non-prioritaire sur le
|
||
comportement de l'application. Il peux être redéfini pour chacun des serveurs LDAP.</p>
|
||
</div>
|
||
<ul>
|
||
<li>
|
||
<p><code>cacheLSprofiles</code></p>
|
||
<p>Activation/Désactivation de la mise en cache des profils des utilisateurs connectés
|
||
(<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a>).</p>
|
||
<p>Valeurs possibles : <code>True</code> ou <code>False</code></p>
|
||
<p>Valeur recommandée : <code>True</code></p>
|
||
<p>Valeur par défaut : <code>False</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>cacheSubDn</code></p>
|
||
<p>Activation/Désactivation de la mise en cache des niveaux de connexion
|
||
(<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">subDn</a>) dans l'annuaire.</p>
|
||
<p>Valeurs possibles : <code>True</code> ou <code>False</code></p>
|
||
<p>Valeur recommandée : <code>True</code></p>
|
||
<p>Valeur par défaut : <code>False</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>cacheSearch</code></p>
|
||
<p>Activation/Désactivation de la mise en cache du résultat des recherches dans l'annuaire.</p>
|
||
<p>Valeurs possibles : <code>True</code> ou <code>False</code></p>
|
||
<p>Valeur recommandée : <code>True</code></p>
|
||
<p>Valeur par défaut : <code>False</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>globalSearch</code></p>
|
||
<p>Activation/Désactivation de la recherche globale dans l'annuaire.</p>
|
||
<p>Valeurs possibles : <code>True</code> ou <code>False</code></p>
|
||
<p>Valeur par défaut : <code>True</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>keepLSsessionActive</code></p>
|
||
<p>Activation/Désactivation du maintient de la LSsession active.</p>
|
||
<p>Valeurs possibles : <code>True</code> ou <code>False</code></p>
|
||
<p>Valeur par défaut : <code>False</code></p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-global-variables-et-constantes-independantes">Variables et constantes indépendantes</h2>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_THEME</code></p>
|
||
<p>Constante déterminant le nom du theme utilisé.</p>
|
||
<p>Valeur par défaut : <em>default</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_TEMPLATES_DIR</code></p>
|
||
<p>Constante déterminant le chemin du dossier des templates.</p>
|
||
<p>Valeur par défaut : <em>templates</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_IMAGES_DIR</code></p>
|
||
<p>Constante déterminant le chemin du dossier des images.</p>
|
||
<p>Valeur par défaut : <em>images</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_CSS_DIR</code></p>
|
||
<p>Constante déterminant le chemin du dossier des CSS.</p>
|
||
<p>Valeur par défaut : <em>css</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSdebug</code></p>
|
||
<p>Variable booléenne déterminant si le débogage à l'écran est activé.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$GLOBALS['LSlog']</code></p>
|
||
<p>Variable permettant de configurer la journalisation de l'application.
|
||
<a href="#conf-global-lslog-configuration-de-la-journalisation">Voir section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>NB_LSOBJECT_LIST</code></p>
|
||
<p>Constante déterminant le nombre d'objet affichés par page de résultat de recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>NB_LSOBJECT_LIST_SELECT</code></p>
|
||
<p>Constante déterminant le nombre d'objet affichés par page de résultat de recherche dans une
|
||
fenêtre <em>LSselect</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$GLOBALS['NB_LSOBJECT_LIST_CHOICES']</code></p>
|
||
<p>Variable permettant de configurer la liste des choix proposés à l'utilisateur pour le nombre
|
||
maximum d'objets affichés par page de résultat de recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>MAX_SEND_FILE_SIZE</code></p>
|
||
<p>Constante déterminant la taille maximale d'un fichier envoyé à travers les formulaires.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$GLOBALS['defaultJSscripts']</code></p>
|
||
<p>Tableau déterminant les fichiers Javascript à charger sur toute les pages.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$GLOBALS['defaultCSSfiles']</code></p>
|
||
<p>Tableau déterminant les fichiers CSS à charger sur toute les pages. Ces fichiers seront chargés
|
||
dans l'ordre et en dernier permettant de surcharger tous paramètres de style.</p>
|
||
</li>
|
||
</ul></section><h3 class="nav-section-title">Connexion LDAP</h3><section class="print-page" id="conf-global-ldap"><h1 id="conf-global-ldap-configuration-des-serveurs-ldap">Configuration des serveurs LDAP</h1>
|
||
<p>Cette section décrit le tableau de configuration des différents serveurs LDAP utilisés par
|
||
l'application. Ce tableau contient lui même un tableau par serveur LDAP.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSconfig'] = array(</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> ...</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> 'ldap_servers' => array(</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> array (</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> 'name' => [nom de l'annuaire],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x"> 'ldap_config'=> array(</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x"> // Définition des paramètres de connexion à l'annuaire</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x"> 'useUserCredentials' => [boolean],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x"> 'useAuthzProxyControl' => [boolean],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x"> 'LSauth' => array (</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x"> 'method' => [LSauth method],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> 'api_method' => [LSauth method],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x"> 'LSobjects' => array(</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> '[object type 1]',</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> '[object type 2]' => array(</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x"> 'filter' => '[LDAP filter]',</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a><span class="x"> 'filter_function' => [callable],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a><span class="x"> 'password_attribute' => '[attribute name]',</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="x"> 'web_access' => [booléen],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a><span class="x"> 'api_access' => [booléen],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a><span class="x"> )</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="x"> )</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="x"> 'LSprofiles' => array (</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a><span class="x"> // Définition des LSprofiles</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a><span class="x"> 'cacheLSprofiles' => [boolean],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="x"> 'cacheSearch' => [boolean],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a><span class="x"> 'globalSearch' => [boolean],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a><span class="x"> 'LSaccess' => array (</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a><span class="x"> [Type LSobject 1],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a><span class="x"> [Type LSobject 2],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a><span class="x"> ...</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a><span class="x"> 'subDn' => array(</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a><span class="x"> // Définition des sous-niveaux de l'annuaire</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a><span class="x"> 'subDnLabel' => [nom des sous-niveaux],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a><span class="x"> 'recoverPassword' => array(</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a><span class="x"> // Définition des paramètres de configuration de la récupération de mot de passe</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a><span class="x"> 'defaultView' => [view],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a><span class="x"> 'emailSender' => [email],</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-45" id="__codelineno-0-45" name="__codelineno-0-45"></a><span class="x"> 'keepLSsessionActive' => [booléen]</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-46" id="__codelineno-0-46" name="__codelineno-0-46"></a><span class="x"> )</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-47" id="__codelineno-0-47" name="__codelineno-0-47"></a><span class="x"> ...</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-48" id="__codelineno-0-48" name="__codelineno-0-48"></a><span class="x">);</span>
|
||
<a href="#conf-global-ldap-__codelineno-0-49" id="__codelineno-0-49" name="__codelineno-0-49"></a><span class="x">...</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>name</code></p>
|
||
<p>Le nom d'affichage de ce serveur Ldap (utilisé lorsque plusieurs serveur LDAP sont déclarés).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ldap_config</code></p>
|
||
<p>Informations de connexion au serveur LDAP. Ces informations sont structurées selon les attentes de
|
||
la librairie <a href="http://pear.php.net/package/Net_LDAP2">Net_LDAP2</a>.
|
||
<a href="http://pear.php.net/manual/fr/package.networking.net-ldap.connecting.php">Plus d'informations</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>useUserCredentials</code></p>
|
||
<p>Booléen définissant si il faut utiliser les identifiants de l'utilisateur pour se connecter à
|
||
l'annuaire (<em>false</em> par défaut). Si cette option est activée, la connexion à l'annuaire LDAP sera
|
||
établie avec la configuration fournie dans le paramètre <em>ldap_config</em> en écrasant les informations
|
||
de connexion (<em>binddn</em> et <em>bindpwd</em>) par ceux de l'utilisateur. Si l'utilisateur n'est pas encore
|
||
connecté, la connexion sera étalie sans modifier la configuration fournie.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>useAuthzProxyControl</code></p>
|
||
<p>Booléen définissant si, lorsqu'on utilise les identifiants de l'utilisateur pour se connecter à
|
||
l'annuaire, il faut utiliser une authentification via <em>proxy authorization</em>. Dans ce cas, les
|
||
identifiants de l'utilisateur ne seront pas, à proprement parlé, utilisés pour se connecter à
|
||
l'annuaire, mais une demande de <em>proxy authorization</em> en tant que l'utilisateur connecté sera
|
||
faites à l'aide des identifiants de l'application. Ce mode nécessite une configuration
|
||
particulière au niveau de l'annuaire pour autoriser le compte de l'application à faire des
|
||
demandes de <em>proxy authorization</em> en tant que les autres utilisateurs de l'annuaire.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSprofiles</code></p>
|
||
<p>Définition des profils d'utilisateurs se connectant à l'annuaire.
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSauth</code></p>
|
||
<p>Ce tableau défini les paramètres d'authentification à l'application.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>method</code></p>
|
||
<p>Nom de la méthode d'authentification
|
||
<a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a>. Exemple : pour
|
||
utiliser la classe <code>LSauthMethod_HTTP</code>, la valeur de ce paramètre sera <code>HTTP</code>.
|
||
<em>Paramètre facultatif, méthode par défaut : <code>basic</code>.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>api_method</code></p>
|
||
<p>Nom de la méthode d'authentification
|
||
<a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> à utilisée lors
|
||
d'une connexion à l'API. Exemple : pour utiliser la classe <code>LSauthMethod_HTTP</code>, la valeur
|
||
de ce paramètre sera <code>HTTP</code>. <em>Paramètre facultatif, méthode par défaut : <code>HTTP</code>.</em></p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Toutes les <a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> ne
|
||
supportent pas forcément le mode API.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSobjects</code></p>
|
||
<p>Tableau listant les types <a href="#conf-lsobject-configuration-lsobject">LSobjects</a> pouvant se
|
||
connecter à l'application. Les valeurs de ce tableau peuvent être un nom de type d'objet ou bien
|
||
tableau détaillant les paramètres de connexion de ce type d'objet.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du filtre de recherche de l'utilisateur à sa
|
||
connexion. Ce format sera composé avec l'identifiant fourni par l'utilisateur. Cela peut par
|
||
exemple permettre à l'utilisateur de se connecter en fournissant son login ou son email comme
|
||
identifiant. Exemple de valeur : <code>(|(uid=%{user})(mail=%{user}))</code>.
|
||
<em>Paramètre facultatif, filtre par défaut composé à l'aide de l'attribut RDN.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter_function</code></p>
|
||
<p><em>Callable</em> (au sens PHP) utilisé pour filtrer les utilisateurs trouvés dans l'annuaire à
|
||
partir des autres paramètres : cette fonction, si elle est définie, sera appelée pour chaque
|
||
utilisateur trouvé, avec pour unique paramètre, une référence à l'objet LDAP correspondant
|
||
(<code>LSldapObject</code>). Cette méthode devra alors retourner <code>true</code> ou <code>false</code> pour respectivement
|
||
autoriser ou interdire l'accès à l'application à l'utilisateur.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Si un utilisateur est exclus par cette méthode et qu'aucun autre utilisateur correspondant
|
||
n'a été trouvé dans l'annuaire, une page d'erreur sera affichée et indiquera que l'accès à
|
||
l'application est refusée.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>password_attribute</code></p>
|
||
<p>Nom de l'attribut stockant le mot de passe de ce type
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a>.
|
||
<em>Paramètre facultatif, valeur par défaut : <code>userPassword</code>.</em></p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>C'est cet attribut de l'utilisateur qui sera modifié par la fonctionnalité de récupération
|
||
de mot de passe.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>web_access</code></p>
|
||
<p>Permet de définir si ce type d'objet à le droit d'utiliser l'interface web (facultatif, par
|
||
défaut : <code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>api_access</code></p>
|
||
<p>Permet de définir si ce type d'objet à le droit d'utiliser l'API (facultatif, par défaut :
|
||
<code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>allow_multi_match</code></p>
|
||
<p>Booléen permettant de définir si un doublon d'identifiant utilisateur est autorisé. Si c'est le
|
||
cas et lorsqu'un identifiant fourni par l'utilisateur a sa connexion a permi de trouver plus
|
||
d'un utilisateur possible correspondant, l'application tentera de déterminer lequel de ces
|
||
utilisateurs correspond à la tentative d'authentification. La méthodologie employée dépendra de
|
||
la <a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> configurée. Par
|
||
exemple, la <a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> <code>basic</code>
|
||
tentera de s'identifier avec le mot de passe. Dans tous cas, si cette méthode n'a pas permis
|
||
d'identifier un seul utilisateur, l'authentification échoura. <em>Paramètre facultatif, valeur par
|
||
défaut : <code>False</code>.</em></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>cacheLSprofiles</code></p>
|
||
<p>Activation/Désactivation de la mise en cache des <a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a>
|
||
des utilisateurs connectés à ce serveur.</p>
|
||
<p>Valeur par défaut : <em>valeur de la variable globale du même nom</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>cacheSearch</code></p>
|
||
<p>Activation/Désactivation de la mise en cache du résultat des recherches sur ce serveur.</p>
|
||
<p>Valeur par défaut : <em>valeur de la variable globale du même nom</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>globalSearch</code></p>
|
||
<p>Activation/Désactivation de la recherche globale sur ce serveur en particulier. Par défaut, la
|
||
valeur du paramètre global <code>globalSearch</code> est utilisée.</p>
|
||
<p>Valeur par défaut : <em>valeur de la variable globale du même nom</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSaccess</code> <a name="LSaccess"></a></p>
|
||
<p>Définition des types d'<a href="#conf-lsobject-configuration-lsobject">LSobjects</a> devant
|
||
apparaître dans le menu de l'interface.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce paramètre n'est utilisé que pour les annuaires n'ayant pas de sous-niveaux
|
||
(<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">subDn</a>).</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>subDn</code></p>
|
||
<p>Définition des sous-niveaux de connexion à l'annuaire.
|
||
<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">Voir section concernée</a>.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce paramètre remplace le paramètre <a href="#conf-global-ldap-LSaccess">LSaccess</a> dans le cas d'un annuaire
|
||
multi-niveaux.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>subDnLabel</code></p>
|
||
<p>Définition du label utilisé pour qualifier les sous-niveaux de connexion.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce paramètre est utile uniquement dans le cas d'un annuaire multi-niveaux.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>recoverPassword</code></p>
|
||
<p>Définition des paramètres de la récupération de mot de passe.
|
||
<a href="#conf-global-ldap-recoverpassword-recuperation-de-mot-de-passe">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>defaultView</code></p>
|
||
<p>Définition de la vue par défaut de l'application. Par défaut, une page blanche est affichée et il
|
||
est possible de définir à l'aide de ce paramètre la vue qui s'affichera. Ce paramètre peut prendre
|
||
comme valeur :</p>
|
||
<ul>
|
||
<li><code>SELF</code> pour la vue <em>Mon compte</em></li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le nom d'un <a href="#conf-lsobject-configuration-lsobject">LSobject</a> pour afficher la liste de
|
||
ce type d'objet</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le nom d'une vue d'un <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> au format
|
||
<code>[addon]::[viewId]</code> pour afficher cette vue</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>emailSender</code></p>
|
||
<p>Adresse mail utilisée par LdapSaisie pour envoyer des e-mails en relation avec cet annuaire. Cette
|
||
adresse est celle utilisée par défaut. L'adresse utilisée peut également être configurée dans le
|
||
contexte de configuration du module devant envoyer des e-mails.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>keepLSsessionActive</code></p>
|
||
<p>Activation/Désactivation du maintient de la LSsession active.</p>
|
||
<p>Valeurs possibles : <code>True</code> ou <code>False</code></p>
|
||
<p>Valeur par défaut : <em>valeur de la variable globale du même nom</em></p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-global-ldap-lsprofile"><h1 id="conf-global-ldap-lsprofile-profils-dutilisateurs-lsprofile">Profils d'utilisateurs (LSprofile)</h1>
|
||
<p>Cette section décrit la manière dont sont définis les profils d'utilisateurs se connectant à
|
||
l'interface appelés <em>LSprofile</em>. Il est possible d'attribuer un profil à l'utilisateur connecté sur
|
||
tout ou partie de l'annuaire LDAP.</p>
|
||
<h2 id="conf-global-ldap-lsprofile-profils-dutilisateurs-par-defaut">Profils d'utilisateurs par défaut</h2>
|
||
<p>Il existe des profils d'utilisateurs par défaut, non liée à la configuration de l'application:</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>user</code></p>
|
||
<p>Tous les utilisateurs connectés à l'utilisateur. Ce <em>LSprofile</em> est valide sur l'ensemble de
|
||
l'annuaire.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>self</code></p>
|
||
<p>L'utilisateur connecté sur son objet correspondant dans l'annuaire. Ce <em>LSprofile</em> est utile pour
|
||
donner des droits à l'utilisateur sur lui-même.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>nom du type de l'objet connecté</code></p>
|
||
<p>Un <em>LSprofile</em> du nom du type d'objet utilisateur connecté est automatiquement ajouté à
|
||
l'utilisateur. Ainsi, si l'utilisateur connecté est un
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobject</a> <code>LSpeople</code> par exemple, il aura le
|
||
<em>LSprofile</em> <code>LSpeople</code> sur tous l'annuaire. Ce <em>LSprofile</em> est utile pour donner des droits à tous
|
||
un type d'objets pouvant se connecter à l'application (par exemple, tous les utilisateurs
|
||
applicatifs).</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-global-ldap-lsprofile-profils-dutilisateurs-personalises">Profils d'utilisateurs personalisés</h2>
|
||
<p>Il est possible de définir autant de profils d'utilisateurs que l'on souhaite. Pour chaque profil
|
||
d'utilisateur personnalisé, il faudra définir dans quelles parties de l'annuaire ce profil existe
|
||
(Exemple : les admistrateurs de groupes existent uniquement dans la branche de l'annuaire stockant
|
||
les groupes). Enfin pour chaque partie de l'annuaire, il faudra définir la manière d'identifier si
|
||
l'utilisateur qui se connecte appartient à ce profil.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-lsprofile-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'LSprofile' => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> [nom d'un LSprofile] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> [label] => [label du LSprofile],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> [basedn] => [dn utilisateur],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> [autre basedn] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> [dn d'un utilisateur] => NULL,
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> [autre dn] => array ( // via un listage de l'attribut d'un objet
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'attr' => [nom de l'attribut clé de l'objet],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'attr_value' => [format de la valeur de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'LSobject' => [nom du type LSobject de l'objet]
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> )
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> 'LSobjects' => array ( // via une liste d'objet sur lequel l'utilisateur a des pouvoirs
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> [nom du LSobject] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> 'attr' => [nom de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> 'attr_value' => [format de la valeur de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> // ou
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> 'filter' => [format du filtre de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a>
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> 'basedn' => [basedn de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> 'params' => [configuration de la recherche]
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> [nom quelconque] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a> 'filters' => array(
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a> array(
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a> 'LSobject' => [nom du LSobject],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a> 'attr' => [nom de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a> 'attr_value' => [format de la valeur de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a> // ou
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a> 'filter' => [format du filtre de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a>
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a> 'basedn' => [basedn de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a> 'params' => [configuration de la recherche]
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a> ...
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a> )
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a> ...
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a>),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a>...
|
||
</code></pre></div>
|
||
<p>Le paramètre <code>LSprofiles</code> est un tableau associatif contenant, en valeur clé, le nom d'un
|
||
<em>LSprofile</em> et en valeur associée, la configuration nécessaire pour déterminer si l'utilisateur
|
||
connecté appartient à ce LSprofile pour tout ou partie de l'annuaire.</p>
|
||
<p>Dans chaque configuration de <em>LSprofile</em>, il est possible d'identifier l'appartenance ou non de
|
||
l'utilisateur connecté de deux manières :</p>
|
||
<ul>
|
||
<li>
|
||
<p>Pour une branche de l'annuaire donnée (<em>basedn</em>) : en listant les utilisateurs appartenant à ce
|
||
<em>LSprofile</em> pour tous les objets de la branche. Il sera possible de lister les utilisateurs dont
|
||
on connait le <em>DN</em> ou de lister les utilisateurs appartenant à une liste stockée dans l'annuaire
|
||
(par exemple la liste des membres d'un groupe).</p>
|
||
<ul>
|
||
<li>
|
||
<p>Liste des DNs d'utilisateurs :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-lsprofile-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>'LSprofile' => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> [nom du LSprofile] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> [basedn] => [dn utilisateur],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> // ou si plusieurs DNs
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> [autre basedn] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> [dn d'un utilisateur] => NULL,
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> [dn d'un utilisateur 2] => NULL
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a> ...
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a> ...
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a>),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a>...
|
||
</code></pre></div>
|
||
<p>Explication : Pour un <em>LSprofile</em> et un <em>basedn</em> donnés, on définit l'utilisateur appartenant au
|
||
<em>LSprofile</em> en donnant son <em>DN</em>. Si on souhaite lister plusieurs utilisateurs, on utilise un
|
||
tableau associatif dans lequel les clés sont les <em>DNs</em> des utilisateurs et les valeurs associées
|
||
sont toutes <em>NULL</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Liste d'utilisateurs stockée dans l'annuaire :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-lsprofile-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>'LSprofile' => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-2" id="__codelineno-2-2" name="__codelineno-2-2"></a> [nom du LSprofile] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-3" id="__codelineno-2-3" name="__codelineno-2-3"></a> [basedn] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-4" id="__codelineno-2-4" name="__codelineno-2-4"></a> [DN d'un object] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-5" id="__codelineno-2-5" name="__codelineno-2-5"></a> 'attr' => [nom de l'attribut clé de l'objet],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-6" id="__codelineno-2-6" name="__codelineno-2-6"></a> 'attr_value' => [format de la valeur de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-7" id="__codelineno-2-7" name="__codelineno-2-7"></a> 'LSobject' => [nom du type LSobject de l'objet]
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-8" id="__codelineno-2-8" name="__codelineno-2-8"></a> )
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-9" id="__codelineno-2-9" name="__codelineno-2-9"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-10" id="__codelineno-2-10" name="__codelineno-2-10"></a> ...
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-11" id="__codelineno-2-11" name="__codelineno-2-11"></a>),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-2-12" id="__codelineno-2-12" name="__codelineno-2-12"></a>...
|
||
</code></pre></div>
|
||
<p>Explication : Pour un <em>LSprofile</em> et un <em>basedn</em> donnés, on liste les utilisateurs du
|
||
<em>LSprofile</em> référencés dans l'attribut <code>attr</code> de l'object de type <code>LSobject</code> et selon le format
|
||
de valeur décrit dans <code>attr_value</code>.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Pour un type de <em>LSobject</em> donné : en listant les objets pour lesquels l'utilisateur aura les
|
||
droits du LSprofile. Il sera possible, à travers une recherche paramétrable dans l'annuaire, de
|
||
lister les objets pour lesquels l'utilisateur appartiendra au <em>LSprofile</em>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-lsprofile-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a>'LSprofile' => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-2" id="__codelineno-3-2" name="__codelineno-3-2"></a> [nom d'un LSprofile] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-3" id="__codelineno-3-3" name="__codelineno-3-3"></a> 'LSobjects' => array ( // via un liste d'objet pour lequel l'utilisateur
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-4" id="__codelineno-3-4" name="__codelineno-3-4"></a> // appartient au LSprofile
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-5" id="__codelineno-3-5" name="__codelineno-3-5"></a> [nom du LSobject] => array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-6" id="__codelineno-3-6" name="__codelineno-3-6"></a> 'attr' => [nom de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-7" id="__codelineno-3-7" name="__codelineno-3-7"></a> 'attr_value' => [format de la valeur de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-8" id="__codelineno-3-8" name="__codelineno-3-8"></a> // or
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-9" id="__codelineno-3-9" name="__codelineno-3-9"></a> 'filter' => [format du filtre de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-10" id="__codelineno-3-10" name="__codelineno-3-10"></a>
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-11" id="__codelineno-3-11" name="__codelineno-3-11"></a> 'basedn' => [format du basedn de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-12" id="__codelineno-3-12" name="__codelineno-3-12"></a> 'params' => [configuration de la recherche]
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-13" id="__codelineno-3-13" name="__codelineno-3-13"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-14" id="__codelineno-3-14" name="__codelineno-3-14"></a> array (
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-15" id="__codelineno-3-15" name="__codelineno-3-15"></a> 'filters' => array(
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-16" id="__codelineno-3-16" name="__codelineno-3-16"></a> array(
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-17" id="__codelineno-3-17" name="__codelineno-3-17"></a> 'LSobject' => [nom du LSobject],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-18" id="__codelineno-3-18" name="__codelineno-3-18"></a> 'attr' => [nom de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-19" id="__codelineno-3-19" name="__codelineno-3-19"></a> 'attr_value' => [format de la valeur de l'attribut clé],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-20" id="__codelineno-3-20" name="__codelineno-3-20"></a> // ou
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-21" id="__codelineno-3-21" name="__codelineno-3-21"></a> 'filter' => [format du filtre de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-22" id="__codelineno-3-22" name="__codelineno-3-22"></a>
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-23" id="__codelineno-3-23" name="__codelineno-3-23"></a> 'basedn' => [format du basedn de recherche],
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-24" id="__codelineno-3-24" name="__codelineno-3-24"></a> 'params' => [configuration de la recherche]
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-25" id="__codelineno-3-25" name="__codelineno-3-25"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-26" id="__codelineno-3-26" name="__codelineno-3-26"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-27" id="__codelineno-3-27" name="__codelineno-3-27"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-28" id="__codelineno-3-28" name="__codelineno-3-28"></a> ...
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-29" id="__codelineno-3-29" name="__codelineno-3-29"></a> )
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-30" id="__codelineno-3-30" name="__codelineno-3-30"></a> ),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-31" id="__codelineno-3-31" name="__codelineno-3-31"></a> ...
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-32" id="__codelineno-3-32" name="__codelineno-3-32"></a>),
|
||
<a href="#conf-global-ldap-lsprofile-__codelineno-3-33" id="__codelineno-3-33" name="__codelineno-3-33"></a>...
|
||
</code></pre></div>
|
||
<p>Explications : Dans la configuration d'un <em>LSprofile</em>, la valeur clé <em>LSobjects</em> signifie qu'on
|
||
est dans un cas de la délégation de droits sur des types d'LSobject. Dans ce tableau associatif,
|
||
il est possible de définir un ou plusieurs types de LSobject pour lesquels on délègue des droits
|
||
via des recherches simples ou enchaînées. Le fonctionnement simple consiste à partir de l'objet de
|
||
l'utilisateur et à générer un filtre et une base de recherche sur un type de LSobject. Le
|
||
fonctionnement enchainée consiste à faire un première recherche à partir de l'objet de
|
||
l'utilisateur puis à recommencer à partir des objets trouvés en construisant une liste de filtres
|
||
de recherche pour chaque objet qui seront combinés via l'opérateur booléen <em>ou</em>. Dans le cadre
|
||
d'un fonctionnement enchainée, la base de recherche est toujours générer à partir de l'objet de
|
||
l'utilisateur connecté.</p>
|
||
<p>Pour configurer une délégation de type simple on mettra le nom du LSobject dans la clé du tableau
|
||
et dans la valeur un tableau définissant la recherche. Il est possible de ne pas utiliser la clé
|
||
du tableau comme nom du LSobject grâce à la clé de configuration <em>LSobject</em>.</p>
|
||
<p>Pour configurer une délégation de type enchaîné on pourra utiliser n'importe quelle valeur unique
|
||
pour la clé du tableau et pour la valeur un tableau contenant une unique clé <em>filters</em>. La valeur
|
||
associée à cette clé est celle d'une délégation de type simple où la clé <em>LSobject</em> est devenue
|
||
obligatoire.</p>
|
||
<p>Cette configuration contient les paramètres d'une ou plusieurs recherches dans l'annuaire en
|
||
considérant que l'utilisateur connecté aura les droits du LSprofile sur les objets retournés. Les
|
||
paramètres de la recherche sont :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSobject</code></p>
|
||
<p>C'est le nom du LSobject recherché. <em>(Paramètre facultatif pour
|
||
une délégation de type simple)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>attr</code></p>
|
||
<p>Nom de l'attribut des LSobjets contenant une valeur clé qui
|
||
permettra d'identifier l'utilisateur comme ayant droit.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>attr_value</code></p>
|
||
<p>Le format de la valeur clé prise par l'attribut <code>attr</code>. Ce format est composé à partir des
|
||
données de l'objet de l'utilisateur connecté. Voir le paragraphe
|
||
<a href="#conf-global-lsformat-format-parametrable">Format paramètrable</a> pour plus d'informations sur
|
||
l'écriture du format.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p>Ce paramètre remplace les paramètres <code>attr</code> et <code>attr_value</code>. Il est possible ici d'écrire
|
||
directement le format paramètrable du filtre recherche dans l'annuaire. Ce filtre sera
|
||
automatiquement agrémenté des conditions sur l'attribut <em>objectclass</em>. Voir le paragraphe
|
||
<a href="#conf-global-lsformat-format-parametrable">Format paramètrable</a> pour plus d'informations sur
|
||
l'écriture du format.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>basedn</code></p>
|
||
<p>C'est le format paramétrable du <em>basedn</em> de la recherche généré à partir de l'utilisateur
|
||
connecté. Il est possible ainsi de la limiter sur les LSojects d'une branche précise de
|
||
l'annuaire. Voir le paragraphe <a href="#conf-global-lsformat-format-parametrable">Format paramètrable</a> pour
|
||
plus d'informations sur l'écriture du format. <em>(Paramètre facultatif)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>params</code></p>
|
||
<p>C'est un tableau associatif contenant les paramètres étendus de la recherche. Voir le paragraphe
|
||
<a href="#conf-global-ldap_search_params-parametres-etendus-des-recherches-dans-lannuaire">Paramètres étendus des recherches dans l'annuaire</a>
|
||
pour plus de détails. <em>(Paramètre facultatif)</em></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<p>Par ailleurs, il est possible d'attribuer un label plus explicite à chaque <em>LSprofile</em> à l'aide de
|
||
la clé <code>label</code>. Ce label sera utilisé pour faire référence au <em>LSprofile</em> lorsque nécéssaire.
|
||
<em>(Paramètre facultatif)</em></p></section><section class="print-page" id="conf-global-ldap-subdn"><h1 id="conf-global-ldap-subdn-sous-niveaux-de-connexion">Sous-niveaux de connexion</h1>
|
||
<p>Cette section décrit la manière de définir des sous-niveaux de connexion à l'annuaire (<em>subDn</em>). Le
|
||
concept de sous-niveau de connexion sert à déclarer les niveaux logiques de l'annuaire. Par exemple,
|
||
dans un annuaire dans lequel sont stockés des objets concernant plusieurs organisations et que
|
||
celles-ci se distinguent grâce à la présence d'une séparation dans l'arbre, il sera alors possible
|
||
de définir des sous-niveaux de connexion pour chacune des organisations.</p>
|
||
<p><strong>Exemple d'arborescence d'annuaire utilisant le concept de sous-niveaux correspondant à des sociétés :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-subdn-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>|- o=ls
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>| |- ou=companies
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>| | |- ou=company1
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>| | | |- ou=people
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>| | | |- ou=groups
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>| | |- ou=company2
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a>| | | |- ou=people
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a>| | | |- ou=groups
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>| |- ou=people
|
||
<a href="#conf-global-ldap-subdn-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a>| |- ou=groups
|
||
</code></pre></div>
|
||
<p>Explications : Il est possible dans cet exemple de définir des sous-niveaux de connexion
|
||
correspondants aux sociétés. Dans chacune de ces sociétés, on retrouve les <em>OU</em> correspondant au
|
||
type d'<em>LSobjets</em>. Lors de la connexion à l'interface, l'utilisateur devra choisir dans quel
|
||
sous-niveau de l'annuaire il souhaite se connecter. Une fois connecté, l'utilisateur manipulera
|
||
uniquement les objets du sous-niveau de l'annuaire dans lequel il se trouve. Il lui sera également
|
||
possible de changer de sous-niveau de connexion à travers l'interface : une liste déroulante est
|
||
disponible pour cela dans le menu.</p>
|
||
<p>Il existe deux manières de déclarer des sous-niveaux de connexion à l'annuaire :</p>
|
||
<ul>
|
||
<li>En déclarant manuellement un <em>subDn</em> de l'annuaire et en lui donnant un nom.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>En listant les <em>LSobjets</em> d'un type précis et en utilisant leurs données pour constituer le nom
|
||
des sous-niveaux. Cette liste est constituée en effectuant une recherche dans l'annuaire. Il est
|
||
possible de définir un <em>basedn</em> particulier pour cette recherche.</li>
|
||
</ul>
|
||
<p>Pour chacune de ces méthodes on définira également les types d'<em>LSobjets</em> qui sont présents dans
|
||
cette branche de l'annuaire.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-subdn-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>'subDn' => array(
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> // Déclaration manuelle
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> '[Nom du sous-niveau]' => array(
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> 'dn' => '[basedn du sous-niveau]',
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> 'nologin' => true, // Désactive la connection dans ce subDn
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> 'LSobjects' => array( // Liste des types d'LSobjets présents dans le sous-niveau
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> [LSobject1],
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a> [LSobject2],
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a> ...
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a> )
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a> ),
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a> // Liste de LSobjets
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a> 'LSobject' => array(
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a> '[type d'LSobject]' => array( // le type d'LSobjet à lister
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a> 'basedn' => '[basedn]', // Le basedn de la recherche
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a> 'displayValue' => '[format]', // Format du nom des sous-niveaux
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a> 'nologin' => true, // Désactive la connection dans ces subDn
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-18" id="__codelineno-1-18" name="__codelineno-1-18"></a> 'onlyAccessible' => True, // Pour que seul les LSobjet accessible à l'utilisateur soit listé
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-19" id="__codelineno-1-19" name="__codelineno-1-19"></a> 'LSobjects' => array( // Liste des types d'LSobjets présents dans les sous-niveaux
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-20" id="__codelineno-1-20" name="__codelineno-1-20"></a> [LSobject1],
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-21" id="__codelineno-1-21" name="__codelineno-1-21"></a> [LSobject2],
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-22" id="__codelineno-1-22" name="__codelineno-1-22"></a> ...
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-23" id="__codelineno-1-23" name="__codelineno-1-23"></a> )
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-24" id="__codelineno-1-24" name="__codelineno-1-24"></a> )
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-25" id="__codelineno-1-25" name="__codelineno-1-25"></a> )
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-26" id="__codelineno-1-26" name="__codelineno-1-26"></a>),
|
||
<a href="#conf-global-ldap-subdn-__codelineno-1-27" id="__codelineno-1-27" name="__codelineno-1-27"></a>...
|
||
</code></pre></div></section><section class="print-page" id="conf-global-ldap-recoverpassword"><h1 id="conf-global-ldap-recoverpassword-recuperation-de-mot-de-passe">Récupération de mot de passe</h1>
|
||
<p>Cette section décrit la manière de configurer la récupération de mot de passe par les utilisateurs.
|
||
Le mécanisme de récupération de mot de passe fonctionne en deux parties :</p>
|
||
<ul>
|
||
<li>
|
||
<p>Dans un premier lieu, l'utilisateur ayant perdu son mot de passe accède à l'interface de
|
||
récupération à partir de la page de connexion. L'interface lui demande de saisir son identifiant
|
||
et éventuellement de sélectionner le serveur LDAP concerné. Une fois ces informations saisies, une
|
||
recherche de l'utilisateur est effectuée dans l'annuaire et si celui-ci est trouvé, la valeur de
|
||
l'attribut <code>recoveryHashAttr</code> de l'objet est alors redéfinie avec une valeur aléatoire.</p>
|
||
<p>Un mail est ensuite envoyé à l'utilisateur en utilisant la première valeur de l'attribut
|
||
<code>mailAttr</code> comme adresse. Ce mail est formé à partir des paramètres du tableau associatif
|
||
<code>recoveryHashMail</code>.
|
||
Celui-ci doit contenir le sujet du mail dans <code>subject</code> et le corps du message dans <code>msg</code>. Ces deux
|
||
informations sont des <a href="#conf-global-lsformat-format-parametrable">formats paramètrables</a> composés avec,
|
||
comme valeur clé, l'URL de retour à laquelle l'utilisateur devra se rendre pour accèder à la
|
||
seconde étape de la récupération de son mot de passe.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>L'utilisateur doit donc se rendre sur l'interface par l'intermédiaire de l'URL qui lui aura été
|
||
fournie dans le mail de l'étape précédente. Cette URL contient la valeur de l'attribut
|
||
<code>recoveryHashAttr</code> précédement définie. A partir de cette information, une recherche est effectuée
|
||
dans l'annuaire pour retrouver l'utilisateur correspondant.</p>
|
||
<p>Si l'utilisateur est retrouvé, un nouveau mot de passe lui est généré en utilisant les paramètres
|
||
de configuration éventuellement définis dans la configuration HTML de l'attribut "mot de passe".
|
||
Pour avoir plus d'information sur ces paramètres, consulter la documentation du type d'attribut
|
||
HTML
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-lsattr_html_password"><em>LSattr_html_password</em></a>.
|
||
L'attribut <code>recoveryHashAttr</code> est quant à lui supprimé.</p>
|
||
<p>Ensuite, un mail est composé à partir des paramètres du tableau associatif <code>newPasswordMail</code> et
|
||
est envoyé à l'utilisateur. Ce tableau doit contenir le sujet du mail dans <code>subject</code> et le corps
|
||
du message dans <code>msg</code>. Ces deux informations sont des
|
||
<a href="#conf-global-lsformat-format-parametrable">formats paramètrables</a> composés avec, comme valeur clé, le
|
||
nouveau mot de passe de l'utilisateur.</p>
|
||
</li>
|
||
</ul>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-ldap-recoverpassword-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'recoverPassword' => array(
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'mailAttr' => '[attribut mail]',
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'recoveryHashAttr' => '[attribut hash]',
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'recoveryEmailSender' => '[adresse mail utilisée par LdapSaisie pour l'envoi des mails]',
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'recoveryHashMail' => array( // 1er mail : avec l'URL pour l'accès à la 2nde partie
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'subject' => '[sujet du mail]',
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'msg' => "[message contenant le mot clé %{url}]"
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> ),
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'newPasswordMail' => array( // 2nd mail : avec le mot de passe
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'subject' => '[sujet du mail]',
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> 'msg' => "[message contenant le mot clé %{mdp}]"
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> )
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a>),
|
||
<a href="#conf-global-ldap-recoverpassword-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a>...
|
||
</code></pre></div></section><h1 class="nav-section-title-end">Ended: Connexion LDAP</h1><section class="print-page" id="conf-global-lslog"><h1 id="conf-global-lslog-configuration-de-la-journalisation-lslog">Configuration de la journalisation (LSlog)</h1>
|
||
<p>Cette section décrit le tableau de configuration de la journalisation de l'application.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-lslog-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSlog'] = array(</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> 'enable' => [booléen],</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> 'level' => '[niveau]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> 'log_errors_context' => [booléen],</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> 'log_errors_context_with_args' => [booléen],</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x"> 'log_errors_context_args_max_length' => [entier],</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x"> 'handlers' => array(</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x"> '[handler 1]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x"> array (</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x"> 'handler' => [handler 2],</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x"> 'enabled' => [booléen],</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x"> 'level' => '[niveau]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> 'loggers' => array('logger1', [...]),</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x"> 'excluded_loggers' => array('logger2', [...]),</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> 'format' => '[LSformat]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> 'cli_format' => '[LSformat]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x"> 'datetime_prefix' => [booléen],</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a><span class="x"> 'datetime_format' => '[format date()]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a><span class="x"> // Autres paramètres propre à ce handler</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="x"> [...]</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a><span class="x"> [...]</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a><span class="x"> 'loggers' => array (</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="x"> 'logger1' => array (</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a><span class="x"> 'level' => 'DEBUG',</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a><span class="x"> 'logger2' => array (</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="x"> 'enabled' => false,</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a><span class="x"> ),</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a><span class="x"> [...]</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a><span class="x"> );</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a><span class="x">);</span>
|
||
<a href="#conf-global-lslog-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a><span class="x">...</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>enable</code></p>
|
||
<p>Booléen permatant d'activer ou désactiver complètement la journalisation. Par défaut : <code>False</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>level</code></p>
|
||
<p>Ce paramètre défini le niveau minimum de la journalisation : tous les messages des niveaux
|
||
inférieurs ne seront pas inclus dans le journal de l'application. Les niveaux de journalisation
|
||
gérés par l'application sont (dans l'ordre du plus petit au plus grand) :</p>
|
||
<ul>
|
||
<li><code>TRACE</code></li>
|
||
<li><code>DEBUG</code></li>
|
||
<li><code>INFO</code></li>
|
||
<li><code>WARNING</code></li>
|
||
<li><code>ERROR</code></li>
|
||
<li><code>FATAL</code></li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>log_errors_context</code></p>
|
||
<p>Booléen permatant de définir si le contexte <em>(=backtrace)</em> doit être inclus lors de la
|
||
journalisation d'une erreurs.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>log_errors_context_with_args</code></p>
|
||
<p>Booléen permatant de définir si les arguments des méthodes/fonctions appelées doivent être
|
||
inclus lors de la journalisation du contexte des erreurs.
|
||
<strong>Note :</strong> ce paramètre n'as aucun effet si le paramètre <code>log_errors_context</code> n'est pas activé.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>log_errors_context_args_max_length</code></p>
|
||
<p>Ce paramètre permet de définir à partir de quelle longueur les arguments des méthodes/fonctions
|
||
appelées et journalisés seront tronqués (par défaut : <code>1000</code>). <strong>Note :</strong> pour désactiver le
|
||
troncage, mettre ce paramètre à zéro.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>handlers</code></p>
|
||
<p>Tableau permettant de configurer les <em>handlers</em> de la journalisation. Chaque <em>handler</em> gère les
|
||
messages journalisés d'une manière qui lui est propre.</p>
|
||
<p>Plusieurs <em>handlers</em> peuvent être configurés en même temps (y compris plusieurs <em>handlers</em> du même
|
||
type).</p>
|
||
<p>Ce tableau peut contenir simplement le nom du type de <em>handler</em> à utiliser ou bien des tableaux
|
||
configurant un à un chacun des <em>handlers</em>. Dans ce second cas, la structure de la configuration
|
||
d'un <em>handler</em> est la suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-lslog-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">array(</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> 'handler' => [type],</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> 'level' => '[niveau]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> 'loggers' => array('logger1', [...]),</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> 'excluded_loggers' => array('logger2', [...]),</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> 'format' => '[LSformat]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> 'cli_format' => '[LSformat]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> 'datetime_prefix' => [booléen],</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> 'datetime_format' => '[format date()]',</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> // Autres paramètres propre à ce handler</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> [...]</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x">)</span>
|
||
<a href="#conf-global-lslog-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="x">...</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>handler</code></p>
|
||
<p>Type du <em>handler</em> (voir ci-dessous).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>level</code></p>
|
||
<p>Ce paramètre défini le niveau minimum de la journalisation spécifique à cet <em>handler</em>. Si ce
|
||
paramètre est omis, le niveau global sera utilisé. Les valeurs possibles de ce paramètre sont
|
||
les mêmes que pour le paramètre <code>$GLOBALS['LSlog']['level']</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>enabled</code></p>
|
||
<p>Booléen permettant d'activer ou désactiver cet <em>handler</em> (paramètre facultatif, par défaut :
|
||
<code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>loggers</code></p>
|
||
<p>Liste exhautive des composants dont les messages doivent être traités par ce handler (paramètre
|
||
facultatif, par défaut : tous les composants).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>excluded_loggers</code></p>
|
||
<p>Liste exhautive des composants dont les messages ne doivent pas être traités par ce handler
|
||
(paramètre facultatif, par défaut : aucun composant).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> des messages de cet journalisé par ce handler. Ce
|
||
format est composé à partir des informations décritent ci-dessous. Par défaut :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-lslog-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>%{requesturi} - %{remoteaddr} - %{ldapservername} - %{authuser} - %{logger} - %{level} - %{message}
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>level</code></p>
|
||
<p>Le niveau du message.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>message</code></p>
|
||
<p>Le message.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>logger</code></p>
|
||
<p>Le composant ayant déchenché cette journalisation.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>clibinpath</code></p>
|
||
<p>Le nom du script ayant déclenché cette jounalisation (uniquement en cas d'exécution en ligne
|
||
de commande).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>requesturi</code></p>
|
||
<p>L'URL de la page courante (uniquement dans un contexte Web).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>remoteaddr</code></p>
|
||
<p>L'adresse IP du client (uniquement dans un contexte Web).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ldapservername</code></p>
|
||
<p>Le nom du serveur LDAP courant.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>authuser</code></p>
|
||
<p>Le DN de l'utilisateur connecté (uniquement dans un contexte Web).</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>cli_format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> des messages de cet journalisé par ce handler dans
|
||
le cas d'une exécution en ligne de commande. Ce format est composé à partir des même
|
||
informations que le paramètre <code>format</code> (voir ci-dessus). Par défaut :
|
||
</p><div class="highlight"><pre><span></span><code><a href="#conf-global-lslog-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a>%{clibinpath} - %{logger} - %{level} - %{message}
|
||
</code></pre></div><p></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>datetime_format</code></p>
|
||
<p>Booléen permettant de définir si le message doit être préfixé de la date et heure courante. La
|
||
valeur par défaut dépends de l'handler (en règle général, toujours actif sauf lorsque le canal
|
||
de journalisation l'ajoute déjà).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>datetime_format</code></p>
|
||
<p>Format de la date et heure lorsque celle-ci est ajoutée en préfixe du message (voir paramètre
|
||
<code>datetime_format</code>). Le format correspond à celui attendu par la function <code>date()</code> de
|
||
<a href="http://www.php.net/">PHP</a>. Consultez la <a href="http://php.net/date">documentation officielle</a> pour
|
||
plus de détails (Par défaut : <code>Y/m/d H:i:s</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<p>Il existe plusieurs types d'<em>handlers</em> gérés par l'application :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>file</code></p>
|
||
<p>Journalisation dans un simple fichier texte. Le chemin du fichier peut être configuré via le
|
||
paramètre <code>path</code>. Si ce paramètre est omis, le chemin du fichier par défaut est soit la
|
||
valeur de la variable <code>$GLOBALS['LSlog']['filename']</code> (pour la rétro-compatibilité avec les
|
||
anciennes versions d'LdapSaisie) ou à défaut : <code>tmp/LS.log</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>syslog</code></p>
|
||
<p>Journalisation via le service <em>syslog</em>. Il est possible de configurer une priorité
|
||
systématique pour les messages journalisés. À défaut, la priorité sera déterminée
|
||
automatiquement en fonction du niveau du message. Les valeurs
|
||
possibles de ce paramètre sont : <code>EMERG, ALERT, CRITICAL,ERROR, WARNING, NOTICE, INFO, DEBUG</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>system</code></p>
|
||
<p>Journalisation via le gestionnaire d'erreurs PHP. Cet <em>handler</em> utilise la fonction
|
||
<a href="http://www.php.net/">PHP</a> <code>error_log</code>. Pour plus d'informations sur comment configurer le
|
||
gestionnaire d'erreurs PHP, consulter la
|
||
<a href="https://www.php.net/error_log">documentation officielle</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>email</code></p>
|
||
<p>Journalisation via l'envoi d'un email : chaque message journalisé déclenchera l'envoi d'un email
|
||
au destinataire configuré. L'adresse email du destinataire peut-être configurée via le paramètre
|
||
<code>recipient</code>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Il est conseillé d'utiliser ce type d'<em>handler</em> avec un niveau minimum de journalisation
|
||
important (<code>FATAL</code> recommandé) pour ne pas déclencher un nombre trop important d'envois
|
||
d'emails.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>loggers</code></p>
|
||
<p>Tableau permettant de configurer la journalisation composant par composant. Chaque composant peut
|
||
avoir son propre <code>logger</code> ce qui permet alors, par exemple, de configurer le niveau de log
|
||
spécifiquement pour ce composant.</p>
|
||
<p>Le nom des composant correspond en général au nom de la classe PHP correspondante, ou bien encore
|
||
le nom d'une commande (lors d'une exécution en ligne de commande).</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Par défaut, le nom du composant ayant déclenché un message journalisé est affiché juste avant
|
||
le niveau de log.</p>
|
||
</div>
|
||
<ul>
|
||
<li>
|
||
<p><code>enabled</code></p>
|
||
<p>Booléen permettant de désactiver complètement les logs du composant (par défaut: <code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>level</code></p>
|
||
<p>Niveau de log spécifique pour ce composant (par défaut: le niveau de log global).</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-global-lsformat"><h1 id="conf-global-lsformat-format-parametrable-lsfomat">Format paramétrable (LSfomat)</h1>
|
||
<p>Un <em>format paramétrable</em> est une chaîne de caractères contenant des mots clés formés comme dans
|
||
l'exemple suivant :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-global-lsformat-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>%{[nom du mot clé][:A][:B][! ou _][~][%]}
|
||
</code></pre></div>
|
||
<p>Le nom du mot clé peut contenir des lettres de "a" à "z", de "A" à "Z" et des chiffres de 0 à 9. Ces
|
||
mots clés seront remplacés par les valeurs passées en paramètres et liées au contexte d'utilisation.
|
||
Les paramètres <em>:A</em> et <em>:B</em> permettent d'extraire une partie de la chaîne complète avant la
|
||
substitution.</p>
|
||
<p>Le paramètre <code>A</code> correspond, lorsque <code>B</code> n'est pas défini, au nombre maximum de caractères à
|
||
extraire de la chaîne de substitution. <em>A</em> doit être un entier dont le signe influ, comme expliqué
|
||
ci-dessous :</p>
|
||
<ul>
|
||
<li>Si <code>A</code> est positif, les <code>A</code> premiers caractères de la chaîne de substitution seront extraits.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Si <code>A</code> est négatif, les <code>|A|</code> derniers caractères de la chaîne de substitution seront extraits.</li>
|
||
</ul>
|
||
<p>Lorsque le paramètre <code>B</code> est défini, <code>A</code> correspond au rang du premier caractère à partir duquel la
|
||
chaîne de substitution sera découpée et <code>B</code> le nombre maximum de caractères à extraire. Le signe de
|
||
<code>B</code> influera comme expliqué dans le premier cas. Si <code>B</code> vaut zéro, la totalité de la longeur de la
|
||
chaîne sera retournée en tenant compte de <code>A</code> pour le rang du premier caractère.</p>
|
||
<p>Il existe par ailleurs des paramètres permettant de modifier la valeur de substitution avant son
|
||
utilisation :</p>
|
||
<ul>
|
||
<li>Les paramètres <em>!</em> ou <em>_</em> permettre respectivement de forcer la mise en majuscule ou en minuscule ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le paramètre <em>~</em> permet de forcer la suppression des accents ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Le paramètre <em>%</em> permet de protéger les caractères éligibles en entités HTML.</li>
|
||
</ul>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Lorsque qu'une seule valeur clé est disponible pour la substitution, le nom du mot clé n'importe
|
||
pas. Tous les mots clés trouvés dans le format seront remplacés par cette seule valeur.</p>
|
||
</div></section><section class="print-page" id="conf-global-ldap_search_params"><h1 id="conf-global-ldap_search_params-parametres-etendus-des-recherches-dans-lannuaire">Paramètres étendus des recherches dans l'annuaire</h1>
|
||
<p>Les paramètres des recherches sont ceux supportés par
|
||
<a href="http://pear.php.net/package/Net_LDAP2">Net_LDAP2</a>. Ces paramètres sont passés sous la forme d'un
|
||
tableau associatif. Les paramètres supportés sont détaillés ci-dessous :</p>
|
||
<table>
|
||
<thead>
|
||
<tr class="header">
|
||
<th>Nom</th>
|
||
<th>Description</th>
|
||
<th>Valeur par défaut</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr class="odd">
|
||
<td><code>scope</code></td>
|
||
<td><p>Définition de l'étendue de la recherche :</p>
|
||
<ul>
|
||
<li><p><code>base</code> - Sur une entrée seulement</p></li>
|
||
<li><p><code>one</code> - Sur les entrées imédiatement contenu par le <code>basedn</code> de la recherche</p></li>
|
||
<li><p><code>sub</code> - Sur l'arbre entier</p></li>
|
||
</ul></td>
|
||
<td><code>sub</code></td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><code>sizelimit</code></td>
|
||
<td>Le nombre maximum d'entrées retournées par la recherche.</td>
|
||
<td><code>0</code> (illimité)</td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><code>timelimit</code></td>
|
||
<td>Le délai d'attente maximum de la réponse du serveur en secondes.</td>
|
||
<td><code>0</code> (illimité)</td>
|
||
</tr>
|
||
<tr class="even">
|
||
<td><code>attrsonly</code></td>
|
||
<td>Si <em>vrai</em>, seuls les noms des atttributs seront retournés.</td>
|
||
<td><code>false</code></td>
|
||
</tr>
|
||
<tr class="odd">
|
||
<td><code>attributes</code></td>
|
||
<td>Tableau contenant les noms des attributs que les entrées retournées peuvent contenir et que l'on souhaite récupérer.</td>
|
||
<td><code>array()</code>(tous)</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<p>Pour plus d'information sur le sujet, vous pouvez consulter la documentation officiel du projet
|
||
<a href="http://pear.php.net/package/Net_LDAP2">Net_LDAP2</a>.</p></section><h1 class="nav-section-title-end">Ended: Configuration globale</h1><h2 class="nav-section-title">Objets de l'annuaire</h2><section class="print-page" id="conf-lsobject"><h1 id="conf-lsobject-configuration-lsobject">Configuration LSobject</h1>
|
||
<p>Cette partie décrit la manière de configurer les différents types de LSobjets manipulés par
|
||
LdapSaisie.</p>
|
||
<p>La configuration des LSobjects est stockée dans le dossier <code>/conf/LSobjects</code>. Dans ce dossier, on
|
||
retrouve un fichier par type d'LSobject, nommé de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>config.LSobjects.[nom du type d'LSobject].php
|
||
</code></pre></div>
|
||
<p>Ce fichier contient la déclaration de la configuration du type d'LSobject qui est stocké dans la
|
||
variable globale <code>$GLOBALS['LSobjects']['[nom du type d'LSobject]']</code>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">$GLOBALS['LSobjects']['[nom du type d'LSobject]'] = array (</span>
|
||
<a href="#conf-lsobject-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> 'objectclass' => array(</span>
|
||
<a href="#conf-lsobject-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> 'objetclass1',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> 'objetclass2',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> 'filter' => '[filtre LDAP]',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> 'rdn' => 'attr1',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> 'LSaddons' => [LSaddon(s)],</span>
|
||
<a href="#conf-lsobject-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="x"> 'container_dn' => 'ou=people',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a><span class="x"> 'generate_container_dn' => '[callable]',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a><span class="x"> 'container_auto_create' => array(</span>
|
||
<a href="#conf-lsobject-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a><span class="x"> // Information des configurations pour la création du conteneur du type d'LSobjet</span>
|
||
<a href="#conf-lsobject-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a><span class="x"> // lors de la création nouveau subDn</span>
|
||
<a href="#conf-lsobject-__codelineno-1-18" id="__codelineno-1-18" name="__codelineno-1-18"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-__codelineno-1-19" id="__codelineno-1-19" name="__codelineno-1-19"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-20" id="__codelineno-1-20" name="__codelineno-1-20"></a><span class="x"> 'disable_creation' => [boolean]',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-21" id="__codelineno-1-21" name="__codelineno-1-21"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-22" id="__codelineno-1-22" name="__codelineno-1-22"></a><span class="x"> 'before_modify' => 'function1',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-23" id="__codelineno-1-23" name="__codelineno-1-23"></a><span class="x"> 'after_modify' => 'function2',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-24" id="__codelineno-1-24" name="__codelineno-1-24"></a><span class="x"> 'after_create' => 'function3',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-25" id="__codelineno-1-25" name="__codelineno-1-25"></a><span class="x"> 'after_delete' => 'function4',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-26" id="__codelineno-1-26" name="__codelineno-1-26"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-27" id="__codelineno-1-27" name="__codelineno-1-27"></a><span class="x"> 'label' => 'objet1',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-28" id="__codelineno-1-28" name="__codelineno-1-28"></a><span class="x"> 'display_name_format' => '[format]',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-29" id="__codelineno-1-29" name="__codelineno-1-29"></a><span class="x"> 'displayAttrName' => '[booleen]',</span>
|
||
<a href="#conf-lsobject-__codelineno-1-30" id="__codelineno-1-30" name="__codelineno-1-30"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-31" id="__codelineno-1-31" name="__codelineno-1-31"></a><span class="x"> //Custom Actions</span>
|
||
<a href="#conf-lsobject-__codelineno-1-32" id="__codelineno-1-32" name="__codelineno-1-32"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsobject-__codelineno-1-33" id="__codelineno-1-33" name="__codelineno-1-33"></a><span class="x"> // Configuration des customActions pour ce type d'objet</span>
|
||
<a href="#conf-lsobject-__codelineno-1-34" id="__codelineno-1-34" name="__codelineno-1-34"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-__codelineno-1-35" id="__codelineno-1-35" name="__codelineno-1-35"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-36" id="__codelineno-1-36" name="__codelineno-1-36"></a><span class="x"> // LSrelation</span>
|
||
<a href="#conf-lsobject-__codelineno-1-37" id="__codelineno-1-37" name="__codelineno-1-37"></a><span class="x"> 'LSrelation' => array(</span>
|
||
<a href="#conf-lsobject-__codelineno-1-38" id="__codelineno-1-38" name="__codelineno-1-38"></a><span class="x"> // Configuration des LSrelations entre ce type d'objet et les autres</span>
|
||
<a href="#conf-lsobject-__codelineno-1-39" id="__codelineno-1-39" name="__codelineno-1-39"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-__codelineno-1-40" id="__codelineno-1-40" name="__codelineno-1-40"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-41" id="__codelineno-1-41" name="__codelineno-1-41"></a><span class="x"> // LSform</span>
|
||
<a href="#conf-lsobject-__codelineno-1-42" id="__codelineno-1-42" name="__codelineno-1-42"></a><span class="x"> 'LSform' => array (</span>
|
||
<a href="#conf-lsobject-__codelineno-1-43" id="__codelineno-1-43" name="__codelineno-1-43"></a><span class="x"> // Configuration des formulaires de l'objet</span>
|
||
<a href="#conf-lsobject-__codelineno-1-44" id="__codelineno-1-44" name="__codelineno-1-44"></a><span class="x"> ), // fin LSform</span>
|
||
<a href="#conf-lsobject-__codelineno-1-45" id="__codelineno-1-45" name="__codelineno-1-45"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-46" id="__codelineno-1-46" name="__codelineno-1-46"></a><span class="x"> // LSsearch</span>
|
||
<a href="#conf-lsobject-__codelineno-1-47" id="__codelineno-1-47" name="__codelineno-1-47"></a><span class="x"> 'LSsearch' => array (</span>
|
||
<a href="#conf-lsobject-__codelineno-1-48" id="__codelineno-1-48" name="__codelineno-1-48"></a><span class="x"> // Configuration des recherches de l'objet</span>
|
||
<a href="#conf-lsobject-__codelineno-1-49" id="__codelineno-1-49" name="__codelineno-1-49"></a><span class="x"> ), // fin LSsearch</span>
|
||
<a href="#conf-lsobject-__codelineno-1-50" id="__codelineno-1-50" name="__codelineno-1-50"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-51" id="__codelineno-1-51" name="__codelineno-1-51"></a><span class="x"> 'globalSearch' => [booleen],</span>
|
||
<a href="#conf-lsobject-__codelineno-1-52" id="__codelineno-1-52" name="__codelineno-1-52"></a><span class="x"> 'globalSearch_extraDisplayedColumns' => [booleen],</span>
|
||
<a href="#conf-lsobject-__codelineno-1-53" id="__codelineno-1-53" name="__codelineno-1-53"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-54" id="__codelineno-1-54" name="__codelineno-1-54"></a><span class="x"> // ioFormat</span>
|
||
<a href="#conf-lsobject-__codelineno-1-55" id="__codelineno-1-55" name="__codelineno-1-55"></a><span class="x"> 'ioFormat' => array (</span>
|
||
<a href="#conf-lsobject-__codelineno-1-56" id="__codelineno-1-56" name="__codelineno-1-56"></a><span class="x"> // Configuration des formats d'import/export de l'objet</span>
|
||
<a href="#conf-lsobject-__codelineno-1-57" id="__codelineno-1-57" name="__codelineno-1-57"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-__codelineno-1-58" id="__codelineno-1-58" name="__codelineno-1-58"></a>
|
||
<a href="#conf-lsobject-__codelineno-1-59" id="__codelineno-1-59" name="__codelineno-1-59"></a><span class="x"> // Attributs</span>
|
||
<a href="#conf-lsobject-__codelineno-1-60" id="__codelineno-1-60" name="__codelineno-1-60"></a><span class="x"> 'attrs' => array (</span>
|
||
<a href="#conf-lsobject-__codelineno-1-61" id="__codelineno-1-61" name="__codelineno-1-61"></a><span class="x"> // Configuration des attributs du type d'LSobjet</span>
|
||
<a href="#conf-lsobject-__codelineno-1-62" id="__codelineno-1-62" name="__codelineno-1-62"></a><span class="x"> )</span>
|
||
<a href="#conf-lsobject-__codelineno-1-63" id="__codelineno-1-63" name="__codelineno-1-63"></a><span class="x">);</span>
|
||
<a href="#conf-lsobject-__codelineno-1-64" id="__codelineno-1-64" name="__codelineno-1-64"></a><span class="x">...</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>objectclass</code></p>
|
||
<p>La liste des <em>objectclass</em> des objets.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p>Filtre de recherche LDAP applicable à tout les objets de ce type et qui sera utilisé lors de
|
||
chaque recherche de ce type d'objet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>rdn</code></p>
|
||
<p>Nom de l'attribut correspondant au <em>RDN</em> des objets LDAP.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSaddons</code></p>
|
||
<p>LSaddon(s) dont le type d'objet dépend. Ce peut être un tableau de chaînes de caractères ou une
|
||
simpe chaîne de caractères correspondant au(x) nom(s) du/des LSaddon(s) en dépendance.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>container_dn</code></p>
|
||
<p>Elément pour construire le <em>basedn</em> de stockage de ce type d'objet. Par exemple, si le <em>basedn</em> de
|
||
l'annuaire est <code>o=ls</code> et que les objets <em>utilisateurs</em> sont stockés dans la branche de l'annuaire
|
||
<code>ou=people,o=ls</code>, alors <code>container_dn</code> devra valoir <code>ou=people</code>.</p>
|
||
<p>Lorsque l'annuaire possède des <a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">subDn</a>, les
|
||
objets seront cherchés dans le <em>basedn</em> résultant de la concaténation du paramètre <code>container_dn</code>,
|
||
d'une virgule et du <em>basedn</em> correspondant au
|
||
<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">subDn</a> courant.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>generate_container_dn</code></p>
|
||
<p><em>Callable</em> (au sens PHP), utilisé pour générer la valeur du paramètre <code>container_dn</code>
|
||
dynamiquement. Ce <em>callable</em> prend en paramètre l'objet LSobject à
|
||
créer et retourne la valeur du paramètre <code>container_dn</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>container_auto_create</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration nécessaires à la création des
|
||
<code>container_dn</code> dans les nouveaux objets utilisés comme
|
||
<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">subDn</a>.
|
||
<a href="#conf-lsobject-container_auto_create-creation-automatique-du-conteneur-des-lsobjets-dans-un-subdn">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>disable_creation</code></p>
|
||
<p>Booléen permetant de desactiver la creation de ce type d'objet de manière globale.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>before_modify</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaine de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées avant la modification d'un objet.
|
||
<a href="#conf-lsobject-triggers-declencheurs_1">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>after_modify</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaine de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées après la modification d'un objet.
|
||
<a href="#conf-lsobject-triggers-declencheurs_1">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>after_create</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaine de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées après la création d'un objet.
|
||
<a href="#conf-lsobject-triggers-declencheurs_1">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>after_delete</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaine de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées après la suppression d'un objet.
|
||
<a href="#conf-lsobject-triggers-declencheurs_1">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Nom générique au pluriel qualifiant le type d'objet. Exemple : <em>Utilisateurs</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>display_name_format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">Format paramètrable</a> du nom des objets composés à
|
||
partir des valeurs d'affichage des attributs de l'objet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>displayAttrName</code></p>
|
||
<p>Booléen définissant si le nom des attributs doit être affiché en préfixe de leur message d'aide
|
||
(paramètre <code>help_info</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>customActions</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration des
|
||
<a href="#conf-lsobject-customactions-customactions">customActions</a>.
|
||
<a href="#conf-lsobject-customactions-customactions">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSrelation</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration des
|
||
<a href="#conf-lsobject-lsrelation-lsrelation">LSrelations</a>. <a href="#conf-lsobject-lsrelation-lsrelation">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSform</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration des <a href="#conf-lsobject-lsform-lsform">LSforms</a> des
|
||
LSobjects. <a href="#conf-lsobject-lsform-lsform">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSsearch</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration des recherches de
|
||
LSobject de ce type dans l'annuaire.
|
||
<a href="#conf-lsobject-lssearch-lssearch">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>globalSearch</code></p>
|
||
<p>Inclure ou non ce type d'objet dans le résultat des recherches globales (Par défaut : <code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>globalSearch_extraDisplayedColumns</code></p>
|
||
<p>Afficher ou non les colonnes supplémentaires pour ce type d'objet dans le résultat des recherches
|
||
globales (Par défaut : <code>True</code>). Pour plus de détails les colonnes supplémentaires,
|
||
<a href="#conf-lsobject-lssearch-lssearch">voir la section dédiée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ioFormat</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration des formats de fichiers
|
||
d'import/export de ce type d'LSobject.
|
||
<a href="#conf-lsobject-ioformat-ioformat">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>attrs</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration des attributs des objets.
|
||
<a href="#conf-lsobject-lsattribute-configuration-des-attributs">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul></section><h3 class="nav-section-title">Attributs</h3><section class="print-page" id="conf-lsobject-lsattribute"><h1 id="conf-lsobject-lsattribute-configuration-des-attributs">Configuration des attributs</h1>
|
||
<p>Cette section décrit les options de configuration des attributs des
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a>. Les attributs sont définis dans le tableau
|
||
associatif <code>attrs</code> de la configuration des <a href="#conf-lsobject-configuration-lsobject">LSobjects</a>. Dans ce
|
||
tableau, les clé les noms des attributs et les valeurs liés sont la configuration des attributs.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Contrairement à ce qui existe dans le standard LDAP, les noms des attributs sont sensibles à la
|
||
casse. Il faut que le nom des attributs dans LdapSaisie soient scrupuleusement les mêmes que
|
||
ceux retourné par <a href="http://pear.php.net/package/Net_LDAP2">Net_LDAP2</a></p>
|
||
</div>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'attrs' => array (
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> /* ----------- start -----------*/
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'attr1' => array (
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'label' => '[label de l'attr1',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'displayAttrName' => '[booleen]',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'help_info' => '[Message d'aide sur l'attribut attr1]',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'help_info_in_view' => '[booleen]',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'ldap_type' => 'ldaptype1',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'ldap_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> // Options LDAP liées au type LDAP de l'attribut
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> 'html_type' => 'htmltype1',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> 'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> // Options HTML liées au type HTML de l'attribut
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> 'no_value_label' => '[No set value label]',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> 'multiple' => 0,
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> 'required' => 1,
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> 'generate_function' => 'fonction1',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> 'generate_value_format' => '[LSformat]',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> 'default_value' => 'valeur1',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> 'set_default_value_on_creation_if_empty' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> 'force_generation_if_empty' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a> 'check_data' => array (
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a> // Régle de vérification syntaxique des données saisies
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a> 'validation' => array (
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a> // Règle de vérification d'intégrité des données saisies
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a> 'rights' => array(
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a> 'LSprofile1' => 'droit1',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a> 'LSprofile2' => 'droit2',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a> 'view' => 1,
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a> 'form' => array (
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a> 'create' => 1,
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a> 'modify' => 0,
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a> 'dependAttrs' => array(
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a> // Attributs en dépendance
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a> 'onDisplay' => 'fonction2'
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-45" id="__codelineno-0-45" name="__codelineno-0-45"></a>
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-46" id="__codelineno-0-46" name="__codelineno-0-46"></a> 'before_modify' => 'function1',
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-47" id="__codelineno-0-47" name="__codelineno-0-47"></a> 'after_modify' => 'function2'
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-48" id="__codelineno-0-48" name="__codelineno-0-48"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-49" id="__codelineno-0-49" name="__codelineno-0-49"></a> /* ----------- end -----------*/
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-50" id="__codelineno-0-50" name="__codelineno-0-50"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-51" id="__codelineno-0-51" name="__codelineno-0-51"></a>);
|
||
<a href="#conf-lsobject-lsattribute-__codelineno-0-52" id="__codelineno-0-52" name="__codelineno-0-52"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label de l'attribut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>displayAttrName</code></p>
|
||
<p>Booléen définissant si le nom de l'attribut doit être affiché en préfixe du message d'aide
|
||
(paramètre <code>help_info</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>help_info</code></p>
|
||
<p>Message d'aide qui sera affiché dans une bulle d'aide à côté du nom de l'attribut dans les
|
||
formulaires.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>help_info_in_view</code></p>
|
||
<p>Booléen définissant si le message d'aide doit être affiché sur la vue de visualisation de l'objet.</p>
|
||
<p>Valeurs possibles : <em>0</em> ou <em>1</em></p>
|
||
<p>Valeur par défaut : <em>0</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ldap_type</code></p>
|
||
<p>Le type LDAP de l'attribut (facultatif, par défaut:
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_ascii-lsattr_ldap_ascii">LSattr_ldap_ascii</a>).
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-configuration-des-attributs-ldap">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ldap_options</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration du type LDAP de l'attribut.
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-configuration-des-attributs-ldap">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>html_type</code></p>
|
||
<p>Le type HTML de l'attribut (facultatif, par défaut:
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">LSattr_html_text</a>).
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-configuration-des-attributs-html">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>html_options</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration du type HTML de l'attribut.
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-configuration-des-attributs-html">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>no_value_label</code></p>
|
||
<p>Label affiché lorsque l'attribut n'a pas de valeur (facultatif).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>multiple</code></p>
|
||
<p>Booléen définissant si cet attribut peut stocker plusieurs valeurs.</p>
|
||
<p>Valeurs possibles : <em>0</em> ou <em>1</em></p>
|
||
<p>Valeur par défaut : <em>0</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>required</code></p>
|
||
<p>Booléen définissant si cet attribut doit obligatoirement être défini.</p>
|
||
<p>Valeurs possibles : <em>0</em> ou <em>1</em></p>
|
||
<p>Valeur par défaut : <em>0</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>generate_function</code></p>
|
||
<p>Nom de la fonction permettant de générer la valeur de l'attribut. Cette fonction sera éxecutée, en
|
||
passant en premier paramètre, l'objet <a href="#conf-lsobject-configuration-lsobject">LSobject</a> courant.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>generate_value_format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> permettant la génération de l'attribut.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette méthode de génération est utilisée uniquement si aucune fonction de génération de la
|
||
valeur n'est définie (paramètre <code>generate_function</code>).</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>default_value</code></p>
|
||
<p>Valeur par défaut de l'attribut.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Il doit s'agir de la valeur telque retournée par le formulaire web. Ainsi, par exemple dans le
|
||
cas d'un attribut booléen, les valeurs possibles sont <code>yes</code> ou <code>no</code>.</p>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette valeur est également utilisée dans le cadre de la génération automatique de la valeur de
|
||
l'attribut si aucune autre méthode n'est disponible (via une fonction ou un
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a>).</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>set_default_value_on_creation_if_empty</code></p>
|
||
<p>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 : <em>1</em>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>force_generation_if_empty</code></p>
|
||
<p>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 : <em>0</em>).</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>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
|
||
<code>set_default_value_on_creation_if_empty</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>check_data</code></p>
|
||
<p>Tableau associatif contenant les règles de vérification syntaxique des données de l'attribut.
|
||
<a href="#conf-lsobject-lsattribute-check_data-configuration-des-regles-de-verification-syntaxique">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>validation</code></p>
|
||
<p>Tableau associatif contenant les règles de vérification d'intégrité des données de l'attribut.
|
||
<a href="#conf-lsobject-lsattribute-validation-configuration-des-regles-de-verification-dintegrite">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>rights</code></p>
|
||
<p>Tableau associatif dont les clés sont les noms des
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a> ayant des droits sur cet
|
||
attribut et les valeurs associées sont les droits correspondants. La valeur des droits d'un
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofile</a> peut être <code>r</code> pour le droit de
|
||
lecture ou <code>w</code> pour le droit de lecture-écriture. Par défaut, un
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofile</a> n'a aucun droit.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>view</code></p>
|
||
<p>Booléen définissant si l'attribut est, ou non, affiché lors de la visualisation des objets du type
|
||
courant.</p>
|
||
<p>Valeurs possibles : <em>0</em> ou <em>1</em></p>
|
||
<p>Valeur par défaut : <em>0</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>form</code></p>
|
||
<p>Tableau associatif dont les clés sont les noms des <a href="#conf-lsobject-lsform-lsform">LSforms</a> et les valeurs
|
||
associées la définition de l'affichage dans ce <a href="#conf-lsobject-lsform-lsform">LSform</a>. Si cette valeur vaut
|
||
<code>0</code>, alors l'attribut sera lecture-seule et si cette valeur vaut <code>1</code>, cet attribut sera affiché
|
||
en lecture-écriture.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>dependAttrs</code></p>
|
||
<p>Tableau associatif listant les attributs dépendants de celui-ci. Les attributs listés ici seront
|
||
regénérés lors de chaque modification de l'attribut courant. Cette génération sera effectuée avec
|
||
la fonction définie dans le paramètre <code>generate_function</code> de l'attribut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>onDisplay</code></p>
|
||
<p>Nom ou liste de nom des fonctions retournant les valeurs d'affichages de l'attribut. Si c'est une
|
||
liste, chacune des fonctions seront executée les unes après les autres. Ces fonctions seront
|
||
éxecutées, en passant en premier paramètre, le tableau des valeurs de l'objet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>before_modify</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaine de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées avant toutes modifications de la valeur de l'attribut.
|
||
<a href="#conf-lsobject-lsattribute-triggers-declencheurs">Voir la section concernée</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>after_modify</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaine de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées après toutes modifications de la valeur de l'attribut.
|
||
<a href="#conf-lsobject-lsattribute-triggers-declencheurs">Voir la section concernée</a></p>
|
||
</li>
|
||
</ul></section><h4 class="nav-section-title">Types d'attribut LDAP (LSattr_ldap)</h4><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-configuration-des-attributs-ldap-lsattr_ldap">Configuration des attributs LDAP (LSattr_ldap)</h1>
|
||
<p>Cette section décrit les options propres à chacun des types d'attributs LDAP supportés par
|
||
LdapSaisie.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_ascii"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_ascii-lsattr_ldap_ascii">LSattr_ldap_ascii</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une chaine de caractère. Ce
|
||
type est le type par défaut.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean-lsattr_ldap_boolean">LSattr_ldap_boolean</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une booléen. On attend ici par
|
||
booléen, tout attribut ne pouvant prendre que deux valeurs pré-définies correspond pour l'un à <em>Oui</em>
|
||
et l'autre à <em>Non</em></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'ldap_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'true_value' => '[valeur correspondant à Vrai]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'false_value' => '[valeur correspondant à Faux]'
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>true_value</code></p>
|
||
<p>La valeur de l'attribut correspondant à <em>Vrai</em>. (Par défaut : <code>TRUE</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>false_value</code></p>
|
||
<p>La valeur de l'attribut correspondant à <code>False</code>. (Par défaut : <code>FALSE</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Les valeurs possibles pour le paramètre <code>default_value</code> sont <code>yes</code> et <code>no</code>.</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_compositevaluetojson"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_compositevaluetojson-lsattr_ldap_compositevaluetojson">LSattr_ldap_compositeValueToJSON</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs composites dont les valeurs respectent le format
|
||
suivant : <code>[key1=value1][key2=value2][...]</code></p>
|
||
<p>Ce type d'attribut LDAP sera utilisé pour convertir la valeur en son équivalent <code>JSON</code> pour pouvoir
|
||
être traité à l'aide du type d' attribut HTML
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-lsattr_html_jsoncompositeattribute">LSattr_html_jsonCompositeAttribute</a>.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-lsattr_ldap_date">LSattr_ldap_date</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une date.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Au sein d'LdapSaisie, les dates manipulées au travers ce type d'attribut LDAP, sont au format
|
||
<em>timestamp</em>. Il s'agit donc de nombres entiers correpondants au nombre de secondes depuis le 1
|
||
janvier 1970.</p>
|
||
<p>Le type d'attribut HTML utilisé conjointement avec ce type d'attribut LDAP devra être prévu pour
|
||
recevoir et fournir des dates au format <em>timestamp</em>, comme c'est le cas pour le <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-lsattr_html_date">type d'attribut
|
||
HTML <em>date</em></a>.</p>
|
||
</div>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'ldap_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'timestamp' => [Booléen], // Si la date est stockée au format timestamp
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'formats' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> '[Format de stockage principal]', // Par défaut : "YmdHisO"
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> '[Formats de stockage alternatifs]', // Par défaut : "YmdHis.vO" & "YmdHis.uO"
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'timezone' => '[Fuseau horaire]', // Default : "UTC"
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>timestamp</code></p>
|
||
<p>Booléen définissant si la date est stockée sous la forme d'un timestamp Unix (nombre de secondes
|
||
depuis le 1er janvier 1970 à 00:00:00 UTC).</p>
|
||
<p>Si <code>timestamp</code> est vrai, LdapSaisie ne tient pas compte du paramètre format.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>formats</code></p>
|
||
<p>Formats de stockage de la date dans l'annuaire. Ces formats sont composés à partir des motifs clés
|
||
gérés par la fonction <code>date()</code> de PHP. Pour plus d'information, consulter
|
||
<a href="http://www.php.net/date">la documentation officielle</a>. Plusieurs formats peuvent être définis,
|
||
mais en cas de stockage d'une nouvelle valeur, se sera le premier format défini qui sera utilisé.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>La valeur par défaut est <em>["YmdHisO", "YmdHis.vO", "YmdHis.uO"]</em>, correspondant à la syntaxe
|
||
<code>Generalized Time</code> (sans et avec les milli-secondes ou micro-secondes) telle que définie dans
|
||
la <a href="https://tools.ietf.org/html/rfc4517">RFC4517</a>.
|
||
Exemples : <code>20091206230506Z</code> <em>(=2009/12/06 23:05:66 UTC)</em>, <code>20190613143537+0200</code>
|
||
<em>(=2019/06/13 14:35:37 UTC+0200)</em> ou <code>20230818121005.307+0200</code>
|
||
<em>(=2023/08/18 12:10:05.307 UTC+0200)</em>.</p>
|
||
</div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Si vous exploitez un attribut stockant une date incluant les milli-secondes ou les
|
||
micro-secondes, ce type d'attribut LDAP sera capable de gérer l'interpratation des valeurs
|
||
stockées, en outre le type d'attribut
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-lsattr_html_date">LSattr_html_date</a>, s'appuyant sur les
|
||
méthodes standards <code>strftime()</code> et <code>strptime()</code>, ne permettra pas aujourd'hui leur saisie et
|
||
affichage.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>timezone</code></p>
|
||
<p>Fuseau horaire de stockage des dates dans l'annuaire LDAP. Les valeurs possibles sont documentées
|
||
dans <a href="https://www.php.net/timezones">la documentation officielle de PHP</a>. (Par défaut : <code>UTC</code>)</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_image"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_image-lsattr_ldap_image">LSattr_ldap_image</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une image. Pour le moment,
|
||
aucun traitement particulier n'est appliqué pour le stockage.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_naivedate"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_naivedate-lsattr_ldap_naivedate">LSattr_ldap_naiveDate</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une date dont la <em>timezone</em>
|
||
doit être ignorée. Côté LDAP, les dates seront stockées au format UTC étant donnée que la syntaxe
|
||
LDAP exige une <em>timezone</em>, cependant celle-ci sera complètement ignorée. Ce type peut-être utilisé
|
||
à la place du type <a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-lsattr_ldap_date">LSattr_ldap_date</a>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_naivedate-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'ldap_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_naivedate-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'format' => '[Format de stockage]', // Default : "%Y%m%d%H%M%SZ"
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_naivedate-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_naivedate-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>format</code></p>
|
||
<p>Format de stockage de la date dans l'annuaire. Ce format est composé à partir des motifs clés
|
||
gérés par la fonction <code>strftime()</code> de PHP. Pour plus d'information, consulter
|
||
<a href="http://www.php.net/strftime">la documentation officielle</a>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>La valeur par défaut est <em>%Y%m%d%H%M%SZ</em>, correspondant à la syntaxe <code>Generalized Time</code> (sans
|
||
les micro-secondes) telle que définie dans la <a href="https://tools.ietf.org/html/rfc4517">RFC4517</a>.
|
||
Exemple : <code>20091206230506Z</code> <em>(=2009/12/06 23:05:66 UTC)</em>.</p>
|
||
</div>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_numeric"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_numeric-lsattr_ldap_numeric">LSattr_ldap_numeric</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est un nombre. Pour le moment,
|
||
aucun traitement particulier est n'appliqué pour le stockage.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-lsattr_ldap_password">LSattr_ldap_password</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est un mot de passe.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'ldap_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'encode' => '[Type d'encodage du mot de passe]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'encode_function' => '[Nom de la fonction d'encodage]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'verify_function' => '[Nom de la fonction de vérification]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'no_random_crypt_salt' => '[Booléen]', // Désactivation de l'utilisation d'une salt aléatoire
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'wildcardPassword' => '[mot de passe(s) en clair]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'encodedWildcardPassword' => '[mot de passe(s) encodé(s)]'
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>encode</code></p>
|
||
<p>Nom du type d'encodage du mot de passe utilisé. Les types d'encodages supportés sont les
|
||
suivants :</p>
|
||
<ul>
|
||
<li><code>argon2</code> (ou <code>argon2i</code>, PHP >= 7.2)</li>
|
||
<li><code>argon2id</code> (PHP >= 7.3)</li>
|
||
<li><code>md5crypt</code></li>
|
||
<li><code>crypt</code></li>
|
||
<li><code>ext_des</code></li>
|
||
<li><code>blowfish</code></li>
|
||
<li><code>sha</code></li>
|
||
<li><code>sha256</code></li>
|
||
<li><code>sha512</code></li>
|
||
<li><code>ssha</code></li>
|
||
<li><code>ssha256</code></li>
|
||
<li><code>ssha512</code></li>
|
||
<li><code>smd5</code></li>
|
||
<li><code>md5</code></li>
|
||
<li><code>clear</code></li>
|
||
</ul>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Valeur par défaut : <code>md5crypt</code></p>
|
||
</div>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Si le type d'encodage est inconnu, ou qu'il n'est pas supporté par le serveur web, un message
|
||
d'erreur alertera l'utilisateur et le mot de passe sera stocké en clair.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>encode_function</code></p>
|
||
<p>Nom d'une function qui sera utilisée afin d'encoder le mot de passe. Cette fonction recevra deux
|
||
paramètres : le <code>LSldapObject</code> et le mot de passe en clair.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>verify_function</code></p>
|
||
<p>Nom d'une function qui sera utilisée afin de valider un mot de passe soumis par l'utilisateur par
|
||
rapport à celui stocké dans l'annuaire. Cette fonction recevra trois paramètres : le
|
||
<code>LSldapObject</code>,le mot de passe en clair et le mot de passe hashé. Si ce paramètre est omis et que
|
||
le paramètre <code>encode_function</code> est défini, le mot de passe à tester sera encodé à nouveau à l'aide
|
||
de la fonction <code>encode_function</code> et le résultat sera comparé avec le mot de passe stocké dans
|
||
l'annuaire.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>no_random_crypt_salt</code></p>
|
||
<p>Désactivation de l'utilisation d'une salt générée aléatoirement au profit de l'utilisation des
|
||
deux premiers caractères du mot de passe. Ce paramètre impacte uniquement le type de cryptage
|
||
<code>crypt</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>wildcardPassword</code></p>
|
||
<p>Mot de passe (ou tableau de mot de passe) qui sera ajouté systématiquement, en plus du mot de
|
||
passe choisi. Il sera encodé de la même manière que pour le mot de passe choisi avant
|
||
enregistrement.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>encodedWildcardPassword</code></p>
|
||
<p>Mot de passe (ou tableau de mot de passe) qui sera ajouté systématiquement, en plus du mot de
|
||
passe choisi. Contrairement à la directive <code>wildcardPassword</code>, le mot de passe ne sera pas encodé
|
||
avant enregistrement.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette directive peut cohabiter avec sa cousine <code>wildcardPassword</code>. Les mot de passes contenus
|
||
dans les deux directives seront alors ajoutés.</p>
|
||
</div>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_postaladdress"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_postaladdress-lsattr_ldap_postaladdress">LSattr_ldap_postaladdress</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est construite sur le modèle de
|
||
l'attribut standard <em>postalAddress</em>, c'est à dire dont les lignes sont séparées à l'aide du
|
||
caractère de délimiteur <code>$</code>.</p>
|
||
<p>Lors de la lecture des valeurs de ce type d'attribut dans l'annuaire, les caractères <code>$</code> seront
|
||
remplacés par des caractères <code>\n</code> et, à l'inverse, lors de l'écriture des valeurs de ce type
|
||
d'attribut dans l'annuaire, les caractères <code>\n</code> seront remplacés par des caractères <code>$</code>.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-lsattr_ldap_pwdhistory">LSattr_ldap_pwdHistory</h1>
|
||
<p>Ce type est utilisé pour la gestion de l'attribut standard <em>pwdHistory</em>. Cet attribut, accessible en
|
||
lecture uniquement, stocke dans un format prédéfini l'historique des mots de passe d'une utilisateur
|
||
avec pour chaque entrée :</p>
|
||
<ul>
|
||
<li>la date et heure de l'ajout du mot de passe dans l'historique</li>
|
||
<li>l'OID de la syntaxe du mot de passe</li>
|
||
<li>la longueur du mot de passe</li>
|
||
<li>le mot de passe (hâché)</li>
|
||
</ul>
|
||
<p>Ce type d'attribut LDAP permettra de convertir la valeur en son équivalent <code>JSON</code> pour pouvoir être
|
||
traité à l'aide du type d'attribut HTML
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-lsattr_html_jsoncompositeattribute">LSattr_html_jsonCompositeAttribute</a>.</p>
|
||
<p><strong>Exemple de valeur de l'attribut pwdHistory :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>20201202144718Z#1.3.6.1.4.1.1466.115.121.1.40#105#{SSHA512}XDSiR6Sh6W7gyVIk6Rr2OUv8rNPr+0rHF99d9lcirE/TnnEdkjkncIi5iPubErL5lpfgh8gXLgSfmqvmFcMqXLToC25xIqyk
|
||
</code></pre></div>
|
||
<p><strong>Exemple de valeur tranformée :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>{"time":1606920438,"syntaxOID":"1.3.6.1.4.1.1466.115.121.1.40","length":105,"hashed_password":"{SSHA512}XDSiR6Sh6W7gyVIk6Rr2OUv8rNPr+0rHF99d9lcirE/TnnEdkjkncIi5iPubErL5lpfgh8gXLgSfmqvmFcMqXLToC25xIqyk"}
|
||
</code></pre></div>
|
||
<p><strong>Exemple de configuration complète de l'attribut :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>'pwdHistory' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-2" id="__codelineno-2-2" name="__codelineno-2-2"></a> 'label' => 'Passwords in history',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-3" id="__codelineno-2-3" name="__codelineno-2-3"></a> 'ldap_type' => 'pwdHistory',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-4" id="__codelineno-2-4" name="__codelineno-2-4"></a> 'html_type' => 'jsonCompositeAttribute',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-5" id="__codelineno-2-5" name="__codelineno-2-5"></a> 'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-6" id="__codelineno-2-6" name="__codelineno-2-6"></a> 'components' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-7" id="__codelineno-2-7" name="__codelineno-2-7"></a> 'time' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-8" id="__codelineno-2-8" name="__codelineno-2-8"></a> 'label' => 'Date added to history',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-9" id="__codelineno-2-9" name="__codelineno-2-9"></a> 'type' => 'text',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-10" id="__codelineno-2-10" name="__codelineno-2-10"></a> 'required' => true,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-11" id="__codelineno-2-11" name="__codelineno-2-11"></a> 'multiple' => false,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-12" id="__codelineno-2-12" name="__codelineno-2-12"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-13" id="__codelineno-2-13" name="__codelineno-2-13"></a> 'syntaxOID' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-14" id="__codelineno-2-14" name="__codelineno-2-14"></a> 'label' => 'Syntax OID',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-15" id="__codelineno-2-15" name="__codelineno-2-15"></a> 'type' => 'text',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-16" id="__codelineno-2-16" name="__codelineno-2-16"></a> 'required' => true,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-17" id="__codelineno-2-17" name="__codelineno-2-17"></a> 'multiple' => false,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-18" id="__codelineno-2-18" name="__codelineno-2-18"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-19" id="__codelineno-2-19" name="__codelineno-2-19"></a> 'length' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-20" id="__codelineno-2-20" name="__codelineno-2-20"></a> 'label' => 'Length',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-21" id="__codelineno-2-21" name="__codelineno-2-21"></a> 'type' => 'text',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-22" id="__codelineno-2-22" name="__codelineno-2-22"></a> 'required' => true,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-23" id="__codelineno-2-23" name="__codelineno-2-23"></a> 'multiple' => false,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-24" id="__codelineno-2-24" name="__codelineno-2-24"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-25" id="__codelineno-2-25" name="__codelineno-2-25"></a> 'hashed_password' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-26" id="__codelineno-2-26" name="__codelineno-2-26"></a> 'label' => 'Hashed password',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-27" id="__codelineno-2-27" name="__codelineno-2-27"></a> 'type' => 'text',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-28" id="__codelineno-2-28" name="__codelineno-2-28"></a> 'required' => true,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-29" id="__codelineno-2-29" name="__codelineno-2-29"></a> 'multiple' => false,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-30" id="__codelineno-2-30" name="__codelineno-2-30"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-31" id="__codelineno-2-31" name="__codelineno-2-31"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-32" id="__codelineno-2-32" name="__codelineno-2-32"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-33" id="__codelineno-2-33" name="__codelineno-2-33"></a> 'no_value_label' => 'History is empty.',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-34" id="__codelineno-2-34" name="__codelineno-2-34"></a> 'multiple' => 1,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-35" id="__codelineno-2-35" name="__codelineno-2-35"></a> 'rights' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-36" id="__codelineno-2-36" name="__codelineno-2-36"></a> 'admin' => 'r',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-37" id="__codelineno-2-37" name="__codelineno-2-37"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-38" id="__codelineno-2-38" name="__codelineno-2-38"></a> 'view' => 1,
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_pwdhistory-__codelineno-2-39" id="__codelineno-2-39" name="__codelineno-2-39"></a>),
|
||
</code></pre></div>
|
||
<p>La date et heure de l'ajout du mot de passe dans l'historique est convertie dans un format lisible.
|
||
Par défaut, ce format est <code>AAAA/MM/JJ HH:MM:SS</code>, mais il peut aussi est personnalisé via le
|
||
paramètre <code>date_format</code>. Ce format est composé à partir des motifs clés gérés par la fonction
|
||
<code>date()</code> de PHP. Pour plus d'information, consulter
|
||
<a href="http://www.php.net/date">la documentation officielle</a>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>La valeur par défaut est <em>YmdHisO</em>, correspondant à la syntaxe <code>Generalized Time</code> telle que
|
||
définie dans la <a href="https://tools.ietf.org/html/rfc4517">RFC4517</a> et prévu par le
|
||
<a href="http://tools.ietf.org/id/draft-behera-ldap-password-policy-10.txt">Draft-behera-ldap-password-policy</a>
|
||
spécifiant cet attribut standard.</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_sambaacctflags"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_sambaacctflags-lsattr_ldap_sambaacctflags">LSattr_ldap_sambaAcctFlags</h1>
|
||
<p>Ce type est prévu pour gérer l'attribut <em>sambaAcctFlags</em> du schéma Samba, qui au travers d'une seule
|
||
et unique valeur, respectant un format prévu, liste l'ensemble des drapeaux actifs d'un compte
|
||
Samba. Il transforme l'unique valeur de l'attribut LDAP en une liste de drapeaux actuellement
|
||
activés sur le compte. Il est conçu pour être utilisé conjointement avec le type d'attribut HTML
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_sambaacctflags-lsattr_html_sambaacctflags">LSattr_html_sambaAcctFlags</a>.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_shadowexpire"><h1 id="conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_shadowexpire-lsattr_ldap_shadowexpire">LSattr_ldap_shadowExpire</h1>
|
||
<p>Ce type est prévu pour gérer l'attribut <code>shadowExpire</code> du schéma POSIX, qui une stocke une date sous
|
||
la forme d'un entier correspondant au nombre de jours depuis le premier 1er 1970. Il est prévu pour
|
||
être utilisé conjointement avec le type d'attribut HTML
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-lsattr_html_date">LSattr_html_date</a>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Malgrés son nom, ce type d'attribut LDAP peux être utilisé pour d'autres attributs stockant ce
|
||
même format de date, tel-que l'attribut <code>shadowLastChange</code>.</p>
|
||
</div></section><h1 class="nav-section-title-end">Ended: Types d'attribut LDAP (LSattr_ldap)</h1><h4 class="nav-section-title">Types d'attribut HTML (LSattr_html)</h4><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html"><h1 id="conf-lsobject-lsattribute-lsattr_html-configuration-des-attributs-html-lsattr_html">Configuration des attributs HTML (LSattr_html)</h1>
|
||
<p>Cette section décrit les options propres à chacun des types d'attributs HTML supportés par
|
||
LdapSaisie.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_boolean"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_boolean-lsattr_html_boolean">LSattr_html_boolean</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est un booléen.</p>
|
||
<p>La valeur retournée est l'une des chaînes de caractères suivantes :</p>
|
||
<ul>
|
||
<li><code>yes</code> pour <em>Vrai</em></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>no</code> pour <code>False</code></li>
|
||
</ul>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_boolean-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_boolean-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'true_label' => '[label]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_boolean-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'false_label' => '[label]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_boolean-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_boolean-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>true_label</code></p>
|
||
<p>Label affiché pour désigner la valeur <code>True</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>false_label</code></p>
|
||
<p>Label affiché pour désigner la valeur <code>False</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour le moment, les attributs à valeurs multiples ne sont pas gérés.</p>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour maîtriser les valeurs stockées dans l'annuaire, il faut coupler ce type d'attribut HTML
|
||
avec le type d'attribut LDAP <a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_boolean-lsattr_ldap_boolean">boolean</a></p>
|
||
</div>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>La définition de la valeur par défaut d'un attribut utilisant ce type HTML (paramètre
|
||
<code>default_value</code>), doit se faire à l'aide des valeurs <code>yes</code> ou <code>no</code>.</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_date"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-lsattr_html_date">LSattr_html_date</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une date. L'outil de sélection
|
||
de date <a href="http://mootools.net/forge/p/mootools_datepicker">MooTools-DatePicker</a> est utilisé pour la
|
||
sélection graphique de la date et de l'heure.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'format' => '[Format d'affichage de la date]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'time' => '[Booleen pour le choix ou non de l heure]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'manual' => '[Booleen pour l edition manuelle ou non]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'showNowButton' => '[Booleen]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'showTodayButton' => '[Booleen]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'style' => '[Nom du style utilise]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'special_values' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> '[value]' => '[label]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_date-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>format</code></p>
|
||
<p>Format d'affichage de la date dans le champ de saisie. Ce format est composé à partir des motifs
|
||
clés suivants :</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Mot clé</th>
|
||
<th>Valeur de substitution</th>
|
||
<th>Exemple de valeur</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>%a</code></td>
|
||
<td>Nom abrégé du jour de la semaine</td>
|
||
<td>De Sun à Sat</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%A</code></td>
|
||
<td>Nom complet du jour de la semaine</td>
|
||
<td>De Sunday à Saturday</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%b</code></td>
|
||
<td>Nom du mois, abrégé, suivant la locale</td>
|
||
<td>De Jan à Dec</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%B</code></td>
|
||
<td>Nom complet du mois, suivant la locale</td>
|
||
<td>De January à December</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%c</code></td>
|
||
<td>Date et heure préférées, basées sur la locale</td>
|
||
<td>Exemple : Tue Feb 5 00:45:10 2009 pour le 5 Février 2009 à 12:45:10 AM</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%d</code></td>
|
||
<td>Jour du mois en numérique, sur 2 chiffres (avec le zéro initial)</td>
|
||
<td>De 01 à 31</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%e</code></td>
|
||
<td>Jour du mois, avec un espace précédant le premier chiffre. L'implémentation Windows est différente, voyez après pour plus d'informations.</td>
|
||
<td>De 1 à 31</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%H</code></td>
|
||
<td>L'heure, sur 2 chiffres, au format 24 heures</td>
|
||
<td>De 00 à 23</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%I</code></td>
|
||
<td>Heure, sur 2 chiffres, au format 12 heures</td>
|
||
<td>De 01 à 12</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%j</code></td>
|
||
<td>Jour de l'année, sur 3 chiffres avec un zéro initial</td>
|
||
<td>001 à 366</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%m</code></td>
|
||
<td>Mois, sur 2 chiffres</td>
|
||
<td>De 01 (pour Janvier) à 12 (pour Décembre)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%M</code></td>
|
||
<td>Minute, sur 2 chiffres</td>
|
||
<td>De 00 à 59</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%p</code></td>
|
||
<td>'AM' ou 'PM', en majuscule, basé sur l'heure fournie</td>
|
||
<td>Exemple : AM pour 00:31, PM pour 22:23</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%s</code></td>
|
||
<td>Timestamp de l'époque Unix (identique à la fonction time())</td>
|
||
<td>Exemple : 305815200 pour le 10 Septembre 1979 08:40:00 AM</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%S</code></td>
|
||
<td>Seconde, sur 2 chiffres</td>
|
||
<td>De 00 à 59</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%T</code></td>
|
||
<td>Identique à "%H:%M:%S" Exemple : 21:34:17 pour 09:34:17 PM</td>
|
||
<td></td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%U</code></td>
|
||
<td>Numéro de la semaine de l'année donnée, en commençant par le premier Lundi comme première semaine</td>
|
||
<td>13 (pour la 13ème semaine pleine de l'année)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%w</code></td>
|
||
<td>Représentation numérique du jour de la semaine</td>
|
||
<td>De 0 (pour Dimanche) à 6 (pour Samedi)</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%y</code></td>
|
||
<td>L'année, sur 2 chiffres</td>
|
||
<td>Exemple : 09 pour 2009, 79 pour 1979</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%Y</code></td>
|
||
<td>L'année, sur 4 chiffres</td>
|
||
<td>Exemple : 2038</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%z</code></td>
|
||
<td>Soit le décalage horaire depuis UTC, ou son abréviation (suivant le système d'exploitation)</td>
|
||
<td>Exemple : -0500 ou EST pour l'heure de l'Est</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%Z</code></td>
|
||
<td>Le décalage horaire ou son abréviation NON fournie par %z (suivant le système d'exploitation)</td>
|
||
<td>Exemple : -0500 ou EST pour l'heure de l'Est</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>%%</code></td>
|
||
<td>Le caractère de pourcentage ("%")</td>
|
||
<td>---</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>La valeur par défaut est <em>%d/%m/%Y, %T</em>. Exemple : <em>23/04/2009, 23:03:04</em></p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>time</code></p>
|
||
<p>Booléen définissant si l'outil de sélection permetra ou non le choix de l'heure en plus de la date</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>manual</code></p>
|
||
<p>Booléen autorisant ou non l'édition manuelle du champs. Si ce paramètre vaut <code>False</code>, la sélection
|
||
se fera uniquement à l'aide de l'outil graphique</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>showNowButton</code></p>
|
||
<p>Booléen définissant si le bouton <em>Maintenant</em> est affiché ou non. Par défaut, il est affiché.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>showTodayButton</code></p>
|
||
<p>Booléen définissant si le bouton <em>Aujourd'hui</em> est affiché ou non. Par défaut, il est affiché.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>style</code></p>
|
||
<p>Nom du style d'affichage de l'outil de sélection. Les valeurs possibles sont par défaut :</p>
|
||
<ul>
|
||
<li><code>default</code></li>
|
||
<li><code>dashboard</code></li>
|
||
<li><code>vista</code></li>
|
||
<li><code>jqui</code></li>
|
||
</ul>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>La création de nouveau thème est possible. Pour plus d'information, consulter
|
||
<a href="http://mootools.net/forge/p/mootools_datepicker">l'aide de l'outil de sélection de date</a>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>special_values</code></p>
|
||
<p>Tableau listant les valeurs spéciales que peut prendre l'attribut. Dans ce tableau associatif, la
|
||
clé doit correspondre à la valeur de l'attribut (telle que fournie par
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_date-lsattr_ldap_date">l'attribut LDAP</a>) et la valeur associée au
|
||
label associé.</p>
|
||
<p>Ces valeurs spéciales seront proposées à l'utilisateur sous la forme de cases à cocher dans le
|
||
formulaire. Elles peuvent permettre par exemple de données une signification particulière au zéro
|
||
pour un attribut LDAP stockant un <em>timestamp</em>.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_gpg_pub_key"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_gpg_pub_key-lsattr_html_gpg_pub_key">LSattr_html_gpg_pub_key</h1>
|
||
<p>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.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_image"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_image-lsattr_html_image">LSattr_html_image</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une image. Pour le moment, les
|
||
attributs à valeurs multiples ne sont pas gérés.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-lsattr_html_jsoncompositeattribute">LSattr_html_jsonCompositeAttribute</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont les valeurs sont des dictionnaires de valeurs
|
||
encodées aux formats <em>JSON</em>.</p>
|
||
<p>Exemple de valeur gérée :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="p">{</span><span class="nt">"component1"</span><span class="p">:</span><span class="w"> </span><span class="s2">"value1"</span><span class="p">,</span><span class="w"> </span><span class="nt">"component2"</span><span class="p">:</span><span class="w"> </span><span class="s2">"value2"</span><span class="p">,</span><span class="w"> </span><span class="nt">"component3"</span><span class="p">:</span><span class="w"> </span><span class="s2">"value3"</span><span class="p">}</span>
|
||
</code></pre></div>
|
||
<p>Le principe est que ces dictionnaires contienent plusieurs composants référencés par leur clé et
|
||
stockant une valeur dont le type peut être un texte libre ou bien être issue d'une liste déroulante
|
||
configurable selon le même principe que le type d'attribut
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-lsattr_html_select_list">LSattr_html_select_list</a>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> 'components' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> '[clé composant 1]' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> 'label' => '[Label du composant]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> 'help_info' => '[Message d'aide sur le composant]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> 'type' => '[Type de la valeur stocké]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> 'required' => [Booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a> 'multiple' => [Booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a> 'check_data' => => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a> // Régle de vérification syntaxique des données saisies
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a> '[clé composant 2]' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a> 'label' => '[Label du composant 2]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a> 'type' => 'select_list',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a> 'required' => [Booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a> 'options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-18" id="__codelineno-1-18" name="__codelineno-1-18"></a> [Configuration équivalente à un attribut LSattr_html_select_list]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-19" id="__codelineno-1-19" name="__codelineno-1-19"></a> )
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-20" id="__codelineno-1-20" name="__codelineno-1-20"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-21" id="__codelineno-1-21" name="__codelineno-1-21"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-22" id="__codelineno-1-22" name="__codelineno-1-22"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-23" id="__codelineno-1-23" name="__codelineno-1-23"></a> 'fullWidth' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-24" id="__codelineno-1-24" name="__codelineno-1-24"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-__codelineno-1-25" id="__codelineno-1-25" name="__codelineno-1-25"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>components</code></p>
|
||
<p>Tableau associatif obligatoire contenant en valeur clé, l'identifiant des composants,
|
||
correspondant à la clé dans le dictionnaire <em>JSON</em>, et en valeurs associés, la configuration du
|
||
composant.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label du composant.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>help_info</code></p>
|
||
<p>Message d'aide sur le composant (affiché uniquement en mode édition).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>type</code></p>
|
||
<p>Le type de valeur du composant. Les types possibles sont <code>text</code> ou <code>select_list</code> pour
|
||
respectivement soit une valeur saisie librement, soit une valeur sélectionnée parmis une liste
|
||
déroulante.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>options</code></p>
|
||
<p>Dans le cadre d'un composant de type <code>select_list</code>, cela correspond à la configuration de la
|
||
liste déroulante. Cette configuration utilise la même syntaxe de configuration que celle du type
|
||
d'attribut <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-lsattr_html_select_list">LSattr_html_select_list</a> et son
|
||
paramètre <code>html_options</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>multiple</code></p>
|
||
<p>Booléen définissant si ce composant peut stocker plusieurs valeurs (Par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>required</code></p>
|
||
<p>Booléen définissant si ce composant doit obligatoirement être défini (Par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>check_data</code></p>
|
||
<p>Tableau associatif contenant les règles de vérification syntaxique des données du composant. Ces
|
||
règles sont configurables de la même manière que les celles des valeurs attributs.
|
||
<a href="#conf-lsobject-lsattribute-check_data-configuration-des-regles-de-verification-syntaxique">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>fullWidth</code></p>
|
||
<p>Booléen permettant de définir si l'affichage dans le formulaire doit se faire sur toute la largeur
|
||
disponible de la page (Par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-lsattr_html_labeledvalue">LSattr_html_labeledValue</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est prefixé d'un <code>label</code> et qui
|
||
respecte le format suivant : <code>[label]valeur</code>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'labels' => array ( // Liste des labels possible
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'label1' => 'Libellé label1',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'label2' => 'Libellé label2',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'translate_labels' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_labeledvalue-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>labels</code></p>
|
||
<p>Tableau associatif obligatoire contenant en valeur clé, le <code>label</code> utilisé dans la valeur stockée
|
||
et en valeur associée, le valeur d'affichage du <code>label</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>translate_labels</code></p>
|
||
<p>Booléen permettant d'activer/désactiver la traduction des labels (Par défaut : <code>True</code>).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_mail"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_mail-lsattr_html_mail">LSattr_html_mail</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une adresse e-mail. En plus
|
||
d'un affichage adapté, il offre la possibilité d'envoyer des mails directement depuis l'interface de
|
||
l'application.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mail-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mail-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'disableMailSending' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mail-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mail-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>disableMailSending</code></p>
|
||
<p>Désactive l'envoi de mail depuis l'interface pour cet attribut.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Ceci ne désactive pas pour autant le lien HTML de type <em>mailto:</em>. Pour cela, utilisez plutôt
|
||
le type d'attribut HTML <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">text</a>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce type d'attribut HTML est dérivé du type <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">text</a>. Il
|
||
profite donc de toutes les fonctionnalités d'un champ de ce type (autogénération, ...).</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-lsattr_html_maildir">LSattr_html_maildir</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est le chemin d'une maildir.
|
||
Typiquement, ce type attribut HTML est utile dans le cas de l'attribut <em>mailbox</em> utilisé par
|
||
maildrop pour stocker le chemin des boites mails. Ce type d'attribut offre la possibilité de gérér
|
||
un niveau de l'attribut et à travers les déclencheurs gérés par LdapSaisie la création, la
|
||
modification et ou la suppression de la boite mails.
|
||
Le <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a>
|
||
<a href="#conf-lsaddon-lsaddon_maildir-lsaddon_maildir">maildir</a> est utilisé pour manipuler la boite
|
||
mail à distance.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Actuellement, cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> ne gérant que l'accès via FTP
|
||
au serveur distant, l'API d'accès via FTP est attaquée directement.</p>
|
||
</div>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'LSform' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> '[LSform1]' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> '[LSform2]' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'remoteRootPathRegex' => "[Expression régulière pour matcher le dossier à créer]",
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'archiveNameFormat' => "[LSformat du chemin/nom du fichier une fois archiver]"
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSform</code></p>
|
||
<p>Tableau associatif obligatoire contenant en valeur clé le nom des <a href="#conf-lsobject-lsform-lsform">LSforms</a>
|
||
dans lesquels la fonctionnalité de modification de la boite mail sera présente. Les valeurs
|
||
attachées sont des booléens définissant si la modification est active par défaut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>remoteRootPathRegex</code></p>
|
||
<p>Expression régulière (compatible Perl) facultative dont le but est de <em>matcher</em> dans la valeur
|
||
complète du chemin distant de la <em>maildir</em>, le chemin de la <em>maildir</em> à créer une fois connecté
|
||
sur le serveur.</p>
|
||
<p>Exemple : Si le chemin complet de la <em>maildir</em> est <code>/home/vmail/user</code>, mais que l'utilisateur FTP
|
||
lorsqu'il se connecte arrive directement dans <code>/home/vmail</code>, et faut définir le paramètre
|
||
<code>remoteRootPathRegex</code> de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_maildir-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>/^\/home\/vmail\/([^\/]*)\/+$/
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>archiveNameFormat</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du nom du dossier de la <em>maildir</em> une
|
||
fois archivée. Si ce format est défini, le dossier ne sera pas supprimé mais déplacé ou rénommé.
|
||
Le format sera construit avec pour seul mot clé, le nom de l'ancien dossier. Exemple : Si le
|
||
dossier de la maildir est <code>/home/vmail/user</code> et le paramètre <code>archiveNameFormat</code> vaut
|
||
<code>%{old}.bckp</code>, le dossier sera renommé en <code>/home/vmail/user.bckp</code>.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce format est interprété après application de la routine liée au paramètre
|
||
<code>remoteRootPathRegex</code>. Ainsi, dans l'exemple précédent, si le paramètre <code>remoteRootPathRegex</code>
|
||
tronquait uniquement le nom du dossier final, c'est à dire <code>user</code>, le format une fois
|
||
interprété donnerai <code>user.bckp</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_mailquota"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_mailquota-lsattr_html_mailquota">LSattr_html_mailQuota</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est le quota d'une boite mail. Le
|
||
format de la valeur générée correspondant au format attendu par le serveur de mail
|
||
<a href="http://www.courier-mta.org/">Courier</a>] par défaut. Exemple : <em>50000000S</em> correspond à un quota de
|
||
50Mio.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mailquota-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mailquota-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'suffix' => '[suffix]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mailquota-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> )
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mailquota-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_mailquota-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>suffix</code></p>
|
||
<p>Chaine de caractères suffixant la valeur du quota (Par défaut : <code>S</code>).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_password"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-lsattr_html_password">LSattr_html_password</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est un mot de passe.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'isLoginPassword' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'generationTool' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'autoGenerate' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'length' => [nombre de caractères],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'chars' => array ( // Caractères que peut contenir le mot de passe
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> array( // Liste caractère avec un nombre mininum d'apparition supérieur à 1
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'nb' => [nb caractères],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'chars' => '[liste de caractères possibles]'
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> '[autre liste de caractères possibles]', // Liste caractère avec un nombre
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> // d'apparitions égal à 1
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> 'use_pwgen' => [booléen], // Utiliser pwgen pour la génération du mot de passe
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> 'pwgen_path' => "/path/to/pwgen",
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> 'pwgen_opts' => "[options à passer à pwgen]",
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> 'verify' => [booléen], // Activation de l'outil de vérification du mot de passe
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> 'viewHash' => [booléen], // Activation de l'outil de visualisation du mot de passe haché
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> 'confirmChange' => [booléen], // Activation de la confirmation en cas de changement du mot de passe
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> 'confirmChangeQuestion' => "[LSformat]", // LSformat de la question de confirmation du changement du mot de passe
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> 'mail' => array( // Configuration de l'envoi du mot de passe par mail
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> 'subject' => "[LSformat du sujet du mail]",
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a> 'msg' => "[LSformat du message du mail]",
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a> 'mail_attr' => 'mail', // Attribut mail de l'objet
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a> 'get_mail_attr_function' => '[function]', // Fonction retournant l'attribut mail de l'objet
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a> 'send' => 1, // Activation par défaut de l'envoi du mot de passe
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a> 'ask' => 1, // Laisser le choix à l'utilisateur
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a> 'canEdit' => 1, // Activation de l'édition du LSformat du message par l'utilisateur
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a> 'checkDomain' => false, // Désactivation de la vérification du domaine de l'adresse email
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a> 'domain' => '[nom de domaine]', // Nom de domaine obligatoire lors de la validation de l'adresse email
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a> )
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_password-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>isLoginPassword</code></p>
|
||
<p>Booléen définissant si le mot de passe est celui utilisé par l'utilisateur pour se logguer à
|
||
l'annuaire LDAP. Si c'est le cas, pour vérifier si le mot de passe correspond avec un autre, une
|
||
tentative de connexion de l'utilisateur à l'annuaire sera faite. (Par défaut : <code>False</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>generationTool</code></p>
|
||
<p>Booléen définissant si l'outil de génération de mot de passe est activé.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>autoGenerate</code></p>
|
||
<p>Active la génération automatique du mot de passe lorsque l'attribut n'a encore aucune valeur de
|
||
définie. Il faut également que l'outil de génération soit activé (<code>generationTool</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>length</code></p>
|
||
<p>Nombre de caractères que devront contenir les mots de passe générés.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>chars</code></p>
|
||
<p>Tableau contenant une liste de listes de caractères possibles pour composer le mot de passe. Dans
|
||
chacune de ces listes, au moins un caractère sera utilisé dans le nouveau mot de passe. Il est
|
||
possible de définir un nombre supérieur de caractères d'une liste devant apparaître dans les mots
|
||
de passe générés en spécifiant un tableau associatif dont la clé <em>nb</em> associra le nombre entier de
|
||
caractères et la clé <em>chars</em> la liste de caractères. Une liste de caractères est un chaîne.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>use_pwgen</code></p>
|
||
<p>Booléen définissant si la commande <code>pwgen</code> doit être utilisé pour générer le mot de passe.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>pwgen_path</code></p>
|
||
<p>Chemin d'accès au binaire <code>pwgen</code>. (Par défaut : <code>pwgen</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>pwgen_opts</code></p>
|
||
<p>Options à passer à la commande <code>pwgen</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>verify</code></p>
|
||
<p>Booléen définissant si l'outil de vérification du mot de passe est activé. Si celui-ci est activé,
|
||
l'utilisateur pourra entrer un mot de passe dans le champ et cliquer sur un bouton qui lancera une
|
||
procédure de vérification du mot de passe via un test de connexion à l'annuaire.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>viewHash</code></p>
|
||
<p>Booléen définissant si l'utilisateur aura accès à la fonctionnalité de visualisation du mot de
|
||
passe haché.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>confirmInput</code></p>
|
||
<p>Booléen définissant si un second champ mot de passe sera affiché dans le formulaire pour que
|
||
l'utilisateur confirme la saisie du nouveau mot de passe.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>confirmInputError</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message d'erreur affiché à
|
||
l'utilisateur si le mot de passe saisie dans le champs de confirmation ne correspond pas au
|
||
nouveau mot de passe. <em>Paramètre facultatif.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>confirmChange</code></p>
|
||
<p>Booléen définissant si l'utilisateur devra confirmer le changement de ce mot de passe. Lorsque
|
||
cette fonctionnalité est activée, l'utilisateur verra apparaître une popup de confirmation à la
|
||
validation du formulaire s'il a saisi un nouveau mot de passe.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>confirmChangeQuestion</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> de la question posée à l'utilisateur
|
||
en cas de changement du mot de passe et si la fonctionnalité est activée. Il sera composé à l'aide
|
||
du <em>label</em> de l'attribut. <em>Paramètre facultatif.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>clearView</code></p>
|
||
<p>Booléen définissant si l'utilisateur pourra voir le mot de passe en clair par défaut (y comris en
|
||
mode visualisation uniquement).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>clearEdit</code></p>
|
||
<p>Booléen définissant si l'utilisateur éditera le mot de passe au travers un champs HTML de type
|
||
<em>text</em> et donc lisible ou au travers un champs HTML de type <em>password</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>mail</code></p>
|
||
<p>Paramètres de configuration de l'envoi par mail du mot de passe à l'utilisateur. Lorsque cet outil
|
||
est activé, lors de la modification/création du mot de passe, l'utilisateur pourra recevoir un
|
||
mail lui spécifiant son nouveau mot de passe.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>send</code></p>
|
||
<p>Booléen définissant si l'envoi du mot de passe est activé par défaut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ask</code></p>
|
||
<p>Booléen définissant si on laisse le choix à l'utilisateur d'activer ou non l'envoi du mot de
|
||
passe par mail.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>canEdit</code></p>
|
||
<p>Booléen définissant si on laisse la possibilité à l'utilisateur d'éditer le
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message et du sujet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>subject</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du sujet du mail. Ce format sera
|
||
composé avec la valeur du nouveau mot de passe de l'utilisateur.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>msg</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message du mail. Ce format sera
|
||
composé avec les informations de l'object LDAP, y compris le mot clé <em>%{password}</em> correspondant
|
||
à la valeur du nouveau mot de passe de l'utilisateur.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>mail_attr</code></p>
|
||
<p>Le nom de l'attribut listant les mails possibles de l'utilisateur. Par défaut, la première
|
||
valeur de l'attribut sera utilisée comme adresse mail destinatrice. Cet attribut peut également
|
||
être un tableau de plusieurs noms d'attributs. Dans ce cas, la première valeur correcte sera
|
||
retenue. Si <code>canEdit</code> est activé, l'utilisateur pourra choisir l'adresse mail destinatrice parmi
|
||
la liste des valeurs de l'attribut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>get_mail_attr_function</code></p>
|
||
<p>Nom de la fonction (ou <code>callable</code> au sens PHP) qui sera utilisé pour récupérer le nom de
|
||
l'attribut listant les mails possibles de l'utilisateur. Cette fonction prendra en paramètre,
|
||
l'objet <code>LSformElement</code> courant et devra retourner une valeur équivalente au paramètre de
|
||
configuration <code>mail_attr</code>. Si ce paramètre est défini, il prévalera toujours sur le paramètre
|
||
<code>mail_attr</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>bcc</code></p>
|
||
<p>Mettre en <em>BCC</em> un mail systématiquement (ou plusieurs en les séparant par des virgules).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>headers</code></p>
|
||
<p>Un tableau de type clé/valeur ou la clé est le nom d'un header à ajouter au mail et la valeur
|
||
est la valeur de l'header en question.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>checkDomain</code></p>
|
||
<p>Booléen définissant si le domaine de l'adresse mail doit être validée. *Paramètre facultatif,
|
||
par défaut: <code>True</code></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>domain</code></p>
|
||
<p>Nom de domaine obligatoire lors de la validation de l'adresse mail. Ce paramètre peut être une
|
||
simple chaine correspondant au domaine ou un tableau listant plusieurs domaines valides.
|
||
<em>Paramètre facultatif, par défaut tous les domaines sont acceptés.</em></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress-lsattr_html_postaladdress">LSattr_html_postaladdress</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs du type de l'attribut standard <em>postalAddress</em>.
|
||
Ce type d'attribut permet d'afficher, en plus de l'adresse, un lien composé à partir d'informations
|
||
de l'objet permettant par exemple d'afficher un lien vers une carte géocalisant l'adresse postale.</p>
|
||
<p>Par défaut, le lien ajouté sera un lien de recherche de l'adresse postale générée à partir de la
|
||
valeur de l'attribut (en remplaçant les retours à la ligne (<code>\n</code>) par des espaces) via le service
|
||
<a href="http://nominatim.openstreetmap.org/">Nominatim d'OpenStreetMap</a>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Dans le cadre du fonctionnement par défaut et pour maîtriser les valeurs stockées dans
|
||
l'annuaire, il faut coupler ce type d'attribut HTML avec le type d'attribut LDAP
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_postaladdress-lsattr_ldap_postaladdress">postaladdress</a></p>
|
||
</div>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'map_url_pattern_format' => '[LSformat]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'map_url_pattern_generate_function' => '[callable]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'map_url_format' => '[LSformat]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_postaladdress-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>map_url_pattern_format</code></p>
|
||
<p>Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> doit permettre de générer la valeur
|
||
de l'adresse postale qui sera insérée dans l'URL du lien ajouté dans l'interface.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>map_url_pattern_generate_function</code></p>
|
||
<p>Ce paramètre permet de définir une fonction qui sera utilisée à la place du paramètre
|
||
<code>map_url_pattern_format</code> pour générer la valeur de l'adresse postale qui sera insérée dans l'URL
|
||
du lien ajouté dans l'interface. Cette fonction prendra en paramètre l'objet <em>LSformElement</em>
|
||
courant et devra retourner une chaîne de caractères correspondant à l'adresse postale à insérer
|
||
dans le lien de l'interface. Par défaut, la fonction
|
||
<code>LSformElement_postaladdress__generate_pattern</code> est utilisée.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>map_url_format</code></p>
|
||
<p>Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> doit permettre de générer l'URL du
|
||
lien ajouté dans l'interface. Il sera composé avec les informations de l'objet LDAP, y compris le
|
||
mot clé <code>%{pattern}</code> correspondant à la valeur de l'adresse postale générée à l'aide des
|
||
paramètres précédents. Par défaut, la format suivant sera utilisé :
|
||
<code>http://nominatim.openstreetmap.org/search.php?q=%{pattern}</code></p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_pre"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_pre-lsattr_html_pre">LSattr_html_pre</h1>
|
||
<p>Ce type est dérivé du type <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_textarea-lsattr_html_textarea">LSattr_html_textarea</a> et
|
||
permet simplement que lors de l'affichage de la valeur, celle-ci soit affichée en respectant les
|
||
retours à la ligne et en utilisant une police de caractères <code>monospace</code>. Cela reproduit l'affichage
|
||
d'une balise HTML <code>pre</code>.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_rss"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_rss-lsattr_html_rss">LSattr_html_rss</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est l'URL d'un flux RSS. Il propose
|
||
directement dans l'interface, la possibilité d'accèder au flux RSS.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce type d'attribut HTML est dérivé du type <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">text</a>. Il
|
||
profite donc de toutes les fonctionnalités d'un champ de ce type (autogénération, ...).</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_sambaacctflags"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_sambaacctflags-lsattr_html_sambaacctflags">LSattr_html_sambaAcctFlags</h1>
|
||
<p>Ce type est prévu pour gérer l'attribut <em>sambaAcctFlags</em> du schéma Samba, qui au travers d'une seule
|
||
et unique valeur, respectant un format prévu, liste l'ensemble des drapeaux actifs d'un compte
|
||
Samba. Il est conçu pour être utilisé conjointement avec le type d'attribut LDAP
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_sambaacctflags-lsattr_ldap_sambaAcctFlags">LSattr_ldap_sambaAcctFlags</a>.</p>
|
||
<p>Pour définir la valeur par défaut de cet attribut, il faut définir paramètre <code>default_value</code> comme
|
||
un tableau des drapeaux telque prévu par Samba :</p>
|
||
<p>- <code>U</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte utilisateur standard
|
||
</code></pre></div>
|
||
<p>- <code>W</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte de poste de travail approuvé
|
||
</code></pre></div>
|
||
<p>- <code>S</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte de serveur approuvé
|
||
</code></pre></div>
|
||
<p>- <code>I</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte de domaine approuvé
|
||
</code></pre></div>
|
||
<p>- <code>M</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte de connexion Majority Node Set (MNS)
|
||
</code></pre></div>
|
||
<p>- <code>H</code></p>
|
||
<div class="highlight"><pre><span></span><code>Dossier personnel requis
|
||
</code></pre></div>
|
||
<p>- <code>N</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte sans mot de passe
|
||
</code></pre></div>
|
||
<p>- <code>X</code></p>
|
||
<div class="highlight"><pre><span></span><code>Le mot de passe n'expire jamais
|
||
</code></pre></div>
|
||
<p>- <code>D</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte désactivé
|
||
</code></pre></div>
|
||
<p>- <code>T</code></p>
|
||
<div class="highlight"><pre><span></span><code>Copie temporaire d'un autre compte
|
||
</code></pre></div>
|
||
<p>- <code>L</code></p>
|
||
<div class="highlight"><pre><span></span><code>Compte automatiquement bloqué
|
||
</code></pre></div>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_sambaacctflags-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a> Exemple de valeur par défaut...
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_sambaacctflags-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>'default_value' => array('U', 'X'),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_sambaacctflags-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>...
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Ce type d'attribut est implémenté en dérivant le type <em>LSattr_html_select_box</em> dont les valeurs
|
||
possibles sont pré-configurées (paramètre <code>possible_values</code>). Même si cela n'est pas forcément
|
||
utiles, les autres paramètres du type parent restent utilisables.</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_box"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_box-lsattr_html_select_box">LSattr_html_select_box</h1>
|
||
<p>Ce type est identique au type <em>LSattr_html_select_list</em> excepté qu'il utilise en lieu et place d'une
|
||
balise HTML <code>select</code>, plusieurs balises HTML <code>input</code> de type <code>checkbox</code> en cas de valeurs multiples
|
||
ou de type <code>radio</code> en cas de valeur unique. Les paramètres de configuration de la classe
|
||
<em>LSattr_html_select_list</em> sont tous hérités et fonctionnent donc de la même manière. Par ailleurs,
|
||
ce type dispose également de paramètres qui lui sont propre (voir ci-dessous).</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_box-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_box-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'inline' => [Booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_box-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_box-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>inline</code></p>
|
||
<p>Booléen définissant si les valeurs possibles doivent être affichées sur une même ligne ou non
|
||
(Faux par défaut).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-lsattr_html_select_list">LSattr_html_select_list</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont les valeurs font partie d'une liste statique
|
||
ou dynamique. Il est possible de lister des valeurs statiques et également des références à d'autres
|
||
<a href="#conf-configuration-lsobject">LSobjects</a>. La référence à un objet correspond à une
|
||
valeur clé, référente à un objet précis, qui peut être soit la valeur d'un de ses attributs, soit
|
||
son <em>DN</em>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'possible_values' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> '[LSformat de la valeur clé]' => '[LSformat du nom d'affichage]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'OTHER_OBJECT' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'object_type' => '[Type d'LSobject]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'display_name_format' => '[LSformat du nom d'affichage des LSobjects]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'value_attribute' => '[Nom de l'attribut clé]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'values_attribute' => '[Nom de l'attribut clé multi-valeur]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'filter' => '[Filtre de recherche des LSobject]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> 'scope' => '[Scope de la recherche]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> 'basedn' => '[Basedn de la recherche]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> 'onlyAccessible' => '[Booléen]'
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> 'OTHER_ATTRIBUTE' => '[attr]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> // Or :
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> 'OTHER_ATTRIBUTE' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> '[attr1]' => '[label1]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> '[attr2]' => '[label2]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> // Or :
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> 'OTHER_ATTRIBUTE' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a> 'attr' => [attr],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a> 'json_component_key' => '[Composant JSON clé]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a> 'json_component_label' => '[Composant JSON label]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a> array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a> 'label' => '[LSformat du nom du groupe de valeurs]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a> 'possible_values' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a> '[LSformat de la valeur clé]' => '[LSformat du nom d'affichage]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a> 'OTHER_OBJECT' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a> )
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a> )
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a> )
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a> 'get_possible_values' => [callable],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a> 'translate_labels' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a> 'sort' => [Booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a> 'sortDirection' => '[ASC|DESC]'
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_list-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>possible_values</code></p>
|
||
<p>Tableau associatif obligatoire contenant en valeur clé le
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> des valeurs clés prisent par
|
||
l'attribut et en valeurs associées, le <a href="#conf-global-lsformat-format-parametrable">LSformat</a>
|
||
des noms d'affichage de ces valeurs. Ces <a href="#conf-global-lsformat-format-parametrable">LSformats</a>
|
||
sont composés à partir des valeurs de l'objet courant (attributs, dn, ...).</p>
|
||
<p>Si la valeur clé est égale à <code>OTHER_OBJECT</code>, une liste
|
||
d'<a href="#conf-configuration-lsobject">LSobject</a> sera insérée dans la liste des valeurs
|
||
possibles. La valeur associée est alors un tableau associatif dont les valeurs clés sont les noms
|
||
des paramètres de configuration de la recherche de ces
|
||
<a href="#conf-configuration-lsobject">LSobjects</a> et les valeurs associées, les valeurs des
|
||
paramètres.</p>
|
||
<p>Il est possible de regrouper des valeurs de l'attribut en plaçant leur déclaration dans un
|
||
sous-tableau. Ce sous-tableau devra contenir la clé <code>label</code> dont la valeur associé sera le
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> du nom du groupe de valeurs. Ce
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> est composé à partir des valeurs de
|
||
l'objet courant (attributs, dn, ...). Une seconde clé <code>possible_values</code> regroupera les valeurs
|
||
possibles du groupe. Comme pour le tableau principal, la clé <code>OTHER_OBJECT</code> permet d'imcorporer
|
||
une liste d'<a href="#conf-configuration-lsobject">LSobject</a>.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>object_type</code></p>
|
||
<p>Nom du type d'<a href="#conf-configuration-lsobject">LSobject</a> en référence.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>display_name_format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du nom d'affichage des objets lors
|
||
de leur sélection.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>value_attribute</code></p>
|
||
<p>Nom de l'attribut des <a href="#conf-configuration-lsobject">LSobjects</a> en référence servant
|
||
de valeur clé et permettant de les identifier (Exemple : <code>dn</code> ou <code>uid</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>values_attribute</code></p>
|
||
<p>Nom de l'attribut des <a href="#conf-configuration-lsobject">LSobjects</a> en référence servant
|
||
de catalogue de valeurs. Dans ce mode, la valeur n'a pas de label et est affichée directement
|
||
dans l'interface. Ce paramètre peut-être utilisé en complément ou non du paramètre
|
||
<code>value_attribute</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p>Filtre falcultatif de la recherche des LSobjets. Il sera dans tous les cas agrémenté des valeurs
|
||
des <em>objectclass</em> du type d'<a href="#conf-configuration-lsobject">LSobject</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>scope</code></p>
|
||
<p>Scope falcultatif de la recherche des LSobjets.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>basedn</code></p>
|
||
<p>Basedn falcultatif de la recherche des LSobjets.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>onlyAccessible</code></p>
|
||
<p>Booléen falcultatif définissant si seul les LSobjets auxquels l'utilisateur connecté à accès
|
||
doivent être considérés comme sélectionnables (Faux par défaut).</p>
|
||
</li>
|
||
</ul>
|
||
<p>Si la valeur clé est égale à <code>OTHER_ATTRIBTE</code>, une liste de valeur possible sera composée à l'aide
|
||
des valeurs d'un (ou plusieurs) autre attribut de l'objet courant. La valeur associée peut être
|
||
alors :</p>
|
||
<ul>
|
||
<li>soit le nom d'un attribut dont les valeurs seront utilisées comme valeurs possibles (la valeur
|
||
affichée est égale à la valeur stockée).</li>
|
||
</ul>
|
||
<ul>
|
||
<li>soit un tableau associatif dont les valeurs clés sont les noms des attributs dont les valeurs
|
||
seront utilisés comme valeurs possibles et dont les valeurs associés seront les labels sous
|
||
lesquels ces valeurs seront regroupées (la valeur affichée est égale à la valeur stockée).</li>
|
||
</ul>
|
||
<ul>
|
||
<li>soit un tableau associatif référençant un attribut sous la clé <code>attr</code> dont les valeurs seront
|
||
utilisées comme valeurs possibles. Cet attribut peut-être du type
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_jsoncompositeattribute-lsattr_html_jsoncompositeattribute">LSattr_html_jsonCompositeAttribute</a>.
|
||
Il sera alors possible d'utiliser les valeurs d'un composant en particulier en le référençant à
|
||
l'aide de la clé <code>json_component_key</code>. Il est également possible de référencer un autre
|
||
composant à l'aide de la clé <code>json_component_label</code> et dont les valeurs seront utilisées comme
|
||
valeurs affichées lors de la sélection. À défaut, les valeurs affichées seront identiques à
|
||
celles stockées.</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>get_possible_values</code></p>
|
||
<p>Paramètre permettant de spécifier un <em>callable</em> qui sera utilisé pour lister les valeurs possibles
|
||
de l'attribut. Il recevra en paramètres les informations suivantes:</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>$options</code></p>
|
||
<p>Les options HTML de l'attribut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$name</code></p>
|
||
<p>Le nom de l'attribut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>&$ldapObject</code></p>
|
||
<p>Une référence à l'objet <code>LSldapObject</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<p>La valeur de retour attendue est un tableau associatif des valeurs possibles de l'attribut avec la
|
||
valeur que prendra l'attribut en tant que clé et le label correspondant en tant que valeur. Tout
|
||
autre retour sera considéré comme un échec et déclenchera une erreur.</p>
|
||
<p>Il est également possible de regrouper des valeurs possibles de l'attribut: pour cela, le tableau
|
||
retourné devra lui-même contenir un tableau associatif contenant la label traduit du groupe sous
|
||
la clé <code>label</code> et les valeurs possibles du groupe sous la clé <code>possible_values</code>.</p>
|
||
<p>Les valeurs retournées pourront être combinées avec les autres valeurs possibles configurées de
|
||
l'attribut. La prise en charge du tri des valeurs possibles est assurée par la fonction appelante
|
||
sauf dans le cas des sous-groupes de valeurs possibles. Dans ce cas, la méthode
|
||
<code>LSattr_html_select_list :: _sort()</code> pourra être utilisée pour trier les valeurs du sous-groupe :
|
||
cette méthode accepte en paramètre une référence du tableau des valeurs possibles ainsi que les
|
||
options HTML de l'attribut.</p>
|
||
<p>Si la traduction des labels des valeurs possibles de l'attribut est activées (voir ci-dessous),
|
||
celle-ci doit être prise en charge par la fonction configurée.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>translate_labels</code></p>
|
||
<p>Booléen permettant d'activer/désactiver la traduction des labels (Par défaut : <code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sort</code></p>
|
||
<p>Booléen définissant si les valeurs possibles doivent être triées ou non (Vrai par défaut). Le trie
|
||
est effectué sur les libellés des valeurs possibles.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sortDirection</code></p>
|
||
<p>Mot clé déterminant le sens du trie des valeurs possibles.</p>
|
||
<p>Valeurs possibles : <code>ASC</code> ou <code>DESC</code> (<code>ASC</code> par défaut).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-lsattr_html_select_object">LSattr_html_select_object</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont les valeurs sont des références à d'autres
|
||
<a href="#conf-configuration-lsobject">LSobjects</a>. Chaque référence à un objet correspond à une
|
||
valeur prise par l'attribut. Les valeurs clés référant à un
|
||
<a href="#conf-configuration-lsobject">LSobject</a> sont soit la valeur d'un de leurs attributs,
|
||
soit leur <em>DN</em>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> selectable_object => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'object_type' => '[Type d'LSobject selectionnable]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'display_name_format' => '[LSformat du nom d'affichage des LSobjects]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'value_attribute' => '[Nom de l'attribut clé des LSobjects]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'filter' => '[Filtre de recherche]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'onlyAccessible' => '[Booléen]'
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> 'ordered' => [Booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> 'sort' => [Booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> 'sortDirection' => '[ASC|DESC]'
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_select_object-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>selectable_object</code></p>
|
||
<p>Tableau dont chaque valeur correspond à un tableau associatif spécifiant un type
|
||
d'<a href="#conf-configuration-lsobject">LSobject</a> sélectionnable. Pour chaque type d'objet
|
||
sélectionnable, les paramètres suivants doivent être renseignés :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>object_type</code></p>
|
||
<p>Nom du type d'<a href="#conf-configuration-lsobject">LSobject</a> en référence
|
||
<em>(Paramètre obligatoire)</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>display_name_format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du nom d'affichage des objets lors
|
||
de leur sélection <em>(Paramètre facultatif)</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>value_attribute</code></p>
|
||
<p>Nom de l'attribut des <a href="#conf-configuration-lsobject">LSobjects</a> en référence servant
|
||
de valeur clé et permettant de les identifier <em>(Paramètre obligatoire, exemples : <code>dn</code> ou <code>uid</code>)</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p>Filtre de recherche qui sera ajouter au filtre par défaut lors de la sélection des objets
|
||
<em>(Paramètre facultatif)</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>onlyAccessible</code></p>
|
||
<p>Booléen définissant si seul les LSobjets auxquels l'utilisateur connecté à accès doivent être
|
||
considérés comme sélectionnables <em>(Paramètre facultatif, par défaut: <code>False</code>)</em>.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>ordered</code></p>
|
||
<p>Booléen définissant si la liste des objets choisis doit être ordonnable ou non <em>(Paramètre
|
||
facultatif, par défaut: <code>False</code>)</em>. Cela aura pour effet d'activer une fonctionnalité dynamique de
|
||
l'interface permettant de remonter ou descendre dans la liste les objets choisis.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette fonctionnalité désactive automatiquement le trie des objets à l'affichage.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sort</code></p>
|
||
<p>Booléen définissant si la liste des objets choisis doit être triée ou non <em>(Paramètre facultatif,
|
||
par défaut: <code>True</code>)</em>. Le trie est effectué sur les libellés des objets choisis.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sortDirection</code></p>
|
||
<p>Mot clé déterminant le sens du trie des objets choisis.</p>
|
||
<p>Valeurs possibles : <code>ASC</code> ou <code>DESC</code> (<code>ASC</code> par défaut).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_ssh_key"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_ssh_key-lsattr_html_ssh_key">LSattr_html_ssh_key</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une clef publique SSH. Il
|
||
permet dans l'interface, d'avoir un affichage adapté à ce type de donnée.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_tel"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_tel-lsattr_html_tel">LSattr_html_tel</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est un numéro de téléphone. Lors de
|
||
l'affichage, un lien hypertexte avec une URI de type <code>tel:~~</code> est affiché.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce type d'attribut HTML est dérivé du type <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">text</a>. Il
|
||
profite donc de toutes les fonctionnalités d'un champ de ce type (autogénération, ...).</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_text"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">LSattr_html_text</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une chaîne de caractères devant
|
||
être affichée dans un champ <em>input</em> HTML de type <em>text</em>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'generate_value_format' => '[LSformat pour la génération de la valeur]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'autoGenerateOnCreate' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'autoGenerateOnModify' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'withoutAccent' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'replaceSpaces' => "[chaîne de remplacement]",
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'upperCase' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'lowerCase' => [booleen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> // Autocomplétion
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> 'autocomplete' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> 'object_type' => '[Type d'LSobject]', // facultatif (voir ci-dessous)
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> 'value_attributes' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> '[attr1]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> '[attr2]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> 'filter' => '[filtre LDAP]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> 'basedn' => '[base DN spécifique]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> 'scope' => '[scope de recherche]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> 'displayFormat' => '[LSformat]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> 'onlyAccessible' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a>
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>generate_value_format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> de la valeur utilisée pour la
|
||
génération automatique de celle-ci à partir des informations saisies dans le formulaire. Les
|
||
valeurs clefs du format sont les noms des attributs de l'objet. Seuls les attributs affichés au
|
||
moins en lecture seule dans le formulaire peuvent être utilisés dans le format. Une seule valeur
|
||
par attribut sera utilisée pour la génération : celle du premier champ (dans l'ordre d'apparition
|
||
dans le formulaire).</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Seuls les éléments du formulaire de type HTML <em>input</em>, <em>select</em> ou <em>textarea</em> peuvent être
|
||
utilisés.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>autoGenerateOnCreate</code></p>
|
||
<p>Activation de la génération automatique lorsque celui-ci est vide au moment du chargement du
|
||
formulaire (par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>autoGenerateOnModify</code></p>
|
||
<p>Activation de la génération automatique lors de chaque modification de la valeur des champs du
|
||
formulaire lié (par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>withoutAccent</code></p>
|
||
<p>Activation de la suppression des accents dans la chaîne de caractères générée automatiquement
|
||
(par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>withoutAccent</code></p>
|
||
<p>Activation du remplacement des accents dans la chaîne de caractères générée automatiquement. La
|
||
valeur de remplacement est celle du paramètre (par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>upperCase</code></p>
|
||
<p>Activation de la mise en majuscule de la valeur générée automatiquement (par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>lowerCase</code></p>
|
||
<p>Activation de la mise en minuscule de la valeur générée automatiquement (par défaut : <code>False</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>autocomplete</code></p>
|
||
<p>Paramètrage de l'autocomplétion des valeurs saisies : on paramètre ici la recherche des valeurs
|
||
possibles de l'attribut dans l'annuaire qui peut se faire :</p>
|
||
<ul>
|
||
<li>Sur la base d'un type d'<a href="#conf-configuration-lsobject">LSobject</a> donné :
|
||
l'autocomplétion se fera alors comme n'importe quelle recherche d'un type d'objet donné.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Sur la base d'une recherche brute dans l'annuaire : l'autocomplétion se fera alors au travers
|
||
une recherche brute dans l'annuaire sur n'importe quels objets ayant un des attributs spécifiés
|
||
dans le paramètre <code>value_attributes</code> correspondant.</li>
|
||
</ul>
|
||
<p>Les paramètres associés à ces deux cas de figure sont décrits ci-dessous :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>object_type</code></p>
|
||
<p>Le type d'<a href="#conf-configuration-lsobject">LSobject</a> recherché.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>value_attributes</code></p>
|
||
<p>Le(s) nom de l'attribut stockant les valeurs possibles recherchées. Il peut s'agir d'une chaîne
|
||
de caractères ou d'un tableau s'il y a plusieurs attributs.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>pattern_filter</code></p>
|
||
<p>Le <a href="#conf-global-lsformat-format-parametrable">LSformat</a> du filtre de recherche à partir
|
||
du mot clé recherché. Ce paramètre est facultatif et utile que dans le cas d'une recherche sans
|
||
type d'<a href="#conf-configuration-lsobject">LSobject</a> précis. S'il est défini, ce
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> sera composé à l'aide du mot clé
|
||
recherché. À défaut, le filtre de recherche sera composé à l'aide des différents
|
||
<code>value_attributes</code> configurés.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p>Un filtre de recherche facultatif venant en plus de celui calculé automatiquement à partir du
|
||
mot clé de recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>basedn</code></p>
|
||
<p>Le <em>basedn</em> de la recherche. <em>Paramètre facultatif.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>scope</code></p>
|
||
<p>Le <em>scope</em> de la recherche. <em>Paramètre facultatif, par défaut : <code>sub</code>.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>display_name_format</code></p>
|
||
<p>Le <a href="#conf-global-lsformat-format-parametrable">LSformat</a> d'affichage des objets trouvés.
|
||
Ce paramètre est facultatif et par défaut, il s'agira du format d'affichage propre au type
|
||
d'<a href="#conf-configuration-lsobject">LSobject</a> (si défini) et à défaut, la valeur
|
||
possible trouvée sera affichée. Si est configuré, ce
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> sera composé à l'aide des valeurs
|
||
brutes des attributs des objets correspondants avec en plus la valeur possible trouvée dans le
|
||
mot clé <code>value</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>only_accessible</code></p>
|
||
<p>Booléen falcultatif définissant si seul les
|
||
<a href="#conf-configuration-lsobject">LSobjects</a> auxquels l'utilisateur connecté à accès
|
||
doivent être considérés comme sélectionnables (Faux par défaut). Ce paramètre n'est appliqué que
|
||
dans le cas d'une recherche pour un type d'<a href="#conf-configuration-lsobject">LSobject</a>
|
||
donné.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_textarea"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_textarea-lsattr_html_textarea">LSattr_html_textarea</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une chaine de caractères trop
|
||
longue pour être saisie dans un champs HTML <em>imput</em> de type <em>text</em> et est plus adapté à un champ
|
||
HTML <em>textarea</em>.</p></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_url"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_url-lsattr_html_url">LSattr_html_url</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une URL. Il propose directement
|
||
dans l'interface, la possibilité d'accèder au site ou encore de l'ajouter dans ses favoris
|
||
(lorsque le navigateur le supporte).</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce type d'attribut HTML est dérivé du type <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">text</a>. Il
|
||
profite donc de toutes les fonctionnalités d'un champ de ce type (autogénération, ...).</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-lsattr_html_valuewithunit">LSattr_html_valueWithUnit</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est un entier auxquel un facteur
|
||
peut s'appliquer (par exemple : <code>Kilo, Méga, ...</code>).</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'units' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> '[facteur1]' => '[label unit1]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> '[facteur2]' => '[label unit2]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> [...]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'translate_labels' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'nb_decimals' => [number of decimals],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'dec_point' => '[decimals point]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'thousands_sep' => '[thousands separator]',
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> 'store_integer' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> 'round_down' => [booléen],
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> )
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_valuewithunit-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>units</code></p>
|
||
<p>Tableau associatif dont la clé est un entier correspondant au facteur et la valeur est le label de
|
||
l'unité. (Par exemple : <code>1 => Octet, 1024 => Kilo-octet, ...</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>translate_labels</code></p>
|
||
<p>Booléen permettant d'activer/désactiver la traduction des labels (Par défaut : <code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>nb_decimals</code></p>
|
||
<p>Le nombre de décimals à afficher en cas de nombre non-entier (Par défaut : <code>2</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>dec_point</code></p>
|
||
<p>Le caractère à utiliser comme séparateur de décimal (Par défaut, une virgule).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>thousands_sep</code></p>
|
||
<p>Le caractère à utiliser comme séparateur de milliers (Par défaut, un espace).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>store_integer</code></p>
|
||
<p>Booléen permettant d'activer/désactiver le stockage de valeurs entières (Par défaut : <code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>round_down</code></p>
|
||
<p>Booléen permettant d'arrondir à l'entier inférieur (et non à l'entier supérieur par défaut) en cas
|
||
de stockage de valeurs entières.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg-lsattr_html_wysiwyg">LSattr_html_wysiwyg</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est du code HTML et dont l'édition
|
||
doit être fait à l'aide d'un éditeur <em>WYSIWYG</em>. La librairie <a href="https://www.tinymce.com">TinyMCE</a>
|
||
est utilisée pour cela.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'html_options' => array(
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'extra_options' => array (
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> [Options à passer à TinyMCE]
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>),
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_wysiwyg-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>extra_options</code></p>
|
||
<p>Ce paramètre permet de passer des options à <a href="https://www.tinymce.com">TinyMCE</a> pour personnaliser
|
||
son comportement. Par exemple, il est possible d'utiliser le paramètre <code>valid_styles</code> pour définir
|
||
quels styles CSS sont autorisés. Pour plus d'informations, consultez la documentation de
|
||
<a href="https://www.tinymce.com">TinyMCE</a> .</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_xmpp"><h1 id="conf-lsobject-lsattribute-lsattr_html-lsattr_html_xmpp-lsattr_html_xmpp">LSattr_html_xmpp</h1>
|
||
<p>Ce type est utilisé pour la gestion des attributs dont la valeur est une adresse XMPP. Il propose
|
||
directement dans l'interface, la possibilité de lancer une fenêtre de dialogue avec l'interlocuteur
|
||
de son client XMPP préféré.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette fonctionnalité n'est supporté uniquement par les navigateurs web supportant les URI de
|
||
type <code>xmpp://</code>.</p>
|
||
</div>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ce type d'attribut HTML est dérivé du type <a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_text-lsattr_html_text">text</a>. Il
|
||
profite donc de toutes les fonctionnalités d'un champ de ce type (autogénération, ...).</p>
|
||
</div></section><h1 class="nav-section-title-end">Ended: Types d'attribut HTML (LSattr_html)</h1><h4 class="nav-section-title">Règles de vérification syntaxique (LSformRule)</h4><section class="print-page" id="conf-lsobject-lsattribute-check_data"><h1 id="conf-lsobject-lsattribute-check_data-configuration-des-regles-de-verification-syntaxique">Configuration des règles de vérification syntaxique</h1>
|
||
<p>Cette section décrit la manière de configuer des règles de vérification syntaxique sur les données
|
||
des attributs. Ces règles seront utilisées pour vérifier que les valeurs saisies par un utilisateur
|
||
dans un formulaire sont correctes.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'check_data' => array (
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> '[regle1]' => array(
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'msg' => "[Message d'erreur]",
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'params' => array(
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> // Paramètres de la règle
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> )
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>),
|
||
<a href="#conf-lsobject-lsattribute-check_data-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a>...
|
||
</code></pre></div>
|
||
<p>Le paramètre <code>check_data</code> est un tableau associatif dont les clés sont les noms des règles de
|
||
vérification syntaxique actives et les valeurs associées sont des tableaux associatifs contenant les
|
||
paramètres des règles.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>msg</code></p>
|
||
<p>Le message d'erreur à afficher lors que la règle n'est pas respectée (optionnel).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>params</code></p>
|
||
<p>Tableau associatif contenant les paramètres de la règle. Les paramètres possibles sont propres à
|
||
chaque type de règle. Les clès sont les noms des paramètres et les valeurs associés, les valeurs
|
||
des paramètres.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-alphanumeric"><h1 id="conf-lsobject-lsattribute-check_data-alphanumeric-alphanumeric">alphanumeric</h1>
|
||
<p>Cette règle vérifie que la valeur est une chaîne de caractères composée uniquement de lettres
|
||
non-accuentées, en minuscule ou en majuscule et/ou de chiffres.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>withAccents</code></p>
|
||
<p>Si le paramètre est à <em>true</em>, les lettres accentuées seront acceptées.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-callable"><h1 id="conf-lsobject-lsattribute-check_data-callable-callable">callable</h1>
|
||
<p>Cette règle vérifie que la valeur saisie est correcte en utilisant une fonction personnalisée. Cette
|
||
fonction devra prendre en paramètres la valeur à valider, le tableau des paramètres de la règle
|
||
ainsi qu'un pointeur sur l'objet <em>LSformElement</em>. Sur la base de ses informations, elle devra
|
||
valider la valeur et retourner <code>True</code> si la valeur est valide et <code>False</code> sinon.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>callable</code></p>
|
||
<p>Le nom de la fonction (ou tout autre <code>callable</code> au sens PHP) de validation.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-date"><h1 id="conf-lsobject-lsattribute-check_data-date-date">date</h1>
|
||
<p>Cette règle vérifie que la valeur saisie est bien une date et qu'elle respecte un format précis.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>format</code></p>
|
||
<p>Format de la date à respecter. Ce format doit être compatible avec la fonction <code>strftime()</code> de
|
||
PHP. <a href="http://www.php.net/strftime">Voir la documentation de la fonction</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>special_values</code></p>
|
||
<p>Tableau listant les valeurs spéciales que peut prendre l'attribut. Dans ce tableau, seules les
|
||
valeurs sont utilisées et les clés n'ont pas d'importance. Ces valeurs spéciales n'auront pas
|
||
forcément besoin de respecter le format attendu.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-differentpassword"><h1 id="conf-lsobject-lsattribute-check_data-differentpassword-differentpassword">differentPassword</h1>
|
||
<p>Cette règle vérifie que la valeur saisie ne correspond pas à un des mots de passe stockés dans
|
||
d'autres attributs du même objet.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Les autres attributs doivent utiliser le type d'attribut <em>LDAP</em>
|
||
<a href="#conf-lsobject-lsattribute-lsattr_ldap-lsattr_ldap_password-lsattr_ldap_password">LSattr_ldap_password</a>.</p>
|
||
</div>
|
||
<ul>
|
||
<li>
|
||
<p><code>otherPasswordAttributes</code></p>
|
||
<p>La liste des autres attributs dont les mots de passe doivent être différent.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-email"><h1 id="conf-lsobject-lsattribute-check_data-email-email">email</h1>
|
||
<p>Cette règle vérifie que la valeur saisie est bien une adresse e-mail. Il est possible de vérifier si
|
||
elle appartient bien à un domaine en particulier ou encore de vérifier si le domaine existe et qu'il
|
||
possède un serveur de mail(MX).</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>domain</code></p>
|
||
<p>Nom de domaine obligatoire. Ce paramètre peut être une simple chaine correspondant au domaine ou
|
||
un tableau listant plusieurs domaines possibles.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>checkDomain</code></p>
|
||
<p>Booléen définissant si le domaine de l'adresse mail doit être validée.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-filesize"><h1 id="conf-lsobject-lsattribute-check_data-filesize-filesize">filesize</h1>
|
||
<p>Cette règle vérifie que la valeur est un fichier dont la taille en octets respecte les limites
|
||
passées en paramètre.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>minSize</code></p>
|
||
<p>Taille minimum.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>maxSize</code></p>
|
||
<p>Taille maximum.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-gpg_pub_key"><h1 id="conf-lsobject-lsattribute-check_data-gpg_pub_key-gpg_pub_key">gpg_pub_key</h1>
|
||
<p>Cette règle vérifie que la valeur est une clé publique GPG. Pour cela, la clé est importée dans un
|
||
<em>keyring</em> GnuPG.</p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-imagefile"><h1 id="conf-lsobject-lsattribute-check_data-imagefile-imagefile">imagefile</h1>
|
||
<p>Cette règle vérifie que la valeur est bien un fichier et que le type mime de celui-ci est bien une
|
||
image. Cette règle utilise la règle mimetype en spécifiant si l'utilisateur ne le fait pas que le
|
||
type mime doit respecter la regex suivante : <code>/image\/.*/</code></p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Cette règle est une simple interface à la règle mimetype, il est donc possible de passer
|
||
d'autres paramètres propres à ce type.</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-imagesize"><h1 id="conf-lsobject-lsattribute-check_data-imagesize-imagesize">imagesize</h1>
|
||
<p>Cette règle vérifie que la valeur est une image dont la taille en pixels respecte les limites
|
||
passées en paramètre.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>minWidth</code></p>
|
||
<p>Largeur minimum.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>maxWitdh</code></p>
|
||
<p>Largeur maximum.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>minHeight</code></p>
|
||
<p>Hauteur minimum.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>maxHeight</code></p>
|
||
<p>Hauteur maximum.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-inarray"><h1 id="conf-lsobject-lsattribute-check_data-inarray-inarray">inarray</h1>
|
||
<p>Cette règle vérifie que la valeur saisie fait partie d'une liste de valeurs autorisées
|
||
(ou interdites).</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>possible_values</code></p>
|
||
<p>Tableau listant les valeurs autorisées.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>reverse</code></p>
|
||
<p>Booléen permettant d'inverser la logique de validation : si <code>reverse</code> est vrai, la valeur testée
|
||
sera acceptée si elle ne fait pas partie des valeurs possibles (Paramètre facultatif, par défaut :
|
||
<code>False</code>).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-integer"><h1 id="conf-lsobject-lsattribute-check_data-integer-integer">integer</h1>
|
||
<p>Cette règle vérifie que la valeur saisie est un entier. Les paramètres permettent de spécifier
|
||
éventuellement si la valeur doit être positive ou négative et également de borner les valeurs
|
||
valides.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>positive</code></p>
|
||
<p>Booléen définissant si la valeur doit être positive.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>negative</code></p>
|
||
<p>Booléen définissant si la valeur doit être negative.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>min</code></p>
|
||
<p>Valeur minimale (supérieur ou égale).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>max</code></p>
|
||
<p>Valeur maximale (inférieur ou égale).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-ldapsearchuri"><h1 id="conf-lsobject-lsattribute-check_data-ldapsearchuri-ldapsearchuri">ldapSearchURI</h1>
|
||
<p>Cette règle vérifie que la valeur est une URI de recherche LDAP valide, c'est à dire, par exemple,
|
||
<code>ldaps://ldap.example.com:636/o=example?attr1,attr2?one?(gidNumber=100)</code></p>
|
||
<p>Cette vérification commence par découper la valeur à l'aide du sépérateur <code>?</code> et elle s'assure
|
||
ensuite :</p>
|
||
<ul>
|
||
<li>Que la première partie est bien une URI LDAP valide. Si l'hôte LDAP est spécifié, elle s'assure
|
||
qu'il soit une adresse IP ou un nom de domaine valide. Si le port LDAP est spécifié, elle s'assure
|
||
également qu'il soit correct et que l'hôte est également bien spécifié.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Si la base de recherche est spécifiée, elle s'assure qu'elle soit compatible avec la racine de
|
||
l'annuaire connecté.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Si un ou plusieurs attributs sont spécifiés, elle les vérifie un à un afin de vérifier qu'il
|
||
s'agit de nom d'attribut valide.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Que le scope de recherche soit bien spécifié et valide.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Si le filtre de recherche est spécifié, elle vérifie qu'il soit valide.</li>
|
||
</ul>
|
||
<p><strong>Paramêtres de configuration :</strong></p>
|
||
<ul>
|
||
<li>
|
||
<p><code>check_resolving_ldap_host</code></p>
|
||
<p>Si l'hôte du serveur LDAP est spécifié et qu'il s'agit d'un nom de domaine valide, un tentative de
|
||
résolution DNS sera également faite (optionnel, par défaut : <code>True</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>host_required</code></p>
|
||
<p>Booléen détermintant si une erreur est relevée en cas d'absence de l'hôte LDAP. (optionnel,
|
||
par défaut : <code>False</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>basedn_required</code></p>
|
||
<p>Booléen détermintant si une erreur est relevée en cas d'absence de base de recherche. (optionnel,
|
||
par défaut : <code>False</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>scope_required</code></p>
|
||
<p>Booléen détermintant si une erreur est relevée en cas d'absence de portée de recherche.
|
||
(optionnel, par défaut : <code>True</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>attr_required</code></p>
|
||
<p>Booléen détermintant si une erreur est relevée en cas d'absence d'attribut recherché. (optionnel,
|
||
par défaut : <code>False</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>max_attrs_count</code></p>
|
||
<p>Nombre maximum d'attribut recherchés. (optionnel, par défaut : pas de limite)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter_required</code></p>
|
||
<p>Booléen détermintant si une erreur est relevée en cas d'absence de filtre de recherche.
|
||
(optionnel, par défaut : <code>False</code>)</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-lettersonly"><h1 id="conf-lsobject-lsattribute-check_data-lettersonly-lettersonly">lettersonly</h1>
|
||
<p>Cette règle vérifie que la valeur est une chaîne de caractères composée uniquement de lettres
|
||
non-accuentées, en minuscule ou en majuscule.</p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-maxlength"><h1 id="conf-lsobject-lsattribute-check_data-maxlength-maxlength">maxlength</h1>
|
||
<p>Cette règle vérifie que la valeur saisie est une chaine de caractères dont la longueur est inférieur
|
||
ou égale à la valeur passées en paramètre.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>limit</code></p>
|
||
<p>Limite supérieur (ou égale) de la longueur de la chaîne de caratères.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-mimetype"><h1 id="conf-lsobject-lsattribute-check_data-mimetype-mimetype">mimetype</h1>
|
||
<p>Cette règle vérifie que la valeur est bien un fichier et que le type mime de celui-ci est correct.
|
||
Il est possible de vérifier si le type mime fait partie d'une liste ou encore s'il valide une
|
||
expression régulière.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>mimeType</code></p>
|
||
<p>Type mime obligatoire. Ce paramètre peut être une simple chaine correspondant au type mime ou un
|
||
tableau listant plusieurs possibilités.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>mimeTypeRegEx</code></p>
|
||
<p>Expression régulière que doit respecter le type mime.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-minlength"><h1 id="conf-lsobject-lsattribute-check_data-minlength-minlength">minlength</h1>
|
||
<p>Cette règle vérifie que la valeur saisie est une chaine de caractères dont la longueur est supérieur
|
||
ou égale à la valeur passée en paramètre.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>limit</code></p>
|
||
<p>Limite inférieure (ou égale) de la longueur de la chaîne de caratères.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-nonzero"><h1 id="conf-lsobject-lsattribute-check_data-nonzero-nonzero">nonzero</h1>
|
||
<p>Cette régle vérifie que la valeur est une valeur numérique non nulle.</p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-nopunctuation"><h1 id="conf-lsobject-lsattribute-check_data-nopunctuation-nopunctuation">nopunctuation</h1>
|
||
<p>Cette régle vérifie que la valeur est une chaîne de caractères ne contenant pas de signe de
|
||
ponctuation. Les caractères suivants sont actuellement exclus :
|
||
<code>( ) . \ / \ * \ ^ \ ? # ! @ $ % + = , " ' > < ~ [ ] { }</code></p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-numberofvalues"><h1 id="conf-lsobject-lsattribute-check_data-numberofvalues-numberofvalues">numberOfValues</h1>
|
||
<p>Cette règle vérifie que le nombre de valeurs de l'attribut est comprise entre les limites passées en
|
||
paramètre.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>min</code></p>
|
||
<p>Nombre minimum de valeurs (paramètre optionnel).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>max</code></p>
|
||
<p>Nombre maximum de valeurs (paramètre optionnel).</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-numeric"><h1 id="conf-lsobject-lsattribute-check_data-numeric-numeric">numeric</h1>
|
||
<p>Cette régle vérifie que la valeur est une valeur numérique.</p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-password"><h1 id="conf-lsobject-lsattribute-check_data-password-password">password</h1>
|
||
<p>Cette règle vérifie que la valeur est un mot de passe respectant la politique de sécurité définie
|
||
par les paramètres de la règle.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>minlength</code></p>
|
||
<p>Longueur minimale du mot de passe.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>maxlength</code></p>
|
||
<p>Longueur maximale du mot de passe.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>prohibitedValues</code></p>
|
||
<p>Tableau de valeurs interdites.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>regex</code></p>
|
||
<p>Expression(s) régulière(s) que doit respecter le mot de passe. Ce paramètre peut être une
|
||
expression régulière au format <a href="http://php.net/pcre.pattern">PCRE</a> ou un tableau d'expressions
|
||
régulières.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>minValidRegex</code></p>
|
||
<p>Le nombre minimum d'expression régulière qui doivent être validées pour que le mot de passe soit
|
||
considéré comme correct. Ce paramètre est optionnel, par défaut, toutes les expressions régulières
|
||
doivent être validées.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-rangelength"><h1 id="conf-lsobject-lsattribute-check_data-rangelength-rangelength">rangelength</h1>
|
||
<p>Cette règle vérifie que la valeur saisie est une chaine de caractères dont la longueur est comprise
|
||
entre deux valeurs passées en paramètre.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>limits</code></p>
|
||
<p>Tableau contenant deux valeurs, la première étant la limite inférieure ou égale et la seconde la
|
||
limite supérieure ou égale.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-regex"><h1 id="conf-lsobject-lsattribute-check_data-regex-regex">regex</h1>
|
||
<p>Cette règle vérifie que la valeur saisie respecte bien l'expression régulière passée en paramètre.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>regex</code></p>
|
||
<p>L'expression régulière devant être respectée. Cette expression régulière doit être au format
|
||
<a href="http://php.net/pcre.pattern">PCRE</a>.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-required"><h1 id="conf-lsobject-lsattribute-check_data-required-required">required</h1>
|
||
<p>Cette régle vérifie que la valeur n'est pas une chaîne de caractères de longueur nulle.</p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-ssh_pub_key"><h1 id="conf-lsobject-lsattribute-check_data-ssh_pub_key-ssh_pub_key">ssh_pub_key</h1>
|
||
<p>Cette règle vérifie que la valeur est une clé publique SSH.</p>
|
||
<p>Cette vérification utilise tout d'abord une expression régulière pour valider la forme syntaxique de
|
||
la clé publique (<code>ssh-[type] [clé au format base64] [commentaire]</code>) puis tente de décoder la partie
|
||
en base64 de la clé pour vérifier qu'il s'agit bien d'une chaine de caractères.</p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-telephonenumber"><h1 id="conf-lsobject-lsattribute-check_data-telephonenumber-telephonenumber">telephonenumber</h1>
|
||
<p>Cette régle vérifie que la valeur est un numéro de téléphone français. Celui-ci doit respecter
|
||
l'expression regulière suivante : <code>/^(01|02|03|04|05|06|08|09)[0-9]{8}$/</code></p></section><section class="print-page" id="conf-lsobject-lsattribute-check_data-zxcvbn"><h1 id="conf-lsobject-lsattribute-check_data-zxcvbn-zxcvbn">zxcvbn</h1>
|
||
<p>Cette règle vérifie la sécurité d'un mot de passe en utilisant la librairie
|
||
<a href="https://gitlab.easter-eggs.com/ee/zxcvbn-php">ZxcvbnPhp</a>. Cette librairie s'appuie sur un ensemble
|
||
de vérifications permettant de déterminer à quel point le mot de passe choisi est commun, prévisible
|
||
et plus globalement, estime en combien de temps il pourra être cassé par une personne malveillante.
|
||
Sur la base de l'analyse du mot de passe saisi, des conseils seront donnés à l'utilisateur pour le
|
||
guider dans le choix d'un mot de passe sûre.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>La librairie <code>ZxcvbnPhp</code> n'est compatible qu'avec PHP 7 et supérieur.</p>
|
||
</div>
|
||
<ul>
|
||
<li>
|
||
<p><code>minScore</code></p>
|
||
<p>Le score minimal pour que le mot de passe soit accepté. Il doit s'agir d'un entier compris entre
|
||
0 (le plus faible) et 4 (le plus sécurisé). Paramètre facultatif valant 4 par défaut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>minGuessesLog10</code></p>
|
||
<p>Permet de définir le logarithme en base 10 du nombre minimum estimé de tentative pour deviner le
|
||
mot de passe. Par exemple, si <code>minGuessesLog10</code> est égal à 6, cela signifie que le mot de passe
|
||
ne sera accepté que si <code>Zxcvbn</code> estime qu'il faut au moins 1 million (10^6) de tentatives pour le
|
||
deviner. Paramètre facultatif valant 10 par défaut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>userDataAttrs</code></p>
|
||
<p>Liste d'attributs de l'objet dont les valeurs seront passées à la librairie <code>Zxcvbn</code> qui les
|
||
considérera comme associés à l'utilisateur. Ainsi, par exemple, si l'utilisateur utilise son nom
|
||
de famille ou encore son prénom dans son mot de passe, la librairie pourra lui indiqué que cela ne
|
||
le protège que peut des attaques ciblées. Paramètre facultatif, mais il est fortement conseillé de
|
||
renseigner un maximum d'attributs contenant des informations personnelles relatives à l'utilisteur.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>banPersonalInfo</code></p>
|
||
<p>Booléen permettant d'interdire toutes utilisations d'informations personnelles dans le choix du mot
|
||
de passe. Paramètre facultatif et vrai par défaut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>showWarning</code></p>
|
||
<p>Booléen définissant si les messages d'alertes retournés par la librairie <code>Zxcvbn</code> doivent être
|
||
affichés à l'utilisateur. Paramètre facultatif et vrai par défaut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>showSuggestions</code></p>
|
||
<p>Booléen définissant si les messages de suggestions retournés par la librairie <code>Zxcvbn</code> doivent
|
||
être affichés à l'utilisateur. Paramètre facultatif et vrai par défaut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>customDictionaries</code></p>
|
||
<p>Tableau associatif permettant de configurer des dictionnaires personnalisés : les clés contiennent
|
||
le nom de la collection de dictionnaires et les valeurs associées, le chemin vers un fichier JSON
|
||
contenant la collection de dictionnaires. Ces fichiers doivent contenir un objet racine dont les
|
||
clés sont des chaînes de caractères correspondant au nom des dictionnaires et les valeurs
|
||
associés sont des listes de mots <strong>en minuscule</strong> triées par ordre décroissant de fréquence
|
||
d'utilisation.</p>
|
||
<p>Exemple:</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-check_data-zxcvbn-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="p">{</span>
|
||
<a href="#conf-lsobject-lsattribute-check_data-zxcvbn-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="w"> </span><span class="nt">"dictionnaire1"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"mot1"</span><span class="p">,</span><span class="w"> </span><span class="s2">"mot2"</span><span class="p">],</span>
|
||
<a href="#conf-lsobject-lsattribute-check_data-zxcvbn-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="w"> </span><span class="nt">"dictionnaire2"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"mot3"</span><span class="p">,</span><span class="w"> </span><span class="s2">"mot4"</span><span class="p">]</span>
|
||
<a href="#conf-lsobject-lsattribute-check_data-zxcvbn-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="p">}</span>
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>banDictionaries</code></p>
|
||
<p>Ce paramètre permet d'interdire tous mots issues de certains dictionnaires. Il s'agit d'un
|
||
tableau devant contenir les noms des dictionaires interdits. La librairie <code>Zxcvbn</code> fournis
|
||
les dictionnaires suivant :</p>
|
||
<ul>
|
||
<li><code>us_tv_and_film</code> : les mots les plus courrament utilisés dans les séries et films américains</li>
|
||
<li><code>passwords</code> : les mot de passse les plus courrament utilisés</li>
|
||
<li><code>male_names</code> : les prénoms masculins les plus courrant</li>
|
||
<li><code>female_names</code> : les prénoms féminins les plus courrant</li>
|
||
<li><code>surnames</code> : les nom de familles les plus courrant aux États Unis</li>
|
||
<li><code>english_wikipedia</code> : les mots les plus courrament utilisés dans les articles en anglais de
|
||
Wikipédia</li>
|
||
<li><code>french_wikipedia</code> : les mots les plus courrament utilisés dans les articles en français de
|
||
Wikipédia</li>
|
||
<li>
|
||
<p><code>user_inputs</code> : les informations personnelles fournis lors de la validation du mot de passe</p>
|
||
<p><strong>Note :</strong> lister ce dictionnaire dans se paramètre à le même effet que le paramètre
|
||
<code>banPersonalInfo</code> documenté ci-dessus.</p>
|
||
</li>
|
||
</ul>
|
||
<p>Vous pouvez également lister ici tout dictionnaires personnalisés que vous auriez ajouté grâce
|
||
au paramètre <code>customDictionaries</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>zxcvbn_autoload_path</code></p>
|
||
<p>Le chemin vers le fichier de chargement automatique des classes de la librairie <em>ZxcvbnPhp</em>. Ce
|
||
paramètre est facultatif et vaut par défaut <code>Zxcvbn/autoload.php</code>, ce qui est adapté si vous
|
||
utiliser le paquet Debian <code>php-zxcvbn</code> disponible sur le dépôt Debian du projet LdapSaisie.</p>
|
||
</li>
|
||
</ul></section><h1 class="nav-section-title-end">Ended: Règles de vérification syntaxique (LSformRule)</h1><section class="print-page" id="conf-lsobject-lsattribute-validation"><h1 id="conf-lsobject-lsattribute-validation-configuration-des-regles-de-verification-dintegrite">Configuration des règles de vérification d'intégrité</h1>
|
||
<p>Cette section décrit la manière de configurer des règles de vérification d'intégrité sur les données
|
||
des attributs. Il est possible de valider la valeur de l'attribut par l'intermédiraire de la
|
||
vérification de résultat d'une recherche paramètrable dans l'annuaire ou encore d'appeler une
|
||
fonction de votre choix pour effectuer la vérification voulue.</p>
|
||
<h2 id="conf-lsobject-lsattribute-validation-validation-par-lanalyse-du-resultat-dune-recherche-dans-lannuaire">Validation par l'analyse du résultat d'une recherche dans l'annuaire</h2>
|
||
<p>Une telle règle permet de vérifier si les valeurs des attributs n'entrent pas en conflit avec
|
||
d'autres objets de l'annuaire. Ce test peut également permetre de vérifier si les valeurs devant
|
||
faire référence à d'autres objets de l'annuaire sont correctes.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-validation-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>'validation' => array (
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> array(
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'msg' => "[LSformat du message d'erreur]",
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'filter' => '[LSformat du filtre de la recherche]',
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'object_type' => '[Type d'LSobject recherché]',
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'basedn' => '[BaseDn de la recherche]',
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'scope' => '[Scope de la recherche]',
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'result' => '[Résultat positif de la recherche]',
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'except_current_object' => '[Exclure l'objet courant]'
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a>),
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>msg</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message d'erreur à afficher lorsque la
|
||
validation échoue. Ce format est construit avec les valeurs du
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobject</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du filtre de la recherche. Ce format peut
|
||
être construit avec toutes les valeurs du LSobject (attributs, DN, ...) et également avec la
|
||
valeur à valider en utilisant pour mot clé <code>%{val}</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>object_type</code></p>
|
||
<p>Le nom du type d'LSobject recherché. Si un type est spécifié, le filtre de la recherche sera une
|
||
combinaison de celui du paramètre <code>filter</code> et du filtre composé à partir des <em>objectClass</em> du type
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a>. <em>Paramètre facultatif.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>basedn</code></p>
|
||
<p>Le <em>basedn</em> de la recherche <em>(Paramètre facultatif, par défaut : racine de l'annuaire)</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>scope</code></p>
|
||
<p>Le <em>scope</em> de la recherche <em>(Paramètre facultatif, par défaut : <code>sub</code>)</em>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>result</code></p>
|
||
<p>Le résultat de la recherche : si <code>result</code> vaut zéro, la recherche ne devra retourner aucun objet
|
||
pour que la validation soit réussie. Sinon, la recherche devra retourner au moins un objet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>except_current_object</code></p>
|
||
<p>Booléen définissant si l'objet courrant doit être exclu du résultat de la recherche. Ce paramètre
|
||
n'est évalué quand cas de création (formulaire <code>create</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-lsobject-lsattribute-validation-validation-par-lexecution-dune-fonction">Validation par l'exécution d'une fonction</h2>
|
||
<p>Il est possible d'effectuer la validation de l'attribut par l'exécution d'une fonction de votre
|
||
choix. Il lui sera passé en paramètre une référence à l'objet <code>LSldapObject</code> courant. Si la fonction
|
||
ne retourne pas <em>true</em>, la validation échouera.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-validation-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>'validation' => array (
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> ..
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> array(
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> 'msg' => "[LSformat du message d'erreur]",
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> 'function' => '[Nom de la fonction de validation]'
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> ),
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> ...
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a>),
|
||
<a href="#conf-lsobject-lsattribute-validation-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a>...
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>msg</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message d'erreur à afficher lorsque la
|
||
validation échoue. Ce format est construit avec les valeurs du
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobject</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>function</code></p>
|
||
<p>Le nom de la fonction à exécuter. Si cette fonction n'existe pas, un message d'erreur sera affiché
|
||
et la validation échouera.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsattribute-triggers"><h1 id="conf-lsobject-lsattribute-triggers-declencheurs">Déclencheurs</h1>
|
||
<p>Cette section décrit la manière de paramétrer des déclencheurs afin que LdapSaisie exécute durant
|
||
ses processus, et à des moments bien précis des traitements d'un
|
||
<a href="#conf-lsobject-lsattribute-configuration-des-attributs">LSattributes</a>, des fonctions que vous pourrez développer vous
|
||
même. De plus, le résultat de l'exécution de vos fonctions pourra influer sur le déroulement des
|
||
processus.</p>
|
||
<p>Actuellement, les évènements suivant sont gérés :</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Nom</th>
|
||
<th>Description</th>
|
||
<th>Bloquant</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>before_create</code></td>
|
||
<td>Avant la création du LSobject, lorsque l'attribut a au moins une valeur.</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_create</code></td>
|
||
<td>Après la création du LSobject, lorsque l'attribut a au moins une valeur.</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>before_modify</code></td>
|
||
<td>Avant la modification de la valeur de l'attribut.</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_modify</code></td>
|
||
<td>Après la modification de la valeur de l'attribut.</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>before_delete</code></td>
|
||
<td>Avant la suppression du LSobject contenant l'attribut.</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_delete</code></td>
|
||
<td>Après la suppression du LSobject contenant l'attribut.</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Si un événement est dit <em>bloquant</em>, lors de l'exécution des actions liées, si une des fonctions
|
||
retourne <code>false</code>, le processus s'arrêtera.</p>
|
||
</div>
|
||
<h2 id="conf-lsobject-lsattribute-triggers-configuration">Configuration</h2>
|
||
<p>La configuration des déclencheurs se fait dans la définition des
|
||
<a href="#conf-lsobject-lsattribute-configuration-des-attributs">LSattributes</a>. Par exemple, pour définir les fonctions à
|
||
exécuter après la modification de la valeur de l'attribut <em>mail</em> du type de
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobject</a> <em>LSpeople</em>, c'est à dire lors de leur évenement
|
||
<code>after_modify</code>, il faut définir la variable suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-triggers-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>$GLOBALS['LSobjects']['LSpeople']['attrs']['mail']['after_modify']
|
||
</code></pre></div>
|
||
<p>Cette variable peut contenir soit une chaine de caractères correspondant au nom de la fonction à
|
||
exécuter, soit un tableau de chaînes de caractères correspondant aux noms des fonctions à exécuter.</p>
|
||
<h2 id="conf-lsobject-lsattribute-triggers-ecriture-dune-fonction">Écriture d'une fonction</h2>
|
||
<p>Une fonction exécuté par un déclencheur d'un LSattribute se déclare de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">/*</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> * Ma fonction à exécuter lors de l'évènement [event]</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> * Paramètre :</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> * - $object : Le LSobject contenant le LSattribute sur lequel l'évenement</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> * survient</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> * Valeurs retournées :</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> * - True : Tout s'est bien passé</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> * - False : Une erreur est survenue ou la fonction souhaite bloquer le</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> * processus lors d'un évènement bloquant.</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x"> */</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="x">function maFonction ($object) {</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a><span class="x"> // Actions</span>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a>
|
||
<a href="#conf-lsobject-lsattribute-triggers-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a><span class="x">}</span>
|
||
</code></pre></div>
|
||
<p>Cette fonction doit prendre pour seul paramètre, le LSobject contenant le LSattribute sur lequel
|
||
l'évenement survient et doit retourner soit <code>True</code> si tout s'est bien passé, soit <code>False</code> en cas de
|
||
problème. Dans le cas d'un événement bloquant, si la fonction retourne <code>False</code>, le processus est
|
||
arrêté.</p></section><h1 class="nav-section-title-end">Ended: Attributs</h1><section class="print-page" id="conf-lsobject-container_auto_create"><h1 id="conf-lsobject-container_auto_create-creation-automatique-du-conteneur-des-lsobjets-dans-un-subdn">Création automatique du conteneur des LSobjets dans un subDn</h1>
|
||
<p>Cette section décrit la manière de configurer la création automatique des conteneurs des LSobjets.
|
||
Si le <em>basedn</em> correspondant à la branche de stockage des <a href="#conf-lsobject-configuration-lsobject">LSobjects</a>
|
||
n'existe pas, LdapSaisie tentera de le créer à partir de la configuration de la variable
|
||
<code>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['container_auto_create']</code>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-container_auto_create-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['container_auto_create'] = array (
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'objectclass' => array(
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'objectclass1',
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'objectclass2',
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> ...
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> ),
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'attrs' => array(
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'attr1' => 'val1',
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'attr2' => array(
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'val2',
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> 'val3',
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> ...
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> ),
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> ...
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> )
|
||
<a href="#conf-lsobject-container_auto_create-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a>);
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>objectclass</code></p>
|
||
<p>La liste des <em>objectclass</em> de l'objet conteneur.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>attrs</code></p>
|
||
<p>Un tableau associatif dont les clés sont les noms des attributs de l'objet conteneur à définir et
|
||
dont les valeurs associées sont la/les valeur(s) de ces attributs.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-triggers"><h1 id="conf-lsobject-triggers-declencheurs">Déclencheurs</h1>
|
||
<p>Cette section décrit la manière de paramétrer des déclencheurs afin que LdapSaisie exécute durant
|
||
ses processus, et à des moments bien précis des traitements d'un
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobject</a>, des fonctions que vous pourrez développer vous même. De
|
||
plus, le résultat de l'exécution de vos fonctions pourra influer sur le déroulement des processus.</p>
|
||
<p>Actuellement, les évenements suivant sont gérés :</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Nom</th>
|
||
<th>Description</th>
|
||
<th>Bloquant</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>before_create</code></td>
|
||
<td>Avant la création du LSobject.</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_create</code></td>
|
||
<td>Après la création du LSobject.</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>before_modify</code></td>
|
||
<td>Avant la modification du LSobject</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_modify</code></td>
|
||
<td>Après la modification du LSobject</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>before_rename</code></td>
|
||
<td>Avant de renommer le LSobject</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_rename</code></td>
|
||
<td>Après avoir renommé le LSobject</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>before_delete</code></td>
|
||
<td>Avant la suppression du LSobject</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_delete</code></td>
|
||
<td>Après la suppression du LSobject</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Si un événement est dit <em>bloquant</em>, lors de l'exécution des actions liées, si une des fonctions
|
||
retourne <code>false</code>, le processus s'arrêtera.</p>
|
||
</div>
|
||
<h2 id="conf-lsobject-triggers-configuration">Configuration</h2>
|
||
<p>La configuration des déclencheurs se fait dans la définition des types
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobjects</a>. Par exemple, pour définir les fonctions à exécuter
|
||
après la modification des LSobjects de type <em>LSpeople</em>, c'est à dire lors de leur évènement
|
||
<code>after_modify</code>, il faut définir la variable suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-triggers-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSobjects']['[nom du type d'LSobject]']['after_modify']</span>
|
||
</code></pre></div>
|
||
<p>Cette variable peut contenir soit une chaine de caractères correspondant au nom de la fonction à
|
||
exécuter, soit un tableau de chaînes de caractères correspondant aux noms des fonctions à exécuter.</p>
|
||
<h2 id="conf-lsobject-triggers-ecriture-dune-fonction">Écriture d'une fonction</h2>
|
||
<p>Une fonction exécuté par un déclencheur d'un LSobject se déclare de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-triggers-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">/*</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> * Ma fonction à exécuter lors de l'evenement [event]</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> * Paramètre :</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> * - $object : Le LSobject sur lequel l'évènement survient</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> * Valeurs retournées :</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> * - True : Tout s'est bien passé</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> * - False : Une erreur est survenue ou la fonction souhaite bloquer le</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> * processus lors d'un évènement bloquant.</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> */</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x">function maFonction ($object) {</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a><span class="x"> // Actions</span>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a>
|
||
<a href="#conf-lsobject-triggers-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a><span class="x">}</span>
|
||
</code></pre></div>
|
||
<p>Cette fonction doit prendre pour seul paramètre, le LSobject sur lequel l'évènement survient et doit
|
||
retourner soit <code>True</code> si tout s'est bien passé, soit <code>False</code> en cas de problème. Dans le cas d'un
|
||
événement bloquant, si la fonction retourne <code>False</code>, le processus est arrêté.</p></section><section class="print-page" id="conf-lsobject-customactions"><h1 id="conf-lsobject-customactions-actions-personnalisees-customactions">Actions personnalisées (customActions)</h1>
|
||
<p>Cette section décrit la manière de configurer les actions personnalisées exécutables sur les
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a> appelées <em>customActions</em>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-customactions-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['customActions'] = array (
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'action1' => array(
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'label' => '[label l'action]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'hideLabel' => '[booléen]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'helpInfo' => '[label d'aide]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'icon' => '[nom de l'icône de l'action]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'function' => '[fonction à exécuter]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'question_format' => '[LSformat de la question de confirmation]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'onSuccessMsgFormat' => '[LSformat du message à afficher en cas de succès de l'action]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'disableOnSuccessMsg' => '[booléen]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> 'noConfirmation' => '[booléen]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> 'redirectToObjectList' => '[booléen]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> 'noRedirect' => '[booléen]',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> 'accessMethods' => array(
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> 'web',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> 'api',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> ),
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> 'rights' => array(
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> 'LSprofile1',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> 'LSprofile2',
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> ...
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> )
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> )
|
||
<a href="#conf-lsobject-customactions-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a>);
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>hideLabel</code></p>
|
||
<p>Cache le label dans le bouton de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>helpInfo</code></p>
|
||
<p>Le label du message d'aide qui sera affiché au survole du bouton de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>icon</code></p>
|
||
<p>Nom de l'îcone à afficher dans le bouton de l'action. Ce nom correspond au nom du fichier de
|
||
l'image (sans l'extention) qui devra se trouver dans le dossier
|
||
<code>src/images/[nom du theme d'images]/</code> ou dans le dossier <code>src/local/images</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>function</code></p>
|
||
<p>Le nom de la fonction à exécuter qui implémente l'action personnalisée Cette fonction prendra en
|
||
seule paramètre le <a href="#conf-lsobject-configuration-lsobject">LSobject</a> sur lequel l'action devra être
|
||
exécutée et retournera <code>True</code> en cas de succès ou <code>False</code> en cas d'échec d'exécution de la fonction.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>question_format</code></p>
|
||
<p>Le <a href="#conf-global-lsformat-format-parametrable">LSformat</a> de la question de confirmation
|
||
d'exécution de l'action. Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> sera composé à
|
||
l'aide du nom de l'objet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>onSuccessMsgFormat</code></p>
|
||
<p>Le <a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message à afficher en cas de succès
|
||
d'exécution de l'action. Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> sera composé à
|
||
l'aide du nom de l'objet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>disableOnSuccessMsg</code></p>
|
||
<p>Booléen permetant de désactiver le message afficher en cas de succès d'exécution de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>noConfirmation</code></p>
|
||
<p>Booléen permetant de désactiver la confirmation de l'exécution de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>redirectToObjectList</code></p>
|
||
<p>Booléen permetant de rediriger l'utilisateur vers la liste des objets plutôt que sur la fiche de
|
||
l'objet après l'execution de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>noRedirect</code></p>
|
||
<p>Booléen permetant de désactiver la redirection de l'utilisateur après l'execution de l'action.
|
||
Cela permet à la fonction de définir son propre fichier de template de retour et donc d'afficher
|
||
une page personnalisable.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>rights</code></p>
|
||
<p>Tableau contenant la liste des noms des
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a> ayant le droit d'exécuter cette
|
||
action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>accessMethods</code></p>
|
||
<p>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 : <code>web</code> pour les accès via l'interface
|
||
web et <code>api</code> pour les accès via l'API.</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-lsobject-customactions-ecriture-dune-fonction-implementant-une-customaction">Écriture d'une fonction implémentant une customAction</h2>
|
||
<p>Une fonction implémentant une <em>customAction</em> se déclare de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-customactions-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>/*
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> * Ma fonction implémentant ma customAction
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> *
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> * Paramètre :
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> * - $object : Le LSobject sur lequel mon action doit être exécutée
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> *
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> * Valeurs retournées :
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a> * - True : Tout s'est bien passé
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a> * - False : Une erreur est survenue
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a> * - Cas particulier pour une exécution via l'API : un tableau des données
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a> * à retourner. Exemple :
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a> * ["success" => true, "extra_info1" => "...", "extra_info2" => "..."]
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a> */
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a>function maFonction ($object) {
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a>
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a> // Actions
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a>
|
||
<a href="#conf-lsobject-customactions-__codelineno-1-18" id="__codelineno-1-18" name="__codelineno-1-18"></a>}
|
||
</code></pre></div>
|
||
<p>Cette fonction doit prendre pour seul paramètre, le <a href="#conf-lsobject-configuration-lsobject">LSobject</a> sur
|
||
lequel l'action personnalisée doit être exécutée et doit retourner soit <code>True</code> si tout s'est bien
|
||
passé, soit <code>False</code> en cas de problème.</p>
|
||
<p>Une <em>customAction</em> 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é
|
||
<code>success</code> 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
|
||
<code>LSsession :: get('api_mode')</code>. Vous pouvez prendre exemple sur le code de la méthode
|
||
<code>showTechInfo()</code> fournie par le LSaddon <a href="#conf-lsaddon-lsaddon_showtechinfo">showTechInfo</a>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Ces fonctions sont le plus couramment définies au sein d'
|
||
<a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a>.</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-lsrelation"><h1 id="conf-lsobject-lsrelation-les-relations-entre-les-objets-de-lannuire-lsrelation">Les relations entre les objets de l'annuire (LSrelation)</h1>
|
||
<p>Cette section décrit la manière de configurer les relations entre les
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a> appelées <em>LSrelation</em>.</p>
|
||
<p>Dans le cadre d'une liaison dîte <em>simple</em>, c'est à dire une liaison au travers la valeur d'un
|
||
attribut qui fera directement référence à un autre objet (<em>DN</em> ou la première valeur d'un attribut
|
||
de référence), pourra être configurée simplement en spécifiant l'attribut de liaison et le type de
|
||
valeur qu'il contient. Dans le cas d'une liaison plus complexe, il sera possible de développer vous
|
||
même des méthodes de mise en relation.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsrelation-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSrelation'] = array (</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> 'relation1' => array(</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> 'label' => '[label de la relation]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> 'emptyText' => "[texte affiché si aucune relation avec d'autres objets</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> n'existe pour l'objet courant]",</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x"> 'LSobject' => '[le type d'LSobjet en relation]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x"> 'display_name_format' => '[LSformat du nom d'affichage des LSobjet en relation]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x"> 'canEdit_attribute' => '[nom d'attribut]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x"> // Liaison simple</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x"> 'linkAttribute' => '[attribut de liaison]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x"> 'linkAttributeValue' => '[valeur de l'attribut de liaison]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> 'linkAttributeOtherValues' => array('[autres valeurs possible de l'attribut de liaison]', [...]),</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> // Liaison complexe</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> 'list_function' => '[méthode1]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x"> 'getkeyvalue_function' => '[methode2]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a><span class="x"> 'update_function' => '[methode3]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a><span class="x"> 'remove_function' => '[methode4]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="x"> 'rename_function' => '[methode5]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a><span class="x"> 'canEdit_function' => '[methode6]',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="x"> 'rights' => array(</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a><span class="x"> 'LSprofile1' => 'r',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="x"> 'LSprofile2' => 'w',</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a><span class="x"> )</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a><span class="x"> )</span>
|
||
<a href="#conf-lsobject-lsrelation-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label de la relation.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>emptyText</code></p>
|
||
<p>Le texte à afficher pour décrire le fait que l'objet courant n'a aucune relation d'établie avec
|
||
d'autres <a href="#conf-lsobject-configuration-lsobject">LSobjects</a>. Exemple (au sujet d'un utilisateur) :
|
||
<em>N'appartient à aucun groupe.</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSobject</code></p>
|
||
<p>Le type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation avec le type courant.
|
||
<em>(Facultatif en cas de liaison complexe)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>display_name_format</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> du nom d'affichage des objets en relation.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>canEdit_attribute</code></p>
|
||
<p>Le nom de l'attibut du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation devant être
|
||
éditable par l'utilisateur pour que celui-ci puisse modifier la relation. Dans le cadre d'une
|
||
relation simple, celui-ci peut, si nécessaire, être différent du paramètre <code>linkAttribute</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>linkAttribute</code></p>
|
||
<p>Dans le cadre d'une relation simple, il s'agit de l'attribut de liaison du type
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation avec le type courant, c'est à dire
|
||
l'attribut dans lequel on retrouve une valeur en relation avec l'objet courant.
|
||
<em>(Facultatif en cas de liaison complexe)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>linkAttributeValue</code></p>
|
||
<p>Dans le cadre d'une relation simple, il s'agit du type de valeur prisent par l'attribut de liaison
|
||
du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation avec le type courant. Il peut
|
||
s'agir du mot clé <code>dn</code> si l'attribut de liaison contient le <em>DN</em> de l'objet courant ou bien le nom
|
||
d'un attribut du type d'objet courant dont la première valeur sera stockée par l'attribut de
|
||
liaison. <em>(Facultatif en cas de liaison complexe)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>linkAttributeOtherValues</code></p>
|
||
<p>Dans le cadre d'une relation simple, il s'agit d'autres types de valeur possiblement prisent par
|
||
l'attribut en plus de celui défini par le paramètre <code>linkAttributeValue</code>. Ce paramètre ne sert
|
||
qu'a détecter des liaisons établies à l'aide de valeurs autres que celle relative au paramètre
|
||
<code>linkAttributeValue</code> : en cas de nouvelle liaison, c'est la valeur associée à ce dernier qui sera
|
||
utilisée pour établir la liaison. <em>(Facultatif en cas de liaison complexe)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>list_function</code></p>
|
||
<p>La méthode de la classe du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation,
|
||
permettant de lister les objets de ce type en relation avec l'objet courant.
|
||
<em>(Facultatif en cas de liaison simple)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>getkeyvalue_function</code></p>
|
||
<p>La méthode de la classe du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation,
|
||
permettant d'obtenir la valeur clé à stocker pour établir la relation entre l'objet courant et
|
||
d'autres objets du type concerné. <em>(Facultatif en cas de liaison simple)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>update_function</code></p>
|
||
<p>La méthode de la classe du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation,
|
||
permettant de mettre à jour les relations existantes entre l'objet courant et les objets du type
|
||
concerné. Cette liste d'objets en relation est établie par l'utilisateur à travers l'interface.
|
||
<em>(Facultatif en cas de liaison simple)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>remove_function</code></p>
|
||
<p>La méthode de la classe du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation
|
||
permettant de supprimer une relation existante entre l'objet courant et un objet du type concerné.
|
||
<em>(Facultatif en cas de liaison simple)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>rename_function</code></p>
|
||
<p>La méthode de la classe du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation
|
||
permettant d'effectuer les actions nécessaires lorsque l'objet courant est renommé dans le but
|
||
de maintenir les valeurs clés permettant d'établir les relations entre l'objet courant et les
|
||
objets en relation avec lui. <em>(Facultatif en cas de liaison simple)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>canEdit_function</code></p>
|
||
<p>La méthode de la classe du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> en relation
|
||
permettant de vérifier que l'utilisateur à le droit de modifier la relation avec un objet
|
||
en particulier. <em>(Facultatif en cas de liaison simple)</em></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>rights</code></p>
|
||
<p>Tableau associatif dont les clés sont les noms des
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a> ayant des droits sur cette
|
||
relation et dont les valeurs associées sont les droits correspondants. La valeur des droits d'un
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofile</a> peut être <code>r</code> pour le droit de
|
||
lecture ou <code>w</code> pour le droit de lecture-écriture.Par défaut, un
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofile</a> n'a aucun droit.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lsform"><h1 id="conf-lsobject-lsform-les-formulaires-lsform">Les formulaires (LSform)</h1>
|
||
<p>Cette section décrit la manière de paramétrer les formulaires d'LdapSaisie pour un type
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobject</a> donné. Pour chaque type
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a>, il faut configurer plusieurs formulaires
|
||
correspondant aux vues gérées par LdapSaisie (création, modification, ...). Les formulaires se
|
||
configurent par plusieurs biais :</p>
|
||
<ul>
|
||
<li>Via la configuration des attributs : La configuration des attributs détermine la présence ou non
|
||
des attributs dans les formulaires. Elle permet également de définir si on souhaite bloquer leur
|
||
présence en lecture seulement.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Via les droits de l'utilisateur connecté sur les attributs de l'objet à éditer : en fonction des
|
||
droits de l'utilisateur sur un attribut, celui-ci apparaîtra en lecture-écriture ou en lecture
|
||
uniquement voir pas du tout.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Via la configuration au niveau de chaque type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> : il
|
||
y est possible de définir le comportement globale du formulaire comme la validation via Ajax ou
|
||
encore la disposition logique des attributs dans le formulaire.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsform-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSform'] = array (
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> 'ajaxSubmit' => [booléen],
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'layout' => array (
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> // Configuration de la disposition logique des attributs
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> ),
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'dataEntryForm' => array (
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> // Configuration des masques de saisie
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> )
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>
|
||
<a href="#conf-lsobject-lsform-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a>);
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>ajaxSubmit</code></p>
|
||
<p>Booléen définissant si le formulaire sera envoyé via une requête Ajax plutôt qu'à travers un
|
||
rafraîchissement de la page. Par défaut : <code>True</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>layout</code></p>
|
||
<p>Tableau contenant la configuration de l'affichage du formulaire : il est possible de définir la
|
||
disposition des attributs dans le formulaire en les regroupant dans des onglets et en les
|
||
faisant apparaître dans un ordre logique.
|
||
<a href="#conf-lsobject-lsform-configuration-de-laffichage">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>dataEntryForm</code></p>
|
||
<p>Tableau contenant la configuration des masques de saisie : il est possible de définir des
|
||
masques de saisie pour faire en sorte que lors de la création d'un objet, seul un certain nombre
|
||
d'élements soit demandé à l'utilisateur.
|
||
<a href="#conf-lsobject-lsform-configuration-des-masques-de-saisie">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-lsobject-lsform-configuration-de-laffichage">Configuration de l'affichage</h2>
|
||
<p>La configuration des <em>layout</em> se situe dans la configuration des
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a>, dans la variable <code>layout</code>
|
||
(<code>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSform']['layout']</code>). Cette variable est un
|
||
tableau associatif dont la clé est l'identifiant de l'onglet et dont la valeur associée est la
|
||
configuration de l'onglet.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsform-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSform']['layout'] = array (</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> 'onglet1' => array(</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> 'label' => '[label de l'onglet]',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> 'img' => 1, // Valeur possible 1 ou 0</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> 'args' => array (</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> 'arg1',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> 'arg2',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> )</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label de l'onglet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>img</code></p>
|
||
<p>Affiche ou non l'image d'un éventuel attribut de type HTML
|
||
<a href="#conf-lsobject-lsattribute-lsattr_html-lsattr_html_image-lsattr_html_image">LSattr_html_image</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>args</code></p>
|
||
<p>Tableau associatif contenant une liste ordonnée des attributs qui apparaîtront dans l'onglet.</p>
|
||
</li>
|
||
</ul>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Lorsqu'un <em>layout</em> est défini, celui-ci est <em>"suivi à la lettre"</em> pour l'affichage du
|
||
<a href="#conf-lsobject-lsform-lsform">LSform</a>. Ainsi, si un attribut est défini dans la configuration de l'objet comme
|
||
présent dans le <a href="#conf-lsobject-lsform-lsform">LSform</a> courant, mais que celui-ci n'est pas présent dans le <em>layout</em>,
|
||
il ne sera pas du tout affiché.</p>
|
||
</div>
|
||
<h3 id="conf-lsobject-lsform-configuration-des-masques-de-saisie">Configuration des masques de saisie</h3>
|
||
<p>La configuration des masques de saisie (<em>dataEntryForm</em>) se situe dans la configuration des
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a>, dans la variable <code>dataEntryForm</code>
|
||
(<code>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSform']['dataEntryForm']</code>). Cette variable est
|
||
un tableau associatif dont la clé est l'identifiant du masque de saisie et dont la valeur associée
|
||
est sa configuration.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lsform-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a><span class="x">$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSform']['dataEntryForm'] = array (</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-2" id="__codelineno-2-2" name="__codelineno-2-2"></a><span class="x"> 'masque1' => array(</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-3" id="__codelineno-2-3" name="__codelineno-2-3"></a><span class="x"> 'label' => '[label du masque de saisie]',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-4" id="__codelineno-2-4" name="__codelineno-2-4"></a><span class="x"> 'disabledLayout' => [booleen],</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-5" id="__codelineno-2-5" name="__codelineno-2-5"></a><span class="x"> 'displayedElements' => array (</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-6" id="__codelineno-2-6" name="__codelineno-2-6"></a><span class="x"> 'attr1',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-7" id="__codelineno-2-7" name="__codelineno-2-7"></a><span class="x"> 'attr2',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-8" id="__codelineno-2-8" name="__codelineno-2-8"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-9" id="__codelineno-2-9" name="__codelineno-2-9"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-10" id="__codelineno-2-10" name="__codelineno-2-10"></a><span class="x"> 'defaultValues' => array (</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-11" id="__codelineno-2-11" name="__codelineno-2-11"></a><span class="x"> 'attr3' => [value],</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-12" id="__codelineno-2-12" name="__codelineno-2-12"></a><span class="x"> 'attr4' => [value],</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-13" id="__codelineno-2-13" name="__codelineno-2-13"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-14" id="__codelineno-2-14" name="__codelineno-2-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-15" id="__codelineno-2-15" name="__codelineno-2-15"></a><span class="x"> 'requiredAllAttributes' => [booleen],</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-16" id="__codelineno-2-16" name="__codelineno-2-16"></a><span class="x"> 'requiredAttributes' => array (</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-17" id="__codelineno-2-17" name="__codelineno-2-17"></a><span class="x"> 'attr1',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-18" id="__codelineno-2-18" name="__codelineno-2-18"></a><span class="x"> 'attr2',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-19" id="__codelineno-2-19" name="__codelineno-2-19"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-20" id="__codelineno-2-20" name="__codelineno-2-20"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-21" id="__codelineno-2-21" name="__codelineno-2-21"></a><span class="x"> 'forceGeneration' => array (</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-22" id="__codelineno-2-22" name="__codelineno-2-22"></a><span class="x"> 'attr1',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-23" id="__codelineno-2-23" name="__codelineno-2-23"></a><span class="x"> 'attr2',</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-24" id="__codelineno-2-24" name="__codelineno-2-24"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-25" id="__codelineno-2-25" name="__codelineno-2-25"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-26" id="__codelineno-2-26" name="__codelineno-2-26"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-27" id="__codelineno-2-27" name="__codelineno-2-27"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lsform-__codelineno-2-28" id="__codelineno-2-28" name="__codelineno-2-28"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label du masque de saisie.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>disabledLayout</code></p>
|
||
<p>Active ou non les <a href="#conf-lsobject-lsform-configuration-de-laffichage">layouts</a> pour ce masque de saisie.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>displayedElements</code></p>
|
||
<p>Tableau contenant la liste des attributs qui devront être saisie dans le masque de saisie.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>defaultValues</code></p>
|
||
<p>Tableau associatif contenant la liste des valeurs par défaut des attributs. Les valeurs multiples
|
||
sont possibles en utilisant des tableaux.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Les valeurs seront vue comme des valeurs retournées par le formulaire et non comme des valeurs
|
||
des attribus LDAP eux-même. Ainsi et par exemple, un attribut traité comme un booléen dans un
|
||
formulaire pourra prendre comme valeur par défaut <code>yes</code> ou <code>no</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>requiredAttributes</code></p>
|
||
<p>Tableau contenant la liste des attributs obligatoires du masque de saisie. Cette liste d'attributs
|
||
obligatoires viendra en complément de la configuration des attributs. Il est ainsi possible de
|
||
rendre des attributs obligatoires durant la saisie d'un masque tout en les laissant facultatif le
|
||
reste du temps.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>requiredAllAttributes</code></p>
|
||
<p>Si ce parametre vaut <code>True</code>, tout les attributs du masque de saisie seront tous obligatoires de la
|
||
même manière qu'avec le paramètre <code>requiredAttributes</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>forceGeneration</code></p>
|
||
<p>Tableau contenant la liste des attributs dont la génération sera forcée lors de la validation du
|
||
formation.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsobject-lssearch"><h1 id="conf-lsobject-lssearch-recherche-des-objets-dans-lannuaire-lssearch">Recherche des objets dans l'annuaire (LSsearch)</h1>
|
||
<p>Cette section décrit la manière de paramétrer les recherches dans l'annuaire pour un type
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> donné.</p>
|
||
<p>La configuration des <em>LSsearch</em> se situe dans la configuration des
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a>, dans la variable <code>LSsearch</code>
|
||
(<code>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSsearch']</code>).</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSsearch'] = array (</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> 'attrs' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> 'attr1',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> 'attr2',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x"> 'attr3' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x"> 'searchLSformat' => '[LSformat]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x"> 'approxLSformat' => '[LSformat]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x"> ...</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x"> 'params' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> // Paramètres de la recherche</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x"> 'pattern' => '[string]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> 'sizelimit' => [integer],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> 'recursive' => [boolean],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x"> 'approx' => [boolean],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a><span class="x"> 'withoutCache' => [boolean],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a><span class="x"> 'onlyAccessible' => [boolean],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="x"> // Paramètres de tri</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a><span class="x"> 'sortBy' => [displayName|subDn],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a><span class="x"> 'sortDirection' => [ASC|DESC],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="x"> 'sortlimit' => [integer],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a><span class="x"> // Paramètre d'affichage</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="x"> 'displayFormat' => [LSformat],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a><span class="x"> 'nbObjectsByPage' => [integer],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a><span class="x"> 'nbObjectsByPageChoices' => array([integer], [integer], ...),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a><span class="x"> 'validPatternRegex' => '[regex]'</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a><span class="x"> 'predefinedFilters' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a><span class="x"> 'filter1' => 'label filter1',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a><span class="x"> 'filter2' => 'label filter2'</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a><span class="x"> 'extraDisplayedColumns' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a><span class="x"> 'col1' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a><span class="x"> 'label' => 'label column 1',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a><span class="x"> 'LSformat' => '[LSformat]'</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a><span class="x"> 'col2' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a><span class="x"> 'label' => 'label column 2',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a><span class="x"> 'generateFunction' => '[fonction de génération]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a><span class="x"> 'additionalAttrs' => array('[attr1]', '[attr2]', ...),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a><span class="x"> 'escape' => [booléen],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-45" id="__codelineno-0-45" name="__codelineno-0-45"></a><span class="x"> 'col3' => array(</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-46" id="__codelineno-0-46" name="__codelineno-0-46"></a><span class="x"> 'label' => 'label column 3',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-47" id="__codelineno-0-47" name="__codelineno-0-47"></a><span class="x"> 'LSformat' => '[LSformat]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-48" id="__codelineno-0-48" name="__codelineno-0-48"></a><span class="x"> 'alternativeLSformats' => array (</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-49" id="__codelineno-0-49" name="__codelineno-0-49"></a><span class="x"> '[LSformat 1]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-50" id="__codelineno-0-50" name="__codelineno-0-50"></a><span class="x"> '[LSformat 2]'</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-51" id="__codelineno-0-51" name="__codelineno-0-51"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-52" id="__codelineno-0-52" name="__codelineno-0-52"></a><span class="x"> 'formaterLSformat' => '[LSformat]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-53" id="__codelineno-0-53" name="__codelineno-0-53"></a><span class="x"> 'formaterFunction' => '[fonction de formatage]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-54" id="__codelineno-0-54" name="__codelineno-0-54"></a><span class="x"> 'cssStyle' => '[CSS style]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-55" id="__codelineno-0-55" name="__codelineno-0-55"></a><span class="x"> 'visibleTo' => array (</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-56" id="__codelineno-0-56" name="__codelineno-0-56"></a><span class="x"> '[LSprofile 1]',</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-57" id="__codelineno-0-57" name="__codelineno-0-57"></a><span class="x"> '[LSprofile 2]'</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-58" id="__codelineno-0-58" name="__codelineno-0-58"></a><span class="x"> )</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-59" id="__codelineno-0-59" name="__codelineno-0-59"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-60" id="__codelineno-0-60" name="__codelineno-0-60"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-61" id="__codelineno-0-61" name="__codelineno-0-61"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-62" id="__codelineno-0-62" name="__codelineno-0-62"></a><span class="x"> // Configuration des customActions pour les recherches de ce type d'objet</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-63" id="__codelineno-0-63" name="__codelineno-0-63"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-64" id="__codelineno-0-64" name="__codelineno-0-64"></a><span class="x"> 'showSelectionBoxes' => [boolean],</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-0-65" id="__codelineno-0-65" name="__codelineno-0-65"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>attrs</code></p>
|
||
<p>Tableau listant les attributs pouvant être utilisés dans les filtres de recherche LDAP employés
|
||
par LdapSaisie. Lorsqu'un motif de recherche est passé par l'utilisateur, LdapSaisie composera un
|
||
filtre LDAP à partir de cette liste.</p>
|
||
<p>Lors d'une recherche non-approximative, le filtre de recherche sera composé (par défaut) de la
|
||
manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>(|(attr1=*motif*)(attr2=*motif*)...)
|
||
</code></pre></div>
|
||
<p>Lors d'une recherche approximative, le filtre de recherche sera composé (par défaut) de la manière
|
||
suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>(|(attr1=~motif)(attr2~=motif)...)
|
||
</code></pre></div>
|
||
<p>Il est également possible de paramétrer la manière dont sera composé le filtre de recherche
|
||
attribut par attribut à l'aide des paramètres <code>searchLSformat</code> et <code>approxLSformat</code>.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Ces filtres, une fois composés, sont insérés dans un autre, filtrant en plus sur les
|
||
<em>ObjectClass</em> du type d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a>(& (&(objectclass=oc1)(objectclass=oc2)) (filtre) )
|
||
</code></pre></div>
|
||
</div>
|
||
<ul>
|
||
<li>
|
||
<p><code>searchLSformat</code></p>
|
||
<p>Ce paramètre est un <a href="#conf-global-lsformat-format-parametrable">LSformat</a> permettant de définir,
|
||
attribut par attribut, comment le filtre de recherche LDAP est composé à partir d'un motif de
|
||
recherche et en cas de recherche non-approximative.</p>
|
||
<p>Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> est composé à l'aide des éléments
|
||
<code>name</code>, le nom de l'attribut et <code>pattern</code>, le motif de recherche.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-4-1" id="__codelineno-4-1" name="__codelineno-4-1"></a>(%{name}=%{pattern})
|
||
</code></pre></div>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Le filtre déduit doit obligatoirement commencer par <code>(</code> et se terminer par <code>)</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>approxLSformat</code></p>
|
||
<p>Ce paramètre est un <a href="#conf-global-lsformat-format-parametrable">LSformat</a> permettant de définir,
|
||
attribut par attribut, comment le filtre de recherche LDAP est composé à partir d'un motif de
|
||
recherche et en cas de recherche approximative.</p>
|
||
<p>Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> est composé à l'aide des éléments
|
||
<code>name</code>, le nom de l'attribut et <code>pattern</code>, le motif de recherche.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-5-1" id="__codelineno-5-1" name="__codelineno-5-1"></a>(%{name}=~%{pattern})
|
||
</code></pre></div>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Le filtre déduit doit obligatoirement commencer par <code>(</code> et se terminer par <code>)</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>params</code></p>
|
||
<p>Tableau des paramètres par défaut d'une recherche. Ce tableau contient les paramètres qui seront
|
||
utilisés pour initialisé une recherche. Ces paramètres pourront être redéfini par l'utilisateur
|
||
ou par l'application en fonction du contexte dans lequel cette recherche est effectuée.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>pattern</code></p>
|
||
<p>Mot clé de la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sizelimit</code></p>
|
||
<p>Entier determinant le nombre maximum d'objet pouvant être retournés dans une recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>recursive</code></p>
|
||
<p>Booléen déterminant si la recherche récursive est activée.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>approx</code></p>
|
||
<p>Booléen déterminant si la recherche approximative est activée.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>withoutCache</code></p>
|
||
<p>Booléen déterminant si le cache de recherche doit être utilisé.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>onlyAccessible</code></p>
|
||
<p>Booléen déterminant si seul les objets accessibles à l'utilisateur connecté doivent être
|
||
retournés par la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sortBy</code></p>
|
||
<p>Mot clé déterminant sur quel valeur/colonne le résultat de recherche sera trié.</p>
|
||
<p>Valeurs possibles : <code>displayName</code>, <code>subDn</code> ou <code>NULL</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sortDirection</code></p>
|
||
<p>Mot clé déterminant le sens du trie du résultat de la recherche.</p>
|
||
<p>Valeurs possibles : <code>ASC</code>, <code>DESC</code> ou <code>NULL</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sortlimit</code></p>
|
||
<p>Entier determinant le nombre maximum d'objet pouvant être triés dans le résultat d'une
|
||
recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>displayFormat</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> d'affichage du nom de l'objet dans le
|
||
résultat de la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>nbObjectsByPage</code></p>
|
||
<p>Entier déterminant le nombre d'objet maximum affichés dans une page de résultat de la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>nbObjectsByPageChoices</code></p>
|
||
<p>Tableau des choix proposés à l'utilisateur pour le nombre d'objets maximum affichés dans une
|
||
page de résultat de la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>validPatternRegex</code></p>
|
||
<p>Expression régulière de validation des mots clés de recherche pour ce type
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a>.</p>
|
||
<p>(Par défaut : <code>/^[\w\-_\\\'\"^[]\(\){}\=\+\£\%\$\€\.\:\;\,\?\/\@]+$/iu</code>)</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>predefinedFilters</code></p>
|
||
<p>Tableau associatif contenant des filtres prédéfinis pour la recherche. Les clés sont les filtres
|
||
au format LDAP et les valeurs sont les labels associés.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>extraDisplayedColumns</code></p>
|
||
<p>Tableau associatif contenant des colonnes supplémentaires à afficher dans les résultats de
|
||
recherche. Les clés sont les identifiants des colonnes supplémentaires et les valeurs sont leur
|
||
configuration définie à partir des paramètres suivant :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label de la colonne.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSformat</code></p>
|
||
<p>Le <a href="#conf-global-lsformat-format-parametrable">LSformat</a> d'affichage de la colonne. Ce format
|
||
est composé à partir des attributs des objets LDAP dans leur format brut.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>alternativeLSformats</code></p>
|
||
<p>Tableau des <a href="#conf-global-lsformat-format-parametrable">LSformats</a> alternatifs à utiliser si le
|
||
résultat du format principal est vide. Les formats définis dans cette liste sont essayés les uns
|
||
après les autres et le premier <a href="#conf-global-lsformat-format-parametrable">LSformat</a> retournant
|
||
une valeur non-vide est utilisé.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>formaterLSformat</code></p>
|
||
<p><a href="#conf-global-lsformat-format-parametrable">LSformat</a> optionnel permettant de mettre en forme le
|
||
résultat obtenu des <a href="#conf-global-lsformat-format-parametrable">LSformats</a> précédents. Ce
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> ne sera utilisé que si le résultat obtenu
|
||
précédement n'est pas vide. Il est ainsi possible d'utiliser les paramètres <code>LSformat</code> et
|
||
<code>alternativeLSformats</code> afin de récupérer la valeur à afficher, puis de la mettre en forme grâce
|
||
à ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a>. Ce format est composé à partir des
|
||
attributs des objets LDAP dans leur format brut et de la valeur retournés précedement accessible
|
||
via la variable <code>val</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>formaterFunction</code></p>
|
||
<p>Le nom d'une fonction optionnelle à exécuter pour mettre en forme le résultat obtenu des
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformats</a> précédents. Cette fonction ne sera
|
||
appelée que si le résultat obtenu précédement n'est pas vide. La fonction prendra en paramètre
|
||
la valeur à mettre en forme et retournera la valeur mise en forme.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>generateFunction</code></p>
|
||
<p>Le nom d'une fonction qui sera utilisée pour générer la valeur d'affichage de cette colonne. La
|
||
fonction prendra en paramètre une référence de l'objet <code>LSsearchEntry</code> et retournera la valeur
|
||
de la colonne.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>additionalAttrs</code></p>
|
||
<p>Un tableau de nom d'attributs à inclure dans le resultat de la recherche LDAP. Ce tableau permet
|
||
notamment d'inclure les attributs nécessaires au bon fonctionnement de la fonction
|
||
<code>generateFunction</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>escape</code></p>
|
||
<p>Ce paramètre booléen permet de définir si, lors de l'affichage, le contenu de la colonne doit
|
||
être transformé pour protéger les caractères éligibles en entités HTML. Par défaut, ce paramètre
|
||
est <code>True</code>.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Cette fonctionnalité existe pour des raisons de sécurité et notamment en protection des
|
||
failles <code>XSS</code>. Si vous désactivez cette fonctionnalité, il est important de gérer la
|
||
problématique de sécurité par ailleurs.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>cssStyle</code></p>
|
||
<p>Ce paramètre permet de définir un style CSS personnalisé pour la colonne. S'il est défini, le
|
||
contenu de ce paramètre sera ajouté en tant qu'attribut <code>style</code> des balises <code>th</code> et <code>td</code> de la
|
||
colone.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>visibleTo</code></p>
|
||
<p>Ce paramètre permet de restreindre la visibilité de cette colonne aux seuls
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a> spécifiés. S'il est omis, la
|
||
colonne sera visible pour tous.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>customActions</code></p>
|
||
<p>Tableau associatif contenant les paramètres de configuration des
|
||
<a href="#conf-lsobject-lssearch-customactions">customActions</a>. <a href="#conf-lsobject-lssearch-customactions">Voir la section concernée</a>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>showSelectionBoxes</code></p>
|
||
<p>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 <a href="#conf-lsobject-lssearch-customsactions">customAction</a>. Dans ce cas, les DNs de ces
|
||
objets seront passés à la page d'exécution de la <a href="#conf-lsobject-lssearch-customsactions">customAction</a> via le paramètre
|
||
<code>selected</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-lsobject-lssearch-les-actions-personnalisees-customactions">Les actions personnalisées (customActions)</h2>
|
||
<p>Cette section décrit la manière de configurer les actions personnalisées exécutables sur les
|
||
recherches d'<a href="#conf-lsobject-configuration-lsobject">LSobjects</a> appelées <a href="#conf-lsobject-lssearch-customactions">customActions</a>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-6-1" id="__codelineno-6-1" name="__codelineno-6-1"></a>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['LSsearch']['customActions'] = array (
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-2" id="__codelineno-6-2" name="__codelineno-6-2"></a> 'action1' => array(
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-3" id="__codelineno-6-3" name="__codelineno-6-3"></a> 'label' => '[label l'action]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-4" id="__codelineno-6-4" name="__codelineno-6-4"></a> 'hideLabel' => '[booléen]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-5" id="__codelineno-6-5" name="__codelineno-6-5"></a> 'icon' => '[nom de l'icône de l'action]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-6" id="__codelineno-6-6" name="__codelineno-6-6"></a> 'function' => '[fonction à exécuter]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-7" id="__codelineno-6-7" name="__codelineno-6-7"></a> 'question_format' => '[LSformat de la question de confirmation]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-8" id="__codelineno-6-8" name="__codelineno-6-8"></a> 'onSuccessMsgFormat' => '[LSformat du message à afficher en cas de succès de l'action]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-9" id="__codelineno-6-9" name="__codelineno-6-9"></a> 'disableOnSuccessMsg' => '[booléen]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-10" id="__codelineno-6-10" name="__codelineno-6-10"></a> 'noConfirmation' => '[booléen]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-11" id="__codelineno-6-11" name="__codelineno-6-11"></a> 'redirectToObjectList' => '[booléen]',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-12" id="__codelineno-6-12" name="__codelineno-6-12"></a> 'rights' => array(
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-13" id="__codelineno-6-13" name="__codelineno-6-13"></a> 'LSprofile1',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-14" id="__codelineno-6-14" name="__codelineno-6-14"></a> 'LSprofile2',
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-15" id="__codelineno-6-15" name="__codelineno-6-15"></a> ...
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-16" id="__codelineno-6-16" name="__codelineno-6-16"></a> )
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-17" id="__codelineno-6-17" name="__codelineno-6-17"></a> )
|
||
<a href="#conf-lsobject-lssearch-__codelineno-6-18" id="__codelineno-6-18" name="__codelineno-6-18"></a>);
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>hideLabel</code></p>
|
||
<p>Cache le label dans le bouton de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>icon</code></p>
|
||
<p>Nom de l'îcone à afficher dans le bouton de l'action. Ce nom correspond au nom du fichier de
|
||
l'image (sans l'extention) qui devra se trouver dans le dossier
|
||
<code>/src/images/[nom du theme d'images]/</code> ou dans le dossier <code>src/local/images</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>function</code></p>
|
||
<p>Le nom de la fonction à exécuter qui implémente l'action personnalisée Cette fonction prendra en
|
||
seule paramètre l'objet <a href="#conf-lsobject-lssearch-lssearch">LSsearch</a>. sur lequel l'action devra être exécutée et
|
||
retournera <code>True</code> en cas de succès ou <code>False</code> en cas d'échec d'exécution de la fonction.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>question_format</code></p>
|
||
<p>Le <a href="#conf-global-lsformat-format-parametrable">LSformat</a> de la question de confirmation
|
||
d'exécution de l'action. Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> sera composé à
|
||
l'aide du label de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>onSuccessMsgFormat</code></p>
|
||
<p>Le <a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message à afficher en cas de succès
|
||
d'exécution de l'action. Ce <a href="#conf-global-lsformat-format-parametrable">LSformat</a> sera composé à
|
||
l'aide du label de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>disableOnSuccessMsg</code></p>
|
||
<p>Booléen permetant de désactiver le message afficher en cas de succès d'exécution de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>noConfirmation</code></p>
|
||
<p>Booléen permetant de désactiver la confirmation de l'exécution de l'action.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>redirectToObjectList</code></p>
|
||
<p>Booléen permetant de rediriger ou non l'utilisateur vers la liste des objets (Vrai par défaut).
|
||
Si l'utilisateur n'est redirigé, le template par défaut (ou celui défini durant l'éxécution de la
|
||
fonction) sera affiché.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>rights</code></p>
|
||
<p>Tableau contenant la liste des noms des <a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a>
|
||
ayant le droit d'exécuter cette action.</p>
|
||
</li>
|
||
</ul>
|
||
<h3 id="conf-lsobject-lssearch-ecriture-dune-fonction-implementant-une-customaction">Écriture d'une fonction implémentant une customAction</h3>
|
||
<p>Une fonction implémentant une <em>customAction</em> se déclare de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-7-1" id="__codelineno-7-1" name="__codelineno-7-1"></a><span class="x">/*</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-2" id="__codelineno-7-2" name="__codelineno-7-2"></a><span class="x"> * Ma fonction implémentant ma customAction</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-3" id="__codelineno-7-3" name="__codelineno-7-3"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-4" id="__codelineno-7-4" name="__codelineno-7-4"></a><span class="x"> * Paramètre :</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-5" id="__codelineno-7-5" name="__codelineno-7-5"></a><span class="x"> * - $search : L'objet LSsearch de la recherche sur lequel mon action doit être exécutée</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-6" id="__codelineno-7-6" name="__codelineno-7-6"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-7" id="__codelineno-7-7" name="__codelineno-7-7"></a><span class="x"> * Valeurs retournées :</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-8" id="__codelineno-7-8" name="__codelineno-7-8"></a><span class="x"> * - True : Tout s'est bien passé</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-9" id="__codelineno-7-9" name="__codelineno-7-9"></a><span class="x"> * - False : Une erreur est survenue</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-10" id="__codelineno-7-10" name="__codelineno-7-10"></a><span class="x"> */</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-11" id="__codelineno-7-11" name="__codelineno-7-11"></a><span class="x">function maFonction ($search) {</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-12" id="__codelineno-7-12" name="__codelineno-7-12"></a>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-13" id="__codelineno-7-13" name="__codelineno-7-13"></a><span class="x"> // Actions</span>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-14" id="__codelineno-7-14" name="__codelineno-7-14"></a>
|
||
<a href="#conf-lsobject-lssearch-__codelineno-7-15" id="__codelineno-7-15" name="__codelineno-7-15"></a><span class="x">}</span>
|
||
</code></pre></div>
|
||
<p>Cette fonction doit prendre pour seul paramètre, l'objet <a href="#conf-lsobject-lssearch-lssearch">LSsearch</a>. sur lequel l'action
|
||
personnalisée doit être exécutée et doit retourner soit <code>True</code> si tout s'est bien passé, soit
|
||
<code>False</code> en cas de problème.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>La recherche passée en paramètre n'a pas encore été exécutée. En conséquence, si vous avez
|
||
besoin d'accéder au résultat de la recherche, il est nécessaire d'exécuter au préalable :
|
||
<code>$search -> run();</code>. Cela permet en outre, de modifier les paramètres de la recherche avant de
|
||
l'exécuter. Cela peut par exemple être utile, si vous avez besoin d'accèder aux valeurs
|
||
d'attributs particuliers, d'ajouter des attributs au résultat de la recherche :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-lssearch-__codelineno-8-1" id="__codelineno-8-1" name="__codelineno-8-1"></a><span class="x">$search -> setParam('attributes',array('attr1','attr2'));</span>
|
||
</code></pre></div>
|
||
</div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Ces fonctions sont le plus couramment définies au sein
|
||
d'<a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a>.</p>
|
||
</div></section><section class="print-page" id="conf-lsobject-ioformat"><h1 id="conf-lsobject-ioformat-les-formats-dimportexport-ioformat">Les formats d'import/export (ioFormat)</h1>
|
||
<p>Cette section décrit la manière de paramétrer les formats d'import/export pour un type d'
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobject</a> donné.</p>
|
||
<p>La configuration des <em>ioFormats</em> se situe dans la configuration des
|
||
<a href="#conf-lsobject-configuration-lsobject">LSobjects</a>, dans la variable <code>ioFormat</code>
|
||
(<code>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['ioFormat']</code>). Cette variable est un tableau
|
||
associatif dont la clé est l'identifiant du format et dont la valeur associée est la configuration
|
||
du format.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Le moteur d'importation simule la validation d'un formulaire de création du type
|
||
d'<a href="#conf-lsobject-configuration-lsobject">LSobject</a> (ou de modification en cas d'activation du mode
|
||
mise à jour uniquement, voir ci-dessous). En conséquence :</p>
|
||
<ul>
|
||
<li>seul les attributs présent dans le formulaire de création peuvent être importés.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>tous les attributs obligatoires présents dans le formulaire de création doivent être fournis
|
||
par le fichier source ou générer à partir des autres attributs.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Les valeurs des attributs issus de l'importation seront vue comme des valeurs retournées par
|
||
le formulaire et non comme des valeurs des attribus LDAP eux-même. Ainsi et par exemple, un
|
||
attribut traité comme un booléen dans un formulaire pourra prendre comme valeur par
|
||
défaut <code>yes</code> ou <code>no</code>.</li>
|
||
</ul>
|
||
</div>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-ioformat-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['ioFormat'] = array (
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> '[ioFormat ID]' => array (
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'label' => '[Label du type de fichier]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> 'driver' => '[Pilote d'ioFormat utilisé]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'driver_options' => array([Options du pilote d'ioFormat utilisé]),
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'update_only' => '[Booléen]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'fields => array (
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> '[champ 1]' => '[attribut 1]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> '[champ 2]' => '[attribut 2]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> [...]
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> ),
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> 'generated_fields' => array (
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> '[attribute 3]' => '[LSformat]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> '[attribute 4]' => array('[LSformat1]', '[LSformat2]', ...)
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> '[attribute 5]' => function($attrs, $row) {
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> return array([...]);
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> },
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> [...]
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> ),
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> 'before_import' => array('function1', 'function2'),
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> 'after_import' => 'function3',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> ),
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> [...]
|
||
<a href="#conf-lsobject-ioformat-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a>);
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>label</code></p>
|
||
<p>Le label du format</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>driver</code></p>
|
||
<p>Le pilote a utilisé pour ce format. Le pilote permet de gérér la lecture et l'écriture dans un
|
||
type de fichier d'import/export. Pour plus d'information sur les pilotes disponibles,
|
||
<a href="#conf-lsobject-ioformat-pilote-dioformat">Voir la section concernée.</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>driver_options</code></p>
|
||
<p>Tableau associatif des options du pilote utilisé pour ce format. Pour plus d'informations,
|
||
consulter la documentation du pilote utilisé.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>update_only</code></p>
|
||
<p>Booléen permettant d'activer le mode mise à jour uniquement pour ce format. Dans ce mode, les
|
||
données de l'objet LDAP correspondant seront chargées depuis l'annuaire avant toutes validations
|
||
des données fournies dans le fichier d'import, et ce, dans un formulaire de modifications et non
|
||
pas un formulaire de création autrement. Pour que cela soit possible, il est indispensable que le
|
||
DN de l'objet puisse être déduit depuis les données fournies dans le fichier d'import. Pour cela,
|
||
vous pouvez le fournir via un champ du fichier d'import associé à la clé <code>dn</code> ou à défaut il sera
|
||
généré à partir du RDN dont la valeur devra être fournie dans le fichier d'import. Vous pouvez
|
||
également le générer via le paramètre <code>generated_fields</code> (voir ci-dessous).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>fields</code></p>
|
||
<p>Tableau associatif permettant d'associer un champ du fichier source (la clé) avec attribut de
|
||
l'objet LDAP (la valeur). Il est également possible d'associé un champ avec la valeur <code>dn</code> pour
|
||
fournir le DN de l'objet en mode mise à jour uniquement (voir ci-dessus).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>generated_fields</code></p>
|
||
<p>Tableau associatif permettant de définir soit des
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformats</a>, soit un <em>callable</em> (au sens PHP) pour
|
||
générer les valeurs d'attributs automatiquement. Ce tableau contient en clé, le nom de l'attribut
|
||
à générer (ou <code>dn</code> pour la génération du DN de l'objet en mode mise à jour uniquement), et en
|
||
valeur associée, un ou plusieurs <a href="#conf-global-lsformat-format-parametrable">LSformat</a> ou un
|
||
<em>callable</em> à utiliser pour générer ses valeurs.
|
||
En cas de <a href="#conf-global-lsformat-format-parametrable">LSformat</a>, ils seront composés à l'aide des
|
||
valeurs des autres attributs de l'objet. En cas d'un <em>callable</em>, il sera appeler avec en paramètre
|
||
le tableau des valeurs des autres attributs (<code>$attrs</code>), le tableau des données issues du fichier
|
||
source (<code>$row</code>) et devra retourner le tableau des valeurs générées de l'attribut ou <code>false</code> en cas
|
||
d'erreur.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>before_import</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaîne de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées avant chaque import. <a href="#conf-lsobject-ioformat-declencheurs">Voir la section concernée</a></p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>after_import</code></p>
|
||
<p>Chaîne de caractères (ou tableau de chaîne de caractères) correspondant au nom d'une ou plusieurs
|
||
fonctions qui seront exécutées après chaque import. <a href="#conf-lsobject-ioformat-declencheurs">Voir la section concernée</a></p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-lsobject-ioformat-pilote-dioformat">Pilote d'ioFormat</h2>
|
||
<p>Cette section décrit la manière de configurer les pilotes d'ioFormat utilisés lors des
|
||
imports/exports d'<a href="#conf-lsobject-configuration-lsobject">LSobjects</a>.</p>
|
||
<h3 id="conf-lsobject-ioformat-pilote-de-fichiers-csv">Pilote de fichiers CSV</h3>
|
||
<p>Ce pilote permet de gérer l'import/export de <a href="#conf-lsobject-configuration-lsobject">LSobject</a> à partir
|
||
d'un fichier <code>CSV</code>. Depuis la version 4 d'LdapSaisie, ce pilote utilise les fonctions standards
|
||
<code>fgetcsv()</code> et <code>fputcsv</code> fournis par PHP. Avant cela, la classe PEAR
|
||
<a href="http://pear.php.net/package/File_CSV_DataSource">File_CSV_DataSource</a> était utilisée. Par défaut,
|
||
les paramètres de lecture et d'écriture des fichiers sont : la virgule sert de délimiteur, le
|
||
caractère <code>"</code> peut être utilisé pour encadrer les valeurs des champs et la longueur maximale d'une
|
||
ligne est infini. Ces paramètres peuvent être modifiés en configurant les options du pilote.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-ioformat-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>$GLOBALS['LSobjects']['[nom du type d'LSobject]']['ioFormat']['[ID ioFormat]']['driver_options'] = array (
|
||
<a href="#conf-lsobject-ioformat-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> 'delimiter' => '[délimiteur]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> 'enclosure' => '[caractère d'encadrement de texte]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> 'length' => [longueur maximale d'une ligne],
|
||
<a href="#conf-lsobject-ioformat-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> 'escape' => '[caractère d'échappement]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> 'multiple_value_delimiter' => '[délimiteur]',
|
||
<a href="#conf-lsobject-ioformat-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a>);
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>delimiter</code></p>
|
||
<p>Le caractère utilisé pour délimiter les champs (Par défaut, une virgule).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>length</code></p>
|
||
<p>La longueur maximale d'une ligne du fichier. Si zéro est spécifié, la longueur d'une ligne ne sera
|
||
pas limité, mais la lecture du fichier sera ralentie. (Par défaut : <code>0</code>)</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>enclosure</code></p>
|
||
<p>Le caractère utilisé pour encadrer les valeurs des champs (Par défaut : <code>"</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>escape</code></p>
|
||
<p>Le caractère d'échappement utilisé si un des champs d'une ligne de fichier contient le caractère
|
||
utilisé pour encadrer les valeurs. (Par défaut : <code>\</code>).</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Selon la RFC4180, l'echappement du caractère utilisé pour encadrer les valeurs des champs doit
|
||
se faire en le doublant. Le caractère défini ici est une alternative à ce comportement par
|
||
défaut. Pour désactiver ce caractère d'échappement alternatif, il est possible depuis de la
|
||
version 7.4.0 de PHP de mettre ici une chaine vide.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>multiple_value_delimiter</code></p>
|
||
<p>Le caractère utilisé pour délimiter au sein d'un champs, les valeurs valeurs multiples d'un
|
||
attribut (Par défaut : <code>|</code>).</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="conf-lsobject-ioformat-declencheurs">Déclencheurs</h2>
|
||
<p>Cette section décrit la manière de paramétrer des déclencheurs afin que LdapSaisie exécute durant
|
||
ses processus, et à des moments bien précis des traitements d'un <a href="#conf-lsobject-ioformat-ioformat">ioFormat</a>, des
|
||
fonctions que vous pourrez développer vous même. De plus, le résultat de l'exécution de vos
|
||
fonctions pourra influer sur le déroulement des processus.</p>
|
||
<p>Actuellement, les évenements suivant sont gérés :</p>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>Nom</th>
|
||
<th>Description</th>
|
||
<th>Bloquant</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<td><code>before_import</code></td>
|
||
<td>Avant l'import.</td>
|
||
<td>Oui</td>
|
||
</tr>
|
||
<tr>
|
||
<td><code>after_import</code></td>
|
||
<td>Après l'import'.</td>
|
||
<td>Non</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Si un événement est dit <em>bloquant</em>, lors de l'exécution des actions liées, si une des fonctions
|
||
retourne <code>false</code>, le processus s'arrêtera.</p>
|
||
</div>
|
||
<h3 id="conf-lsobject-ioformat-configuration">Configuration</h3>
|
||
<p>La configuration des déclencheurs se fait dans la définition des types d'<a href="#conf-lsobject-ioformat-ioformat">ioFormat</a>. Par
|
||
exemple, pour définir les fonctions à exécuter après l'import des LSobjects de type <em>LSpeople</em> avec
|
||
son LSioFormat <em>mycsv</em>, c'est à dire lors de leur évènement <code>after_import</code>, il faut définir la
|
||
variable suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-ioformat-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople']['ioFormat']['mycsv']['after_import']</span>
|
||
</code></pre></div>
|
||
<p>Cette variable peut contenir soit une chaine de caractères correspondant au nom de la fonction à
|
||
exécuter, soit un tableau de chaînes de caractères correspondant aux noms des fonctions à exécuter.
|
||
Il est également possible de mettre ici directement des
|
||
<a href="https://www.php.net/manual/fr/functions.anonymous.php">fonctions anonymes</a>.</p>
|
||
<h3 id="conf-lsobject-ioformat-ecriture-dune-fonction">Ecriture d'une fonction</h3>
|
||
<p>Une fonction exécutée par un déclencheur d'un ioFormat se déclare de la manière suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-ioformat-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a><span class="x">/*</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-2" id="__codelineno-3-2" name="__codelineno-3-2"></a><span class="x"> * Ma fonction à exécuter lors de l'evenement [event]</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-3" id="__codelineno-3-3" name="__codelineno-3-3"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-4" id="__codelineno-3-4" name="__codelineno-3-4"></a><span class="x"> * Paramètres :</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-5" id="__codelineno-3-5" name="__codelineno-3-5"></a><span class="x"> * - $ioFormat : Le LSioFormat sur lequel l'évènement survient</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-6" id="__codelineno-3-6" name="__codelineno-3-6"></a><span class="x"> * - $data : Les données de contexte de l'évènement</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-7" id="__codelineno-3-7" name="__codelineno-3-7"></a><span class="x"> *</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-8" id="__codelineno-3-8" name="__codelineno-3-8"></a><span class="x"> * Valeurs retournées :</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-9" id="__codelineno-3-9" name="__codelineno-3-9"></a><span class="x"> * - True : Tout s'est bien passé</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-10" id="__codelineno-3-10" name="__codelineno-3-10"></a><span class="x"> * - False : Une erreur est survenue ou la fonction souhaite bloquer le</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-11" id="__codelineno-3-11" name="__codelineno-3-11"></a><span class="x"> * processus lors d'un évènement bloquant.</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-12" id="__codelineno-3-12" name="__codelineno-3-12"></a><span class="x"> */</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-13" id="__codelineno-3-13" name="__codelineno-3-13"></a><span class="x">function maFonction (&$ioFormat, &$data) {</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-14" id="__codelineno-3-14" name="__codelineno-3-14"></a>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-15" id="__codelineno-3-15" name="__codelineno-3-15"></a><span class="x"> // Actions</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-16" id="__codelineno-3-16" name="__codelineno-3-16"></a>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-3-17" id="__codelineno-3-17" name="__codelineno-3-17"></a><span class="x">}</span>
|
||
</code></pre></div>
|
||
<p>Cette fonction doit accepter deux paramètres, le LSioFormat sur lequel l'évènement survient et un
|
||
tableau des données contextuelles de l'évènement. Elle doit par ailleurs retourner <code>True</code> si tout
|
||
s'est bien passé ou <code>False</code> en cas de problème. Dans le cas d'un événement bloquant, si la fonction
|
||
retourne <code>False</code>, le processus est arrêté.</p>
|
||
<p>Les données contextuelles de l'évènement, passées en paramètre, pourront dépendre du contexte et de
|
||
l'évènement déclencheur, mais pour les moments, il s'agit toujours d'un tableau telque décrit
|
||
ci-dessous :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsobject-ioformat-__codelineno-4-1" id="__codelineno-4-1" name="__codelineno-4-1"></a><span class="x">array(</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-2" id="__codelineno-4-2" name="__codelineno-4-2"></a><span class="x"> 'input_file' => "[/path/of/import.file]",</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-3" id="__codelineno-4-3" name="__codelineno-4-3"></a><span class="x"> 'updateIfExists' => [boolean],</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-4" id="__codelineno-4-4" name="__codelineno-4-4"></a><span class="x"> 'justTry' => [boolean],</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-5" id="__codelineno-4-5" name="__codelineno-4-5"></a><span class="x"> 'objectsData' => array(</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-6" id="__codelineno-4-6" name="__codelineno-4-6"></a><span class="x"> [Données des objets chargés depuis le fichier d'import]</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-7" id="__codelineno-4-7" name="__codelineno-4-7"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-8" id="__codelineno-4-8" name="__codelineno-4-8"></a><span class="x"> 'return' => array(</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-9" id="__codelineno-4-9" name="__codelineno-4-9"></a><span class="x"> 'success' => [boolean],</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-10" id="__codelineno-4-10" name="__codelineno-4-10"></a><span class="x"> 'LSobject' => "[nom du type d'LSobject]",</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-11" id="__codelineno-4-11" name="__codelineno-4-11"></a><span class="x"> 'ioFormat' => "[nom du type d'ioFormat]",</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-12" id="__codelineno-4-12" name="__codelineno-4-12"></a><span class="x"> 'updateIfExists' => [boolean],</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-13" id="__codelineno-4-13" name="__codelineno-4-13"></a><span class="x"> 'justTry' => [boolean],</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-14" id="__codelineno-4-14" name="__codelineno-4-14"></a><span class="x"> 'imported' => array([objets importés]),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-15" id="__codelineno-4-15" name="__codelineno-4-15"></a><span class="x"> 'updated' => array([objets mis à jour]),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-16" id="__codelineno-4-16" name="__codelineno-4-16"></a><span class="x"> 'errors' => array(</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-17" id="__codelineno-4-17" name="__codelineno-4-17"></a><span class="x"> array(</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-18" id="__codelineno-4-18" name="__codelineno-4-18"></a><span class="x"> 'data' => [données de l'objet importé ayant déclenché l'erreur],</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-19" id="__codelineno-4-19" name="__codelineno-4-19"></a><span class="x"> 'errors' => array (</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-20" id="__codelineno-4-20" name="__codelineno-4-20"></a><span class="x"> 'globals' => array("Erreur 1", [...]),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-21" id="__codelineno-4-21" name="__codelineno-4-21"></a><span class="x"> 'attrs' => array(</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-22" id="__codelineno-4-22" name="__codelineno-4-22"></a><span class="x"> 'attr1' => array("Erreur 1", [...]),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-23" id="__codelineno-4-23" name="__codelineno-4-23"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-24" id="__codelineno-4-24" name="__codelineno-4-24"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-25" id="__codelineno-4-25" name="__codelineno-4-25"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-26" id="__codelineno-4-26" name="__codelineno-4-26"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-27" id="__codelineno-4-27" name="__codelineno-4-27"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-28" id="__codelineno-4-28" name="__codelineno-4-28"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-29" id="__codelineno-4-29" name="__codelineno-4-29"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsobject-ioformat-__codelineno-4-30" id="__codelineno-4-30" name="__codelineno-4-30"></a><span class="x">)</span>
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Les clés <code>objectsData</code> et <code>return</code> sont des références. En cas de modification, cela influencera
|
||
respectivement sur les données utilisées pour l'import et sur le résultat de l'import tel
|
||
qu'affiché dans l'interface.</p>
|
||
</div></section><h1 class="nav-section-title-end">Ended: Objets de l'annuaire</h1><h2 class="nav-section-title">Configuration des addons (LSaddons)</h2><section class="print-page" id="conf-lsaddon"><h1 id="conf-lsaddon-configuration-des-lsaddons">Configuration des LSaddons</h1>
|
||
<p>Cette partie décrit la manière de configurer les différents LSaddons actuellement supportés par
|
||
LdapSaisie. Ces addons peuvent avoir un fichier de configuration et il sera alors stocké dans le
|
||
dossier <code>conf/LSaddons/</code> et potera le nom <code>config.LSaddons.[addon name].php</code>.</p></section><section class="print-page" id="conf-lsaddon-lsaddon_accesslog"><h1 id="conf-lsaddon-lsaddon_accesslog-lsaddon_accesslog">LSaddon_accesslog</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fournit la fonction <code>showObjectAccessLogs()</code>
|
||
pouvant être utilisée comme <a href="#conf-lsobject-customactions-customactions">customActions</a> et
|
||
permettant d'afficher les logs d'accès produits par
|
||
<a href="https://www.openldap.org/doc/admin24/overlays.html#Access%20Logging">l'overlay OpenLDAP accesslog</a>
|
||
sur un objet de l'annuaire.</p>
|
||
<p>La constante <code>LS_ACCESSLOG_BASEDN</code> du fichier de configuration de l'addon
|
||
(<code>conf/LSaddons/config.LSaddons.accesslog.php</code>) permet d'indiquer le base DN de la base stockant les
|
||
logs :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>// Accesslog base DN
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>define('LS_ACCESSLOG_BASEDN', 'cn=ldapsaisie-accesslog');
|
||
</code></pre></div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>LdapSaisie se connectera à la base stockant les logs d'accès de l'annuaire avec les mêmes
|
||
paramètres de connexion que pour la base principale (excepté le base DN). Pensez à ajuster les
|
||
ACLs de la base stockant les logs d'accès pour autoriser l'utilisateur d'LdapSaisie à se
|
||
connecter et lire les informations qu'elle contient.</p>
|
||
<p><strong>Exemple d'ACL à mettre en place :</strong>
|
||
</p><div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>to *
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> by dn.exact=uid=ldapsaisie,ou=sysaccounts,o=ls read
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> by * break
|
||
</code></pre></div><p></p>
|
||
</div>
|
||
<p>Ci-dessous, vous trouverez un exemple de configuration de la fonction <code>showObjectAccessLogs()</code> comme
|
||
<a href="#conf-lsobject-customactions-customactions">customActions</a> :</p>
|
||
<p><strong>Exemple d'utilisation :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-2" id="__codelineno-2-2" name="__codelineno-2-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-3" id="__codelineno-2-3" name="__codelineno-2-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-4" id="__codelineno-2-4" name="__codelineno-2-4"></a><span class="x"> 'showObjectAccessLogs' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-5" id="__codelineno-2-5" name="__codelineno-2-5"></a><span class="x"> 'function' => 'showObjectAccessLogs',</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-6" id="__codelineno-2-6" name="__codelineno-2-6"></a><span class="x"> 'label' => 'Show access logs',</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-7" id="__codelineno-2-7" name="__codelineno-2-7"></a><span class="x"> 'hideLabel' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-8" id="__codelineno-2-8" name="__codelineno-2-8"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-9" id="__codelineno-2-9" name="__codelineno-2-9"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-10" id="__codelineno-2-10" name="__codelineno-2-10"></a><span class="x"> 'icon' => 'clock',</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-11" id="__codelineno-2-11" name="__codelineno-2-11"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-12" id="__codelineno-2-12" name="__codelineno-2-12"></a><span class="x"> 'admin'</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-13" id="__codelineno-2-13" name="__codelineno-2-13"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-14" id="__codelineno-2-14" name="__codelineno-2-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-15" id="__codelineno-2-15" name="__codelineno-2-15"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-16" id="__codelineno-2-16" name="__codelineno-2-16"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_accesslog-__codelineno-2-17" id="__codelineno-2-17" name="__codelineno-2-17"></a><span class="x">);</span>
|
||
</code></pre></div></section><section class="print-page" id="conf-lsaddon-lsaddon_asterisk"><h1 id="conf-lsaddon-lsaddon_asterisk-lsaddon_asterisk">LSaddon_asterisk</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> est utilisé pour gérer les fonctionnalités
|
||
spécifiques au serveur de téléphonie Asterisk. Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a>
|
||
donne accès à une fonction permettant l'encodage d'un mot de passe au format spécifique attendu par
|
||
Asterisk. Ce format est un hash MD5 d'une chaine de caractère composée du nom d'utilisateur, d'une
|
||
chaine fixe spécifiée dans la configuration d'Asterisk et du mot de passe en clair.</p></section><section class="print-page" id="conf-lsaddon-lsaddon_exportsearchresultascsv"><h1 id="conf-lsaddon-lsaddon_exportsearchresultascsv-lsaddon_exportsearchresultascsv">LSaddon_exportSearchResultAsCSV</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fournie une fonction du même nom pouvant être
|
||
utilisée comme <a href="#conf-lsobject-lssearch-customactions_1">customActions</a> et permettant de télécharger
|
||
le résultat d'une recherche au format CSV. L'export généré reprend exactement le contenu des
|
||
colonnes du tableau du résultat de la recherche. Le DN de l'objet LDAP correspondant est également
|
||
fournis dans une colonne.</p>
|
||
<p>Des paramètres de configuration sont disponibles dans le fichier de configuration
|
||
<code>config.LSaddons.exportSearchResultAsCSV.php</code>. Ils permettent notamment de contrôller le format du
|
||
fichier CSV généré.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">// CSV file delimiter</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x">define('LS_EXPORTSEARCHRESULTASCSV_DELIMITER',',');</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x">// CSV file enclosure</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x">define('LS_EXPORTSEARCHRESULTASCSV_ENCLOSURE','"');</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x">// CSV file escape character (available since PHP 5.5.4)</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x">define('LS_EXPORTSEARCHRESULTASCSV_ESCAPE_CHAR','\\');</span>
|
||
</code></pre></div>
|
||
<p>Ci-dessous, vous trouverez un exemple de configuration de la fonction <code>exportSearchResultAsCSV()</code>
|
||
comme <a href="#conf-lsobject-lssearch-customactions_1">customActions</a> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople']['LSsearch'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> 'exportSearchResultAsCSV' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> 'label' => 'Export result as CSV',</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> 'icon' => 'export_csv',</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> 'function' => 'exportSearchResultAsCSV',</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> 'admin'</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x"> )</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Le label et l'icône fournis dans cet exemple sont traduits et délivrés avec LdapSaisie.</p>
|
||
</div></section><section class="print-page" id="conf-lsaddon-lsaddon_impersonate"><h1 id="conf-lsaddon-lsaddon_impersonate-lsaddon_impersonate">LSaddon_impersonate</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fournie une fonction du même nom pouvant être
|
||
utilisée comme <a href="#conf-lsobject-customactions-customactions">customActions</a> et permettant de se
|
||
reconnecter en tant qu'un autre utilisateur de l'annuaire.</p>
|
||
<p>Ci-dessous, vous trouverez un exemple de configuration de la fonction <code>impersonate()</code> comme
|
||
<a href="#conf-lsobject-customactions-customactions">customActions</a> :</p>
|
||
<p><strong>Exemple d'utilisation :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> 'impersonate' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> 'function' => 'impersonate',</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x"> 'label' => 'Reconnect as this user',</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x"> 'hideLabel' => True,</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x"> 'icon' => 'user_go',</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x"> 'admin'</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_impersonate-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x">);</span>
|
||
</code></pre></div></section><section class="print-page" id="conf-lsaddon-lsaddon_lsaccessrightsmatrixview"><h1 id="conf-lsaddon-lsaddon_lsaccessrightsmatrixview-lsaddon_lsaccessrightsmatrixview">LSaddon_LSaccessRightsMatrixView</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> offre une interface de visualisation des droits
|
||
d'accès des différents <a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a> configurés.
|
||
Pour chaque type d'objet, la matrice des droits d'accès par attribut et par profil est affiché sous
|
||
la forme d'un tableau.</p>
|
||
<p>Le fichier de configuration permet de définir au travers la variable
|
||
<code>$GLOBALS['LSaccessRightsMatrixView_allowed_LSprofiles']</code> la liste des
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a> autorisés à accéder à cette interface.</p></section><section class="print-page" id="conf-lsaddon-lsaddon_mail"><h1 id="conf-lsaddon-lsaddon_mail-lsaddon_mail">LSaddon_mail</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> est utilisé pour gérer l'envoi de courriels. Il
|
||
utilise pour cela les librairies <a href="http://pear.php.net/">PEAR</a> <em>Mail</em> et <em>Mail_Mime</em> qui doivent être
|
||
installés.</p>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> 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 <code>$GLOBALS['MAIL_TEMPLATES_DIRECTORIES']</code>). Pour chaque modèle, vous
|
||
devez fournir trois fichiers portant le même nom mais avec des extensions différentes :</p>
|
||
<ul>
|
||
<li><code>template.subject</code> : le sujet du courriel. Note : seule la première ligne du fichier est utilisé
|
||
(et passée dans la fonction <code>trim()</code>)</li>
|
||
<li><code>template.html</code> : le contenu HTML du courriel</li>
|
||
<li><code>template.txt</code>: le contenu texte du courriel</li>
|
||
</ul>
|
||
<p>Ces trois fichiers sont utilisés en tant que modèle <a href="http://www.smarty.net/">Smarty</a> 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.</p>
|
||
<p>Par ailleurs, cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fourni une vue de gestion des
|
||
modèles de courriels existants (voir <code>$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS']</code> pour la
|
||
configuration des accès).</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>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.</p>
|
||
</div>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> doit être configuré en éditant son
|
||
fichier de configuration <code>config.LSaddons.mail.php</code>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x"> ***********************************************</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> * Configuration du support de l'envoi de mail *</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> ***********************************************</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> */</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x">// Pear :: Mail</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x">define('PEAR_MAIL','/usr/share/php/Mail.php');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x">// Pear :: Mail_mime</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x">define('PEAR_MAIL_MIME','/usr/share/php/Mail/mime.php');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x">/*</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> * Méthode d'envoie :</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x"> * - mail : envoie avec la méthode PHP mail()</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> * - sendmail : envoie la commande sendmail du système</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> * - smtp : envoie en utilisant un serveur SMTP</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x"> */</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a><span class="x">define('MAIL_SEND_METHOD','smtp');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="x">/*</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a><span class="x"> * Paramètres d'envoie :</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a><span class="x"> * Ces paramètres dépende de la méthode utilisé. Repporté vous à la documentation</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="x"> * de PEAR :: Mail pour plus d'information.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a><span class="x"> * Lien : http://pear.php.net/manual/en/package.mail.mail.factory.php</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="x"> * Infos :</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a><span class="x"> * List of parameter for the backends</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a><span class="x"> * mail</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a><span class="x"> * o If safe mode is disabled, $params will be passed as the fifth</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="x"> * argument to the PHP mail() function. If $params is an array,</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a><span class="x"> * its elements will be joined as a space-delimited string.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a><span class="x"> * sendmail</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a><span class="x"> * o $params["sendmail_path"] - The location of the sendmail program</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a><span class="x"> * on the filesystem. Default is /usr/bin/sendmail.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a><span class="x"> * o $params["sendmail_args"] - Additional parameters to pass to the</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a><span class="x"> * sendmail. Default is -i.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a><span class="x"> * smtp</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a><span class="x"> * o $params["host"] - The server to connect. Default is localhost.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a><span class="x"> * o $params["port"] - The port to connect. Default is 25.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a><span class="x"> * o $params["auth"] - Whether or not to use SMTP authentication.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a><span class="x"> * Default is FALSE.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a><span class="x"> * o $params["username"] - The username to use for SMTP authentication.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a><span class="x"> * o $params["password"] - The password to use for SMTP authentication.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a><span class="x"> * o $params["localhost"] - The value to give when sending EHLO or HELO.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a><span class="x"> * Default is localhost</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-45" id="__codelineno-0-45" name="__codelineno-0-45"></a><span class="x"> * o $params["timeout"] - The SMTP connection timeout.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-46" id="__codelineno-0-46" name="__codelineno-0-46"></a><span class="x"> * Default is NULL (no timeout).</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-47" id="__codelineno-0-47" name="__codelineno-0-47"></a><span class="x"> * o $params["verp"] - Whether to use VERP or not. Default is FALSE.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-48" id="__codelineno-0-48" name="__codelineno-0-48"></a><span class="x"> * o $params["debug"] - Whether to enable SMTP debug mode or not.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-49" id="__codelineno-0-49" name="__codelineno-0-49"></a><span class="x"> * Default is FALSE.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-50" id="__codelineno-0-50" name="__codelineno-0-50"></a><span class="x"> * o $params["persist"] - Indicates whether or not the SMTP connection</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-51" id="__codelineno-0-51" name="__codelineno-0-51"></a><span class="x"> * should persist over multiple calls to the send() method.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-52" id="__codelineno-0-52" name="__codelineno-0-52"></a><span class="x"> */</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-53" id="__codelineno-0-53" name="__codelineno-0-53"></a><span class="x">$GLOBALS['MAIL_SEND_PARAMS'] = NULL;</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-54" id="__codelineno-0-54" name="__codelineno-0-54"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-55" id="__codelineno-0-55" name="__codelineno-0-55"></a><span class="x">/*</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-56" id="__codelineno-0-56" name="__codelineno-0-56"></a><span class="x"> * Headers :</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-57" id="__codelineno-0-57" name="__codelineno-0-57"></a><span class="x"> */</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-58" id="__codelineno-0-58" name="__codelineno-0-58"></a><span class="x">$GLOBALS['MAIL_HEARDERS = array();</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-59" id="__codelineno-0-59" name="__codelineno-0-59"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-60" id="__codelineno-0-60" name="__codelineno-0-60"></a><span class="x">// Catch all sent emails</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-61" id="__codelineno-0-61" name="__codelineno-0-61"></a><span class="x">$GLOBALS['MAIL_CATCH_ALL'] = array();</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-62" id="__codelineno-0-62" name="__codelineno-0-62"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-63" id="__codelineno-0-63" name="__codelineno-0-63"></a><span class="x">/**</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-64" id="__codelineno-0-64" name="__codelineno-0-64"></a><span class="x"> * Email templates</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-65" id="__codelineno-0-65" name="__codelineno-0-65"></a><span class="x"> *</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-66" id="__codelineno-0-66" name="__codelineno-0-66"></a><span class="x"> * This addon offer ability to send email by using templates. Email templates are stored in</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-67" id="__codelineno-0-67" name="__codelineno-0-67"></a><span class="x"> * full-text files in configured directories (see $GLOBALS['MAIL_TEMPLATES_DIRECTORIES']). For each</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-68" id="__codelineno-0-68" name="__codelineno-0-68"></a><span class="x"> * template, you have to provide three files with the same name but with different extensions:</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-69" id="__codelineno-0-69" name="__codelineno-0-69"></a><span class="x"> * - template.subject: the email subject. Note: only the first line is used (and stripped)</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-70" id="__codelineno-0-70" name="__codelineno-0-70"></a><span class="x"> * - template.html: the HTML content of the email</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-71" id="__codelineno-0-71" name="__codelineno-0-71"></a><span class="x"> * - template.txt: the text content of the email</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-72" id="__codelineno-0-72" name="__codelineno-0-72"></a><span class="x"> * All these files will be used as Smarty templates and will be computed using variables provided</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-73" id="__codelineno-0-73" name="__codelineno-0-73"></a><span class="x"> * in the sending context. Note that the Smarty object used to compute the template is not the same</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-74" id="__codelineno-0-74" name="__codelineno-0-74"></a><span class="x"> * as the one used by LdapSaisie to display pages.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-75" id="__codelineno-0-75" name="__codelineno-0-75"></a><span class="x"> *</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-76" id="__codelineno-0-76" name="__codelineno-0-76"></a><span class="x"> * Futhermore, this addon offer a view to list and edit existing template (see</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-77" id="__codelineno-0-77" name="__codelineno-0-77"></a><span class="x"> * $GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] to configured access).</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-78" id="__codelineno-0-78" name="__codelineno-0-78"></a><span class="x"> */</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-79" id="__codelineno-0-79" name="__codelineno-0-79"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-80" id="__codelineno-0-80" name="__codelineno-0-80"></a><span class="x">// List of directory paths where as stored mail templates</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-81" id="__codelineno-0-81" name="__codelineno-0-81"></a><span class="x">// Notes:</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-82" id="__codelineno-0-82" name="__codelineno-0-82"></a><span class="x">// - provided path could be absolute or relative. Relative path are relative to the root base</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-83" id="__codelineno-0-83" name="__codelineno-0-83"></a><span class="x">// sources LdapSaisie directory (commonly /usr/share/ldapsaisie or the src directory if you</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-84" id="__codelineno-0-84" name="__codelineno-0-84"></a><span class="x">// installed it from sources). On Debian installation, you can specify 'local/email_templates' to</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-85" id="__codelineno-0-85" name="__codelineno-0-85"></a><span class="x">// refer to /etc/ldapsaisie/local/email_templates directory/</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-86" id="__codelineno-0-86" name="__codelineno-0-86"></a><span class="x">// - Multiple directories could be specified, sorted so that the first ones take priority over</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-87" id="__codelineno-0-87" name="__codelineno-0-87"></a><span class="x">// the last one.</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-88" id="__codelineno-0-88" name="__codelineno-0-88"></a><span class="x">// - To allow users to edit them using the editor view, these directories must be</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-89" id="__codelineno-0-89" name="__codelineno-0-89"></a><span class="x">// writable by PHP process (commonly runed as www-data).</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-90" id="__codelineno-0-90" name="__codelineno-0-90"></a><span class="x">$GLOBALS['MAIL_TEMPLATES_DIRECTORIES'] = array('local/email_templates');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-91" id="__codelineno-0-91" name="__codelineno-0-91"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-92" id="__codelineno-0-92" name="__codelineno-0-92"></a><span class="x">// List of granted LSprofiles to access mail templates editor view</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-93" id="__codelineno-0-93" name="__codelineno-0-93"></a><span class="x">// WARNING: Sanitizing mail templates is hell... EXPOSE THIS VIEW ONLY TO TRUSTED USERS!</span>
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-0-94" id="__codelineno-0-94" name="__codelineno-0-94"></a><span class="x">$GLOBALS['MAIL_TEMPLATES_EDITOR_VIEW_ACCESS'] = array('admin');</span>
|
||
</code></pre></div>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> offre avant tout la possibilité d'envoyer des
|
||
courriels en utilisant la fonction PHP <code>sendMail()</code> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>bool sendMail(
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a> <string> $to,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> <string> $subject,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> <string> $msg,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> <array(string)> $headers,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> <array> $attachments,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> <string> $eol,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a> <string> $encoding,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a> <boolean> $html
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a>);
|
||
</code></pre></div>
|
||
<p>Pour l'envoi de courriels en utilisant un modèle, il faut utiliser la fonction PHP
|
||
<code>sendMailFromTemplate()</code> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_mail-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>bool sendMailFromTemplate(
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-2-2" id="__codelineno-2-2" name="__codelineno-2-2"></a> <string> $tplname,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-2-3" id="__codelineno-2-3" name="__codelineno-2-3"></a> <string> $to,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-2-4" id="__codelineno-2-4" name="__codelineno-2-4"></a> <array> $variables,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-2-5" id="__codelineno-2-5" name="__codelineno-2-5"></a> <array(string)> $headers,
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-2-6" id="__codelineno-2-6" name="__codelineno-2-6"></a> <array> $attachments
|
||
<a href="#conf-lsaddon-lsaddon_mail-__codelineno-2-7" id="__codelineno-2-7" name="__codelineno-2-7"></a>);
|
||
</code></pre></div></section><section class="print-page" id="conf-lsaddon-lsaddon_maildir"><h1 id="conf-lsaddon-lsaddon_maildir-lsaddon_maildir">LSaddon_maildir</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> est utilisé pour gérer la manipulation distante
|
||
de maildir.</p>
|
||
<p><strong>FIXME</strong></p></section><section class="print-page" id="conf-lsaddon-lsaddon_mailquota"><h1 id="conf-lsaddon-lsaddon_mailquota-lsaddon_mailquota">LSaddon_mailquota</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fournie une fonction <code>mailquota_get_usage</code>
|
||
pouvant être utilisée pour récupérer l'utilisation du quota d'une boîte mail IMAP. Pour cela,
|
||
LdapSaisie se connecte au serveur IMAP en utilisant un compte maître.</p>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fournie une également une fonction
|
||
<code>mailquota_show_usage</code> pouvant être utilisée comme
|
||
<a href="#conf-lsobject-customactions-customactions">customActions</a> et permettant d'afficher l'utilisation
|
||
du quota de la boîte mail correspondante via une message dynamique (<code>LSinfo</code>).</p>
|
||
<p>Des paramètres de configuration sont disponibles dans le fichier de configuration
|
||
<code>config.LSaddons.mailquota.php</code>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">// IMAP Mailbox connection string LSformat (composed with LSldapObject attributes)</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x">// See : https://php.net/imap_open (parameter $mailbox)</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x">define('MAILQUOTA_IMAP_MAILBOX','{localhost}');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x">// IMAP Master user</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x">define('MAILQUOTA_IMAP_MASTER_USER', 'ldapsaisie');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x">// IMAP Master user's password</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x">define('MAILQUOTA_IMAP_MASTER_USER_PWD', 'secret');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x">// IMAP Master user LSformat composed with :</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x">// * masteruser = master username (MAILQUOTA_IMAP_MASTER_USER)</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x">// * LSldapObject attributes</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x">define('MAILQUOTA_IMAP_MASTER_USER_FORMAT', '%{mail}*%{masteruser}');</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x">// IMAP quota root mailbox</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x">define('MAILQUOTA_IMAP_QUOTA_ROOT_MAILBOX', 'INBOX');</span>
|
||
</code></pre></div>
|
||
<p>Ci-dessous, vous trouverez un exemple de configuration de la fonction <code>mailquota_show_usage()</code>
|
||
comme <a href="#conf-lsobject-customactions-customactions">customActions</a> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> 'showmailquotausage' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> 'function' => 'mailquota_show_usage',</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> 'label' => 'Show mail quota usage',</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> 'icon' => 'mail',</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> 'admin'</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x"> )</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_mailquota-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a><span class="x">);</span>
|
||
</code></pre></div></section><section class="print-page" id="conf-lsaddon-lsaddon_phpldapadmin"><h1 id="conf-lsaddon-lsaddon_phpldapadmin-lsaddon_phpldapadmin">LSaddon_phpldapadmin</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> est utilisé pour permettre un lien facile entre
|
||
le logiciel <a href="https://github.com/leenooks/phpLDAPadmin">PhpLdapAdmin</a> et LdapSaisie. Il sera possible
|
||
ainsi à partir d'un objet dans LdapSaisie de voir ce même objet dans
|
||
<a href="https://github.com/leenooks/phpLDAPadmin">PhpLdapAdmin</a>.</p>
|
||
<p>Il est necessaire de configurer l'URL de votre installation de
|
||
<a href="https://github.com/leenooks/phpLDAPadmin">PhpLdapAdmin</a> dans le fichier de configuration
|
||
<code>config.LSaddons.phpldapadmin.php</code>.</p>
|
||
<p><strong>Structure du fichier :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">// PhpLdapAdmin View Object URL format</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x">define('LS_PHPLDAPADMIN_VIEW_OBJECT_URL_FORMAT','//'.$_SERVER['SERVER_NAME'].'/phpldapadmin/cmd.php?cmd=template_engine&server_id=0&dn=%{dn}');</span>
|
||
</code></pre></div>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> offre la possibilité d'utilisé la fonction PHP
|
||
<code>redirectToPhpLdapAdmin()</code> comme <a href="#conf-lsobject-customactions-customactions">customActions</a>.</p>
|
||
<p><strong>Exemple d'utilisation :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> 'redirectPhpLdapAdmin' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> 'function' => 'redirectToPhpLdapAdmin',</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> 'label' => 'See in PhpLdapAdmin',</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> 'hideLabel' => True,</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> 'icon' => 'phpldapadmin',</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x"> 'admin'</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="x"> )</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_phpldapadmin-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a><span class="x">);</span>
|
||
</code></pre></div></section><section class="print-page" id="conf-lsaddon-lsaddon_ppolicy"><h1 id="conf-lsaddon-lsaddon_ppolicy-lsaddon_ppolicy">LSaddon_ppolicy</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fourni :</p>
|
||
<ul>
|
||
<li>
|
||
<p>une fonction <code>ppolicy_extraDisplayColumn_password_expiration</code> pouvant être utilisée pour la
|
||
génération d'une <em>extraDisplayedColumn</em> affichant l'état d'expiration du mot de passe des objets
|
||
d'une recherche.</p>
|
||
<p><strong>Exemple d'utilisation :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a>$GLOBALS['LSobjects']['LSpeople']['LSsearch'] = array (
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a> [...]
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> 'extraDisplayedColumns' => array (
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> [...]
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> 'password_expiration' => array (
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> 'label' => 'Password expiration',
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> 'generateFunction' => 'ppolicy_extraDisplayColumn_password_expiration',
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> 'additionalAttrs' => array('pwdChangedTime', 'pwdPolicySubentry'),
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> 'escape' => false,
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> 'cssStyle' => 'width: 14em; text-align: center;'
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> ),
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> [...]
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> ),
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> [...]
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a>);
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>une fonction <code>ppolicy_export_search_info</code> pouvant être utilisée comme
|
||
<a href="#conf-lsobject-lssearch-customactions_1">actions personnalisées sur les recherches d'LSobjects</a>
|
||
pour exporter au format CSV les informations des politiques de mots de passe des objets retournés
|
||
par la recherche.</p>
|
||
<p><strong>Exemple d'utilisation :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople']['LSsearch'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a><span class="x"> 'exportPpolicyInfo' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a><span class="x"> 'label' => 'Export password policy info',</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a><span class="x"> 'icon' => 'export_csv',</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a><span class="x"> 'function' => 'ppolicy_export_search_info',</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a><span class="x"> 'admin',</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>la méthode d'API <code>exportPpolicyInfo</code> permettant d'exporter les informations des politiques de mots
|
||
de passe de tous les objets d'un type donné. Cette méthode est accessible via l'URL au format
|
||
suivant : <code>/api/1.0/exportPpolicyInfo/[object type]</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>la commande CLI <code>export_ppolicy_info</code> permettant d'exporter les informations des politiques de
|
||
mots de passe de tous les objets d'un type donné.</p>
|
||
<p><strong>Utilisation :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a>ldapsaisie<span class="w"> </span>export_ppolicy_info<span class="w"> </span><span class="o">[</span>object<span class="w"> </span>type<span class="o">]</span><span class="w"> </span><span class="o">[</span>-o<span class="p">|</span>--output<span class="w"> </span>filepath<span class="o">]</span><span class="w"> </span><span class="o">[</span>-j<span class="p">|</span>--json<span class="w"> </span><span class="o">[</span>-p<span class="p">|</span>--pretty<span class="o">]]</span>
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<p>Des paramètres de configuration sont disponibles dans le fichier de configuration
|
||
<code>config.LSaddons.ppolicy.php</code>.</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a><span class="x">// Default password policy object DN (set to null if no default policy is configured)</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-2" id="__codelineno-3-2" name="__codelineno-3-2"></a><span class="x">define('LS_PPOLICY_DEFAULT_DN', null);</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-3" id="__codelineno-3-3" name="__codelineno-3-3"></a>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-4" id="__codelineno-3-4" name="__codelineno-3-4"></a><span class="x">// Ppolicy password warning expiration threshold (in seconds)</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-5" id="__codelineno-3-5" name="__codelineno-3-5"></a><span class="x">define('LS_PPOLICY_WARNING_EXPIRATION_THRESHOLD', 7 * 86400);</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-6" id="__codelineno-3-6" name="__codelineno-3-6"></a>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-7" id="__codelineno-3-7" name="__codelineno-3-7"></a><span class="x">// Ppolicy password critical expiration threshold (in seconds)</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-8" id="__codelineno-3-8" name="__codelineno-3-8"></a><span class="x">define('LS_PPOLICY_CRITICAL_EXPIRATION_THRESHOLD', 2 * 86400);</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-9" id="__codelineno-3-9" name="__codelineno-3-9"></a>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-10" id="__codelineno-3-10" name="__codelineno-3-10"></a><span class="x">// CSV file delimiter</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-11" id="__codelineno-3-11" name="__codelineno-3-11"></a><span class="x">define('LS_PPOLICY_CSV_DELIMITER',';');</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-12" id="__codelineno-3-12" name="__codelineno-3-12"></a>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-13" id="__codelineno-3-13" name="__codelineno-3-13"></a><span class="x">// CSV file enclosure</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-14" id="__codelineno-3-14" name="__codelineno-3-14"></a><span class="x">define('LS_PPOLICY_CSV_ENCLOSURE','"');</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-15" id="__codelineno-3-15" name="__codelineno-3-15"></a>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-16" id="__codelineno-3-16" name="__codelineno-3-16"></a><span class="x">// CSV file escape character (available since PHP 5.5.4)</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-17" id="__codelineno-3-17" name="__codelineno-3-17"></a><span class="x">define('LS_PPOLICY_CSV_ESCAPE_CHAR','\\');</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-18" id="__codelineno-3-18" name="__codelineno-3-18"></a>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-19" id="__codelineno-3-19" name="__codelineno-3-19"></a><span class="x">// List of LSprofiles who are granted to use the exportPpolicyInfo API method</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-20" id="__codelineno-3-20" name="__codelineno-3-20"></a><span class="x">$GLOBALS['LS_PPOLICY_API_GRANTED_PROFILES'] = array('admin');</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-21" id="__codelineno-3-21" name="__codelineno-3-21"></a>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-22" id="__codelineno-3-22" name="__codelineno-3-22"></a><span class="x">// List of extra attributes to include in Ppolicy info export</span>
|
||
<a href="#conf-lsaddon-lsaddon_ppolicy-__codelineno-3-23" id="__codelineno-3-23" name="__codelineno-3-23"></a><span class="x">$GLOBALS['LS_PPOLICY_INFO_EXPORT_EXTRA_ATTRS'] = array();</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_PPOLICY_DEFAULT_DN</code></p>
|
||
<p>Constante définissant le DN de la politique par défaut. Si aucune politique par défaut n'est
|
||
définie, ce paramètre doit valoir <code>null</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_PPOLICY_WARNING_EXPIRATION_THRESHOLD</code></p>
|
||
<p>Constante définissant le seuil d'alerte pour l'expiration des mots de passe (en seconde). Par
|
||
défaut : 7 jours.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_PPOLICY_CRITICAL_EXPIRATION_THRESHOLD</code></p>
|
||
<p>Constante définissant le seuil critique pour l'expiration des mots de passe (en seconde). Par
|
||
défaut : 2 jours.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_PPOLICY_CSV_DELIMITER</code></p>
|
||
<p>Constante définissant le caractère utilisé lors de la génération de l'export CSV comme séparateur
|
||
de champ. Par défaut : un point-virgule.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_PPOLICY_CSV_ENCLOSURE</code></p>
|
||
<p>Constante définissant le caractère utilisé lors de la génération de l'export CSV pour
|
||
l'encadrement des champs. Par défaut : un guillemet double.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LS_PPOLICY_CSV_ESCAPE_CHAR</code></p>
|
||
<p>Constante définissant le caractère utilisé lors de la génération de l'export CSV pour
|
||
l'échappement des champs. Par défaut : une barre oblique inverse.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$GLOBALS['LS_PPOLICY_API_GRANTED_PROFILES']</code></p>
|
||
<p>Tableau global listant les <a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a>
|
||
autorisés à utiliser la méthode d'API <code>exportPpolicyInfo</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$GLOBALS['LS_PPOLICY_INFO_EXPORT_EXTRA_ATTRS']</code></p>
|
||
<p>Tableau global listant les attributs supplémentaires à inclure lors de l'export des informations
|
||
de politique de mots de passe.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsaddon-lsaddon_showsupportinfo"><h1 id="conf-lsaddon-lsaddon_showsupportinfo-lsaddon_showsupportinfo">LSaddon_showSupportInfo</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fourni une page affichant les informations utiles
|
||
pour l'équipe assurant le support de l'application. Cette page est accessible à l'adresse
|
||
<code>addon/showSupportInfo/showMySupportInfo</code>. Elle compile (et permet de télécharger) l'ensemble des
|
||
informations utiles à l'appréciation du contexte d'accès à l'application par l'utilisateur.</p>
|
||
<p>Cette page est accessible par tous les utilisateurs connectés à l'application. Cependant, par
|
||
défaut, il n'y a aucun lien d'accès à celle-ci. Il est possible d'ajouter un lien d'accès dans le
|
||
menu et modifiant la valeur de la constante <code>SHOW_SUPPORT_INFO_IN_MENU</code> à <code>True</code>.</p>
|
||
<p>Une fonction <code>showMySupportInfo()</code> est également fournie et peut-être utilisée comme
|
||
<a href="#conf-lsobject-customactions-customactions">customActions</a>. Elle redirigera alors l'utilisateur
|
||
vers cette page. Ci-dessous, vous trouverez un exemple de configuration de la fonction
|
||
<code>showMySupportInfo()</code> comme <a href="#conf-lsobject-customactions-customactions">customActions</a> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> 'showMySupportInfo' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> 'function' => 'showMySupportInfo',</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x"> 'label' => 'Show my support information',</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x"> 'hideLabel' => True,</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x"> 'icon' => 'terminal',</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x"> 'self'</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_showsupportinfo-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Le label et l'icône fournis dans cet exemple sont traduits et délivrés avec LdapSaisie.</p>
|
||
</div></section><section class="print-page" id="conf-lsaddon-lsaddon_showtechinfo"><h1 id="conf-lsaddon-lsaddon_showtechinfo-lsaddon_showtechinfo">LSaddon_showTechInfo</h1>
|
||
<p>Cet <a href="#conf-lsaddon-configuration-des-lsaddons">LSaddon</a> fournie une fonction du même nom pouvant être
|
||
utilisée comme <a href="#conf-lsobject-customactions-customactions">customActions</a> et permettant d'afficher
|
||
les informations techniques d'un objet de l'annuaire.</p>
|
||
<p>Ci-dessous, vous trouverez un exemple de configuration de la fonction <code>showTechInfo()</code> comme
|
||
<a href="#conf-lsobject-customactions-customactions">customActions</a> :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">$GLOBALS['LSobjects']['LSpeople'] = array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> 'customActions' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> 'showTechInfo' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> 'function' => 'showTechInfo',</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a><span class="x"> 'label' => 'Show technical information',</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x"> 'hideLabel' => True,</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x"> 'noConfirmation' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a><span class="x"> 'disableOnSuccessMsg' => true,</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x"> 'icon' => 'tech_info',</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x"> 'rights' => array (</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="x"> 'admin'</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a><span class="x"> ),</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x"> [...]</span>
|
||
<a href="#conf-lsaddon-lsaddon_showtechinfo-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x">);</span>
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Le label et l'icône fournis dans cet exemple sont traduits et délivrés avec LdapSaisie.</p>
|
||
</div></section><h1 class="nav-section-title-end">Ended: Configuration des addons (LSaddons)</h1><h2 class="nav-section-title">Configuration des méthodes d'authentification (LSauthMethod)</h2><section class="print-page" id="conf-lsauthmethod"><h1 id="conf-lsauthmethod-configuration-des-methodes-dauthentification-lsauthmethod">Configuration des méthodes d'authentification (LSauthMethod)</h1>
|
||
<p>Cette partie décrit la manière de configurer les méthodes d'authentification d'LdapSaisie appelée
|
||
LSauthMethod). Ces librairies peuvent avoir un fichier de configuration et il sera alors stocké dans
|
||
le dossier <code>conf/LSauth/</code>.</p></section><section class="print-page" id="conf-lsauthmethod-lsauthmethod_anonymous"><h1 id="conf-lsauthmethod-lsauthmethod_anonymous-lsauthmethod_anonymous">LSauthMethod_anonymous</h1>
|
||
<p>Cette <a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> est utilisée pour gérer
|
||
l'authentification automatique des utilisateurs arrivant (équivalent à un mode anonyme). Cette
|
||
librairie doit être configurée en éditant le fichier de configuration
|
||
<code>conf/LSauth/config.LSauthMethod_anonymous.php</code> et notament en définissant la constante
|
||
<code>LSAUTHMETHOD_ANONYMOUS_USER</code> contenant le login d'un utilisateur dont les droits d'accès seront
|
||
endossés par tout les personnes utilisant LdapSaisie.</p></section><section class="print-page" id="conf-lsauthmethod-lsauthmethod_cas"><h1 id="conf-lsauthmethod-lsauthmethod_cas-lsauthmethod_cas">LSauthMethod_CAS</h1>
|
||
<p>Cette <a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> est utilisée pour gérer
|
||
l'authentification via un service SSO CAS. Cette librairie doit être configurée en éditant le
|
||
fichier de configuration <code>conf/LSauth/config.LSauthMethod_CAS.php</code>.</p>
|
||
<p><strong>Structure du fichier :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">/*</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> *****************************************************</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> * Configuration of the CAS authentification support *</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> *****************************************************</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> */</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x">// phpCAS Path (http://www.ja-sig.org/wiki/display/CASC/phpCAS)</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x">define('PHP_CAS_PATH','/usr/share/php/CAS.php');</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x">// phpCAS Debug File</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x">// define('PHP_CAS_DEBUG_FILE','/tmp/phpCAS.log');</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a><span class="x">// Disable logout</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="x">define('LSAUTH_CAS_DISABLE_LOGOUT',false);</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="x">// CAS Server version (used constant name know by phpCAS : CAS_VERSION_1_0 or CAS_VERSION_2_0)</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="x">define('LSAUTH_CAS_VERSION','CAS_VERSION_2_0');</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a><span class="x">// CAS Server hostname</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="x">define('LSAUTH_CAS_SERVER_HOSTNAME','cas.univ.fr');</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a><span class="x">// CAS Server port</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="x">define('LSAUTH_CAS_SERVER_PORT',443);</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="x">// CAS Server URI (empty by default)</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a><span class="x">// define('LSAUTH_CAS_SERVER_URI','cas/');</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a><span class="x">// No SSL validation for the CAS server</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="x">define('LSAUTH_CAS_SERVER_NO_SSL_VALIDATION',false);</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a><span class="x">// CAS server SSL CA Certificate path</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_cas-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a><span class="x">//define('LSAUTH_CAS_SERVER_SSL_CACERT','');</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>PHP_CAS_PATH</code></p>
|
||
<p>Le chemin d'accès du fichier <code>CAS.php</code> de la librairie
|
||
<a href="http://www.ja-sig.org/wiki/display/CASC/phpCAS">phpCAS</a>. Le chemin d'exemple correspond au chemin
|
||
résultant d'une installation via <a href="http://pear.php.net/">PEAR</a> sur une Debian (Lenny).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>PHP_CAS_DEBUG_FILE</code></p>
|
||
<p>Chemin du fichier de log de la librairie <a href="http://www.ja-sig.org/wiki/display/CASC/phpCAS">phpCAS</a>.
|
||
Commenter la ligne pour désactiver les logs.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTH_CAS_DISABLE_LOGOUT</code></p>
|
||
<p>Booléen définissant si l'utilisateur peut se déconnecter du serveur CAS depuis l'interface.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Remarque : l'appel de l'URL de déconnexion via une requête <code>GET</code> supprimera la session PHP et
|
||
donc la session LdapSaisie sans déconnecter pour autant l'utilisateur au niveau du serveur
|
||
CAS. Cela peut donc permettre de gérer la déconnexion automatique au niveau d'LdapSaisie suite
|
||
à une déconnexion au niveau du CAS à traver le concepte de <code>Global Logout</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTH_CAS_VERSION</code></p>
|
||
<p>Nom de la constant <a href="http://www.ja-sig.org/wiki/display/CASC/phpCAS">phpCAS</a> permettant de définir
|
||
la version CAS du serveur. Actuellement, la librairie
|
||
<a href="http://www.ja-sig.org/wiki/display/CASC/phpCAS">phpCAS</a> ne reconnait que la constante
|
||
<code>CAS_VERSION_1_0</code> pour la version 1 de CAS ou la constante <code>CAS_VERSION_2_0</code> pour la version 2 de
|
||
CAS.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Remarque : Des tests on montrés que l'utilisation d'une compatibilité CAS version 2 peut
|
||
également fonctionner sur un version 3 du serveur CAS.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTH_CAS_SERVER_HOSTNAME</code></p>
|
||
<p>Le nom d'hôte du serveur CAS.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTH_CAS_SERVER_PORT</code></p>
|
||
<p>Le port d'écoute du serveur CAS.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTH_CAS_SERVER_URI</code></p>
|
||
<p>Le dossier HTTP dans lequel se trouve le service CAS. Exemple : Pour un service CAS accessible via
|
||
l'URL <code>https://cas.univ.fr/cas/</code>, la constante devra valoir <code>cas/</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTH_CAS_SERVER_NO_SSL_VALIDATION</code></p>
|
||
<p>Booléen permettant de désactiver la validation du certificat SSL du serveur CAS lors des requêtes
|
||
de validation des tickets CAS.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTH_CAS_SERVER_SSL_CACERT</code></p>
|
||
<p>Chemin d'accès du fichier contenant le certificat SSL de la CA du serveur CAS au format PEM.
|
||
Commenter la ligne pour désactiver ce paramètre.</p>
|
||
</li>
|
||
</ul></section><section class="print-page" id="conf-lsauthmethod-lsauthmethod_http"><h1 id="conf-lsauthmethod-lsauthmethod_http-lsauthmethod_http">LSauthMethod_HTTP</h1>
|
||
<p>Cette <a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> est utilisée pour gérer
|
||
l'authentification via les variables d'environnements définies suite à une authentification,
|
||
potentiellement déléguée au serveur web.</p>
|
||
<p>Cette méthode récupère dans l'environment d'exécution PHP, le nom d'utilisateur et le mot de passe
|
||
de l'utilisateur connecté. À partir du nom d'utilisateur, une recherche dans l'annuaire sera
|
||
effectuée pour trouver l'utilisateur correspondant. L'authentification sera réussie uniquement si un
|
||
et un seul utilisateur est retourné par la recherche et si une authentification auprès de l'annuaire
|
||
LDAP réussie à l'aide du DN de l'objet LDAP trouvé et du mot de passe fourni.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>En cas d'authentification déléguée au serveur web, il est possible de désactiver la vérification
|
||
du mot de passe via le paramètre <code>LSAUTHMETHOD_HTTP_TRUST_WITHOUT_PASSWORD_CHALLENGE</code>
|
||
(voir ci-dessous).</p>
|
||
</div>
|
||
<p>Les variables d'environnements utilisées pour authentifier l'utilisateur connecté dépendent de la
|
||
méthode configurée via la constante <code>LSAUTHMETHOD_HTTP_METHOD</code> (voir ci-dessous). Si ces variables
|
||
ne sont pas disponibles, une erreur HTTP 403 sera générée pour réclamer une authentification à
|
||
l'utilisateur.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette <a href="#conf-lsauthmethod-configuration-des-lsauthmethods">LSauthMethod</a> supporte le mode API et il s'agit
|
||
de la méthode utilisée par défaut dans ce mode.</p>
|
||
</div>
|
||
<p>Cette librairie peut être configurée en éditant le fichier de configuration
|
||
<code>conf/LSauth/config.LSauthMethod_HTTP.php</code>.</p>
|
||
<p><strong>Structure du fichier :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="x">/*</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="x"> *****************************************************</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="x"> * Configuration of the HTTP authentification support *</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="x"> *****************************************************</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="x"> */</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="x">// Don't check HTTP server's login/password by LDAP authentication challenge</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="x">//define('LSAUTHMETHOD_HTTP_TRUST_WITHOUT_PASSWORD_CHALLENGE',true);</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="x">// Authentication realm (API mode only)</span>
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a><span class="x">//define('LSAUTHMETHOD_HTTP_API_REALM', ___('LdapSaisie API - Authentication required'));</span>
|
||
</code></pre></div>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTHMETHOD_HTTP_TRUST_WITHOUT_PASSWORD_CHALLENGE</code></p>
|
||
<p>Permet de désactiver le test d'authentification auprès de l'annuaire LDAP. Pour cela, cette
|
||
constante doit être définie et valoir <code>True</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTHMETHOD_HTTP_METHOD</code></p>
|
||
<p>Permet de définir la méthode utilisée par le serveur web pour passer à <a href="http://www.php.net/">PHP</a>
|
||
l'identifiant de l'utilisateur connecté et son mot de passe.</p>
|
||
<p>Cette constance peut pendre les valeurs suivantes :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>PHP_PASS</code></p>
|
||
<p>Dans cette méthode, le serveur web défini les variables d'environnement <code>PHP_AUTH_USER</code> et
|
||
<code>PHP_AUTH_PW</code>. Cette méthode est la méthode par défaut et convient en cas d'utilisation de
|
||
<code>mod_php</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>REMOTE_USER</code></p>
|
||
<p>Dans cette méthode, le serveur web défini la variable d'environnement <code>REMOTE_USER</code>. Cette
|
||
variable ne contient que l'identifiant de l'utilisateur connecté. Cette méthode ne peut donc
|
||
être utilisée que conjointement avec l'activation du paramètre
|
||
<code>LSAUTHMETHOD_HTTP_TRUST_WITHOUT_PASSWORD_CHALLENGE</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>AUTHORIZATION</code></p>
|
||
<p>Dans cette méthode, le serveur web passe le contenu de l'entête HTTP <code>Authorization</code> dans la
|
||
variable d'environnement <code>HTTP_AUTHORIZATION</code>. Cette méthode convient en cas d'utilisation de
|
||
<a href="http://www.php.net/">PHP</a> en mode CGI ou encore via PHP-FPM.</p>
|
||
<p>Pour utiliser cette méthode, il faudra adapter la configuration du serveur web. Par exemple,
|
||
pour Apache HTTPd, vous pouvez utiliser le module <code>rewrite</code> et la règle de réécriture suivante :</p>
|
||
<div class="highlight"><pre><span></span><code><a href="#conf-lsauthmethod-lsauthmethod_http-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a>RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTHMETHOD_HTTP_LOGOUT_REMOTE_URL</code></p>
|
||
<p>URL de déconnexion externe, utile par exemple dans le contexte d'une connexion via un service SSO.
|
||
L'utilisateur sera automatiquement redirigé vers cette URL après sa déconnexion effective au
|
||
niveau d'LdapSaisie.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Si cette URL de déconnexion n'est pas défini, le bouton de déconnexion sera masqué.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LSAUTHMETHOD_HTTP_REALM</code></p>
|
||
<p>Domaine d'authentification (<code>reaml</code>) utilisé pour réclamer l'authentification de l'utilisateur
|
||
(facultatif).</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour que le message soit traduit, utilisez la fonction <code>___()</code> (voir exemple).</p>
|
||
</div>
|
||
</li>
|
||
</ul></section><h1 class="nav-section-title-end">Ended: Configuration des méthodes d'authentification (LSauthMethod)</h1><h1 class="nav-section-title-end">Ended: Configuration</h1><section class="print-page" id="api"><h1 id="api-api">API</h1>
|
||
<p>Depuis la version 4.0, LdapSaisie offre une API visant à permettre de faire les mêmes choses que ce
|
||
qu'il est possible d'accomplir via l'interface web. L'idée n'est bien entendue pas de se substituer
|
||
systématiquement à la possibilité de se connecter directement à l'annuaire, mais plutôt d'offrir une
|
||
API web pour l'intégration d'outil préférant ce mode d'interaction, ou encore, pour exposer des
|
||
méthodes accès aux données de l'annuaire tout en profitant des logiques métiers
|
||
implémentées/configurées dans LdapSaisie : validation syntaxique et d'unicité, règle de génération
|
||
et d'interdépendances des attributs, déclencheurs, ...</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Cette API est actuellement dans une phase de test et n'offre pas encore toutes les
|
||
fonctionnalités proposées dans l'interface web. Elle est vouée à évoluer pour intégrer petit à
|
||
petit un maximum de fonctionnalités. Des contributions à ce sujet seront plus qu'appréciée !</p>
|
||
</div>
|
||
<h2 id="api-authentification">Authentification</h2>
|
||
<p>L'authentification à l'API utilise le même composant <code>LSauth</code> que lors d'une authentification à
|
||
l'interface web, cependant, ce composant s'adapte pour prendre en compte de mode de connexion. Par
|
||
défaut, la méthode d'authentification utilisée sera
|
||
<a href="#conf-lsauthmethod-lsauthmethod_http-LSauthMethod_HTTP">LSauthMethod_HTTP</a> et permettra de se
|
||
connecter en spécifiant le nom d'utilisateur et le mot de l'utilisateur cherchant à se connecter via
|
||
une authentification basique HTTP.</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Il est à noter que tous les types d'utilisateur ne peuvent pas forcément utiliser l'API : le
|
||
paramètre <code>api_access</code> doit être explicitement positionné à <code>True</code> dans
|
||
<a href="#conf-global-ldap-configuration-des-serveurs-ldap">la configuration du serveur LDAP</a>.</p>
|
||
</div>
|
||
<p>Une fois connecté, l'utilisateur endossera les droits associés à ses
|
||
<a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a>, tout comme un utilisateur
|
||
connecté à l'interface web.</p>
|
||
<h2 id="api-methodes-exposees">Méthodes exposées</h2>
|
||
<p>Les URLs des méthodes de l'API ont été construites par mimétisme sur celle de l'interface web et
|
||
sous la racine web <code>api/</code>. Par ailleurs, un numéro de version d'API a été insérée dans chacune
|
||
d'elles afin d'anticiper toutes évolutions futures majeures nécéssitants de conserver une
|
||
rétrocompatibilité avec les anciennes versions de l'API.</p>
|
||
<p>Toutes les méthodes retournent des informations au format JSON et accepte le paramètre <code>pretty</code>
|
||
permettant d'obtenir un retour plus facilement lisible. Les chaines de caractères échangées doivent
|
||
par ailleurs être encodées en UTF-8. On trouvera par ailleurs dans le retour JSON :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>success</code></p>
|
||
<p>Booléen précisant si l'action demandée a correctement été exécutée.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>messages</code></p>
|
||
<p>Ce tableau pourra être présent et lister les messages d'informations générées par l'action
|
||
demandée. Il s'agira des mêmes messages que ceux affichés dans l'interface web lorsque les
|
||
actions équivalentes y sont faites.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>errors</code>
|
||
Ce tableau pourra être présent et lister les messages d'erreurs générées par l'action demandée.</li>
|
||
</ul>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Les messages d'informations et d'erreurs générées par l'application sont traduites dans la
|
||
langue courante qui peut être spécifiée via le paramètre <code>lang</code> accepté par toutes les méthodes
|
||
(exemple : <code>fr_FR</code> ou <code>en_US</code>).</p>
|
||
</div>
|
||
<p>Lorsqu'une méthode cible un type d'objets, voir un objet en particulier, ces informations seront
|
||
transmises dans l'URL appelée. Si le type d'objet ou l'objet demandé est introuvable, une erreur
|
||
HTTP 404 sera générée.</p>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p>Sauf précision contraire, toutes les méthodes exposées sont accessibles uniquement via les
|
||
méthodes HTTP <code>GET</code> ou <code>POST</code>. L'accès via une autre méthode retournera une erreur 404.</p>
|
||
</div>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]</code></p>
|
||
<p>Cette méthode permet de rechercher/lister les informations d'un type d'objets de l'annuaire en
|
||
particulier. Le type de l'objet est précisé dans l'URL et doit être encodé en conséquence. 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 :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>filter</code></p>
|
||
<p>Permet de spécifier un filtre de recherche LDAP personnalisé. Celui-ci sera combiné avec les
|
||
paramètres propres au type d'objets recherchés et aux autres paramètres spécifiés (<code>pattern</code>
|
||
par exemple).</p>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>Du fait d'une limitation de la classe <code>Net_LDAP2_Filter</code> utilisée pour analyser le
|
||
filtre passé en paramètre, seuls les filtres simples du type <code>(attribut=valeur)</code> sont
|
||
acceptés ici. Pour les mêmes raisons, il est important que le filtre spécifié soit
|
||
toujours entourné de paranthèses.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>predefinedFilter</code></p>
|
||
<p>Permet de spécifier un des filtres de recherche LDAP prédéfinis dans la configuration du
|
||
type d'objet.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>pattern</code></p>
|
||
<p>Permet de spécifier un mot clé de recherche, comme proposé dans l'interface web.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>approx</code></p>
|
||
<p>Booléen permettant d'activer/désactiver la recherche approximative sur le mot clé. Les
|
||
valeurs acceptées sont <code>1</code> ou <code>0</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>basedn</code></p>
|
||
<p>Permet de spécifier une base de recherche personnalisé pour la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>subDn</code></p>
|
||
<p>Dans le cas d'un serveur LDAP configuré avec des
|
||
<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">sous-niveaux de connexion</a>, permet de
|
||
spécifier le sous-niveau pour la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>scope</code></p>
|
||
<p>Permet de spécifier l'étendue de la recherche dans l'annuaire. Valeurs acceptées: <code>sub</code>,
|
||
<code>one</code> et <code>base</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>recursive</code></p>
|
||
<p>Booléen permettant d'activer/désactiver la recherche recursive, c'est à dire une recherche à
|
||
la racine de l'annuaire (ou du
|
||
<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">sous-niveau de connexion</a>) avec une
|
||
étendue de recherche maximale. Les valeurs acceptées sont <code>1</code> ou <code>0</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>displayFormat</code></p>
|
||
<p>Permet de spécifier un <a href="#conf-global-lsformat-format-parametrable">LSformat</a> personnalisé
|
||
pour le nom des objets dans le résultat de recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>extraDisplayedColumns</code></p>
|
||
<p>Booléen permettant d'activer le retour des colonnes personnalisées dans le résultat de
|
||
recherche. Les valeurs acceptées sont <code>1</code> ou <code>0</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>attributes</code></p>
|
||
<p>Liste des attributs supplémentaires que devra retourner la recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>attributesDetails</code></p>
|
||
<p>Permet d'obtenir les détails sur les valeurs des attributs (au lieu des valeurs au format
|
||
attendu en cas de création/modification de l'objet). Seul la présence de ce paramètre suffit
|
||
à activer ce comportement, sa valeur n'a pas d'importance.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sortBy</code></p>
|
||
<p>Permet de préciser sur quelle information le résultat de recherche doit être trié. Valeurs
|
||
acceptées : <code>displayName</code>, <code>subDn</code> ou un des noms des colonnes personnalisées.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>sortDirection</code></p>
|
||
<p>Permet de préciser l'ordre de tri du résultat de recherche. Valeurs acceptées : <code>ASC</code> (A-Z)
|
||
ou <code>DESC</code> (Z-A).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>page</code></p>
|
||
<p>Permet de préciser la page du résultat de recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>nbObjectsByPage</code></p>
|
||
<p>Permet de préciser le nombre maximum d'objets retournés par page du résultat de recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>all</code></p>
|
||
<p>Permet de réclamer le résultat complet de la recherche (désactivation de la pagination).
|
||
Seul la présence de ce paramètre suffit à activer ce comportement, sa valeur n'a pas
|
||
d'importance.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>as_list</code></p>
|
||
<p>Permet de réclamer un résultat de recherche dans lequel, la clé <code>objects</code> sera une liste et
|
||
non un dictionnaire. Dans ce cas, le DN de l'objet est fourni dans la clé <code>dn</code> des détails
|
||
des objets. Seul la présence de ce paramètre suffit à activer ce comportement, sa valeur n'a pas
|
||
d'importance.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>withoutCache</code></p>
|
||
<p>Booléen permettant de désactiver l'utilisation du cache. Les valeurs acceptées sont <code>1</code> ou
|
||
<code>0</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>keepParamsBetweenSearches</code></p>
|
||
<p>Booléen permettant d'activer/désactiver le stockage en session des paramètres de recherche
|
||
(optionnel, par défaut : <code>False</code>). Les valeurs acceptées sont <code>1</code> ou <code>0</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople?extraDisplayedColumns=1&pretty'
|
||
<a href="#api-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>{
|
||
<a href="#api-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a> "success": true,
|
||
<a href="#api-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> "objects": {
|
||
<a href="#api-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a> "uid=hmartin,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> "name": "Henri MARTIN",
|
||
<a href="#api-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a> "Mail": "henri.martin@ls.com"
|
||
<a href="#api-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> },
|
||
<a href="#api-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> "uid=s.ldapsaisie,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> "name": "Secretariat LdapSaisie",
|
||
<a href="#api-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> "Mail": "secretariat@ldapsaisie.biz"
|
||
<a href="#api-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> },
|
||
<a href="#api-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> "uid=ls,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> "name": "LdapSaisie",
|
||
<a href="#api-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> "Mail": "ldap.saisie@ls.com"
|
||
<a href="#api-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> },
|
||
<a href="#api-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> "uid=erwpa,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> "name": "Erwan PAGE",
|
||
<a href="#api-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> "Mail": "erwan.page@ldapsaisie.biz"
|
||
<a href="#api-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> },
|
||
<a href="#api-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> "uid=user2,ou=people,ou=company1,ou=companies,o=ls": {
|
||
<a href="#api-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> "name": "prenom2 nom2",
|
||
<a href="#api-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> "Mail": "user2@ls.com"
|
||
<a href="#api-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a> }
|
||
<a href="#api-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a> },
|
||
<a href="#api-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a> "total": 14,
|
||
<a href="#api-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a> "params": {
|
||
<a href="#api-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a> "keepParamsBetweenSearches": false,
|
||
<a href="#api-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a> "filter": null,
|
||
<a href="#api-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a> "pattern": null,
|
||
<a href="#api-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a> "predefinedFilter": false,
|
||
<a href="#api-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a> "basedn": null,
|
||
<a href="#api-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a> "scope": null,
|
||
<a href="#api-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a> "sizelimit": 0,
|
||
<a href="#api-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a> "attronly": false,
|
||
<a href="#api-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a> "approx": false,
|
||
<a href="#api-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a> "recursive": true,
|
||
<a href="#api-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a> "attributes": [],
|
||
<a href="#api-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a> "onlyAccessible": true,
|
||
<a href="#api-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a> "sortDirection": null,
|
||
<a href="#api-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a> "sortBy": null,
|
||
<a href="#api-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a> "sortlimit": 0,
|
||
<a href="#api-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a> "displayFormat": "%{cn}",
|
||
<a href="#api-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a> "nbObjectsByPage": 25,
|
||
<a href="#api-__codelineno-0-45" id="__codelineno-0-45" name="__codelineno-0-45"></a> "withoutCache": false,
|
||
<a href="#api-__codelineno-0-46" id="__codelineno-0-46" name="__codelineno-0-46"></a> "extraDisplayedColumns": true
|
||
<a href="#api-__codelineno-0-47" id="__codelineno-0-47" name="__codelineno-0-47"></a> },
|
||
<a href="#api-__codelineno-0-48" id="__codelineno-0-48" name="__codelineno-0-48"></a> "page": 1,
|
||
<a href="#api-__codelineno-0-49" id="__codelineno-0-49" name="__codelineno-0-49"></a> "nbPages": 3
|
||
<a href="#api-__codelineno-0-50" id="__codelineno-0-50" name="__codelineno-0-50"></a>}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/[dn]</code></p>
|
||
<p>Cette méthode permet de récupérer les informations d'un objet de l'annuaire au format JSON. Le
|
||
type de l'objet et son DN sont précisés dans l'URL et doivent être encodés en conséquence. Par
|
||
défaut, les valeurs des attributs retournées sont au format tel qu'attendu en cas de
|
||
création/modification de l'objet. Il est cependant possible d'ajouter le paramètre <code>details</code>
|
||
afin d'obtenir des informations complémentaires sur les valeurs des attributs.</p>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-1-1" id="__codelineno-1-1" name="__codelineno-1-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=hmartin,ou=people,o=ls?pretty'
|
||
<a href="#api-__codelineno-1-2" id="__codelineno-1-2" name="__codelineno-1-2"></a>{
|
||
<a href="#api-__codelineno-1-3" id="__codelineno-1-3" name="__codelineno-1-3"></a> "success": true,
|
||
<a href="#api-__codelineno-1-4" id="__codelineno-1-4" name="__codelineno-1-4"></a> "dn": "uid=hmartin,ou=people,o=ls",
|
||
<a href="#api-__codelineno-1-5" id="__codelineno-1-5" name="__codelineno-1-5"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-1-6" id="__codelineno-1-6" name="__codelineno-1-6"></a> "name": "Henri MARTIN",
|
||
<a href="#api-__codelineno-1-7" id="__codelineno-1-7" name="__codelineno-1-7"></a> "details": false,
|
||
<a href="#api-__codelineno-1-8" id="__codelineno-1-8" name="__codelineno-1-8"></a> "attributes": {
|
||
<a href="#api-__codelineno-1-9" id="__codelineno-1-9" name="__codelineno-1-9"></a> "uid": "hmartin",
|
||
<a href="#api-__codelineno-1-10" id="__codelineno-1-10" name="__codelineno-1-10"></a> "givenName": "Henri",
|
||
<a href="#api-__codelineno-1-11" id="__codelineno-1-11" name="__codelineno-1-11"></a> "sn": "MARTIN",
|
||
<a href="#api-__codelineno-1-12" id="__codelineno-1-12" name="__codelineno-1-12"></a> "cn": "Henri MARTIN",
|
||
<a href="#api-__codelineno-1-13" id="__codelineno-1-13" name="__codelineno-1-13"></a> "mail": "henri.martin@ls.com",
|
||
<a href="#api-__codelineno-1-14" id="__codelineno-1-14" name="__codelineno-1-14"></a> "personalTitle": "M.",
|
||
<a href="#api-__codelineno-1-15" id="__codelineno-1-15" name="__codelineno-1-15"></a> "description": [],
|
||
<a href="#api-__codelineno-1-16" id="__codelineno-1-16" name="__codelineno-1-16"></a> "jpegPhoto": null,
|
||
<a href="#api-__codelineno-1-17" id="__codelineno-1-17" name="__codelineno-1-17"></a> "lsGodfatherDn": [
|
||
<a href="#api-__codelineno-1-18" id="__codelineno-1-18" name="__codelineno-1-18"></a> "uid=eeggs,ou=people,o=ls"
|
||
<a href="#api-__codelineno-1-19" id="__codelineno-1-19" name="__codelineno-1-19"></a> ],
|
||
<a href="#api-__codelineno-1-20" id="__codelineno-1-20" name="__codelineno-1-20"></a> "uidNumber": "101022",
|
||
<a href="#api-__codelineno-1-21" id="__codelineno-1-21" name="__codelineno-1-21"></a> "gidNumber": "102001",
|
||
<a href="#api-__codelineno-1-22" id="__codelineno-1-22" name="__codelineno-1-22"></a> "loginShell": "no",
|
||
<a href="#api-__codelineno-1-23" id="__codelineno-1-23" name="__codelineno-1-23"></a> "homeDirectory": "\/home\/com",
|
||
<a href="#api-__codelineno-1-24" id="__codelineno-1-24" name="__codelineno-1-24"></a> "gecos": null,
|
||
<a href="#api-__codelineno-1-25" id="__codelineno-1-25" name="__codelineno-1-25"></a> "shadowExpire": null,
|
||
<a href="#api-__codelineno-1-26" id="__codelineno-1-26" name="__codelineno-1-26"></a> "shadowMax": null,
|
||
<a href="#api-__codelineno-1-27" id="__codelineno-1-27" name="__codelineno-1-27"></a> "shadowInactive": null,
|
||
<a href="#api-__codelineno-1-28" id="__codelineno-1-28" name="__codelineno-1-28"></a> "shadowLastChange": null,
|
||
<a href="#api-__codelineno-1-29" id="__codelineno-1-29" name="__codelineno-1-29"></a> "sambaSID": "S-1-5-21-2421470416-3566881284-3047381809-203044",
|
||
<a href="#api-__codelineno-1-30" id="__codelineno-1-30" name="__codelineno-1-30"></a> "sambaPrimaryGroupSID": "S-1-5-21-2421470416-3566881284-3047381809-205003",
|
||
<a href="#api-__codelineno-1-31" id="__codelineno-1-31" name="__codelineno-1-31"></a> "sambaAcctFlags": [
|
||
<a href="#api-__codelineno-1-32" id="__codelineno-1-32" name="__codelineno-1-32"></a> "U"
|
||
<a href="#api-__codelineno-1-33" id="__codelineno-1-33" name="__codelineno-1-33"></a> ],
|
||
<a href="#api-__codelineno-1-34" id="__codelineno-1-34" name="__codelineno-1-34"></a> "sambaHomeDrive": null,
|
||
<a href="#api-__codelineno-1-35" id="__codelineno-1-35" name="__codelineno-1-35"></a> "sambaHomePath": null,
|
||
<a href="#api-__codelineno-1-36" id="__codelineno-1-36" name="__codelineno-1-36"></a> "sambaProfilePath": null,
|
||
<a href="#api-__codelineno-1-37" id="__codelineno-1-37" name="__codelineno-1-37"></a> "sambaLogonScript": null,
|
||
<a href="#api-__codelineno-1-38" id="__codelineno-1-38" name="__codelineno-1-38"></a> "sambaLogonTime": null,
|
||
<a href="#api-__codelineno-1-39" id="__codelineno-1-39" name="__codelineno-1-39"></a> "sambaLogoffTime": null,
|
||
<a href="#api-__codelineno-1-40" id="__codelineno-1-40" name="__codelineno-1-40"></a> "sambaKickoffTime": null,
|
||
<a href="#api-__codelineno-1-41" id="__codelineno-1-41" name="__codelineno-1-41"></a> "sambaPwdLastSet": null,
|
||
<a href="#api-__codelineno-1-42" id="__codelineno-1-42" name="__codelineno-1-42"></a> "sambaPwdMustChange": null,
|
||
<a href="#api-__codelineno-1-43" id="__codelineno-1-43" name="__codelineno-1-43"></a> "sambaPwdCanChange": null
|
||
<a href="#api-__codelineno-1-44" id="__codelineno-1-44" name="__codelineno-1-44"></a> },
|
||
<a href="#api-__codelineno-1-45" id="__codelineno-1-45" name="__codelineno-1-45"></a> "relations": {
|
||
<a href="#api-__codelineno-1-46" id="__codelineno-1-46" name="__codelineno-1-46"></a> "groups": {
|
||
<a href="#api-__codelineno-1-47" id="__codelineno-1-47" name="__codelineno-1-47"></a> "cn=direction,ou=groups,o=ls": "direction",
|
||
<a href="#api-__codelineno-1-48" id="__codelineno-1-48" name="__codelineno-1-48"></a> "cn=secretariat,ou=groups,o=ls": "secretariat"
|
||
<a href="#api-__codelineno-1-49" id="__codelineno-1-49" name="__codelineno-1-49"></a> },
|
||
<a href="#api-__codelineno-1-50" id="__codelineno-1-50" name="__codelineno-1-50"></a> "godfather": []
|
||
<a href="#api-__codelineno-1-51" id="__codelineno-1-51" name="__codelineno-1-51"></a> }
|
||
<a href="#api-__codelineno-1-52" id="__codelineno-1-52" name="__codelineno-1-52"></a>}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/create</code></p>
|
||
<p>Cette méthode permet de créer un objet dans l'annuaire. Le type de l'objet qui sera créé est
|
||
précisé dans l'URL et doit être encodé en conséquence. Les informations de l'objet doivent est
|
||
transmises au format <code>x-www-form-urlencoded</code>. Elles peuvent également être au format
|
||
<code>multipart/form-data</code>, en particulier si votre requête contient une image. Par mimétisme avec
|
||
l'interface web, seuls les attributs prévus dans le formulaire de création du type d'objet
|
||
peuvent être passées ici. De la même manière, les attributs non-spécifiés ici, pouront être
|
||
auto-générés en accord avec leur configuration et la requête sera acceptée uniquement si tous
|
||
les attributs obligatoires y sont spécifiés ou s'ils peuvent être auto-générés.</p>
|
||
<p>Le format et la syntaxe des valeurs des attributs dépends de leur type HTML. Ainsi, par exemple,
|
||
un attribut de type HTML <code>boolean</code> acceptera comme valeurs possibles <code>yes</code> ou <code>no</code>. Pour plus
|
||
de détails sur le type de valeur acceptée par un type d'attribut HTML en particulier, consultez
|
||
sa documentation. Vous pouvez également analyser le code de la méthode <code>getPostData()</code> de la
|
||
classe <a href="http://www.php.net/">PHP</a> correspondante.</p>
|
||
<p>Si l'application détecte un souci avec les informations transmises pour les attributs, un
|
||
tableau <code>fields_errors</code> sera présent dans la réponse JSON et contiendra pour chacun des
|
||
attributs problématique, un tableau des messages d'erreurs générées par l'application.</p>
|
||
<p>Si le type d'objet en prévoit, vous pouvez également utiliser un
|
||
<a href="#conf-lsobject-lsform-configuration-des-masques-de-saisie">masque de saisie</a> via le
|
||
paramètre <code>dataEntryForm</code>.</p>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-2-1" id="__codelineno-2-1" name="__codelineno-2-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/create?pretty' -d "uid=foo.bar&personalTitle=M.&givenName=foo&sn=bar&cn=Foo Bar&mail=foo.bar@example.com&userPassword=Y0urS3cr3t&lsGodfatherDn[]=uid=admin,ou=people,o=ls&gidNumber=70000"
|
||
<a href="#api-__codelineno-2-2" id="__codelineno-2-2" name="__codelineno-2-2"></a>{
|
||
<a href="#api-__codelineno-2-3" id="__codelineno-2-3" name="__codelineno-2-3"></a> "success": true,
|
||
<a href="#api-__codelineno-2-4" id="__codelineno-2-4" name="__codelineno-2-4"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-2-5" id="__codelineno-2-5" name="__codelineno-2-5"></a> "dn": "uid=foo.bar,ou=people,o=ls",
|
||
<a href="#api-__codelineno-2-6" id="__codelineno-2-6" name="__codelineno-2-6"></a> "name": "Foo Bar",
|
||
<a href="#api-__codelineno-2-7" id="__codelineno-2-7" name="__codelineno-2-7"></a> "messages": [
|
||
<a href="#api-__codelineno-2-8" id="__codelineno-2-8" name="__codelineno-2-8"></a> "Le mail de notification a \u00e9t\u00e9 envoy\u00e9.",
|
||
<a href="#api-__codelineno-2-9" id="__codelineno-2-9" name="__codelineno-2-9"></a> "L'objet a \u00e9t\u00e9 ajout\u00e9."
|
||
<a href="#api-__codelineno-2-10" id="__codelineno-2-10" name="__codelineno-2-10"></a> ]
|
||
<a href="#api-__codelineno-2-11" id="__codelineno-2-11" name="__codelineno-2-11"></a>}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/[dn]/modify</code></p>
|
||
<p>Cette méthode permet de modifier un objet dans l'annuaire. Le type de l'objet et son DN sont
|
||
précisés dans l'URL et doivent être encodés en conséquence. Les informations de l'objet à
|
||
modifier doivent être transmises au même format que pour la méthode <code>create</code> (voir ci-dessus).
|
||
Comme pour cette dernière, seuls les attributs prévus dans le formulaire de modification du type
|
||
d'objet peuvent être passées ici et la réponse JSON pourra contenir un tableau <code>fields_errors</code>
|
||
contenant les erreurs générées par l'application au sujet des valeurs transmises pour les
|
||
attributs.</p>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-3-1" id="__codelineno-3-1" name="__codelineno-3-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=people,o=ls/modify?pretty' -d "givenName=foo&sn=bar&cn=Foo Bar"
|
||
<a href="#api-__codelineno-3-2" id="__codelineno-3-2" name="__codelineno-3-2"></a>{
|
||
<a href="#api-__codelineno-3-3" id="__codelineno-3-3" name="__codelineno-3-3"></a> "dn": "uid=foo.bar,ou=people,o=ls",
|
||
<a href="#api-__codelineno-3-4" id="__codelineno-3-4" name="__codelineno-3-4"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-3-5" id="__codelineno-3-5" name="__codelineno-3-5"></a> "name": "Foo Bar",
|
||
<a href="#api-__codelineno-3-6" id="__codelineno-3-6" name="__codelineno-3-6"></a> "success": true,
|
||
<a href="#api-__codelineno-3-7" id="__codelineno-3-7" name="__codelineno-3-7"></a> "messages": [
|
||
<a href="#api-__codelineno-3-8" id="__codelineno-3-8" name="__codelineno-3-8"></a> "L'objet a bien \u00e9t\u00e9 modifi\u00e9."
|
||
<a href="#api-__codelineno-3-9" id="__codelineno-3-9" name="__codelineno-3-9"></a> ]
|
||
<a href="#api-__codelineno-3-10" id="__codelineno-3-10" name="__codelineno-3-10"></a>}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/[dn]/remove</code></p>
|
||
<p>Cette méthode permet de supprimer un objet dans l'annuaire. Le type de l'objet et son DN sont
|
||
précisés dans l'URL et doivent être encodés en conséquence.</p>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-4-1" id="__codelineno-4-1" name="__codelineno-4-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=people,o=ls/remove?pretty'
|
||
<a href="#api-__codelineno-4-2" id="__codelineno-4-2" name="__codelineno-4-2"></a>{
|
||
<a href="#api-__codelineno-4-3" id="__codelineno-4-3" name="__codelineno-4-3"></a> "dn": "uid=foo.bar,ou=people,o=ls",
|
||
<a href="#api-__codelineno-4-4" id="__codelineno-4-4" name="__codelineno-4-4"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-4-5" id="__codelineno-4-5" name="__codelineno-4-5"></a> "name": "Foo Bar",
|
||
<a href="#api-__codelineno-4-6" id="__codelineno-4-6" name="__codelineno-4-6"></a> "success": true,
|
||
<a href="#api-__codelineno-4-7" id="__codelineno-4-7" name="__codelineno-4-7"></a> "messages": [
|
||
<a href="#api-__codelineno-4-8" id="__codelineno-4-8" name="__codelineno-4-8"></a> "Foo Bar a bien \u00e9t\u00e9 supprim\u00e9."
|
||
<a href="#api-__codelineno-4-9" id="__codelineno-4-9" name="__codelineno-4-9"></a> ]
|
||
<a href="#api-__codelineno-4-10" id="__codelineno-4-10" name="__codelineno-4-10"></a>}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/[dn]/customAction/[customAction]</code></p>
|
||
<p>Cette méthode permet d'exécuter une <a href="#conf-lsobject-customactions">action personnalisée</a> 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.</p>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-5-1" id="__codelineno-5-1" name="__codelineno-5-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=people,o=ls/customAction/action?pretty'
|
||
<a href="#api-__codelineno-5-2" id="__codelineno-5-2" name="__codelineno-5-2"></a>{
|
||
<a href="#api-__codelineno-5-3" id="__codelineno-5-3" name="__codelineno-5-3"></a> "dn": "uid=foo.bar,ou=people,o=ls",
|
||
<a href="#api-__codelineno-5-4" id="__codelineno-5-4" name="__codelineno-5-4"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-5-5" id="__codelineno-5-5" name="__codelineno-5-5"></a> "name": "Foo Bar",
|
||
<a href="#api-__codelineno-5-6" id="__codelineno-5-6" name="__codelineno-5-6"></a> "success": true,
|
||
<a href="#api-__codelineno-5-7" id="__codelineno-5-7" name="__codelineno-5-7"></a> "messages": [
|
||
<a href="#api-__codelineno-5-8" id="__codelineno-5-8" name="__codelineno-5-8"></a> "L'action personnalis\u00e9e action a \u00e9t\u00e9 correctement ex\u00e9cut\u00e9e sur Foo Bar.",
|
||
<a href="#api-__codelineno-5-9" id="__codelineno-5-9" name="__codelineno-5-9"></a> ]
|
||
<a href="#api-__codelineno-5-10" id="__codelineno-5-10" name="__codelineno-5-10"></a>}
|
||
</code></pre></div>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>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 <a href="#conf-lsobject-customactions-ecriture-dune-fonction-implementant-une-customaction">documentation sur l'écriture d'une fonction implémentant une customAction</a>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/import</code></p>
|
||
<p>Cette méthode permet d'importer des objets d'un type en particulier à partir de données d'import
|
||
formatées selon un <a href="#conf-lsobject-ioformat-ioformat">ioFormat</a> configuré pour ce type
|
||
d'objets. Le type de l'objet est précisé dans l'URL et doit être encodé en conséquence. Par
|
||
mimétisme du comportement de l'interface web, cette méthode accepte des paramètres similaires et
|
||
s'attend à récupérer les données d'import dans le corps de la requête.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>ioFormat</code></p>
|
||
<p>Le nom de l'<a href="#conf-lsobject-ioformat-ioformat">ioFormat</a>des données d'import.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>updateIfExists</code></p>
|
||
<p>Booléen permettant d'activer/désactiver la mise à jour des données des objets s'ils existent
|
||
déjà. Si ce mode est inactif et qu'un objet des données d'import existe déjà, une erreur
|
||
sera remontée. Les valeurs acceptées sont <code>1</code> ou <code>0</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>justTry</code></p>
|
||
<p>Booléen permettant d'activer/désactiver le mode de vérification des données d'import
|
||
uniquement. Si ce mode est actif, les données d'import seront analysées pour vérifier
|
||
qu'elles sont correctes, mais l'import en lui-même ne sera pas effectué. Les valeurs
|
||
acceptées sont <code>1</code> ou <code>0</code>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Le retour de cette méthode en mode <code>justTry</code> est identique à une exécution en mode
|
||
normal. Ce mode permet donc d'anticiper le résultat d'un import à partir d'un jeu de
|
||
données sources.</p>
|
||
</div>
|
||
<div class="admonition warning">
|
||
<p class="admonition-title">Warning</p>
|
||
<p>En mode <code>justTry</code>, seul la vérification syntaxique des données est fiable, car les
|
||
informations doublonnées au sein des données d'import ne pourront être détectées.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<p>En cas d'erreurs détectées dans les informations des objets des données d'import, le tableau
|
||
<code>errors</code> du retour de la méthode contiendra une entrée pour chaque objet en erreur sous le
|
||
format d'un dictionnaire dont la clé <code>data</code> reprendra les informations de l'objet telle que
|
||
chargé (ou générée) depuis les données sources, ainsi qu'un dictionnaire sous la clé <code>errors</code>
|
||
qui contiendra les erreurs globales concernant l'objet sous la clé <code>globals</code> et les erreurs
|
||
propres à ses attributs dans un dictionnaire sous la clé <code>attrs</code>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Les erreurs d'importation sur un objet sont non-bloquantes : l'importation des autres objets
|
||
ne sera pas interrompue.</p>
|
||
</div>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-6-1" id="__codelineno-6-1" name="__codelineno-6-1"></a># curl -u username:secret --data-binary @/path/to/input.file 'https://ldapsaisie/api/1.0/object/LSpeople/import?ioFormat=mycsv&pretty'
|
||
<a href="#api-__codelineno-6-2" id="__codelineno-6-2" name="__codelineno-6-2"></a>{
|
||
<a href="#api-__codelineno-6-3" id="__codelineno-6-3" name="__codelineno-6-3"></a> "success": false,
|
||
<a href="#api-__codelineno-6-4" id="__codelineno-6-4" name="__codelineno-6-4"></a> "LSobject": "LSpeople",
|
||
<a href="#api-__codelineno-6-5" id="__codelineno-6-5" name="__codelineno-6-5"></a> "ioFormat": "mycsv",
|
||
<a href="#api-__codelineno-6-6" id="__codelineno-6-6" name="__codelineno-6-6"></a> "updateIfExists": false,
|
||
<a href="#api-__codelineno-6-7" id="__codelineno-6-7" name="__codelineno-6-7"></a> "justTry": false,
|
||
<a href="#api-__codelineno-6-8" id="__codelineno-6-8" name="__codelineno-6-8"></a> "imported": {
|
||
<a href="#api-__codelineno-6-9" id="__codelineno-6-9" name="__codelineno-6-9"></a> "uid=rturin,ou=people,o=ls": "M. Roger TURIN"
|
||
<a href="#api-__codelineno-6-10" id="__codelineno-6-10" name="__codelineno-6-10"></a> },
|
||
<a href="#api-__codelineno-6-11" id="__codelineno-6-11" name="__codelineno-6-11"></a> "updated": [],
|
||
<a href="#api-__codelineno-6-12" id="__codelineno-6-12" name="__codelineno-6-12"></a> "errors": [
|
||
<a href="#api-__codelineno-6-13" id="__codelineno-6-13" name="__codelineno-6-13"></a> {
|
||
<a href="#api-__codelineno-6-14" id="__codelineno-6-14" name="__codelineno-6-14"></a> "data": {
|
||
<a href="#api-__codelineno-6-15" id="__codelineno-6-15" name="__codelineno-6-15"></a> "uid": [
|
||
<a href="#api-__codelineno-6-16" id="__codelineno-6-16" name="__codelineno-6-16"></a> "lmartin"
|
||
<a href="#api-__codelineno-6-17" id="__codelineno-6-17" name="__codelineno-6-17"></a> ],
|
||
<a href="#api-__codelineno-6-18" id="__codelineno-6-18" name="__codelineno-6-18"></a> "personalTitle": [
|
||
<a href="#api-__codelineno-6-19" id="__codelineno-6-19" name="__codelineno-6-19"></a> "Mme"
|
||
<a href="#api-__codelineno-6-20" id="__codelineno-6-20" name="__codelineno-6-20"></a> ],
|
||
<a href="#api-__codelineno-6-21" id="__codelineno-6-21" name="__codelineno-6-21"></a> "givenName": [
|
||
<a href="#api-__codelineno-6-22" id="__codelineno-6-22" name="__codelineno-6-22"></a> "Ludivine"
|
||
<a href="#api-__codelineno-6-23" id="__codelineno-6-23" name="__codelineno-6-23"></a> ],
|
||
<a href="#api-__codelineno-6-24" id="__codelineno-6-24" name="__codelineno-6-24"></a> "sn": [
|
||
<a href="#api-__codelineno-6-25" id="__codelineno-6-25" name="__codelineno-6-25"></a> "MARTIN"
|
||
<a href="#api-__codelineno-6-26" id="__codelineno-6-26" name="__codelineno-6-26"></a> ],
|
||
<a href="#api-__codelineno-6-27" id="__codelineno-6-27" name="__codelineno-6-27"></a> "mail": [
|
||
<a href="#api-__codelineno-6-28" id="__codelineno-6-28" name="__codelineno-6-28"></a> "lmartin@gmail.com"
|
||
<a href="#api-__codelineno-6-29" id="__codelineno-6-29" name="__codelineno-6-29"></a> ],
|
||
<a href="#api-__codelineno-6-30" id="__codelineno-6-30" name="__codelineno-6-30"></a> "userPassword": [
|
||
<a href="#api-__codelineno-6-31" id="__codelineno-6-31" name="__codelineno-6-31"></a> "123Yh%uT"
|
||
<a href="#api-__codelineno-6-32" id="__codelineno-6-32" name="__codelineno-6-32"></a> ],
|
||
<a href="#api-__codelineno-6-33" id="__codelineno-6-33" name="__codelineno-6-33"></a> "gidNumber": [
|
||
<a href="#api-__codelineno-6-34" id="__codelineno-6-34" name="__codelineno-6-34"></a> "102009"
|
||
<a href="#api-__codelineno-6-35" id="__codelineno-6-35" name="__codelineno-6-35"></a> ],
|
||
<a href="#api-__codelineno-6-36" id="__codelineno-6-36" name="__codelineno-6-36"></a> "loginShell": [
|
||
<a href="#api-__codelineno-6-37" id="__codelineno-6-37" name="__codelineno-6-37"></a> "no"
|
||
<a href="#api-__codelineno-6-38" id="__codelineno-6-38" name="__codelineno-6-38"></a> ],
|
||
<a href="#api-__codelineno-6-39" id="__codelineno-6-39" name="__codelineno-6-39"></a> "cn": [
|
||
<a href="#api-__codelineno-6-40" id="__codelineno-6-40" name="__codelineno-6-40"></a> "Mme Ludivine MARTIN"
|
||
<a href="#api-__codelineno-6-41" id="__codelineno-6-41" name="__codelineno-6-41"></a> ]
|
||
<a href="#api-__codelineno-6-42" id="__codelineno-6-42" name="__codelineno-6-42"></a> },
|
||
<a href="#api-__codelineno-6-43" id="__codelineno-6-43" name="__codelineno-6-43"></a> "errors": {
|
||
<a href="#api-__codelineno-6-44" id="__codelineno-6-44" name="__codelineno-6-44"></a> "globals": [
|
||
<a href="#api-__codelineno-6-45" id="__codelineno-6-45" name="__codelineno-6-45"></a> "Un objet existe d\u00e9j\u00e0 dans l'annuaire LDAP avec le DN uid=lmartin,ou=people,o=ls."
|
||
<a href="#api-__codelineno-6-46" id="__codelineno-6-46" name="__codelineno-6-46"></a> ],
|
||
<a href="#api-__codelineno-6-47" id="__codelineno-6-47" name="__codelineno-6-47"></a> "attrs": []
|
||
<a href="#api-__codelineno-6-48" id="__codelineno-6-48" name="__codelineno-6-48"></a> }
|
||
<a href="#api-__codelineno-6-49" id="__codelineno-6-49" name="__codelineno-6-49"></a> }
|
||
<a href="#api-__codelineno-6-50" id="__codelineno-6-50" name="__codelineno-6-50"></a> ],
|
||
<a href="#api-__codelineno-6-51" id="__codelineno-6-51" name="__codelineno-6-51"></a> "messages": [
|
||
<a href="#api-__codelineno-6-52" id="__codelineno-6-52" name="__codelineno-6-52"></a> "Le mail de notification a \u00e9t\u00e9 envoy\u00e9."
|
||
<a href="#api-__codelineno-6-53" id="__codelineno-6-53" name="__codelineno-6-53"></a> ]
|
||
<a href="#api-__codelineno-6-54" id="__codelineno-6-54" name="__codelineno-6-54"></a>}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/export</code></p>
|
||
<p>Cette méthode permet d'exporter les objets d'un type en particulier dans un
|
||
<a href="#conf-lsobject-ioformat-ioformat">ioFormat</a> configuré pour ce type d'objets. Le type de
|
||
l'objet est précisé dans l'URL et doit être encodé en conséquence.</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>ioFormat</code></p>
|
||
<p>Le nom de l'<a href="#conf-lsobject-ioformat-ioformat">ioFormat</a> .</p>
|
||
</li>
|
||
</ul>
|
||
<p>En tant normal, le retour de cette méthode sera directement le fichier d'export demandé.
|
||
Cependant, si une erreur survient, les paramètres d'export seront repris dans le retour <code>JSON</code>
|
||
de la méthode qui contiendra également les erreurs survenues.</p>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-7-1" id="__codelineno-7-1" name="__codelineno-7-1"></a># curl -u username:secret --data-binary @/path/to/input.file 'https://ldapsaisie/api/1.0/object/LSpeople/export?ioFormat=mycsv&pretty'
|
||
<a href="#api-__codelineno-7-2" id="__codelineno-7-2" name="__codelineno-7-2"></a>login;civility;firstname;name;mail;password;gid;shell
|
||
<a href="#api-__codelineno-7-3" id="__codelineno-7-3" name="__codelineno-7-3"></a>hmartin;M.;Henri;MARTIN;henri.martin@ls.com;********;102001;no
|
||
<a href="#api-__codelineno-7-4" id="__codelineno-7-4" name="__codelineno-7-4"></a>s.ldapsaisie;M.;Secretariat;LdapSaisie;secretariat@ldapsaisie.biz;********;70000;no
|
||
<a href="#api-__codelineno-7-5" id="__codelineno-7-5" name="__codelineno-7-5"></a>ls;M.;Ldap;Saisie;ldap.saisie@ls.com;********;102001;no
|
||
<a href="#api-__codelineno-7-6" id="__codelineno-7-6" name="__codelineno-7-6"></a>erwpa;M.;Erwan;PAGEARD;erwan.page@ldapsaisie.biz;********;102009;no
|
||
<a href="#api-__codelineno-7-7" id="__codelineno-7-7" name="__codelineno-7-7"></a>[...]
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/object/[object type]/[dn]/relation/[relation]</code></p>
|
||
<p>Cette méthode permet de gérer les objets en relation avec un objet en particulier de l'annuaire.
|
||
Le type de l'objet, son DN et le nom de la relation sont précisés dans l'URL et doivent être
|
||
encodés en conséquence. Cette méthode accepte les paramètres <code>add</code> et <code>remove</code> permettant de
|
||
lister le ou les DN d'objet(s) à respectivement ajouter ou supprimer parmis les objets
|
||
actuellement en relation avec l'objet spécifié. Si aucun DN n'est spécifié comme devant être
|
||
ajouté ou supprimé, la méthode retournera simplement les DN des objets en relation. En cas de
|
||
modification demandée, la méthode retournera la nouvelle liste des DNs des objets en relation,
|
||
quel que soit le résultat de l'opération de mise à jour.</p>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-8-1" id="__codelineno-8-1" name="__codelineno-8-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/object/LSpeople/uid=foo.bar,ou=people,o=ls/relation/groups?pretty&add[]=cn=ls,ou=groups,o=ls&add[]=cn=invite,ou=groups,o=ls'
|
||
<a href="#api-__codelineno-8-2" id="__codelineno-8-2" name="__codelineno-8-2"></a>{
|
||
<a href="#api-__codelineno-8-3" id="__codelineno-8-3" name="__codelineno-8-3"></a> "dn": "uid=foo.bar,ou=people,o=ls",
|
||
<a href="#api-__codelineno-8-4" id="__codelineno-8-4" name="__codelineno-8-4"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-8-5" id="__codelineno-8-5" name="__codelineno-8-5"></a> "name": "Foo Bar",
|
||
<a href="#api-__codelineno-8-6" id="__codelineno-8-6" name="__codelineno-8-6"></a> "relation": "groups",
|
||
<a href="#api-__codelineno-8-7" id="__codelineno-8-7" name="__codelineno-8-7"></a> "success": true,
|
||
<a href="#api-__codelineno-8-8" id="__codelineno-8-8" name="__codelineno-8-8"></a> "relatedObjects": [
|
||
<a href="#api-__codelineno-8-9" id="__codelineno-8-9" name="__codelineno-8-9"></a> "cn=ls,ou=groups,o=ls",
|
||
<a href="#api-__codelineno-8-10" id="__codelineno-8-10" name="__codelineno-8-10"></a> "cn=invite,ou=groups,o=ls"
|
||
<a href="#api-__codelineno-8-11" id="__codelineno-8-11" name="__codelineno-8-11"></a> ],
|
||
<a href="#api-__codelineno-8-12" id="__codelineno-8-12" name="__codelineno-8-12"></a> "messages": [
|
||
<a href="#api-__codelineno-8-13" id="__codelineno-8-13" name="__codelineno-8-13"></a> "Objects in relation updated."
|
||
<a href="#api-__codelineno-8-14" id="__codelineno-8-14" name="__codelineno-8-14"></a> ]
|
||
<a href="#api-__codelineno-8-15" id="__codelineno-8-15" name="__codelineno-8-15"></a>}
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>/api/1.0/search</code></p>
|
||
<p>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.</p>
|
||
<p>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 :</p>
|
||
<ul>
|
||
<li><code>filter</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>predefinedFilter</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>pattern</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>approx</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>basedn</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>subDn</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>scope</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>recursive</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>displayFormat</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>extraDisplayedColumns</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>attributes</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>attributesDetails</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>page</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>all</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>as_list</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>withoutCache</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>keepParamsBetweenSearches</code></li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>nbObjectsByPage</code></p>
|
||
<p>Permet de préciser le nombre maximum d'objets retournés par type d'objet ET par page du résultat
|
||
de recherche.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>types</code></p>
|
||
<p>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.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>splited_result</code></p>
|
||
<p>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 <code>objects</code>. Par défaut, tous les objets sont retournés dans la clé
|
||
<code>objects</code> et une sous-clé <code>type</code> 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.</p>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<div class="admonition important">
|
||
<p class="admonition-title">Important</p>
|
||
<p><strong>Pour chaque type d'objets inclus dans la recherche, un filtre et/ou un mot clé de recherche
|
||
doit être spécifié.</strong> Cette méthode n'a pas vocation à permettre de lister tous les objets de
|
||
l'annuaire.</p>
|
||
</div>
|
||
<p><strong>Exemple :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#api-__codelineno-9-1" id="__codelineno-9-1" name="__codelineno-9-1"></a># curl -u username:secret 'https://ldapsaisie/api/1.0/search?pattern=LdapSaisie&pretty'
|
||
<a href="#api-__codelineno-9-2" id="__codelineno-9-2" name="__codelineno-9-2"></a>{
|
||
<a href="#api-__codelineno-9-3" id="__codelineno-9-3" name="__codelineno-9-3"></a> "success": true,
|
||
<a href="#api-__codelineno-9-4" id="__codelineno-9-4" name="__codelineno-9-4"></a> "objects": {
|
||
<a href="#api-__codelineno-9-5" id="__codelineno-9-5" name="__codelineno-9-5"></a> "uid=s.ldapsaisie,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-9-6" id="__codelineno-9-6" name="__codelineno-9-6"></a> "name": "Secretariat LdapSaisie",
|
||
<a href="#api-__codelineno-9-7" id="__codelineno-9-7" name="__codelineno-9-7"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-9-8" id="__codelineno-9-8" name="__codelineno-9-8"></a> "Mail": "secretariat@ldapsaisie.biz"
|
||
<a href="#api-__codelineno-9-9" id="__codelineno-9-9" name="__codelineno-9-9"></a> },
|
||
<a href="#api-__codelineno-9-10" id="__codelineno-9-10" name="__codelineno-9-10"></a> "uid=ls,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-9-11" id="__codelineno-9-11" name="__codelineno-9-11"></a> "name": "LdapSaisie",
|
||
<a href="#api-__codelineno-9-12" id="__codelineno-9-12" name="__codelineno-9-12"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-9-13" id="__codelineno-9-13" name="__codelineno-9-13"></a> "Mail": "ldap.saisie@ls.com"
|
||
<a href="#api-__codelineno-9-14" id="__codelineno-9-14" name="__codelineno-9-14"></a> },
|
||
<a href="#api-__codelineno-9-15" id="__codelineno-9-15" name="__codelineno-9-15"></a> "uid=erwpa,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-9-16" id="__codelineno-9-16" name="__codelineno-9-16"></a> "name": "Erwan PAGE",
|
||
<a href="#api-__codelineno-9-17" id="__codelineno-9-17" name="__codelineno-9-17"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-9-18" id="__codelineno-9-18" name="__codelineno-9-18"></a> "Mail": "erwan.page@ldapsaisie.biz"
|
||
<a href="#api-__codelineno-9-19" id="__codelineno-9-19" name="__codelineno-9-19"></a> },
|
||
<a href="#api-__codelineno-9-20" id="__codelineno-9-20" name="__codelineno-9-20"></a> "uid=invite,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-9-21" id="__codelineno-9-21" name="__codelineno-9-21"></a> "name": "Utilisateur de passage",
|
||
<a href="#api-__codelineno-9-22" id="__codelineno-9-22" name="__codelineno-9-22"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-9-23" id="__codelineno-9-23" name="__codelineno-9-23"></a> "Mail": "invite@ldapsaisie.biz"
|
||
<a href="#api-__codelineno-9-24" id="__codelineno-9-24" name="__codelineno-9-24"></a> },
|
||
<a href="#api-__codelineno-9-25" id="__codelineno-9-25" name="__codelineno-9-25"></a> "uid=demo,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-9-26" id="__codelineno-9-26" name="__codelineno-9-26"></a> "name": "Demonstration LdapSaisie",
|
||
<a href="#api-__codelineno-9-27" id="__codelineno-9-27" name="__codelineno-9-27"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-9-28" id="__codelineno-9-28" name="__codelineno-9-28"></a> "Mail": "demo@ls.com"
|
||
<a href="#api-__codelineno-9-29" id="__codelineno-9-29" name="__codelineno-9-29"></a> },
|
||
<a href="#api-__codelineno-9-30" id="__codelineno-9-30" name="__codelineno-9-30"></a> "uid=admin,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-9-31" id="__codelineno-9-31" name="__codelineno-9-31"></a> "name": "Administration LdapSaisie",
|
||
<a href="#api-__codelineno-9-32" id="__codelineno-9-32" name="__codelineno-9-32"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-9-33" id="__codelineno-9-33" name="__codelineno-9-33"></a> "Mail": "admin@ls.com"
|
||
<a href="#api-__codelineno-9-34" id="__codelineno-9-34" name="__codelineno-9-34"></a> },
|
||
<a href="#api-__codelineno-9-35" id="__codelineno-9-35" name="__codelineno-9-35"></a> "uid=admin3,ou=people,o=ls": {
|
||
<a href="#api-__codelineno-9-36" id="__codelineno-9-36" name="__codelineno-9-36"></a> "name": "ZAdministration LdapSaisie",
|
||
<a href="#api-__codelineno-9-37" id="__codelineno-9-37" name="__codelineno-9-37"></a> "type": "LSpeople",
|
||
<a href="#api-__codelineno-9-38" id="__codelineno-9-38" name="__codelineno-9-38"></a> "Mail": "admin@ls.com"
|
||
<a href="#api-__codelineno-9-39" id="__codelineno-9-39" name="__codelineno-9-39"></a> },
|
||
<a href="#api-__codelineno-9-40" id="__codelineno-9-40" name="__codelineno-9-40"></a> "uid=ldapsaisie,ou=sysaccounts,o=ls": {
|
||
<a href="#api-__codelineno-9-41" id="__codelineno-9-41" name="__codelineno-9-41"></a> "name": "ldapsaisie",
|
||
<a href="#api-__codelineno-9-42" id="__codelineno-9-42" name="__codelineno-9-42"></a> "type": "LSsysaccount"
|
||
<a href="#api-__codelineno-9-43" id="__codelineno-9-43" name="__codelineno-9-43"></a> }
|
||
<a href="#api-__codelineno-9-44" id="__codelineno-9-44" name="__codelineno-9-44"></a> },
|
||
<a href="#api-__codelineno-9-45" id="__codelineno-9-45" name="__codelineno-9-45"></a> "total": null,
|
||
<a href="#api-__codelineno-9-46" id="__codelineno-9-46" name="__codelineno-9-46"></a> "params": {
|
||
<a href="#api-__codelineno-9-47" id="__codelineno-9-47" name="__codelineno-9-47"></a> "keepParamsBetweenSearches": false,
|
||
<a href="#api-__codelineno-9-48" id="__codelineno-9-48" name="__codelineno-9-48"></a> "LSpeople": {
|
||
<a href="#api-__codelineno-9-49" id="__codelineno-9-49" name="__codelineno-9-49"></a> "filter": null,
|
||
<a href="#api-__codelineno-9-50" id="__codelineno-9-50" name="__codelineno-9-50"></a> "pattern": "LdapSaisie",
|
||
<a href="#api-__codelineno-9-51" id="__codelineno-9-51" name="__codelineno-9-51"></a> "predefinedFilter": false,
|
||
<a href="#api-__codelineno-9-52" id="__codelineno-9-52" name="__codelineno-9-52"></a> "basedn": null,
|
||
<a href="#api-__codelineno-9-53" id="__codelineno-9-53" name="__codelineno-9-53"></a> "scope": null,
|
||
<a href="#api-__codelineno-9-54" id="__codelineno-9-54" name="__codelineno-9-54"></a> "sizelimit": 0,
|
||
<a href="#api-__codelineno-9-55" id="__codelineno-9-55" name="__codelineno-9-55"></a> "attronly": false,
|
||
<a href="#api-__codelineno-9-56" id="__codelineno-9-56" name="__codelineno-9-56"></a> "approx": false,
|
||
<a href="#api-__codelineno-9-57" id="__codelineno-9-57" name="__codelineno-9-57"></a> "recursive": true,
|
||
<a href="#api-__codelineno-9-58" id="__codelineno-9-58" name="__codelineno-9-58"></a> "attributes": [],
|
||
<a href="#api-__codelineno-9-59" id="__codelineno-9-59" name="__codelineno-9-59"></a> "onlyAccessible": true,
|
||
<a href="#api-__codelineno-9-60" id="__codelineno-9-60" name="__codelineno-9-60"></a> "sortDirection": null,
|
||
<a href="#api-__codelineno-9-61" id="__codelineno-9-61" name="__codelineno-9-61"></a> "sortBy": null,
|
||
<a href="#api-__codelineno-9-62" id="__codelineno-9-62" name="__codelineno-9-62"></a> "sortlimit": 0,
|
||
<a href="#api-__codelineno-9-63" id="__codelineno-9-63" name="__codelineno-9-63"></a> "displayFormat": "%{cn}",
|
||
<a href="#api-__codelineno-9-64" id="__codelineno-9-64" name="__codelineno-9-64"></a> "nbObjectsByPage": 25,
|
||
<a href="#api-__codelineno-9-65" id="__codelineno-9-65" name="__codelineno-9-65"></a> "withoutCache": false,
|
||
<a href="#api-__codelineno-9-66" id="__codelineno-9-66" name="__codelineno-9-66"></a> "extraDisplayedColumns": true
|
||
<a href="#api-__codelineno-9-67" id="__codelineno-9-67" name="__codelineno-9-67"></a> },
|
||
<a href="#api-__codelineno-9-68" id="__codelineno-9-68" name="__codelineno-9-68"></a> "LSsysaccount": {
|
||
<a href="#api-__codelineno-9-69" id="__codelineno-9-69" name="__codelineno-9-69"></a> "filter": null,
|
||
<a href="#api-__codelineno-9-70" id="__codelineno-9-70" name="__codelineno-9-70"></a> "pattern": "LdapSaisie",
|
||
<a href="#api-__codelineno-9-71" id="__codelineno-9-71" name="__codelineno-9-71"></a> "predefinedFilter": false,
|
||
<a href="#api-__codelineno-9-72" id="__codelineno-9-72" name="__codelineno-9-72"></a> "basedn": null,
|
||
<a href="#api-__codelineno-9-73" id="__codelineno-9-73" name="__codelineno-9-73"></a> "scope": null,
|
||
<a href="#api-__codelineno-9-74" id="__codelineno-9-74" name="__codelineno-9-74"></a> "sizelimit": 0,
|
||
<a href="#api-__codelineno-9-75" id="__codelineno-9-75" name="__codelineno-9-75"></a> "attronly": false,
|
||
<a href="#api-__codelineno-9-76" id="__codelineno-9-76" name="__codelineno-9-76"></a> "approx": false,
|
||
<a href="#api-__codelineno-9-77" id="__codelineno-9-77" name="__codelineno-9-77"></a> "recursive": false,
|
||
<a href="#api-__codelineno-9-78" id="__codelineno-9-78" name="__codelineno-9-78"></a> "attributes": [],
|
||
<a href="#api-__codelineno-9-79" id="__codelineno-9-79" name="__codelineno-9-79"></a> "onlyAccessible": true,
|
||
<a href="#api-__codelineno-9-80" id="__codelineno-9-80" name="__codelineno-9-80"></a> "sortDirection": null,
|
||
<a href="#api-__codelineno-9-81" id="__codelineno-9-81" name="__codelineno-9-81"></a> "sortBy": null,
|
||
<a href="#api-__codelineno-9-82" id="__codelineno-9-82" name="__codelineno-9-82"></a> "sortlimit": 0,
|
||
<a href="#api-__codelineno-9-83" id="__codelineno-9-83" name="__codelineno-9-83"></a> "displayFormat": "%{uid}",
|
||
<a href="#api-__codelineno-9-84" id="__codelineno-9-84" name="__codelineno-9-84"></a> "nbObjectsByPage": 30,
|
||
<a href="#api-__codelineno-9-85" id="__codelineno-9-85" name="__codelineno-9-85"></a> "withoutCache": false,
|
||
<a href="#api-__codelineno-9-86" id="__codelineno-9-86" name="__codelineno-9-86"></a> "extraDisplayedColumns": true
|
||
<a href="#api-__codelineno-9-87" id="__codelineno-9-87" name="__codelineno-9-87"></a> }
|
||
<a href="#api-__codelineno-9-88" id="__codelineno-9-88" name="__codelineno-9-88"></a> },
|
||
<a href="#api-__codelineno-9-89" id="__codelineno-9-89" name="__codelineno-9-89"></a> "page": 1,
|
||
<a href="#api-__codelineno-9-90" id="__codelineno-9-90" name="__codelineno-9-90"></a> "nbPages": 1
|
||
<a href="#api-__codelineno-9-91" id="__codelineno-9-91" name="__codelineno-9-91"></a>}
|
||
</code></pre></div></section><h1 class="nav-section-title">Contribution</h1><section class="print-page" id="contrib"><h1 id="contrib-contribution">Contribution</h1>
|
||
<p>Comme tout projet libre qui se respecte, les contributions à LdapSaisie sont les bienvenues. Ce
|
||
chapitre explique les possibilités de contribution.</p></section><h2 class="nav-section-title">Les addons (LSaddon)</h2><section class="print-page" id="contrib-addons"><h1 id="contrib-addons-les-addons-lsaddon">Les addons (LSaddon)</h1>
|
||
<p>Les <a href="#conf-configuration-des-lsaddons">LSaddons</a> sont utilisés pour implémenter dans LdapSaisie
|
||
des fonctionnalités spécifiques tel que :</p>
|
||
<ul>
|
||
<li>le support d'une famille d'attributs spécifiques (POSIX, Samba, SUPANN…) par le biais de méthodes
|
||
de génération de la valeur de ces attributs par exemple (paramètre <code>generate_function</code>) ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>des tâches communes et génériques (envoi de mails, connexion FTP/SSH…) ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>l'implémentation de <a href="#conf-declencheurs_1">déclencheurs</a> spécifiques à votre environnement :
|
||
création automatique du dossier client sur le serveur de fichiers de l'entreprise, création de la
|
||
boite mail de l'utilisateur… ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>l'implémentation de <a href="#contrib-addons-les-vues-personnalisees">vues personnalisées</a> proposées dans l'interface</li>
|
||
</ul>
|
||
<ul>
|
||
<li>l'implémentation d'action personnalisée sur les <a href="#conf-customactions">objets</a> (synchronisation,
|
||
archivage…) ou sur les <a href="#conf-lsobject-lssearch-customactions">résultats de recherches</a>
|
||
(export, rapport personnalisé…) ;</li>
|
||
</ul>
|
||
<h2 id="contrib-addons-structure-decriture">Structure d'écriture</h2>
|
||
<p>L'écriture d'un <a href="#conf-configuration-des-lsaddons">LSaddon</a> doit respecter une structure
|
||
suffisamment souple afin de ne pas être un frein à vos contributions, tout en permettant d'assurer
|
||
la bonne intégration de votre contribution au projet. Le code que vous écrirez sera réparti dans
|
||
deux fichiers :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>conf/LSaddons/config.LSaddons.[addon name].php</code></p>
|
||
<p>Ce fichier contiendra la configuration de votre <a href="#conf-configuration-des-lsaddons">LSaddon</a>.
|
||
On y retrouvera la déclaration de constances et/ou variables de configuration permettant d'adapter
|
||
votre <a href="#conf-configuration-des-lsaddons">LSaddon</a> à une installation et à un environnement.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>includes/addons/LSaddons.[addon name].php</code></p>
|
||
<p>Ce fichier contiendra le code à proprement dit de votre <a href="#conf-configuration-des-lsaddons">LSaddon</a>.</p>
|
||
<p><strong>Structure du fichier includes/addons/LSaddons.[addon name].php :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#contrib-addons-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="cp"><?php</span>
|
||
<a href="#contrib-addons-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a>
|
||
<a href="#contrib-addons-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a><span class="cm">/*</span>
|
||
<a href="#contrib-addons-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a><span class="cm"> * Error messages</span>
|
||
<a href="#contrib-addons-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a><span class="cm"> */</span>
|
||
<a href="#contrib-addons-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a>
|
||
<a href="#contrib-addons-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a><span class="c1">// Support error messages</span>
|
||
<a href="#contrib-addons-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a><span class="nx">LSerror</span> <span class="o">::</span> <span class="na">defineError</span><span class="p">(</span><span class="s1">'MYADDON_SUPPORT_01'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> <span class="nx">___</span><span class="p">(</span><span class="s2">"MYADDON Support : Unable to load %{dep}."</span><span class="p">)</span>
|
||
<a href="#contrib-addons-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a><span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a>
|
||
<a href="#contrib-addons-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a><span class="nx">LSerror</span> <span class="o">::</span> <span class="na">defineError</span><span class="p">(</span><span class="s1">'MYADDON_SUPPORT_02'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> <span class="nx">___</span><span class="p">(</span><span class="s2">"MYADDON Support : The constant %{const} is not defined."</span><span class="p">)</span>
|
||
<a href="#contrib-addons-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a><span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a>
|
||
<a href="#contrib-addons-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a><span class="c1">// Other orror messages</span>
|
||
<a href="#contrib-addons-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a><span class="nx">LSerror</span> <span class="o">::</span> <span class="na">defineError</span><span class="p">(</span><span class="s1">'MYADDON_01'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> <span class="nx">___</span><span class="p">(</span><span class="s2">"An error : %{msg}."</span><span class="p">)</span>
|
||
<a href="#contrib-addons-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a><span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a>
|
||
<a href="#contrib-addons-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a><span class="nx">LSerror</span> <span class="o">::</span> <span class="na">defineError</span><span class="p">(</span><span class="s1">'MYADDON_02'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> <span class="nx">___</span><span class="p">(</span><span class="s2">"An other error about %{about} : %{msg}"</span><span class="p">)</span>
|
||
<a href="#contrib-addons-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a>
|
||
<a href="#contrib-addons-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="nx">LSerror</span> <span class="o">::</span> <span class="na">defineError</span><span class="p">(</span><span class="s1">'MYADDON_03'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a> <span class="nx">___</span><span class="p">(</span><span class="s2">"Unknown error."</span><span class="p">)</span>
|
||
<a href="#contrib-addons-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a><span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a>
|
||
<a href="#contrib-addons-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="sd">/**</span>
|
||
<a href="#contrib-addons-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a><span class="sd"> * Verify support of my addon by LdapSaisie</span>
|
||
<a href="#contrib-addons-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a><span class="sd"> * @author My Name <my.email@example.com></span>
|
||
<a href="#contrib-addons-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a><span class="sd"> * @return boolean true if my addon is totaly supported, false in other cases</span>
|
||
<a href="#contrib-addons-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a><span class="sd"> **/</span>
|
||
<a href="#contrib-addons-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a><span class="k">function</span> <span class="nf">LSaddon_myaddon_support</span><span class="p">()</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a>
|
||
<a href="#contrib-addons-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a> <span class="nv">$retval</span><span class="o">=</span><span class="k">true</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a>
|
||
<a href="#contrib-addons-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a> <span class="c1">// Check/load dependencies</span>
|
||
<a href="#contrib-addons-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a> <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="nb">class_exists</span><span class="p">(</span><span class="s1">'mylib'</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a> <span class="k">if</span> <span class="p">(</span> <span class="o">!</span><span class="nx">LSsession</span><span class="o">::</span><span class="na">includeFile</span><span class="p">(</span><span class="nx">LS_LIB_DIR</span> <span class="o">.</span> <span class="s1">'class.mylib.php'</span><span class="p">)</span> <span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a> <span class="nx">LSerror</span> <span class="o">::</span> <span class="na">addErrorCode</span><span class="p">(</span><span class="s1">'MYADDON_SUPPORT_01'</span><span class="p">,</span> <span class="s1">'mylib'</span><span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a> <span class="nv">$retval</span><span class="o">=</span><span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-45" id="__codelineno-0-45" name="__codelineno-0-45"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-46" id="__codelineno-0-46" name="__codelineno-0-46"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-47" id="__codelineno-0-47" name="__codelineno-0-47"></a>
|
||
<a href="#contrib-addons-__codelineno-0-48" id="__codelineno-0-48" name="__codelineno-0-48"></a>
|
||
<a href="#contrib-addons-__codelineno-0-49" id="__codelineno-0-49" name="__codelineno-0-49"></a> <span class="nv">$MUST_DEFINE_CONST</span><span class="o">=</span> <span class="k">array</span><span class="p">(</span>
|
||
<a href="#contrib-addons-__codelineno-0-50" id="__codelineno-0-50" name="__codelineno-0-50"></a> <span class="s1">'LS_MYADDON_CONF_O1'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-51" id="__codelineno-0-51" name="__codelineno-0-51"></a> <span class="s1">'LS_MYADDON_CONF_O2'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-52" id="__codelineno-0-52" name="__codelineno-0-52"></a> <span class="o">...</span>
|
||
<a href="#contrib-addons-__codelineno-0-53" id="__codelineno-0-53" name="__codelineno-0-53"></a> <span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-54" id="__codelineno-0-54" name="__codelineno-0-54"></a>
|
||
<a href="#contrib-addons-__codelineno-0-55" id="__codelineno-0-55" name="__codelineno-0-55"></a> <span class="k">foreach</span><span class="p">(</span><span class="nv">$MUST_DEFINE_CONST</span> <span class="k">as</span> <span class="nv">$const</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-56" id="__codelineno-0-56" name="__codelineno-0-56"></a> <span class="k">if</span> <span class="p">(</span> <span class="p">(</span><span class="o">!</span><span class="nb">defined</span><span class="p">(</span><span class="nv">$const</span><span class="p">))</span> <span class="o">||</span> <span class="p">(</span><span class="nb">constant</span><span class="p">(</span><span class="nv">$const</span><span class="p">)</span> <span class="o">==</span> <span class="s2">""</span><span class="p">))</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-57" id="__codelineno-0-57" name="__codelineno-0-57"></a> <span class="nx">LSerror</span> <span class="o">::</span> <span class="na">addErrorCode</span><span class="p">(</span><span class="s1">'MYADDON_SUPPORT_02'</span><span class="p">,</span><span class="nv">$const</span><span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-58" id="__codelineno-0-58" name="__codelineno-0-58"></a> <span class="nv">$retval</span><span class="o">=</span><span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-59" id="__codelineno-0-59" name="__codelineno-0-59"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-60" id="__codelineno-0-60" name="__codelineno-0-60"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-61" id="__codelineno-0-61" name="__codelineno-0-61"></a>
|
||
<a href="#contrib-addons-__codelineno-0-62" id="__codelineno-0-62" name="__codelineno-0-62"></a> <span class="k">if</span> <span class="p">(</span><span class="nv">$retval</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-63" id="__codelineno-0-63" name="__codelineno-0-63"></a> <span class="c1">// Register LSaddon view using LSsession :: registerLSaddonView()</span>
|
||
<a href="#contrib-addons-__codelineno-0-64" id="__codelineno-0-64" name="__codelineno-0-64"></a>
|
||
<a href="#contrib-addons-__codelineno-0-65" id="__codelineno-0-65" name="__codelineno-0-65"></a> <span class="k">if</span> <span class="p">(</span><span class="nb">php_sapi_name</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'cli'</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-66" id="__codelineno-0-66" name="__codelineno-0-66"></a> <span class="c1">// Register LSaddon CLI command using LScli :: add_command()</span>
|
||
<a href="#contrib-addons-__codelineno-0-67" id="__codelineno-0-67" name="__codelineno-0-67"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-68" id="__codelineno-0-68" name="__codelineno-0-68"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-69" id="__codelineno-0-69" name="__codelineno-0-69"></a>
|
||
<a href="#contrib-addons-__codelineno-0-70" id="__codelineno-0-70" name="__codelineno-0-70"></a> <span class="k">return</span> <span class="nv">$retval</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-71" id="__codelineno-0-71" name="__codelineno-0-71"></a><span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-72" id="__codelineno-0-72" name="__codelineno-0-72"></a>
|
||
<a href="#contrib-addons-__codelineno-0-73" id="__codelineno-0-73" name="__codelineno-0-73"></a><span class="sd">/**</span>
|
||
<a href="#contrib-addons-__codelineno-0-74" id="__codelineno-0-74" name="__codelineno-0-74"></a><span class="sd"> * My first function</span>
|
||
<a href="#contrib-addons-__codelineno-0-75" id="__codelineno-0-75" name="__codelineno-0-75"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-__codelineno-0-76" id="__codelineno-0-76" name="__codelineno-0-76"></a><span class="sd"> * Description of this wonderfull function</span>
|
||
<a href="#contrib-addons-__codelineno-0-77" id="__codelineno-0-77" name="__codelineno-0-77"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-__codelineno-0-78" id="__codelineno-0-78" name="__codelineno-0-78"></a><span class="sd"> * @author My Name <my.email@example.com></span>
|
||
<a href="#contrib-addons-__codelineno-0-79" id="__codelineno-0-79" name="__codelineno-0-79"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-__codelineno-0-80" id="__codelineno-0-80" name="__codelineno-0-80"></a><span class="sd"> * @return [type(s) of returned values (pipe separator)] Description of the return of this function</span>
|
||
<a href="#contrib-addons-__codelineno-0-81" id="__codelineno-0-81" name="__codelineno-0-81"></a><span class="sd"> **/</span>
|
||
<a href="#contrib-addons-__codelineno-0-82" id="__codelineno-0-82" name="__codelineno-0-82"></a><span class="k">function</span> <span class="nf">myaddon_first_function</span><span class="p">(</span><span class="nv">$arg1</span><span class="p">,</span> <span class="nv">$arg2</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-83" id="__codelineno-0-83" name="__codelineno-0-83"></a> <span class="c1">// Do some stuff</span>
|
||
<a href="#contrib-addons-__codelineno-0-84" id="__codelineno-0-84" name="__codelineno-0-84"></a> <span class="k">if</span> <span class="p">(</span><span class="nx">something</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-85" id="__codelineno-0-85" name="__codelineno-0-85"></a> <span class="nx">LSerror</span> <span class="o">::</span> <span class="na">addErrorCode</span><span class="p">(</span>
|
||
<a href="#contrib-addons-__codelineno-0-86" id="__codelineno-0-86" name="__codelineno-0-86"></a> <span class="s1">'MYADDON_01'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-87" id="__codelineno-0-87" name="__codelineno-0-87"></a> <span class="s1">'something went wrong'</span> <span class="c1">// Error LSformat unique argument</span>
|
||
<a href="#contrib-addons-__codelineno-0-88" id="__codelineno-0-88" name="__codelineno-0-88"></a> <span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-89" id="__codelineno-0-89" name="__codelineno-0-89"></a> <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-90" id="__codelineno-0-90" name="__codelineno-0-90"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-91" id="__codelineno-0-91" name="__codelineno-0-91"></a>
|
||
<a href="#contrib-addons-__codelineno-0-92" id="__codelineno-0-92" name="__codelineno-0-92"></a> <span class="k">if</span> <span class="p">(</span><span class="nx">something</span> <span class="k">else</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-93" id="__codelineno-0-93" name="__codelineno-0-93"></a> <span class="nx">LSerror</span> <span class="o">::</span> <span class="na">addErrorCode</span><span class="p">(</span>
|
||
<a href="#contrib-addons-__codelineno-0-94" id="__codelineno-0-94" name="__codelineno-0-94"></a> <span class="s1">'MYADDON_02'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-95" id="__codelineno-0-95" name="__codelineno-0-95"></a> <span class="k">array</span><span class="p">(</span> <span class="c1">// Error LSformat arguments</span>
|
||
<a href="#contrib-addons-__codelineno-0-96" id="__codelineno-0-96" name="__codelineno-0-96"></a> <span class="s1">'about'</span> <span class="o">=></span> <span class="s1">'second step'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-__codelineno-0-97" id="__codelineno-0-97" name="__codelineno-0-97"></a> <span class="s1">'msg'</span> <span class="o">=></span> <span class="s1">'something went wrong'</span>
|
||
<a href="#contrib-addons-__codelineno-0-98" id="__codelineno-0-98" name="__codelineno-0-98"></a> <span class="p">)</span>
|
||
<a href="#contrib-addons-__codelineno-0-99" id="__codelineno-0-99" name="__codelineno-0-99"></a> <span class="p">);</span>
|
||
<a href="#contrib-addons-__codelineno-0-100" id="__codelineno-0-100" name="__codelineno-0-100"></a> <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-101" id="__codelineno-0-101" name="__codelineno-0-101"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-102" id="__codelineno-0-102" name="__codelineno-0-102"></a>
|
||
<a href="#contrib-addons-__codelineno-0-103" id="__codelineno-0-103" name="__codelineno-0-103"></a> <span class="k">if</span> <span class="p">(</span><span class="nx">still</span> <span class="nx">something</span> <span class="k">else</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-__codelineno-0-104" id="__codelineno-0-104" name="__codelineno-0-104"></a> <span class="nx">LSerror</span> <span class="o">::</span> <span class="na">addErrorCode</span><span class="p">(</span><span class="s1">'MYADDON_03'</span><span class="p">);</span> <span class="c1">// Error without argument</span>
|
||
<a href="#contrib-addons-__codelineno-0-105" id="__codelineno-0-105" name="__codelineno-0-105"></a> <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-106" id="__codelineno-0-106" name="__codelineno-0-106"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-107" id="__codelineno-0-107" name="__codelineno-0-107"></a> <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
|
||
<a href="#contrib-addons-__codelineno-0-108" id="__codelineno-0-108" name="__codelineno-0-108"></a><span class="p">}</span>
|
||
<a href="#contrib-addons-__codelineno-0-109" id="__codelineno-0-109" name="__codelineno-0-109"></a>
|
||
<a href="#contrib-addons-__codelineno-0-110" id="__codelineno-0-110" name="__codelineno-0-110"></a><span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
<a href="#contrib-addons-__codelineno-0-111" id="__codelineno-0-111" name="__codelineno-0-111"></a>
|
||
<a href="#contrib-addons-__codelineno-0-112" id="__codelineno-0-112" name="__codelineno-0-112"></a><span class="c1">// Defined custom CLI commands functions only on CLI context</span>
|
||
<a href="#contrib-addons-__codelineno-0-113" id="__codelineno-0-113" name="__codelineno-0-113"></a><span class="k">if</span> <span class="p">(</span><span class="nb">php_sapi_name</span><span class="p">()</span> <span class="o">!=</span> <span class="s1">'cli'</span><span class="p">)</span>
|
||
<a href="#contrib-addons-__codelineno-0-114" id="__codelineno-0-114" name="__codelineno-0-114"></a> <span class="k">return</span> <span class="k">true</span><span class="p">;</span> <span class="c1">// Always return true to avoid some warning in log</span>
|
||
<a href="#contrib-addons-__codelineno-0-115" id="__codelineno-0-115" name="__codelineno-0-115"></a>
|
||
<a href="#contrib-addons-__codelineno-0-116" id="__codelineno-0-116" name="__codelineno-0-116"></a><span class="c1">// Defined functions handling custom CLI commands and optionnaly</span>
|
||
<a href="#contrib-addons-__codelineno-0-117" id="__codelineno-0-117" name="__codelineno-0-117"></a><span class="c1">// their arguments autocompleter functions.</span>
|
||
</code></pre></div>
|
||
</li>
|
||
</ul>
|
||
<p>Par convention, la structure de ce fichier est toujours à peu près la même:</p>
|
||
<ul>
|
||
<li>On déclare tout d'abord les messages d'erreurs qui seront potentiellement émis par notre
|
||
<a href="#conf-configuration-des-lsaddons">LSaddon</a> en commençant par les messages d'erreurs liés au
|
||
support de cet <a href="#conf-configuration-des-lsaddons">LSaddon</a>. On utilise pour cela la méthode
|
||
<code>LSerror :: defineError()</code> qui attends en premier argument, l'identifiant du message
|
||
d'erreur et en tant que second argument, le
|
||
<a href="#conf-global-lsformat-format-parametrable">LSformat</a> du message d'erreur. Par convention,
|
||
les identifiants des messages d'erreurs seront en majuscule et préfixés du nom du
|
||
<a href="#conf-configuration-des-lsaddons">LSaddon</a>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>On déclare ensuite une fonction <code>LSaddon_[myaddon]_support</code> qui sera exécutée lors du chargement
|
||
de l'addon et qui permettra de s'assurer du support de celui-ci. Cette fonction devra retourner
|
||
<code>True</code> si c'est le cas ou <code>False</code> dans le cas contraire.</p>
|
||
<p>Cette fonction s'assura notamment :</p>
|
||
<ul>
|
||
<li>que les librairies dont l'addon dépends sont bien chargées et fonctionnelles ;</li>
|
||
<li>que ses variables et constantes de configuration sont bien définies ;</li>
|
||
<li>de déclarer <a href="#contrib-addons-les-vues-personnalisees">les vues personnalisées</a> fournies par cet
|
||
<a href="#conf-configuration-des-lsaddons">LSaddon</a> ;</li>
|
||
<li>de déclarer <a href="#contrib-addons-les-commandes-cli-personnalisees">les commandes <em>CLI</em> personnalisées</a> fournies par
|
||
cet <a href="#conf-configuration-des-lsaddons">LSaddon</a> ;</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>On déclare ensuite les fonctions, classes et éléments fournis et manipulés par l'addon.</li>
|
||
<li>
|
||
<p>Si notre addon offre des <a href="#contrib-addons-les-commandes-cli-personnalisees">commandes <em>CLI</em> personnalisées</a>, les
|
||
fonctions les implémentant ne seront définies, dans un souci de performance, que dans un contexte
|
||
ou elles seraient potentiellement appelables, c'est à dire dans un contexte d'exécution <code>CLI</code>.
|
||
Pour cela, nous utilisons communément la fonction <code>php_sapi_name</code> pour déterminer le contexte
|
||
d'exécution et si celui-ci vaut <code>cli</code>, nous stoppons l'exécution du reste du code du fichier via
|
||
un <code>return true</code>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Il est important dans ce contexte de ne jamais retourner autre chose que <code>True</code> pour éviter
|
||
tout message d'erreur inutile dans les logs.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>On déclare, pour finir, les fonctions implémentant les
|
||
<a href="#contrib-addons-les-commandes-cli-personnalisees">commandes <em>CLI</em> personnalisées</a> et leur éventuelle fonction
|
||
gérant l'autocomplétion des arguments qu'elles acceptent.</li>
|
||
</ul></section><section class="print-page" id="contrib-addons-custom-views"><h1 id="contrib-addons-custom-views-les-vues-personnalisees">Les vues personnalisées</h1>
|
||
<p>Les <a href="#conf-configuration-des-lsaddons">LSaddons</a> peuvent fournir des vues personnalisées qui
|
||
seront accessibles à tout ou parties des utilisateurs de l'application. Ce filtrage d'accès sera
|
||
fait en utilisant les <a href="#conf-global-ldap-lsprofile-profils-dutilisateurs">LSprofiles</a> de
|
||
l'utilisateur connecté sur la
|
||
<a href="#conf-global-ldap-subdn-sous-niveaux-de-connexion">racine courante de l'annuaire LDAP</a>.</p>
|
||
<p>Pour mettre en place une telle vue personnalisée, il est nécessaire de :</p>
|
||
<ul>
|
||
<li>Déclarer cette vue dans la fonction <code>LSaddon_[addon]_support</code> de l'addon à l'aide de la méthode
|
||
<code>LSsession :: registerLSaddonView()</code> ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Déclarer la fonction implémentant cette vue. Cette fonction n'acceptera aucun paramètre et ne
|
||
retournera rien. Elle devra en outre s'occuper de définir son fichier template et charger les
|
||
dépendances de ce dernier (fichiers <em>CSS & JS</em>, variables...).</li>
|
||
</ul>
|
||
<p>Pour implémenter une telle vue personnalisée, vous pouvez vous inspirer de l'exemple fourni
|
||
ci-dessous ou encore des vues fournies par les autres
|
||
<a href="#conf-configuration-des-lsaddons">LSaddons</a> (par exemple, l'addon
|
||
<a href="#conf-lsaddon-lsaddon_exportsearchresultascsv-lsaddon_exportsearchresultascsv">exportSearchResultAsCSV</a>).</p>
|
||
<p><strong>Structure du fichier includes/addons/LSaddons.[addon name].php :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#contrib-addons-custom-views-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="cp"><?php</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="k">function</span> <span class="nf">LSaddon_myaddon_support</span><span class="p">()</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> <span class="nv">$retval</span><span class="o">=</span><span class="k">true</span><span class="p">;</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> <span class="c1">// Some check</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> <span class="k">if</span> <span class="p">(</span><span class="nv">$retval</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> <span class="nv">$retval</span> <span class="o">=</span> <span class="nx">LSsession</span> <span class="o">::</span> <span class="na">registerLSaddonView</span><span class="p">(</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> <span class="s1">'myaddon'</span><span class="p">,</span> <span class="c1">// addon name</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> <span class="s1">'myaddon_view'</span><span class="p">,</span> <span class="c1">// addon view ID</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> <span class="nx">__</span><span class="p">(</span><span class="s1">'MyAddon view'</span><span class="p">),</span> <span class="c1">// addon view label</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> <span class="s1">'myaddon_view'</span><span class="p">,</span> <span class="c1">// callable (ex: function name) that implement addon view</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> <span class="k">array</span><span class="p">(</span><span class="s1">'user'</span><span class="p">),</span> <span class="c1">// array listing allowed LSprofiles</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> <span class="k">true</span> <span class="c1">// Show/hide this addon view in user menu</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> <span class="p">);</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> <span class="k">return</span> <span class="nv">$retval</span><span class="p">;</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="p">}</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a><span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a><span class="sd">/**</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a><span class="sd"> * My addon view handler function</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a><span class="sd"> * Description of this view</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a><span class="sd"> * @author My Name <my.email@example.com></span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a><span class="sd"> * @return void</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a><span class="sd"> **/</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a><span class="k">function</span> <span class="nf">myaddon_view</span><span class="p">()</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a> <span class="c1">// Do some stuff and set some template variables</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a> <span class="nv">$list</span> <span class="o">=</span> <span class="k">array</span> <span class="p">([</span><span class="o">...</span><span class="p">]);</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a> <span class="nx">LStemplate</span> <span class="o">::</span> <span class="na">assign</span><span class="p">(</span><span class="s1">'list'</span><span class="p">,</span> <span class="nv">$list</span><span class="p">);</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a> <span class="c1">// Load some CSS & JS files need on this view</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a> <span class="nx">LStemplate</span> <span class="o">::</span> <span class="na">addCssFile</span><span class="p">(</span><span class="s1">'LSaddon_myadon.css'</span><span class="p">);</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a> <span class="nx">LStemplate</span> <span class="o">::</span> <span class="na">addJSscript</span><span class="p">(</span><span class="s1">'LSaddon_myadon.js'</span><span class="p">);</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a> <span class="c1">// Set template file of the view</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a> <span class="nx">LSsession</span> <span class="o">::</span> <span class="na">setTemplate</span><span class="p">(</span><span class="s1">'LSaddon_myadon_view.tpl'</span><span class="p">);</span>
|
||
<a href="#contrib-addons-custom-views-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a><span class="p">}</span>
|
||
</code></pre></div></section><section class="print-page" id="contrib-addons-cli-commands"><h1 id="contrib-addons-cli-commands-les-commandes-cli-personnalisees">Les commandes <em>CLI</em> personnalisées</h1>
|
||
<h2 id="contrib-addons-cli-commands-introduction">Introduction</h2>
|
||
<p>Les <a href="#conf-configuration-des-lsaddons">LSaddons</a> peuvent fournir des commandes <em>CLI</em>
|
||
personnalisées qui seront accessibles via la commande <code>ldapsaisie</code> fournie avec l'application. Cela
|
||
peut, par exemple, vous permettre de rendre accessible en ligne de commandes une procédure
|
||
implémentée dans le code d'LdapSaisie et vous permettre de mettre en place une tâche planifiée
|
||
exécutant cette procédure régulièrement.</p>
|
||
<p>Pour mettre en place une telle commande <em>CLI</em> personnalisée, il est nécessaire de :</p>
|
||
<ul>
|
||
<li>Déclarer cette commande <em>CLI</em> personnalisée dans la fonction <code>LSaddon_[addon]_support</code> de l'addon
|
||
à l'aide de la méthode <code>LScli::add_command()</code> ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Déclarer la fonction implémentant cette commande <em>CLI</em> personnalisée. Cette fonction acceptera,
|
||
en tant qu'unique paramètre, un tableau des arguments reçus lors de l'exécution de la commande et
|
||
retournera <code>True</code> ou <code>False</code> en cas de succès/d'erreur d'exécution de la commande. Cette valeur
|
||
de retour influencera le code retourné par la commande : <code>0</code> en cas de succès, <code>1</code> en cas
|
||
d'erreur.</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Bien que cela ne soit pas obligatoire, il sera également possible de déclarer une fonction
|
||
permettant l'autocomplétion des arguments acceptés par la commande. Pour plus d'informations à ce
|
||
propos, reportez-vous à la <a href="#contrib-addons-cli-commands-auto-completion">section dédiée</a>.</li>
|
||
</ul>
|
||
<h2 id="contrib-addons-cli-commands-outils-a-votre-disposition">Outils à votre disposition</h2>
|
||
<p>Pour vous aider dans l'écriture de vos méthodes <em>CLI</em>, la classe <code>LScli</code> offre des méthodes
|
||
pour les tâches les plus courantes :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>LScli::usage($error, ...$extra_args)</code></p>
|
||
<p>Affichage du message d'aide de votre commande avant arrêt. Un message d'erreur peut également
|
||
être spécifié avec d'éventuels arguments supplémentaires pour le composer (via <code>sprintf()</code>). Si un
|
||
message d'erreur est fourni, le code de retour de la commande sera <code>1</code> et à défaut, <code>0</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LScli::need_ldap_con()</code></p>
|
||
<p>Permet d'établir la connexion à l'annuaire LDAP (si ce n'est pas déjà fait).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LScli::run_external_command($command, $data_stdin=null, $escape_command_args=true, $cwd=null)</code> :</p>
|
||
<p>Permet d'exécuter une commande externe et de récupérer un tableau contenant le code de
|
||
retour de la commande exécutée, le contenu affiché sur la sortie standard et le contenu
|
||
affiché sur la sortie d'erreur.</p>
|
||
<p>La commande à exécuter peut être passée sous la forme d'une chaîne de caractères ou d'un
|
||
tableau de chaînes de caractères correspondant à la commande et ses arguments. Par défaut,
|
||
les caractères spéciaux contenus dans les paramètres passés à la commande seront
|
||
"échappés", mais il est possible de désactiver cela via le paramètre <code>$escape_command_args</code>.</p>
|
||
<p>Il est possible de fournir des données à passer à la commande via son entrée standard via
|
||
le paramètre <code>$data_stdin</code>.</p>
|
||
<p>Enfin, il est possible de spécifier l'emplacement du dossier courant d'exécution de la
|
||
commande via le paramètre <code>$cwd</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LScli::confirm($question=null)</code></p>
|
||
<p>Permet de demander à l'utilisateur de confirmer quelque chose. La question à poser peut être
|
||
passée en paramètre et cette méthode retournera <code>true</code> ou <code>false</code> en fonction du choix de
|
||
l'utilisateur.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>LScli::parse_arg_value($value, $custom_values=null)</code></p>
|
||
<p>Permet d'interpréter la valeur d'un argument fourni par l'utilisateur. Celui-ci pourra spécifier
|
||
le type de l'argument en préfixant l'argument de son type entre crochets (exemple : <code>[bool]1</code>,
|
||
types supportés : <code>string</code>, <code>str</code>, <code>bool</code>, <code>boolean</code>, <code>int</code>, <code>integer</code>, <code>float</code>, <code>array</code>) et à
|
||
défaut, la valeur sera analysée comme une valeur JSON permettant de passer des paramètres
|
||
complexes à vos méthodes (un tableau associatif arborescent par exemple).</p>
|
||
<p>Des valeurs particulières seront également analysées de manières prédéfinies si elles ne
|
||
sont pas préfixées d'un type particulier. C'est le cas par défaut des chaînes de
|
||
caractères <code>true</code> et <code>false</code> qui seront comprises comme des booléens et <code>null</code> qui sera
|
||
compris comme la valeur <code>NULL</code> au sens PHP.</p>
|
||
<p>Vous pouvez également spécifier vos propres valeurs particulières via l'argument
|
||
<code>$custom_values</code> sous la forme d'un tableau associatif dont les clés sont les valeurs
|
||
particulières fournies par l'utilisateur et la valeur correspondante, la valeur au sens
|
||
<em>PHP</em>.</p>
|
||
<p><strong>Important :</strong> l'analyse des valeurs particulières sera faite en mettant
|
||
<strong>en minuscule</strong> la valeur fournie par l'utilisateur. Il est donc important que vos
|
||
valeurs particulières spécifiées via l'argument <code>$custom_values</code> soient toutes en
|
||
minuscule.</p>
|
||
</li>
|
||
</ul>
|
||
<h2 id="contrib-addons-cli-commands-auto-completion">Auto-complétion</h2>
|
||
<p>Lors de la déclaration de votre commande CLI personnalisée à l'aide de la méthode
|
||
<code>LScli::add_command()</code>, vous avez la possibilité de spécifier une fonction permettant
|
||
l'autocomplétion des arguments acceptés par celle-ci.</p>
|
||
<p>Cette fonction recevra en paramètre :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>$command_args</code></p>
|
||
<p>Un tableau des arguments déjà reçus par la commande.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$comp_word_num</code></p>
|
||
<p>Un entier indiquant le rang de l'argument que l'autocomplétion tente de compléter. Il peut
|
||
s'agir du rang d'un paramètre déjà fourni et présent dans le tableau <code>$command_args</code> ou bien
|
||
d'un rang supérieur aux nombres d'arguments déjà fournis à la commande et dans ce cas il s'agira
|
||
d'autocompléter tous potentiels autres arguments que pourrait accepter cette commande.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$comp_word</code></p>
|
||
<p>Une chaîne de caractères correspondant à ce qu'a déjà saisi l'utilisateur de l'argument que l'on
|
||
tente d'autocompléter. Cette chaîne de caractères peut être vide ou non, en fonction de s'il
|
||
s'agit d'un nouvel argument à autocompléter ou non.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$opts</code></p>
|
||
<p>Un tableau des potentiels arguments globaux acceptés par <em>LScli</em> dans le contexte actuel (par
|
||
exemple, <code>-d</code> ou <code>--debug</code> pour l'activation du mode debug). La réponse de cette fonction devra
|
||
inclure ces potentiels arguments si le contexte d'autocomplétion s'y prête (nouvel argument par
|
||
exemple).</p>
|
||
</li>
|
||
</ul>
|
||
<p>Pour finir, cette fonction devra retourner un tableau des potentielles valeurs que pourrait
|
||
prendre l'argument autocomplété. Si une unique proposition est faite à l'utilisateur, celle-ci
|
||
sera automatiquement proposée à l'utilisateur et à défaut, la liste des valeurs possibles lui
|
||
seront affichées.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour vous aider dans l'écriture d'une telle méthode d'autocomplétion, des méthodes statiques
|
||
sont fournies par la classe <code>LScli</code> pour les autocomplétions les plus courantes :</p>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_class_name()</code> : Autocomplétion du nom d'une classe PHP.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_addon_name()</code> : Autocomplétion du nom d'un
|
||
<a href="#conf-configuration-des-lsaddons">LSaddon</a>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_int()</code> : Autocomplétion d'un nombre entier.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_LSobject_types()</code> : Autocomplétion du nom d'un type
|
||
d'<a href="#conf-configuration-lsobject">LSobject</a>.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_LSobject_dn()</code> : Autocomplétion du DN d'un type précis
|
||
d'<a href="#conf-configuration-lsobject">LSobject</a> de l'annuaire.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_LSobject_attr_name()</code> : Autocomplétion du nom d'un attribut précis
|
||
pour un type d'<a href="#conf-configuration-lsobject">LSobject</a> de l'annuaire.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_LSobject_ioFormat()</code> : Autocomplétion du nom d'un
|
||
<a href="#conf-lsobject-ioformat-ioformat">ioFormat</a> pour un type
|
||
d'<a href="#conf-configuration-lsobject">LSobject</a> de l'annuaire.</li>
|
||
</ul>
|
||
<ul>
|
||
<li><code>LScli::autocomplete_LSform_name()</code> : Autocomplétion du nom d'un formulaire de
|
||
l'application.</li>
|
||
</ul>
|
||
<p>Par ailleurs, la méthode <code>LScli::autocomplete_opts()</code> vous facilitera la construction de la
|
||
liste des valeurs d'autocomplétion de l'argument courant en fonction de ce qui a déjà été
|
||
saisi par l'utilisateur (paramètre <code>$comp_word</code>). Cette méthode s'occupera en l'occurrence de
|
||
filtrer parmi toutes les valeurs contextuelles possibles, celles qui correspondent au préfixe
|
||
fourni par l'utilisateur.</p>
|
||
</div>
|
||
<h2 id="contrib-addons-cli-commands-exemple-dimplementation">Exemple d'implémentation</h2>
|
||
<p>Pour implémenter une telle commande <em>CLI</em> personnalisée, vous pouvez vous inspirer de l'exemple
|
||
fourni ci-dessous ou encore des commandes <em>CLI</em> fournies par les autres
|
||
<a href="#conf-configuration-des-lsaddons">LSaddons</a> ou classes PHP de l'application.</p>
|
||
<p><strong>Structure du fichier includes/addons/LSaddons.[addon name].php :</strong></p>
|
||
<div class="highlight"><pre><span></span><code><a href="#contrib-addons-cli-commands-__codelineno-0-1" id="__codelineno-0-1" name="__codelineno-0-1"></a><span class="cp"><?php</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-2" id="__codelineno-0-2" name="__codelineno-0-2"></a><span class="k">function</span> <span class="nf">LSaddon_myaddon_support</span><span class="p">()</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-3" id="__codelineno-0-3" name="__codelineno-0-3"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-4" id="__codelineno-0-4" name="__codelineno-0-4"></a> <span class="nv">$retval</span><span class="o">=</span><span class="k">true</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-5" id="__codelineno-0-5" name="__codelineno-0-5"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-6" id="__codelineno-0-6" name="__codelineno-0-6"></a> <span class="c1"># Some other checks need to verify your addon support</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-7" id="__codelineno-0-7" name="__codelineno-0-7"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-8" id="__codelineno-0-8" name="__codelineno-0-8"></a> <span class="k">if</span> <span class="p">(</span><span class="nv">$retval</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-9" id="__codelineno-0-9" name="__codelineno-0-9"></a> <span class="k">if</span> <span class="p">(</span><span class="nb">php_sapi_name</span><span class="p">()</span> <span class="o">==</span> <span class="s1">'cli'</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-10" id="__codelineno-0-10" name="__codelineno-0-10"></a> <span class="nx">LScli</span><span class="o">::</span><span class="na">add_command</span><span class="p">(</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-11" id="__codelineno-0-11" name="__codelineno-0-11"></a> <span class="c1"># The CLI command name (required)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-12" id="__codelineno-0-12" name="__codelineno-0-12"></a> <span class="s1">'my_custom_cli_cmd'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-13" id="__codelineno-0-13" name="__codelineno-0-13"></a> <span class="c1"># The CLI command handler (must be callable, required)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-14" id="__codelineno-0-14" name="__codelineno-0-14"></a> <span class="s1">'cli_my_custom_cli_cmd'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-15" id="__codelineno-0-15" name="__codelineno-0-15"></a> <span class="c1"># A short description of what this command does (required)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-16" id="__codelineno-0-16" name="__codelineno-0-16"></a> <span class="s1">'My custom CLI command'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-17" id="__codelineno-0-17" name="__codelineno-0-17"></a> <span class="c1"># A short list of commands available arguments show in usage message</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-18" id="__codelineno-0-18" name="__codelineno-0-18"></a> <span class="c1"># (optional, default: false)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-19" id="__codelineno-0-19" name="__codelineno-0-19"></a> <span class="s1">'[arg1] [arg2] [...]'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-20" id="__codelineno-0-20" name="__codelineno-0-20"></a> <span class="c1"># A long description of what this command does</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-21" id="__codelineno-0-21" name="__codelineno-0-21"></a> <span class="c1"># (optional, default: false)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-22" id="__codelineno-0-22" name="__codelineno-0-22"></a> <span class="s1">'This command permit to ...'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-23" id="__codelineno-0-23" name="__codelineno-0-23"></a> <span class="c1"># Permit to define if this command need connection to LDAP server</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-24" id="__codelineno-0-24" name="__codelineno-0-24"></a> <span class="c1"># (optional, default: true)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-25" id="__codelineno-0-25" name="__codelineno-0-25"></a> <span class="k">true</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-26" id="__codelineno-0-26" name="__codelineno-0-26"></a> <span class="c1"># Callable of the CLI command arguments autocompleter</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-27" id="__codelineno-0-27" name="__codelineno-0-27"></a> <span class="c1"># (optional, default: null)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-28" id="__codelineno-0-28" name="__codelineno-0-28"></a> <span class="s1">'cli_my_custom_cli_cmd_autocompleter'</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-29" id="__codelineno-0-29" name="__codelineno-0-29"></a> <span class="c1"># Allow override if a command already exists with the same name</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-30" id="__codelineno-0-30" name="__codelineno-0-30"></a> <span class="c1"># (optional, default: null)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-31" id="__codelineno-0-31" name="__codelineno-0-31"></a> <span class="k">true</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-32" id="__codelineno-0-32" name="__codelineno-0-32"></a> <span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-33" id="__codelineno-0-33" name="__codelineno-0-33"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-34" id="__codelineno-0-34" name="__codelineno-0-34"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-35" id="__codelineno-0-35" name="__codelineno-0-35"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-36" id="__codelineno-0-36" name="__codelineno-0-36"></a> <span class="k">return</span> <span class="nv">$retval</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-37" id="__codelineno-0-37" name="__codelineno-0-37"></a><span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-38" id="__codelineno-0-38" name="__codelineno-0-38"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-39" id="__codelineno-0-39" name="__codelineno-0-39"></a><span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-40" id="__codelineno-0-40" name="__codelineno-0-40"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-41" id="__codelineno-0-41" name="__codelineno-0-41"></a><span class="c1">// Defined CLI commands functions only on CLI context</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-42" id="__codelineno-0-42" name="__codelineno-0-42"></a><span class="k">if</span> <span class="p">(</span><span class="nb">php_sapi_name</span><span class="p">()</span> <span class="o">!=</span> <span class="s1">'cli'</span><span class="p">)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-43" id="__codelineno-0-43" name="__codelineno-0-43"></a> <span class="k">return</span> <span class="k">true</span><span class="p">;</span> <span class="c1">// Always return true to avoid some warning in log</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-44" id="__codelineno-0-44" name="__codelineno-0-44"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-45" id="__codelineno-0-45" name="__codelineno-0-45"></a><span class="sd">/**</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-46" id="__codelineno-0-46" name="__codelineno-0-46"></a><span class="sd"> * My addon CLI command my_custom_cli_cmd handler function</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-47" id="__codelineno-0-47" name="__codelineno-0-47"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-48" id="__codelineno-0-48" name="__codelineno-0-48"></a><span class="sd"> * Description of this CLI command.</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-49" id="__codelineno-0-49" name="__codelineno-0-49"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-50" id="__codelineno-0-50" name="__codelineno-0-50"></a><span class="sd"> * @param array $command_args Command arguments</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-51" id="__codelineno-0-51" name="__codelineno-0-51"></a><span class="sd"> * - Positional arguments :</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-52" id="__codelineno-0-52" name="__codelineno-0-52"></a><span class="sd"> * - LSobject</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-53" id="__codelineno-0-53" name="__codelineno-0-53"></a><span class="sd"> * - dn</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-54" id="__codelineno-0-54" name="__codelineno-0-54"></a><span class="sd"> * - Optional arguments :</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-55" id="__codelineno-0-55" name="__codelineno-0-55"></a><span class="sd"> * - -f|--force : Force mode</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-56" id="__codelineno-0-56" name="__codelineno-0-56"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-57" id="__codelineno-0-57" name="__codelineno-0-57"></a><span class="sd"> * @author My Name <my.email@example.com></span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-58" id="__codelineno-0-58" name="__codelineno-0-58"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-59" id="__codelineno-0-59" name="__codelineno-0-59"></a><span class="sd"> * @return boolean True on success, false otherwise</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-60" id="__codelineno-0-60" name="__codelineno-0-60"></a><span class="sd"> **/</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-61" id="__codelineno-0-61" name="__codelineno-0-61"></a><span class="k">function</span> <span class="nf">cli_my_custom_cli_cmd</span><span class="p">(</span><span class="nv">$command_args</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-62" id="__codelineno-0-62" name="__codelineno-0-62"></a> <span class="nv">$objType</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-63" id="__codelineno-0-63" name="__codelineno-0-63"></a> <span class="nv">$dn</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-64" id="__codelineno-0-64" name="__codelineno-0-64"></a> <span class="nv">$force_mode</span> <span class="o">=</span> <span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-65" id="__codelineno-0-65" name="__codelineno-0-65"></a> <span class="k">foreach</span> <span class="p">(</span><span class="nv">$command_args</span> <span class="k">as</span> <span class="nv">$arg</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-66" id="__codelineno-0-66" name="__codelineno-0-66"></a> <span class="k">if</span> <span class="p">(</span><span class="nv">$arg</span> <span class="o">==</span> <span class="s1">'-f'</span> <span class="o">||</span> <span class="nv">$arg</span> <span class="o">==</span> <span class="s1">'--force'</span><span class="p">)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-67" id="__codelineno-0-67" name="__codelineno-0-67"></a> <span class="nv">$force_mode</span> <span class="o">=</span> <span class="k">true</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-68" id="__codelineno-0-68" name="__codelineno-0-68"></a> <span class="k">elseif</span> <span class="p">(</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$objType</span><span class="p">))</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-69" id="__codelineno-0-69" name="__codelineno-0-69"></a> <span class="nv">$objType</span> <span class="o">=</span> <span class="nv">$arg</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-70" id="__codelineno-0-70" name="__codelineno-0-70"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-71" id="__codelineno-0-71" name="__codelineno-0-71"></a> <span class="k">elseif</span> <span class="p">(</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$dn</span><span class="p">))</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-72" id="__codelineno-0-72" name="__codelineno-0-72"></a> <span class="nv">$dn</span> <span class="o">=</span> <span class="nv">$arg</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-73" id="__codelineno-0-73" name="__codelineno-0-73"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-74" id="__codelineno-0-74" name="__codelineno-0-74"></a> <span class="k">else</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-75" id="__codelineno-0-75" name="__codelineno-0-75"></a> <span class="nx">LScli</span><span class="o">::</span><span class="na">usage</span><span class="p">(</span><span class="s2">"Invalid </span><span class="si">$arg</span><span class="s2"> parameter."</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-76" id="__codelineno-0-76" name="__codelineno-0-76"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-77" id="__codelineno-0-77" name="__codelineno-0-77"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-78" id="__codelineno-0-78" name="__codelineno-0-78"></a> <span class="k">if</span> <span class="p">(</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$objType</span><span class="p">)</span> <span class="o">||</span> <span class="nb">is_null</span><span class="p">(</span><span class="nv">$dn</span><span class="p">))</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-79" id="__codelineno-0-79" name="__codelineno-0-79"></a> <span class="nx">LScli</span><span class="o">::</span><span class="na">usage</span><span class="p">(</span><span class="s1">'You must provide LSobject type and DN.'</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-80" id="__codelineno-0-80" name="__codelineno-0-80"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-81" id="__codelineno-0-81" name="__codelineno-0-81"></a> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">LSsession</span><span class="o">::</span><span class="na">loadLSobject</span><span class="p">(</span><span class="nv">$objType</span><span class="p">))</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-82" id="__codelineno-0-82" name="__codelineno-0-82"></a> <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-83" id="__codelineno-0-83" name="__codelineno-0-83"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-84" id="__codelineno-0-84" name="__codelineno-0-84"></a> <span class="nv">$obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nv">$objType</span><span class="p">();</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-85" id="__codelineno-0-85" name="__codelineno-0-85"></a> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$obj</span><span class="o">-></span><span class="na">loadData</span><span class="p">(</span><span class="nv">$dn</span><span class="p">))</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-86" id="__codelineno-0-86" name="__codelineno-0-86"></a> <span class="nx">self</span><span class="o">::</span><span class="na">log_fatal</span><span class="p">(</span><span class="s2">"Fail to load object </span><span class="si">$dn</span><span class="s2"> data from LDAP"</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-87" id="__codelineno-0-87" name="__codelineno-0-87"></a> <span class="k">return</span> <span class="k">false</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-88" id="__codelineno-0-88" name="__codelineno-0-88"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-89" id="__codelineno-0-89" name="__codelineno-0-89"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-90" id="__codelineno-0-90" name="__codelineno-0-90"></a> <span class="c1">// Do some stuff on loaded object</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-91" id="__codelineno-0-91" name="__codelineno-0-91"></a> <span class="p">[</span><span class="o">...</span><span class="p">]</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-92" id="__codelineno-0-92" name="__codelineno-0-92"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-93" id="__codelineno-0-93" name="__codelineno-0-93"></a> <span class="k">return</span> <span class="k">true</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-94" id="__codelineno-0-94" name="__codelineno-0-94"></a><span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-95" id="__codelineno-0-95" name="__codelineno-0-95"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-96" id="__codelineno-0-96" name="__codelineno-0-96"></a><span class="sd">/**</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-97" id="__codelineno-0-97" name="__codelineno-0-97"></a><span class="sd"> * Args autocompleter for CLI my_custom_cli_cmd command</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-98" id="__codelineno-0-98" name="__codelineno-0-98"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-99" id="__codelineno-0-99" name="__codelineno-0-99"></a><span class="sd"> * @param array<string> $command_args List of already typed words of the command</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-100" id="__codelineno-0-100" name="__codelineno-0-100"></a><span class="sd"> * @param int $comp_word_num The command word number to autocomplete</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-101" id="__codelineno-0-101" name="__codelineno-0-101"></a><span class="sd"> * @param string $comp_word The command word to autocomplete</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-102" id="__codelineno-0-102" name="__codelineno-0-102"></a><span class="sd"> * @param array<string> $opts List of global available options</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-103" id="__codelineno-0-103" name="__codelineno-0-103"></a><span class="sd"> *</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-104" id="__codelineno-0-104" name="__codelineno-0-104"></a><span class="sd"> * @return array<string> List of available options for the word to autocomplete</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-105" id="__codelineno-0-105" name="__codelineno-0-105"></a><span class="sd"> **/</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-106" id="__codelineno-0-106" name="__codelineno-0-106"></a><span class="k">public</span> <span class="k">static</span> <span class="k">function</span> <span class="nf">cli_my_custom_cli_cmd_autocompleter</span><span class="p">(</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-107" id="__codelineno-0-107" name="__codelineno-0-107"></a> <span class="nv">$command_args</span><span class="p">,</span> <span class="nv">$comp_word_num</span><span class="p">,</span> <span class="nv">$comp_word</span><span class="p">,</span> <span class="nv">$opts</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-108" id="__codelineno-0-108" name="__codelineno-0-108"></a><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-109" id="__codelineno-0-109" name="__codelineno-0-109"></a> <span class="nv">$opts</span> <span class="o">=</span> <span class="nb">array_merge</span><span class="p">(</span><span class="nv">$opts</span><span class="p">,</span> <span class="k">array</span> <span class="p">(</span><span class="s1">'-f'</span><span class="p">,</span> <span class="s1">'--force'</span><span class="p">));</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-110" id="__codelineno-0-110" name="__codelineno-0-110"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-111" id="__codelineno-0-111" name="__codelineno-0-111"></a> <span class="c1">// Handle positional args</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-112" id="__codelineno-0-112" name="__codelineno-0-112"></a> <span class="nv">$objType</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-113" id="__codelineno-0-113" name="__codelineno-0-113"></a> <span class="nv">$objType_arg_num</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-114" id="__codelineno-0-114" name="__codelineno-0-114"></a> <span class="nv">$dn</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-115" id="__codelineno-0-115" name="__codelineno-0-115"></a> <span class="nv">$dn_arg_num</span> <span class="o">=</span> <span class="k">null</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-116" id="__codelineno-0-116" name="__codelineno-0-116"></a> <span class="k">for</span> <span class="p">(</span><span class="nv">$i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nv">$i</span> <span class="o"><</span> <span class="nb">count</span><span class="p">(</span><span class="nv">$command_args</span><span class="p">);</span> <span class="nv">$i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-117" id="__codelineno-0-117" name="__codelineno-0-117"></a> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nb">in_array</span><span class="p">(</span><span class="nv">$command_args</span><span class="p">[</span><span class="nv">$i</span><span class="p">],</span> <span class="nv">$opts</span><span class="p">))</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-118" id="__codelineno-0-118" name="__codelineno-0-118"></a> <span class="c1">// If object type not defined</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-119" id="__codelineno-0-119" name="__codelineno-0-119"></a> <span class="k">if</span> <span class="p">(</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$objType</span><span class="p">))</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-120" id="__codelineno-0-120" name="__codelineno-0-120"></a> <span class="c1">// Defined it</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-121" id="__codelineno-0-121" name="__codelineno-0-121"></a> <span class="nv">$objType</span> <span class="o">=</span> <span class="nv">$command_args</span><span class="p">[</span><span class="nv">$i</span><span class="p">];</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-122" id="__codelineno-0-122" name="__codelineno-0-122"></a> <span class="nx">LScli</span><span class="o">::</span><span class="na">unquote_word</span><span class="p">(</span><span class="nv">$objType</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-123" id="__codelineno-0-123" name="__codelineno-0-123"></a> <span class="nv">$objType_arg_num</span> <span class="o">=</span> <span class="nv">$i</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-124" id="__codelineno-0-124" name="__codelineno-0-124"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-125" id="__codelineno-0-125" name="__codelineno-0-125"></a> <span class="c1">// Check object type exists</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-126" id="__codelineno-0-126" name="__codelineno-0-126"></a> <span class="nv">$objTypes</span> <span class="o">=</span> <span class="nx">LScli</span><span class="o">::</span><span class="na">autocomplete_LSobject_types</span><span class="p">(</span><span class="nv">$objType</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-127" id="__codelineno-0-127" name="__codelineno-0-127"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-128" id="__codelineno-0-128" name="__codelineno-0-128"></a> <span class="c1">// Load it if exist and not trying to complete it</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-129" id="__codelineno-0-129" name="__codelineno-0-129"></a> <span class="k">if</span> <span class="p">(</span><span class="nb">in_array</span><span class="p">(</span><span class="nv">$objType</span><span class="p">,</span> <span class="nv">$objTypes</span><span class="p">)</span> <span class="o">&&</span> <span class="nv">$i</span> <span class="o">!=</span> <span class="nv">$comp_word_num</span><span class="p">)</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-130" id="__codelineno-0-130" name="__codelineno-0-130"></a> <span class="nx">LSsession</span><span class="o">::</span><span class="na">loadLSobject</span><span class="p">(</span><span class="nv">$objType</span><span class="p">,</span> <span class="k">false</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-131" id="__codelineno-0-131" name="__codelineno-0-131"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-132" id="__codelineno-0-132" name="__codelineno-0-132"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-133" id="__codelineno-0-133" name="__codelineno-0-133"></a> <span class="k">elseif</span> <span class="p">(</span><span class="nb">is_null</span><span class="p">(</span><span class="nv">$dn</span><span class="p">))</span> <span class="p">{</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-134" id="__codelineno-0-134" name="__codelineno-0-134"></a> <span class="nv">$dn</span> <span class="o">=</span> <span class="nv">$command_args</span><span class="p">[</span><span class="nv">$i</span><span class="p">];</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-135" id="__codelineno-0-135" name="__codelineno-0-135"></a> <span class="nx">LScli</span><span class="o">::</span><span class="na">unquote_word</span><span class="p">(</span><span class="nv">$dn</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-136" id="__codelineno-0-136" name="__codelineno-0-136"></a> <span class="nv">$dn_arg_num</span> <span class="o">=</span> <span class="nv">$i</span><span class="p">;</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-137" id="__codelineno-0-137" name="__codelineno-0-137"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-138" id="__codelineno-0-138" name="__codelineno-0-138"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-139" id="__codelineno-0-139" name="__codelineno-0-139"></a> <span class="p">}</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-140" id="__codelineno-0-140" name="__codelineno-0-140"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-141" id="__codelineno-0-141" name="__codelineno-0-141"></a> <span class="c1">// If objType not already chosen (or currently autocomplete),</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-142" id="__codelineno-0-142" name="__codelineno-0-142"></a> <span class="c1">// add LSobject types to available options</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-143" id="__codelineno-0-143" name="__codelineno-0-143"></a> <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nv">$objType</span> <span class="o">||</span> <span class="nv">$objType_arg_num</span> <span class="o">==</span> <span class="nv">$comp_word_num</span><span class="p">)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-144" id="__codelineno-0-144" name="__codelineno-0-144"></a> <span class="nv">$opts</span> <span class="o">=</span> <span class="nb">array_merge</span><span class="p">(</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-145" id="__codelineno-0-145" name="__codelineno-0-145"></a> <span class="nv">$opts</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-146" id="__codelineno-0-146" name="__codelineno-0-146"></a> <span class="nx">LScli</span><span class="o">::</span><span class="na">autocomplete_LSobject_types</span><span class="p">(</span><span class="nv">$comp_word</span><span class="p">)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-147" id="__codelineno-0-147" name="__codelineno-0-147"></a> <span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-148" id="__codelineno-0-148" name="__codelineno-0-148"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-149" id="__codelineno-0-149" name="__codelineno-0-149"></a> <span class="c1">// If dn not already chosen (or currently autocomplete), try autocomplete it</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-150" id="__codelineno-0-150" name="__codelineno-0-150"></a> <span class="k">elseif</span> <span class="p">(</span><span class="o">!</span><span class="nv">$dn</span> <span class="o">||</span> <span class="nv">$dn_arg_num</span> <span class="o">==</span> <span class="nv">$comp_word_num</span><span class="p">)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-151" id="__codelineno-0-151" name="__codelineno-0-151"></a> <span class="nv">$opts</span> <span class="o">=</span> <span class="nb">array_merge</span><span class="p">(</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-152" id="__codelineno-0-152" name="__codelineno-0-152"></a> <span class="nv">$opts</span><span class="p">,</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-153" id="__codelineno-0-153" name="__codelineno-0-153"></a> <span class="nx">LScli</span><span class="o">::</span><span class="na">autocomplete_LSobject_dn</span><span class="p">(</span><span class="nv">$objType</span><span class="p">,</span> <span class="nv">$comp_word</span><span class="p">)</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-154" id="__codelineno-0-154" name="__codelineno-0-154"></a> <span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-155" id="__codelineno-0-155" name="__codelineno-0-155"></a>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-156" id="__codelineno-0-156" name="__codelineno-0-156"></a> <span class="k">return</span> <span class="nx">LScli</span><span class="o">::</span><span class="na">autocomplete_opts</span><span class="p">(</span><span class="nv">$opts</span><span class="p">,</span> <span class="nv">$comp_word</span><span class="p">);</span>
|
||
<a href="#contrib-addons-cli-commands-__codelineno-0-157" id="__codelineno-0-157" name="__codelineno-0-157"></a><span class="p">}</span>
|
||
</code></pre></div></section><h1 class="nav-section-title-end">Ended: Les addons (LSaddon)</h1><section class="print-page" id="contrib-form-elements"><h1 id="contrib-form-elements-les-elements-des-formulaires-lsformelement">Les éléments des formulaires (LSformElement)</h1>
|
||
<p>Les <a href="#contrib-form-elements-lsformelements">LSformElements</a> sont les types de champs de formulaire supportés par
|
||
l'application.</p>
|
||
<p>Pour chaque type implémenté, on devra trouver :</p>
|
||
<ul>
|
||
<li>Une classe PHP dérivée de la classe <code>LSattr_html</code> et devant s'appeler
|
||
<code>LSattr_html_[nom du type d'attribut HTML]</code>. Dans celle-ci, il devra être défini à minima la
|
||
variable de classe <code>LSformElement_type</code> permettant de référencer le type
|
||
d'<a href="#contrib-form-elements-lsformelements">LSformElement</a> à utiliser ;</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p>Une classe PHP dérivée de la classe <code>LSformElement</code> et devant s'appeler
|
||
<code>LSformElement_[nom du type d'LSformElement]</code>. Cette classe implémentera tout ce qui concerne
|
||
l'affichage du champ dans le formulaire et le traitement d'une valeur retournée par ce dernier.
|
||
Cela concerne notamment les méthodes suivantes :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>getDisplay()</code></p>
|
||
<p>Retourne les informations d'affichage du champ dans un formulaire sous la forme d'un tableau
|
||
<em>(implémentation obligatoire, pas de méthode par défaut)</em>. Il sera possible de s'appuyer sur la
|
||
méthode <code>getLabelInfos()</code> permettant de générer et récupérer tout ce qui concerne le label du
|
||
champ du formulaire. Il faudra cependant à minima fournir également la clé <code>html</code> dans le
|
||
tableau retourné qui devra contenir le bout de code HTML correspondant au champ du formulaire.
|
||
Communément, ce code HTML est généré en appelant la méthode <code>fetchTemplate()</code>.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>fetchTemplate()</code></p>
|
||
<p>Retourne le code HTML du champ dans le formulaire. L'implémentation de cette méthode est
|
||
facultative et par défaut, cette méthode utilisera la variable de classe <code>$template</code> pour
|
||
connaître le fichier de template à utiliser. Ce fichier de template permettra la génération de
|
||
la liste de tous les champs associés à chacune des valeurs de l'attribut. Individuellement, le
|
||
champ d'une des valeurs de l'attribut est généré à l'aide du fichier de template référencé dans
|
||
la variable de class <code>$fieldTemplate</code>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>La variable de classe <code>$fieldTemplate</code> est également utilisée par la méthode
|
||
<code>LSformElement :: getEmptyField()</code> qui sert à générer le code HTML d'un champ du formulaire
|
||
pour une nouvelle valeur de l'attribut. Cette méthode est notamment utilisée lorsque l'on
|
||
clique sur le bouton permettant d'ajouter une valeur à un champ du formulaire.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>getPostData()</code></p>
|
||
<p>Récupère dans les données postées par le formulaire, celle concernant ce champ. Cette méthode
|
||
devra potentiellement traiter l'ensemble des valeurs de l'attribut envoyées par le formulaire
|
||
et les définir dans le tableau passé en référence en tant que premier argument, les valeurs de
|
||
l'attribut. L'implémentation de cette méthode est facultative et par défaut, un tableau de
|
||
valeurs portant le nom de l'attribut LDAP correspondant sera récupérée comme valeur de
|
||
l'attribut.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour plus d'informations sur le rôle et fonctionnement de cette méthode, référer à la
|
||
méthode par défaut, définie dans la classe PHP parente <code>LSformElement</code>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>setValueFromPostData()</code></p>
|
||
<p>Définit les valeurs de l'attribut à partir des données reçues du formulaire (et récupérées par
|
||
la méthode <code>getPostData</code>). L'implémentation de cette méthode est facultative et par défaut,
|
||
aucune transformation ne sera faites à cette étape sur les données récupérées depuis le
|
||
formulaire. Implémenter cette méthode pourra cependant se révéler utile en cas de champs de
|
||
formulaire complexe (attribut composite par exemple).</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>autocomplete_attr_values()</code></p>
|
||
<p>Génère de la liste des valeurs possibles de l'attribut dans un contexte <em>CLI</em>.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Pour plus d'informations sur le rôle et fonctionnement de cette méthode, référer aux
|
||
commentaires de la méthode par défaut, définie dans la classe PHP parente <code>LSformElement</code>.
|
||
Vous pouvez également vous inspirer des exemples d'implémentations fournies avec les autres
|
||
type d'<a href="#contrib-form-elements-lsformelements">LSformElement</a>.</p>
|
||
</div>
|
||
</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>Un (ou plusieurs) fichier template pour la génération du code HTML du champ du formulaire.
|
||
Communément, le fichier <code>LSformElement.tpl</code> est utilisé pour générer la structure de la liste des
|
||
champs correspondant aux différentes valeurs de l'attribut. Ce template utilise une variable
|
||
<code>$fieldTemplate</code> pour définir quel fichier template devra être utilisé pour générer le code HTML
|
||
de chaque champ associés à une valeur. C'est ce second fichier de template qui est en général à
|
||
fournir à minima avec votre <a href="#contrib-form-elements-lsformelements">LSformElement</a>.</li>
|
||
</ul>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Il peut être utile d'étendre un type d'<a href="#contrib-form-elements-lsformelements">LSformElement</a> existant pour faciliter
|
||
l'implémentation d'un nouveau type. Pour cela, vous devez utiliser l'héritage de classe PHP en
|
||
faisant dériver vos nouvelles classes des classes du <a href="#contrib-form-elements-lsformelements">LSformElement</a> dont vous
|
||
vous inspirer, plutôt que les classes génériques. Vous pouvez prendre exemple sur le type
|
||
d'<a href="#contrib-form-elements-lsformelements">LSformElement</a> <code>pre</code> qui s'inspire du type <code>textarea</code>, ou encore du type
|
||
<code>url</code> dérivé du type <code>text</code>.</p>
|
||
</div></section><section class="print-page" id="contrib-form-rules"><h1 id="contrib-form-rules-les-regles-de-validation-syntaxiques-lsformrule">Les règles de validation syntaxiques (LSformRule)</h1>
|
||
<p>Les <a href="#contrib-form-rules-lsformrules">LSformRules</a> sont les règles syntaxiques applicables aux champs des formulaires.
|
||
Ces règles serviront à s'assurer que les valeurs des champs récupérées des formulaires sont
|
||
syntaxiquement correctes. Elles seront configurables via le paramètre <code>check_data</code> des attributs des
|
||
<a href="#conf-configuration-lsobject">LSobjects</a>.</p>
|
||
<p>Pour chaque type implémenté, on trouvera une classe PHP dérivée de la classe <code>LSformRule</code> et devant
|
||
s'appeler <code>LSattr_rule_[nom du type]</code>. Dans celle-ci, il devra être défini la méthode statique
|
||
<code>validate()</code> qui implémentera le contrôle syntaxique. Cette méthode prendra en paramètres :</p>
|
||
<ul>
|
||
<li>
|
||
<p><code>$value</code></p>
|
||
<p>La valeur à tester.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$options</code></p>
|
||
<p>Un tableau des options définies dans la configuration pour ce contrôle syntaxique.</p>
|
||
</li>
|
||
</ul>
|
||
<ul>
|
||
<li>
|
||
<p><code>$formElement</code></p>
|
||
<p>Une référence au champ du formulaire (objet <a href="#contrib-form-rules-lsformelements">LSformElement</a>).</p>
|
||
</li>
|
||
</ul>
|
||
<p>Cette méthode devra retourner <code>True</code> ou <code>False</code> si la valeur testée est respectivement valide ou
|
||
invalide. Elle pourra également déclencher une exception <code>LSformRuleException</code> qui lui permettra de
|
||
donner des messages d'erreurs elle-même sur le(s) problème(s) detecté(s) durant l'analyse de la
|
||
valeur passée. Le constructeur de ce type d'exception prend en tant que premier paramètre un tableau
|
||
de messages d'erreurs (ou un simple message d'erreur) qui seront retournés à l'utilisateur.</p>
|
||
<div class="admonition note">
|
||
<p class="admonition-title">Note</p>
|
||
<p>Par défaut, les valeurs de l'attribut sont testées une à une via la méthode <code>validate()</code>.
|
||
Cependant, il est possible d'implémenter une méthode de validation pour toutes les valeurs de
|
||
l'attribut en une seule fois en affectant la valeur <code>false</code> à la constante de classe
|
||
<code>validate_one_by_one</code>. Dans ce cas, l'ensemble des valeurs de l'attribut seront passées via le
|
||
paramètre <code>$value</code> à la méthode <code>validate()</code> (sous la forme d'un tableau). Cela pourra par
|
||
exemple être utile pour implémenter une validation de la cohérence des valeurs les unes vis à
|
||
vis des autres (unicité, nombre maximum de valeurs, …).</p>
|
||
</div></section><h1 class="nav-section-title-end">Ended: Contribution</h1></div>
|
||
</article>
|
||
</div>
|
||
<script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
|
||
</div>
|
||
</main>
|
||
<footer class="md-footer">
|
||
<div class="md-footer-meta md-typeset">
|
||
<div class="md-footer-meta__inner md-grid">
|
||
<div class="md-copyright">
|
||
<div class="md-copyright__highlight">
|
||
Easter-eggs
|
||
</div>
|
||
|
||
|
||
Made with
|
||
<a href="https://squidfunk.github.io/mkdocs-material/" rel="noopener" target="_blank">
|
||
Material for MkDocs
|
||
</a>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</footer>
|
||
</div>
|
||
<div class="md-dialog" data-md-component="dialog">
|
||
<div class="md-dialog__inner md-typeset"></div>
|
||
</div>
|
||
<script id="__config" type="application/json">{"base": "../..", "features": [], "search": "../assets/javascripts/workers/search.6ce7567c.min.js", "translations": {"clipboard.copied": "Copi\u00e9 dans le presse-papier", "clipboard.copy": "Copier dans le presse-papier", "search.result.more.one": "1 de plus sur cette page", "search.result.more.other": "# de plus sur cette page", "search.result.none": "Aucun document trouv\u00e9", "search.result.one": "1 document trouv\u00e9", "search.result.other": "# documents trouv\u00e9s", "search.result.placeholder": "Taper pour d\u00e9marrer la recherche", "search.result.term.missing": "Non trouv\u00e9", "select.version": "S\u00e9lectionner la version"}, "version": {"provider": "mike"}}</script>
|
||
<script src="data:text/javascript;base64,InVzZSBzdHJpY3QiOygoKT0+e3ZhciBXaT1PYmplY3QuY3JlYXRlO3ZhciBncj1PYmplY3QuZGVmaW5lUHJvcGVydHk7dmFyIERpPU9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3I7dmFyIFZpPU9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzLFZ0PU9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMsTmk9T2JqZWN0LmdldFByb3RvdHlwZU9mLHlyPU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHksYW89T2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZTt2YXIgaW89KGUsdCxyKT0+dCBpbiBlP2dyKGUsdCx7ZW51bWVyYWJsZTohMCxjb25maWd1cmFibGU6ITAsd3JpdGFibGU6ITAsdmFsdWU6cn0pOmVbdF09ciwkPShlLHQpPT57Zm9yKHZhciByIGluIHR8fCh0PXt9KSl5ci5jYWxsKHQscikmJmlvKGUscix0W3JdKTtpZihWdClmb3IodmFyIHIgb2YgVnQodCkpYW8uY2FsbCh0LHIpJiZpbyhlLHIsdFtyXSk7cmV0dXJuIGV9O3ZhciBzbz0oZSx0KT0+e3ZhciByPXt9O2Zvcih2YXIgbyBpbiBlKXlyLmNhbGwoZSxvKSYmdC5pbmRleE9mKG8pPDAmJihyW29dPWVbb10pO2lmKGUhPW51bGwmJlZ0KWZvcih2YXIgbyBvZiBWdChlKSl0LmluZGV4T2Yobyk8MCYmYW8uY2FsbChlLG8pJiYocltvXT1lW29dKTtyZXR1cm4gcn07dmFyIHhyPShlLHQpPT4oKT0+KHR8fGUoKHQ9e2V4cG9ydHM6e319KS5leHBvcnRzLHQpLHQuZXhwb3J0cyk7dmFyIHppPShlLHQscixvKT0+e2lmKHQmJnR5cGVvZiB0PT0ib2JqZWN0Inx8dHlwZW9mIHQ9PSJmdW5jdGlvbiIpZm9yKGxldCBuIG9mIFZpKHQpKSF5ci5jYWxsKGUsbikmJm4hPT1yJiZncihlLG4se2dldDooKT0+dFtuXSxlbnVtZXJhYmxlOiEobz1EaSh0LG4pKXx8by5lbnVtZXJhYmxlfSk7cmV0dXJuIGV9O3ZhciBNdD0oZSx0LHIpPT4ocj1lIT1udWxsP1dpKE5pKGUpKTp7fSx6aSh0fHwhZXx8IWUuX19lc01vZHVsZT9ncihyLCJkZWZhdWx0Iix7dmFsdWU6ZSxlbnVtZXJhYmxlOiEwfSk6cixlKSk7dmFyIGNvPShlLHQscik9Pm5ldyBQcm9taXNlKChvLG4pPT57dmFyIGk9cD0+e3RyeXtzKHIubmV4dChwKSl9Y2F0Y2goYyl7bihjKX19LGE9cD0+e3RyeXtzKHIudGhyb3cocCkpfWNhdGNoKGMpe24oYyl9fSxzPXA9PnAuZG9uZT9vKHAudmFsdWUpOlByb21pc2UucmVzb2x2ZShwLnZhbHVlKS50aGVuKGksYSk7cygocj1yLmFwcGx5KGUsdCkpLm5leHQoKSl9KTt2YXIgbG89eHIoKEVyLHBvKT0+eyhmdW5jdGlvbihlLHQpe3R5cGVvZiBFcj09Im9iamVjdCImJnR5cGVvZiBwbyE9InVuZGVmaW5lZCI/dCgpOnR5cGVvZiBkZWZpbmU9PSJmdW5jdGlvbiImJmRlZmluZS5hbWQ/ZGVmaW5lKHQpOnQoKX0pKEVyLGZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2Z1bmN0aW9uIGUocil7dmFyIG89ITAsbj0hMSxpPW51bGwsYT17dGV4dDohMCxzZWFyY2g6ITAsdXJsOiEwLHRlbDohMCxlbWFpbDohMCxwYXNzd29yZDohMCxudW1iZXI6ITAsZGF0ZTohMCxtb250aDohMCx3ZWVrOiEwLHRpbWU6ITAsZGF0ZXRpbWU6ITAsImRhdGV0aW1lLWxvY2FsIjohMH07ZnVuY3Rpb24gcyhrKXtyZXR1cm4hIShrJiZrIT09ZG9jdW1lbnQmJmsubm9kZU5hbWUhPT0iSFRNTCImJmsubm9kZU5hbWUhPT0iQk9EWSImJiJjbGFzc0xpc3QiaW4gayYmImNvbnRhaW5zImluIGsuY2xhc3NMaXN0KX1mdW5jdGlvbiBwKGspe3ZhciBmdD1rLnR5cGUscWU9ay50YWdOYW1lO3JldHVybiEhKHFlPT09IklOUFVUIiYmYVtmdF0mJiFrLnJlYWRPbmx5fHxxZT09PSJURVhUQVJFQSImJiFrLnJlYWRPbmx5fHxrLmlzQ29udGVudEVkaXRhYmxlKX1mdW5jdGlvbiBjKGspe2suY2xhc3NMaXN0LmNvbnRhaW5zKCJmb2N1cy12aXNpYmxlIil8fChrLmNsYXNzTGlzdC5hZGQoImZvY3VzLXZpc2libGUiKSxrLnNldEF0dHJpYnV0ZSgiZGF0YS1mb2N1cy12aXNpYmxlLWFkZGVkIiwiIikpfWZ1bmN0aW9uIGwoayl7ay5oYXNBdHRyaWJ1dGUoImRhdGEtZm9jdXMtdmlzaWJsZS1hZGRlZCIpJiYoay5jbGFzc0xpc3QucmVtb3ZlKCJmb2N1cy12aXNpYmxlIiksay5yZW1vdmVBdHRyaWJ1dGUoImRhdGEtZm9jdXMtdmlzaWJsZS1hZGRlZCIpKX1mdW5jdGlvbiBmKGspe2subWV0YUtleXx8ay5hbHRLZXl8fGsuY3RybEtleXx8KHMoci5hY3RpdmVFbGVtZW50KSYmYyhyLmFjdGl2ZUVsZW1lbnQpLG89ITApfWZ1bmN0aW9uIHUoayl7bz0hMX1mdW5jdGlvbiBkKGspe3Moay50YXJnZXQpJiYob3x8cChrLnRhcmdldCkpJiZjKGsudGFyZ2V0KX1mdW5jdGlvbiB5KGspe3Moay50YXJnZXQpJiYoay50YXJnZXQuY2xhc3NMaXN0LmNvbnRhaW5zKCJmb2N1cy12aXNpYmxlIil8fGsudGFyZ2V0Lmhhc0F0dHJpYnV0ZSgiZGF0YS1mb2N1cy12aXNpYmxlLWFkZGVkIikpJiYobj0hMCx3aW5kb3cuY2xlYXJUaW1lb3V0KGkpLGk9d2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKXtuPSExfSwxMDApLGwoay50YXJnZXQpKX1mdW5jdGlvbiBMKGspe2RvY3VtZW50LnZpc2liaWxpdHlTdGF0ZT09PSJoaWRkZW4iJiYobiYmKG89ITApLFgoKSl9ZnVuY3Rpb24gWCgpe2RvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoIm1vdXNlbW92ZSIsSiksZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigibW91c2Vkb3duIixKKSxkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCJtb3VzZXVwIixKKSxkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCJwb2ludGVybW92ZSIsSiksZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigicG9pbnRlcmRvd24iLEopLGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoInBvaW50ZXJ1cCIsSiksZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigidG91Y2htb3ZlIixKKSxkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCJ0b3VjaHN0YXJ0IixKKSxkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCJ0b3VjaGVuZCIsSil9ZnVuY3Rpb24gdGUoKXtkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCJtb3VzZW1vdmUiLEopLGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoIm1vdXNlZG93biIsSiksZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigibW91c2V1cCIsSiksZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigicG9pbnRlcm1vdmUiLEopLGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoInBvaW50ZXJkb3duIixKKSxkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCJwb2ludGVydXAiLEopLGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoInRvdWNobW92ZSIsSiksZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigidG91Y2hzdGFydCIsSiksZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigidG91Y2hlbmQiLEopfWZ1bmN0aW9uIEooayl7ay50YXJnZXQubm9kZU5hbWUmJmsudGFyZ2V0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk9PT0iaHRtbCJ8fChvPSExLHRlKCkpfWRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoImtleWRvd24iLGYsITApLGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoIm1vdXNlZG93biIsdSwhMCksZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigicG9pbnRlcmRvd24iLHUsITApLGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoInRvdWNoc3RhcnQiLHUsITApLGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoInZpc2liaWxpdHljaGFuZ2UiLEwsITApLFgoKSxyLmFkZEV2ZW50TGlzdGVuZXIoImZvY3VzIixkLCEwKSxyLmFkZEV2ZW50TGlzdGVuZXIoImJsdXIiLHksITApLHIubm9kZVR5cGU9PT1Ob2RlLkRPQ1VNRU5UX0ZSQUdNRU5UX05PREUmJnIuaG9zdD9yLmhvc3Quc2V0QXR0cmlidXRlKCJkYXRhLWpzLWZvY3VzLXZpc2libGUiLCIiKTpyLm5vZGVUeXBlPT09Tm9kZS5ET0NVTUVOVF9OT0RFJiYoZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsYXNzTGlzdC5hZGQoImpzLWZvY3VzLXZpc2libGUiKSxkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2V0QXR0cmlidXRlKCJkYXRhLWpzLWZvY3VzLXZpc2libGUiLCIiKSl9aWYodHlwZW9mIHdpbmRvdyE9InVuZGVmaW5lZCImJnR5cGVvZiBkb2N1bWVudCE9InVuZGVmaW5lZCIpe3dpbmRvdy5hcHBseUZvY3VzVmlzaWJsZVBvbHlmaWxsPWU7dmFyIHQ7dHJ5e3Q9bmV3IEN1c3RvbUV2ZW50KCJmb2N1cy12aXNpYmxlLXBvbHlmaWxsLXJlYWR5Iil9Y2F0Y2gocil7dD1kb2N1bWVudC5jcmVhdGVFdmVudCgiQ3VzdG9tRXZlbnQiKSx0LmluaXRDdXN0b21FdmVudCgiZm9jdXMtdmlzaWJsZS1wb2x5ZmlsbC1yZWFkeSIsITEsITEse30pfXdpbmRvdy5kaXNwYXRjaEV2ZW50KHQpfXR5cGVvZiBkb2N1bWVudCE9InVuZGVmaW5lZCImJmUoZG9jdW1lbnQpfSl9KTt2YXIgcXI9eHIoKGh5LE9uKT0+eyJ1c2Ugc3RyaWN0IjsvKiEKICogZXNjYXBlLWh0bWwKICogQ29weXJpZ2h0KGMpIDIwMTItMjAxMyBUSiBIb2xvd2F5Y2h1awogKiBDb3B5cmlnaHQoYykgMjAxNSBBbmRyZWFzIEx1YmJlCiAqIENvcHlyaWdodChjKSAyMDE1IFRpYW5jaGVuZyAiVGltb3RoeSIgR3UKICogTUlUIExpY2Vuc2VkCiAqL3ZhciAkYT0vWyInJjw+XS87T24uZXhwb3J0cz1QYTtmdW5jdGlvbiBQYShlKXt2YXIgdD0iIitlLHI9JGEuZXhlYyh0KTtpZighcilyZXR1cm4gdDt2YXIgbyxuPSIiLGk9MCxhPTA7Zm9yKGk9ci5pbmRleDtpPHQubGVuZ3RoO2krKyl7c3dpdGNoKHQuY2hhckNvZGVBdChpKSl7Y2FzZSAzNDpvPSImcXVvdDsiO2JyZWFrO2Nhc2UgMzg6bz0iJmFtcDsiO2JyZWFrO2Nhc2UgMzk6bz0iJiMzOTsiO2JyZWFrO2Nhc2UgNjA6bz0iJmx0OyI7YnJlYWs7Y2FzZSA2MjpvPSImZ3Q7IjticmVhaztkZWZhdWx0OmNvbnRpbnVlfWEhPT1pJiYobis9dC5zdWJzdHJpbmcoYSxpKSksYT1pKzEsbis9b31yZXR1cm4gYSE9PWk/bit0LnN1YnN0cmluZyhhLGkpOm59fSk7dmFyIEJyPXhyKChJdCxZcik9PnsvKiEKICogY2xpcGJvYXJkLmpzIHYyLjAuMTEKICogaHR0cHM6Ly9jbGlwYm9hcmRqcy5jb20vCiAqCiAqIExpY2Vuc2VkIE1JVCDCqSBaZW5vIFJvY2hhCiAqLyhmdW5jdGlvbih0LHIpe3R5cGVvZiBJdD09Im9iamVjdCImJnR5cGVvZiBZcj09Im9iamVjdCI/WXIuZXhwb3J0cz1yKCk6dHlwZW9mIGRlZmluZT09ImZ1bmN0aW9uIiYmZGVmaW5lLmFtZD9kZWZpbmUoW10scik6dHlwZW9mIEl0PT0ib2JqZWN0Ij9JdC5DbGlwYm9hcmRKUz1yKCk6dC5DbGlwYm9hcmRKUz1yKCl9KShJdCxmdW5jdGlvbigpe3JldHVybiBmdW5jdGlvbigpe3ZhciBlPXs2ODY6ZnVuY3Rpb24obyxuLGkpeyJ1c2Ugc3RyaWN0IjtpLmQobix7ZGVmYXVsdDpmdW5jdGlvbigpe3JldHVybiBVaX19KTt2YXIgYT1pKDI3OSkscz1pLm4oYSkscD1pKDM3MCksYz1pLm4ocCksbD1pKDgxNyksZj1pLm4obCk7ZnVuY3Rpb24gdShWKXt0cnl7cmV0dXJuIGRvY3VtZW50LmV4ZWNDb21tYW5kKFYpfWNhdGNoKEEpe3JldHVybiExfX12YXIgZD1mdW5jdGlvbihBKXt2YXIgTT1mKCkoQSk7cmV0dXJuIHUoImN1dCIpLE19LHk9ZDtmdW5jdGlvbiBMKFYpe3ZhciBBPWRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5nZXRBdHRyaWJ1dGUoImRpciIpPT09InJ0bCIsTT1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJ0ZXh0YXJlYSIpO00uc3R5bGUuZm9udFNpemU9IjEycHQiLE0uc3R5bGUuYm9yZGVyPSIwIixNLnN0eWxlLnBhZGRpbmc9IjAiLE0uc3R5bGUubWFyZ2luPSIwIixNLnN0eWxlLnBvc2l0aW9uPSJhYnNvbHV0ZSIsTS5zdHlsZVtBPyJyaWdodCI6ImxlZnQiXT0iLTk5OTlweCI7dmFyIEY9d2luZG93LnBhZ2VZT2Zmc2V0fHxkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc2Nyb2xsVG9wO3JldHVybiBNLnN0eWxlLnRvcD0iIi5jb25jYXQoRiwicHgiKSxNLnNldEF0dHJpYnV0ZSgicmVhZG9ubHkiLCIiKSxNLnZhbHVlPVYsTX12YXIgWD1mdW5jdGlvbihBLE0pe3ZhciBGPUwoQSk7TS5jb250YWluZXIuYXBwZW5kQ2hpbGQoRik7dmFyIEQ9ZigpKEYpO3JldHVybiB1KCJjb3B5IiksRi5yZW1vdmUoKSxEfSx0ZT1mdW5jdGlvbihBKXt2YXIgTT1hcmd1bWVudHMubGVuZ3RoPjEmJmFyZ3VtZW50c1sxXSE9PXZvaWQgMD9hcmd1bWVudHNbMV06e2NvbnRhaW5lcjpkb2N1bWVudC5ib2R5fSxGPSIiO3JldHVybiB0eXBlb2YgQT09InN0cmluZyI/Rj1YKEEsTSk6QSBpbnN0YW5jZW9mIEhUTUxJbnB1dEVsZW1lbnQmJiFbInRleHQiLCJzZWFyY2giLCJ1cmwiLCJ0ZWwiLCJwYXNzd29yZCJdLmluY2x1ZGVzKEE9PW51bGw/dm9pZCAwOkEudHlwZSk/Rj1YKEEudmFsdWUsTSk6KEY9ZigpKEEpLHUoImNvcHkiKSksRn0sSj10ZTtmdW5jdGlvbiBrKFYpeyJAYmFiZWwvaGVscGVycyAtIHR5cGVvZiI7cmV0dXJuIHR5cGVvZiBTeW1ib2w9PSJmdW5jdGlvbiImJnR5cGVvZiBTeW1ib2wuaXRlcmF0b3I9PSJzeW1ib2wiP2s9ZnVuY3Rpb24oTSl7cmV0dXJuIHR5cGVvZiBNfTprPWZ1bmN0aW9uKE0pe3JldHVybiBNJiZ0eXBlb2YgU3ltYm9sPT0iZnVuY3Rpb24iJiZNLmNvbnN0cnVjdG9yPT09U3ltYm9sJiZNIT09U3ltYm9sLnByb3RvdHlwZT8ic3ltYm9sIjp0eXBlb2YgTX0sayhWKX12YXIgZnQ9ZnVuY3Rpb24oKXt2YXIgQT1hcmd1bWVudHMubGVuZ3RoPjAmJmFyZ3VtZW50c1swXSE9PXZvaWQgMD9hcmd1bWVudHNbMF06e30sTT1BLmFjdGlvbixGPU09PT12b2lkIDA/ImNvcHkiOk0sRD1BLmNvbnRhaW5lcixZPUEudGFyZ2V0LCRlPUEudGV4dDtpZihGIT09ImNvcHkiJiZGIT09ImN1dCIpdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkICJhY3Rpb24iIHZhbHVlLCB1c2UgZWl0aGVyICJjb3B5IiBvciAiY3V0IicpO2lmKFkhPT12b2lkIDApaWYoWSYmayhZKT09PSJvYmplY3QiJiZZLm5vZGVUeXBlPT09MSl7aWYoRj09PSJjb3B5IiYmWS5oYXNBdHRyaWJ1dGUoImRpc2FibGVkIikpdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkICJ0YXJnZXQiIGF0dHJpYnV0ZS4gUGxlYXNlIHVzZSAicmVhZG9ubHkiIGluc3RlYWQgb2YgImRpc2FibGVkIiBhdHRyaWJ1dGUnKTtpZihGPT09ImN1dCImJihZLmhhc0F0dHJpYnV0ZSgicmVhZG9ubHkiKXx8WS5oYXNBdHRyaWJ1dGUoImRpc2FibGVkIikpKXRocm93IG5ldyBFcnJvcihgSW52YWxpZCAidGFyZ2V0IiBhdHRyaWJ1dGUuIFlvdSBjYW4ndCBjdXQgdGV4dCBmcm9tIGVsZW1lbnRzIHdpdGggInJlYWRvbmx5IiBvciAiZGlzYWJsZWQiIGF0dHJpYnV0ZXNgKX1lbHNlIHRocm93IG5ldyBFcnJvcignSW52YWxpZCAidGFyZ2V0IiB2YWx1ZSwgdXNlIGEgdmFsaWQgRWxlbWVudCcpO2lmKCRlKXJldHVybiBKKCRlLHtjb250YWluZXI6RH0pO2lmKFkpcmV0dXJuIEY9PT0iY3V0Ij95KFkpOkooWSx7Y29udGFpbmVyOkR9KX0scWU9ZnQ7ZnVuY3Rpb24gRmUoVil7IkBiYWJlbC9oZWxwZXJzIC0gdHlwZW9mIjtyZXR1cm4gdHlwZW9mIFN5bWJvbD09ImZ1bmN0aW9uIiYmdHlwZW9mIFN5bWJvbC5pdGVyYXRvcj09InN5bWJvbCI/RmU9ZnVuY3Rpb24oTSl7cmV0dXJuIHR5cGVvZiBNfTpGZT1mdW5jdGlvbihNKXtyZXR1cm4gTSYmdHlwZW9mIFN5bWJvbD09ImZ1bmN0aW9uIiYmTS5jb25zdHJ1Y3Rvcj09PVN5bWJvbCYmTSE9PVN5bWJvbC5wcm90b3R5cGU/InN5bWJvbCI6dHlwZW9mIE19LEZlKFYpfWZ1bmN0aW9uIGtpKFYsQSl7aWYoIShWIGluc3RhbmNlb2YgQSkpdGhyb3cgbmV3IFR5cGVFcnJvcigiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uIil9ZnVuY3Rpb24gbm8oVixBKXtmb3IodmFyIE09MDtNPEEubGVuZ3RoO00rKyl7dmFyIEY9QVtNXTtGLmVudW1lcmFibGU9Ri5lbnVtZXJhYmxlfHwhMSxGLmNvbmZpZ3VyYWJsZT0hMCwidmFsdWUiaW4gRiYmKEYud3JpdGFibGU9ITApLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShWLEYua2V5LEYpfX1mdW5jdGlvbiBIaShWLEEsTSl7cmV0dXJuIEEmJm5vKFYucHJvdG90eXBlLEEpLE0mJm5vKFYsTSksVn1mdW5jdGlvbiAkaShWLEEpe2lmKHR5cGVvZiBBIT0iZnVuY3Rpb24iJiZBIT09bnVsbCl0aHJvdyBuZXcgVHlwZUVycm9yKCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiIpO1YucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoQSYmQS5wcm90b3R5cGUse2NvbnN0cnVjdG9yOnt2YWx1ZTpWLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH19KSxBJiZicihWLEEpfWZ1bmN0aW9uIGJyKFYsQSl7cmV0dXJuIGJyPU9iamVjdC5zZXRQcm90b3R5cGVPZnx8ZnVuY3Rpb24oRixEKXtyZXR1cm4gRi5fX3Byb3RvX189RCxGfSxicihWLEEpfWZ1bmN0aW9uIFBpKFYpe3ZhciBBPWppKCk7cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIEY9V3QoViksRDtpZihBKXt2YXIgWT1XdCh0aGlzKS5jb25zdHJ1Y3RvcjtEPVJlZmxlY3QuY29uc3RydWN0KEYsYXJndW1lbnRzLFkpfWVsc2UgRD1GLmFwcGx5KHRoaXMsYXJndW1lbnRzKTtyZXR1cm4gUmkodGhpcyxEKX19ZnVuY3Rpb24gUmkoVixBKXtyZXR1cm4gQSYmKEZlKEEpPT09Im9iamVjdCJ8fHR5cGVvZiBBPT0iZnVuY3Rpb24iKT9BOklpKFYpfWZ1bmN0aW9uIElpKFYpe2lmKFY9PT12b2lkIDApdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKCJ0aGlzIGhhc24ndCBiZWVuIGluaXRpYWxpc2VkIC0gc3VwZXIoKSBoYXNuJ3QgYmVlbiBjYWxsZWQiKTtyZXR1cm4gVn1mdW5jdGlvbiBqaSgpe2lmKHR5cGVvZiBSZWZsZWN0PT0idW5kZWZpbmVkInx8IVJlZmxlY3QuY29uc3RydWN0fHxSZWZsZWN0LmNvbnN0cnVjdC5zaGFtKXJldHVybiExO2lmKHR5cGVvZiBQcm94eT09ImZ1bmN0aW9uIilyZXR1cm4hMDt0cnl7cmV0dXJuIERhdGUucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoUmVmbGVjdC5jb25zdHJ1Y3QoRGF0ZSxbXSxmdW5jdGlvbigpe30pKSwhMH1jYXRjaChWKXtyZXR1cm4hMX19ZnVuY3Rpb24gV3QoVil7cmV0dXJuIFd0PU9iamVjdC5zZXRQcm90b3R5cGVPZj9PYmplY3QuZ2V0UHJvdG90eXBlT2Y6ZnVuY3Rpb24oTSl7cmV0dXJuIE0uX19wcm90b19ffHxPYmplY3QuZ2V0UHJvdG90eXBlT2YoTSl9LFd0KFYpfWZ1bmN0aW9uIHZyKFYsQSl7dmFyIE09ImRhdGEtY2xpcGJvYXJkLSIuY29uY2F0KFYpO2lmKEEuaGFzQXR0cmlidXRlKE0pKXJldHVybiBBLmdldEF0dHJpYnV0ZShNKX12YXIgRmk9ZnVuY3Rpb24oVil7JGkoTSxWKTt2YXIgQT1QaShNKTtmdW5jdGlvbiBNKEYsRCl7dmFyIFk7cmV0dXJuIGtpKHRoaXMsTSksWT1BLmNhbGwodGhpcyksWS5yZXNvbHZlT3B0aW9ucyhEKSxZLmxpc3RlbkNsaWNrKEYpLFl9cmV0dXJuIEhpKE0sW3trZXk6InJlc29sdmVPcHRpb25zIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBEPWFyZ3VtZW50cy5sZW5ndGg+MCYmYXJndW1lbnRzWzBdIT09dm9pZCAwP2FyZ3VtZW50c1swXTp7fTt0aGlzLmFjdGlvbj10eXBlb2YgRC5hY3Rpb249PSJmdW5jdGlvbiI/RC5hY3Rpb246dGhpcy5kZWZhdWx0QWN0aW9uLHRoaXMudGFyZ2V0PXR5cGVvZiBELnRhcmdldD09ImZ1bmN0aW9uIj9ELnRhcmdldDp0aGlzLmRlZmF1bHRUYXJnZXQsdGhpcy50ZXh0PXR5cGVvZiBELnRleHQ9PSJmdW5jdGlvbiI/RC50ZXh0OnRoaXMuZGVmYXVsdFRleHQsdGhpcy5jb250YWluZXI9RmUoRC5jb250YWluZXIpPT09Im9iamVjdCI/RC5jb250YWluZXI6ZG9jdW1lbnQuYm9keX19LHtrZXk6Imxpc3RlbkNsaWNrIix2YWx1ZTpmdW5jdGlvbihEKXt2YXIgWT10aGlzO3RoaXMubGlzdGVuZXI9YygpKEQsImNsaWNrIixmdW5jdGlvbigkZSl7cmV0dXJuIFkub25DbGljaygkZSl9KX19LHtrZXk6Im9uQ2xpY2siLHZhbHVlOmZ1bmN0aW9uKEQpe3ZhciBZPUQuZGVsZWdhdGVUYXJnZXR8fEQuY3VycmVudFRhcmdldCwkZT10aGlzLmFjdGlvbihZKXx8ImNvcHkiLER0PXFlKHthY3Rpb246JGUsY29udGFpbmVyOnRoaXMuY29udGFpbmVyLHRhcmdldDp0aGlzLnRhcmdldChZKSx0ZXh0OnRoaXMudGV4dChZKX0pO3RoaXMuZW1pdChEdD8ic3VjY2VzcyI6ImVycm9yIix7YWN0aW9uOiRlLHRleHQ6RHQsdHJpZ2dlcjpZLGNsZWFyU2VsZWN0aW9uOmZ1bmN0aW9uKCl7WSYmWS5mb2N1cygpLHdpbmRvdy5nZXRTZWxlY3Rpb24oKS5yZW1vdmVBbGxSYW5nZXMoKX19KX19LHtrZXk6ImRlZmF1bHRBY3Rpb24iLHZhbHVlOmZ1bmN0aW9uKEQpe3JldHVybiB2cigiYWN0aW9uIixEKX19LHtrZXk6ImRlZmF1bHRUYXJnZXQiLHZhbHVlOmZ1bmN0aW9uKEQpe3ZhciBZPXZyKCJ0YXJnZXQiLEQpO2lmKFkpcmV0dXJuIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoWSl9fSx7a2V5OiJkZWZhdWx0VGV4dCIsdmFsdWU6ZnVuY3Rpb24oRCl7cmV0dXJuIHZyKCJ0ZXh0IixEKX19LHtrZXk6ImRlc3Ryb3kiLHZhbHVlOmZ1bmN0aW9uKCl7dGhpcy5saXN0ZW5lci5kZXN0cm95KCl9fV0sW3trZXk6ImNvcHkiLHZhbHVlOmZ1bmN0aW9uKEQpe3ZhciBZPWFyZ3VtZW50cy5sZW5ndGg+MSYmYXJndW1lbnRzWzFdIT09dm9pZCAwP2FyZ3VtZW50c1sxXTp7Y29udGFpbmVyOmRvY3VtZW50LmJvZHl9O3JldHVybiBKKEQsWSl9fSx7a2V5OiJjdXQiLHZhbHVlOmZ1bmN0aW9uKEQpe3JldHVybiB5KEQpfX0se2tleToiaXNTdXBwb3J0ZWQiLHZhbHVlOmZ1bmN0aW9uKCl7dmFyIEQ9YXJndW1lbnRzLmxlbmd0aD4wJiZhcmd1bWVudHNbMF0hPT12b2lkIDA/YXJndW1lbnRzWzBdOlsiY29weSIsImN1dCJdLFk9dHlwZW9mIEQ9PSJzdHJpbmciP1tEXTpELCRlPSEhZG9jdW1lbnQucXVlcnlDb21tYW5kU3VwcG9ydGVkO3JldHVybiBZLmZvckVhY2goZnVuY3Rpb24oRHQpeyRlPSRlJiYhIWRvY3VtZW50LnF1ZXJ5Q29tbWFuZFN1cHBvcnRlZChEdCl9KSwkZX19XSksTX0ocygpKSxVaT1GaX0sODI4OmZ1bmN0aW9uKG8pe3ZhciBuPTk7aWYodHlwZW9mIEVsZW1lbnQhPSJ1bmRlZmluZWQiJiYhRWxlbWVudC5wcm90b3R5cGUubWF0Y2hlcyl7dmFyIGk9RWxlbWVudC5wcm90b3R5cGU7aS5tYXRjaGVzPWkubWF0Y2hlc1NlbGVjdG9yfHxpLm1vek1hdGNoZXNTZWxlY3Rvcnx8aS5tc01hdGNoZXNTZWxlY3Rvcnx8aS5vTWF0Y2hlc1NlbGVjdG9yfHxpLndlYmtpdE1hdGNoZXNTZWxlY3Rvcn1mdW5jdGlvbiBhKHMscCl7Zm9yKDtzJiZzLm5vZGVUeXBlIT09bjspe2lmKHR5cGVvZiBzLm1hdGNoZXM9PSJmdW5jdGlvbiImJnMubWF0Y2hlcyhwKSlyZXR1cm4gcztzPXMucGFyZW50Tm9kZX19by5leHBvcnRzPWF9LDQzODpmdW5jdGlvbihvLG4saSl7dmFyIGE9aSg4MjgpO2Z1bmN0aW9uIHMobCxmLHUsZCx5KXt2YXIgTD1jLmFwcGx5KHRoaXMsYXJndW1lbnRzKTtyZXR1cm4gbC5hZGRFdmVudExpc3RlbmVyKHUsTCx5KSx7ZGVzdHJveTpmdW5jdGlvbigpe2wucmVtb3ZlRXZlbnRMaXN0ZW5lcih1LEwseSl9fX1mdW5jdGlvbiBwKGwsZix1LGQseSl7cmV0dXJuIHR5cGVvZiBsLmFkZEV2ZW50TGlzdGVuZXI9PSJmdW5jdGlvbiI/cy5hcHBseShudWxsLGFyZ3VtZW50cyk6dHlwZW9mIHU9PSJmdW5jdGlvbiI/cy5iaW5kKG51bGwsZG9jdW1lbnQpLmFwcGx5KG51bGwsYXJndW1lbnRzKToodHlwZW9mIGw9PSJzdHJpbmciJiYobD1kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGwpKSxBcnJheS5wcm90b3R5cGUubWFwLmNhbGwobCxmdW5jdGlvbihMKXtyZXR1cm4gcyhMLGYsdSxkLHkpfSkpfWZ1bmN0aW9uIGMobCxmLHUsZCl7cmV0dXJuIGZ1bmN0aW9uKHkpe3kuZGVsZWdhdGVUYXJnZXQ9YSh5LnRhcmdldCxmKSx5LmRlbGVnYXRlVGFyZ2V0JiZkLmNhbGwobCx5KX19by5leHBvcnRzPXB9LDg3OTpmdW5jdGlvbihvLG4pe24ubm9kZT1mdW5jdGlvbihpKXtyZXR1cm4gaSE9PXZvaWQgMCYmaSBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiZpLm5vZGVUeXBlPT09MX0sbi5ub2RlTGlzdD1mdW5jdGlvbihpKXt2YXIgYT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaSk7cmV0dXJuIGkhPT12b2lkIDAmJihhPT09IltvYmplY3QgTm9kZUxpc3RdInx8YT09PSJbb2JqZWN0IEhUTUxDb2xsZWN0aW9uXSIpJiYibGVuZ3RoImluIGkmJihpLmxlbmd0aD09PTB8fG4ubm9kZShpWzBdKSl9LG4uc3RyaW5nPWZ1bmN0aW9uKGkpe3JldHVybiB0eXBlb2YgaT09InN0cmluZyJ8fGkgaW5zdGFuY2VvZiBTdHJpbmd9LG4uZm49ZnVuY3Rpb24oaSl7dmFyIGE9T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGkpO3JldHVybiBhPT09IltvYmplY3QgRnVuY3Rpb25dIn19LDM3MDpmdW5jdGlvbihvLG4saSl7dmFyIGE9aSg4NzkpLHM9aSg0MzgpO2Z1bmN0aW9uIHAodSxkLHkpe2lmKCF1JiYhZCYmIXkpdGhyb3cgbmV3IEVycm9yKCJNaXNzaW5nIHJlcXVpcmVkIGFyZ3VtZW50cyIpO2lmKCFhLnN0cmluZyhkKSl0aHJvdyBuZXcgVHlwZUVycm9yKCJTZWNvbmQgYXJndW1lbnQgbXVzdCBiZSBhIFN0cmluZyIpO2lmKCFhLmZuKHkpKXRocm93IG5ldyBUeXBlRXJyb3IoIlRoaXJkIGFyZ3VtZW50IG11c3QgYmUgYSBGdW5jdGlvbiIpO2lmKGEubm9kZSh1KSlyZXR1cm4gYyh1LGQseSk7aWYoYS5ub2RlTGlzdCh1KSlyZXR1cm4gbCh1LGQseSk7aWYoYS5zdHJpbmcodSkpcmV0dXJuIGYodSxkLHkpO3Rocm93IG5ldyBUeXBlRXJyb3IoIkZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBTdHJpbmcsIEhUTUxFbGVtZW50LCBIVE1MQ29sbGVjdGlvbiwgb3IgTm9kZUxpc3QiKX1mdW5jdGlvbiBjKHUsZCx5KXtyZXR1cm4gdS5hZGRFdmVudExpc3RlbmVyKGQseSkse2Rlc3Ryb3k6ZnVuY3Rpb24oKXt1LnJlbW92ZUV2ZW50TGlzdGVuZXIoZCx5KX19fWZ1bmN0aW9uIGwodSxkLHkpe3JldHVybiBBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKHUsZnVuY3Rpb24oTCl7TC5hZGRFdmVudExpc3RlbmVyKGQseSl9KSx7ZGVzdHJveTpmdW5jdGlvbigpe0FycmF5LnByb3RvdHlwZS5mb3JFYWNoLmNhbGwodSxmdW5jdGlvbihMKXtMLnJlbW92ZUV2ZW50TGlzdGVuZXIoZCx5KX0pfX19ZnVuY3Rpb24gZih1LGQseSl7cmV0dXJuIHMoZG9jdW1lbnQuYm9keSx1LGQseSl9by5leHBvcnRzPXB9LDgxNzpmdW5jdGlvbihvKXtmdW5jdGlvbiBuKGkpe3ZhciBhO2lmKGkubm9kZU5hbWU9PT0iU0VMRUNUIilpLmZvY3VzKCksYT1pLnZhbHVlO2Vsc2UgaWYoaS5ub2RlTmFtZT09PSJJTlBVVCJ8fGkubm9kZU5hbWU9PT0iVEVYVEFSRUEiKXt2YXIgcz1pLmhhc0F0dHJpYnV0ZSgicmVhZG9ubHkiKTtzfHxpLnNldEF0dHJpYnV0ZSgicmVhZG9ubHkiLCIiKSxpLnNlbGVjdCgpLGkuc2V0U2VsZWN0aW9uUmFuZ2UoMCxpLnZhbHVlLmxlbmd0aCksc3x8aS5yZW1vdmVBdHRyaWJ1dGUoInJlYWRvbmx5IiksYT1pLnZhbHVlfWVsc2V7aS5oYXNBdHRyaWJ1dGUoImNvbnRlbnRlZGl0YWJsZSIpJiZpLmZvY3VzKCk7dmFyIHA9d2luZG93LmdldFNlbGVjdGlvbigpLGM9ZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtjLnNlbGVjdE5vZGVDb250ZW50cyhpKSxwLnJlbW92ZUFsbFJhbmdlcygpLHAuYWRkUmFuZ2UoYyksYT1wLnRvU3RyaW5nKCl9cmV0dXJuIGF9by5leHBvcnRzPW59LDI3OTpmdW5jdGlvbihvKXtmdW5jdGlvbiBuKCl7fW4ucHJvdG90eXBlPXtvbjpmdW5jdGlvbihpLGEscyl7dmFyIHA9dGhpcy5lfHwodGhpcy5lPXt9KTtyZXR1cm4ocFtpXXx8KHBbaV09W10pKS5wdXNoKHtmbjphLGN0eDpzfSksdGhpc30sb25jZTpmdW5jdGlvbihpLGEscyl7dmFyIHA9dGhpcztmdW5jdGlvbiBjKCl7cC5vZmYoaSxjKSxhLmFwcGx5KHMsYXJndW1lbnRzKX1yZXR1cm4gYy5fPWEsdGhpcy5vbihpLGMscyl9LGVtaXQ6ZnVuY3Rpb24oaSl7dmFyIGE9W10uc2xpY2UuY2FsbChhcmd1bWVudHMsMSkscz0oKHRoaXMuZXx8KHRoaXMuZT17fSkpW2ldfHxbXSkuc2xpY2UoKSxwPTAsYz1zLmxlbmd0aDtmb3IocDtwPGM7cCsrKXNbcF0uZm4uYXBwbHkoc1twXS5jdHgsYSk7cmV0dXJuIHRoaXN9LG9mZjpmdW5jdGlvbihpLGEpe3ZhciBzPXRoaXMuZXx8KHRoaXMuZT17fSkscD1zW2ldLGM9W107aWYocCYmYSlmb3IodmFyIGw9MCxmPXAubGVuZ3RoO2w8ZjtsKyspcFtsXS5mbiE9PWEmJnBbbF0uZm4uXyE9PWEmJmMucHVzaChwW2xdKTtyZXR1cm4gYy5sZW5ndGg/c1tpXT1jOmRlbGV0ZSBzW2ldLHRoaXN9fSxvLmV4cG9ydHM9bixvLmV4cG9ydHMuVGlueUVtaXR0ZXI9bn19LHQ9e307ZnVuY3Rpb24gcihvKXtpZih0W29dKXJldHVybiB0W29dLmV4cG9ydHM7dmFyIG49dFtvXT17ZXhwb3J0czp7fX07cmV0dXJuIGVbb10obixuLmV4cG9ydHMsciksbi5leHBvcnRzfXJldHVybiBmdW5jdGlvbigpe3Iubj1mdW5jdGlvbihvKXt2YXIgbj1vJiZvLl9fZXNNb2R1bGU/ZnVuY3Rpb24oKXtyZXR1cm4gby5kZWZhdWx0fTpmdW5jdGlvbigpe3JldHVybiBvfTtyZXR1cm4gci5kKG4se2E6bn0pLG59fSgpLGZ1bmN0aW9uKCl7ci5kPWZ1bmN0aW9uKG8sbil7Zm9yKHZhciBpIGluIG4pci5vKG4saSkmJiFyLm8obyxpKSYmT2JqZWN0LmRlZmluZVByb3BlcnR5KG8saSx7ZW51bWVyYWJsZTohMCxnZXQ6bltpXX0pfX0oKSxmdW5jdGlvbigpe3Iubz1mdW5jdGlvbihvLG4pe3JldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobyxuKX19KCkscig2ODYpfSgpLmRlZmF1bHR9KX0pO3ZhciBsTD1NdChsbygpKTt2YXIgd3I9ZnVuY3Rpb24oZSx0KXtyZXR1cm4gd3I9T2JqZWN0LnNldFByb3RvdHlwZU9mfHx7X19wcm90b19fOltdfWluc3RhbmNlb2YgQXJyYXkmJmZ1bmN0aW9uKHIsbyl7ci5fX3Byb3RvX189b318fGZ1bmN0aW9uKHIsbyl7Zm9yKHZhciBuIGluIG8pT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG8sbikmJihyW25dPW9bbl0pfSx3cihlLHQpfTtmdW5jdGlvbiBvZShlLHQpe2lmKHR5cGVvZiB0IT0iZnVuY3Rpb24iJiZ0IT09bnVsbCl0aHJvdyBuZXcgVHlwZUVycm9yKCJDbGFzcyBleHRlbmRzIHZhbHVlICIrU3RyaW5nKHQpKyIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbCIpO3dyKGUsdCk7ZnVuY3Rpb24gcigpe3RoaXMuY29uc3RydWN0b3I9ZX1lLnByb3RvdHlwZT10PT09bnVsbD9PYmplY3QuY3JlYXRlKHQpOihyLnByb3RvdHlwZT10LnByb3RvdHlwZSxuZXcgcil9ZnVuY3Rpb24gbW8oZSx0LHIsbyl7ZnVuY3Rpb24gbihpKXtyZXR1cm4gaSBpbnN0YW5jZW9mIHI/aTpuZXcgcihmdW5jdGlvbihhKXthKGkpfSl9cmV0dXJuIG5ldyhyfHwocj1Qcm9taXNlKSkoZnVuY3Rpb24oaSxhKXtmdW5jdGlvbiBzKGwpe3RyeXtjKG8ubmV4dChsKSl9Y2F0Y2goZil7YShmKX19ZnVuY3Rpb24gcChsKXt0cnl7YyhvLnRocm93KGwpKX1jYXRjaChmKXthKGYpfX1mdW5jdGlvbiBjKGwpe2wuZG9uZT9pKGwudmFsdWUpOm4obC52YWx1ZSkudGhlbihzLHApfWMoKG89by5hcHBseShlLHR8fFtdKSkubmV4dCgpKX0pfWZ1bmN0aW9uIE50KGUsdCl7dmFyIHI9e2xhYmVsOjAsc2VudDpmdW5jdGlvbigpe2lmKGlbMF0mMSl0aHJvdyBpWzFdO3JldHVybiBpWzFdfSx0cnlzOltdLG9wczpbXX0sbyxuLGksYT1PYmplY3QuY3JlYXRlKCh0eXBlb2YgSXRlcmF0b3I9PSJmdW5jdGlvbiI/SXRlcmF0b3I6T2JqZWN0KS5wcm90b3R5cGUpO3JldHVybiBhLm5leHQ9cygwKSxhLnRocm93PXMoMSksYS5yZXR1cm49cygyKSx0eXBlb2YgU3ltYm9sPT0iZnVuY3Rpb24iJiYoYVtTeW1ib2wuaXRlcmF0b3JdPWZ1bmN0aW9uKCl7cmV0dXJuIHRoaXN9KSxhO2Z1bmN0aW9uIHMoYyl7cmV0dXJuIGZ1bmN0aW9uKGwpe3JldHVybiBwKFtjLGxdKX19ZnVuY3Rpb24gcChjKXtpZihvKXRocm93IG5ldyBUeXBlRXJyb3IoIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy4iKTtmb3IoO2EmJihhPTAsY1swXSYmKHI9MCkpLHI7KXRyeXtpZihvPTEsbiYmKGk9Y1swXSYyP24ucmV0dXJuOmNbMF0/bi50aHJvd3x8KChpPW4ucmV0dXJuKSYmaS5jYWxsKG4pLDApOm4ubmV4dCkmJiEoaT1pLmNhbGwobixjWzFdKSkuZG9uZSlyZXR1cm4gaTtzd2l0Y2gobj0wLGkmJihjPVtjWzBdJjIsaS52YWx1ZV0pLGNbMF0pe2Nhc2UgMDpjYXNlIDE6aT1jO2JyZWFrO2Nhc2UgNDpyZXR1cm4gci5sYWJlbCsrLHt2YWx1ZTpjWzFdLGRvbmU6ITF9O2Nhc2UgNTpyLmxhYmVsKyssbj1jWzFdLGM9WzBdO2NvbnRpbnVlO2Nhc2UgNzpjPXIub3BzLnBvcCgpLHIudHJ5cy5wb3AoKTtjb250aW51ZTtkZWZhdWx0OmlmKGk9ci50cnlzLCEoaT1pLmxlbmd0aD4wJiZpW2kubGVuZ3RoLTFdKSYmKGNbMF09PT02fHxjWzBdPT09Mikpe3I9MDtjb250aW51ZX1pZihjWzBdPT09MyYmKCFpfHxjWzFdPmlbMF0mJmNbMV08aVszXSkpe3IubGFiZWw9Y1sxXTticmVha31pZihjWzBdPT09NiYmci5sYWJlbDxpWzFdKXtyLmxhYmVsPWlbMV0saT1jO2JyZWFrfWlmKGkmJnIubGFiZWw8aVsyXSl7ci5sYWJlbD1pWzJdLHIub3BzLnB1c2goYyk7YnJlYWt9aVsyXSYmci5vcHMucG9wKCksci50cnlzLnBvcCgpO2NvbnRpbnVlfWM9dC5jYWxsKGUscil9Y2F0Y2gobCl7Yz1bNixsXSxuPTB9ZmluYWxseXtvPWk9MH1pZihjWzBdJjUpdGhyb3cgY1sxXTtyZXR1cm57dmFsdWU6Y1swXT9jWzFdOnZvaWQgMCxkb25lOiEwfX19ZnVuY3Rpb24gaGUoZSl7dmFyIHQ9dHlwZW9mIFN5bWJvbD09ImZ1bmN0aW9uIiYmU3ltYm9sLml0ZXJhdG9yLHI9dCYmZVt0XSxvPTA7aWYocilyZXR1cm4gci5jYWxsKGUpO2lmKGUmJnR5cGVvZiBlLmxlbmd0aD09Im51bWJlciIpcmV0dXJue25leHQ6ZnVuY3Rpb24oKXtyZXR1cm4gZSYmbz49ZS5sZW5ndGgmJihlPXZvaWQgMCkse3ZhbHVlOmUmJmVbbysrXSxkb25lOiFlfX19O3Rocm93IG5ldyBUeXBlRXJyb3IodD8iT2JqZWN0IGlzIG5vdCBpdGVyYWJsZS4iOiJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuIil9ZnVuY3Rpb24gTihlLHQpe3ZhciByPXR5cGVvZiBTeW1ib2w9PSJmdW5jdGlvbiImJmVbU3ltYm9sLml0ZXJhdG9yXTtpZighcilyZXR1cm4gZTt2YXIgbz1yLmNhbGwoZSksbixpPVtdLGE7dHJ5e2Zvcig7KHQ9PT12b2lkIDB8fHQtLSA+MCkmJiEobj1vLm5leHQoKSkuZG9uZTspaS5wdXNoKG4udmFsdWUpfWNhdGNoKHMpe2E9e2Vycm9yOnN9fWZpbmFsbHl7dHJ5e24mJiFuLmRvbmUmJihyPW8ucmV0dXJuKSYmci5jYWxsKG8pfWZpbmFsbHl7aWYoYSl0aHJvdyBhLmVycm9yfX1yZXR1cm4gaX1mdW5jdGlvbiBxKGUsdCxyKXtpZihyfHxhcmd1bWVudHMubGVuZ3RoPT09Milmb3IodmFyIG89MCxuPXQubGVuZ3RoLGk7bzxuO28rKykoaXx8IShvIGluIHQpKSYmKGl8fChpPUFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKHQsMCxvKSksaVtvXT10W29dKTtyZXR1cm4gZS5jb25jYXQoaXx8QXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwodCkpfWZ1bmN0aW9uIG50KGUpe3JldHVybiB0aGlzIGluc3RhbmNlb2YgbnQ/KHRoaXMudj1lLHRoaXMpOm5ldyBudChlKX1mdW5jdGlvbiBmbyhlLHQscil7aWYoIVN5bWJvbC5hc3luY0l0ZXJhdG9yKXRocm93IG5ldyBUeXBlRXJyb3IoIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLiIpO3ZhciBvPXIuYXBwbHkoZSx0fHxbXSksbixpPVtdO3JldHVybiBuPU9iamVjdC5jcmVhdGUoKHR5cGVvZiBBc3luY0l0ZXJhdG9yPT0iZnVuY3Rpb24iP0FzeW5jSXRlcmF0b3I6T2JqZWN0KS5wcm90b3R5cGUpLHMoIm5leHQiKSxzKCJ0aHJvdyIpLHMoInJldHVybiIsYSksbltTeW1ib2wuYXN5bmNJdGVyYXRvcl09ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sbjtmdW5jdGlvbiBhKGQpe3JldHVybiBmdW5jdGlvbih5KXtyZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHkpLnRoZW4oZCxmKX19ZnVuY3Rpb24gcyhkLHkpe29bZF0mJihuW2RdPWZ1bmN0aW9uKEwpe3JldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihYLHRlKXtpLnB1c2goW2QsTCxYLHRlXSk+MXx8cChkLEwpfSl9LHkmJihuW2RdPXkobltkXSkpKX1mdW5jdGlvbiBwKGQseSl7dHJ5e2Mob1tkXSh5KSl9Y2F0Y2goTCl7dShpWzBdWzNdLEwpfX1mdW5jdGlvbiBjKGQpe2QudmFsdWUgaW5zdGFuY2VvZiBudD9Qcm9taXNlLnJlc29sdmUoZC52YWx1ZS52KS50aGVuKGwsZik6dShpWzBdWzJdLGQpfWZ1bmN0aW9uIGwoZCl7cCgibmV4dCIsZCl9ZnVuY3Rpb24gZihkKXtwKCJ0aHJvdyIsZCl9ZnVuY3Rpb24gdShkLHkpe2QoeSksaS5zaGlmdCgpLGkubGVuZ3RoJiZwKGlbMF1bMF0saVswXVsxXSl9fWZ1bmN0aW9uIHVvKGUpe2lmKCFTeW1ib2wuYXN5bmNJdGVyYXRvcil0aHJvdyBuZXcgVHlwZUVycm9yKCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC4iKTt2YXIgdD1lW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSxyO3JldHVybiB0P3QuY2FsbChlKTooZT10eXBlb2YgaGU9PSJmdW5jdGlvbiI/aGUoZSk6ZVtTeW1ib2wuaXRlcmF0b3JdKCkscj17fSxvKCJuZXh0IiksbygidGhyb3ciKSxvKCJyZXR1cm4iKSxyW1N5bWJvbC5hc3luY0l0ZXJhdG9yXT1mdW5jdGlvbigpe3JldHVybiB0aGlzfSxyKTtmdW5jdGlvbiBvKGkpe3JbaV09ZVtpXSYmZnVuY3Rpb24oYSl7cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uKHMscCl7YT1lW2ldKGEpLG4ocyxwLGEuZG9uZSxhLnZhbHVlKX0pfX1mdW5jdGlvbiBuKGksYSxzLHApe1Byb21pc2UucmVzb2x2ZShwKS50aGVuKGZ1bmN0aW9uKGMpe2koe3ZhbHVlOmMsZG9uZTpzfSl9LGEpfX1mdW5jdGlvbiBIKGUpe3JldHVybiB0eXBlb2YgZT09ImZ1bmN0aW9uIn1mdW5jdGlvbiB1dChlKXt2YXIgdD1mdW5jdGlvbihvKXtFcnJvci5jYWxsKG8pLG8uc3RhY2s9bmV3IEVycm9yKCkuc3RhY2t9LHI9ZSh0KTtyZXR1cm4gci5wcm90b3R5cGU9T2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpLHIucHJvdG90eXBlLmNvbnN0cnVjdG9yPXIscn12YXIgenQ9dXQoZnVuY3Rpb24oZSl7cmV0dXJuIGZ1bmN0aW9uKHIpe2UodGhpcyksdGhpcy5tZXNzYWdlPXI/ci5sZW5ndGgrYCBlcnJvcnMgb2NjdXJyZWQgZHVyaW5nIHVuc3Vic2NyaXB0aW9uOgpgK3IubWFwKGZ1bmN0aW9uKG8sbil7cmV0dXJuIG4rMSsiKSAiK28udG9TdHJpbmcoKX0pLmpvaW4oYAogIGApOiIiLHRoaXMubmFtZT0iVW5zdWJzY3JpcHRpb25FcnJvciIsdGhpcy5lcnJvcnM9cn19KTtmdW5jdGlvbiBRZShlLHQpe2lmKGUpe3ZhciByPWUuaW5kZXhPZih0KTswPD1yJiZlLnNwbGljZShyLDEpfX12YXIgVWU9ZnVuY3Rpb24oKXtmdW5jdGlvbiBlKHQpe3RoaXMuaW5pdGlhbFRlYXJkb3duPXQsdGhpcy5jbG9zZWQ9ITEsdGhpcy5fcGFyZW50YWdlPW51bGwsdGhpcy5fZmluYWxpemVycz1udWxsfXJldHVybiBlLnByb3RvdHlwZS51bnN1YnNjcmliZT1mdW5jdGlvbigpe3ZhciB0LHIsbyxuLGk7aWYoIXRoaXMuY2xvc2VkKXt0aGlzLmNsb3NlZD0hMDt2YXIgYT10aGlzLl9wYXJlbnRhZ2U7aWYoYSlpZih0aGlzLl9wYXJlbnRhZ2U9bnVsbCxBcnJheS5pc0FycmF5KGEpKXRyeXtmb3IodmFyIHM9aGUoYSkscD1zLm5leHQoKTshcC5kb25lO3A9cy5uZXh0KCkpe3ZhciBjPXAudmFsdWU7Yy5yZW1vdmUodGhpcyl9fWNhdGNoKEwpe3Q9e2Vycm9yOkx9fWZpbmFsbHl7dHJ5e3AmJiFwLmRvbmUmJihyPXMucmV0dXJuKSYmci5jYWxsKHMpfWZpbmFsbHl7aWYodCl0aHJvdyB0LmVycm9yfX1lbHNlIGEucmVtb3ZlKHRoaXMpO3ZhciBsPXRoaXMuaW5pdGlhbFRlYXJkb3duO2lmKEgobCkpdHJ5e2woKX1jYXRjaChMKXtpPUwgaW5zdGFuY2VvZiB6dD9MLmVycm9yczpbTF19dmFyIGY9dGhpcy5fZmluYWxpemVycztpZihmKXt0aGlzLl9maW5hbGl6ZXJzPW51bGw7dHJ5e2Zvcih2YXIgdT1oZShmKSxkPXUubmV4dCgpOyFkLmRvbmU7ZD11Lm5leHQoKSl7dmFyIHk9ZC52YWx1ZTt0cnl7aG8oeSl9Y2F0Y2goTCl7aT1pIT1udWxsP2k6W10sTCBpbnN0YW5jZW9mIHp0P2k9cShxKFtdLE4oaSkpLE4oTC5lcnJvcnMpKTppLnB1c2goTCl9fX1jYXRjaChMKXtvPXtlcnJvcjpMfX1maW5hbGx5e3RyeXtkJiYhZC5kb25lJiYobj11LnJldHVybikmJm4uY2FsbCh1KX1maW5hbGx5e2lmKG8pdGhyb3cgby5lcnJvcn19fWlmKGkpdGhyb3cgbmV3IHp0KGkpfX0sZS5wcm90b3R5cGUuYWRkPWZ1bmN0aW9uKHQpe3ZhciByO2lmKHQmJnQhPT10aGlzKWlmKHRoaXMuY2xvc2VkKWhvKHQpO2Vsc2V7aWYodCBpbnN0YW5jZW9mIGUpe2lmKHQuY2xvc2VkfHx0Ll9oYXNQYXJlbnQodGhpcykpcmV0dXJuO3QuX2FkZFBhcmVudCh0aGlzKX0odGhpcy5fZmluYWxpemVycz0ocj10aGlzLl9maW5hbGl6ZXJzKSE9PW51bGwmJnIhPT12b2lkIDA/cjpbXSkucHVzaCh0KX19LGUucHJvdG90eXBlLl9oYXNQYXJlbnQ9ZnVuY3Rpb24odCl7dmFyIHI9dGhpcy5fcGFyZW50YWdlO3JldHVybiByPT09dHx8QXJyYXkuaXNBcnJheShyKSYmci5pbmNsdWRlcyh0KX0sZS5wcm90b3R5cGUuX2FkZFBhcmVudD1mdW5jdGlvbih0KXt2YXIgcj10aGlzLl9wYXJlbnRhZ2U7dGhpcy5fcGFyZW50YWdlPUFycmF5LmlzQXJyYXkocik/KHIucHVzaCh0KSxyKTpyP1tyLHRdOnR9LGUucHJvdG90eXBlLl9yZW1vdmVQYXJlbnQ9ZnVuY3Rpb24odCl7dmFyIHI9dGhpcy5fcGFyZW50YWdlO3I9PT10P3RoaXMuX3BhcmVudGFnZT1udWxsOkFycmF5LmlzQXJyYXkocikmJlFlKHIsdCl9LGUucHJvdG90eXBlLnJlbW92ZT1mdW5jdGlvbih0KXt2YXIgcj10aGlzLl9maW5hbGl6ZXJzO3ImJlFlKHIsdCksdCBpbnN0YW5jZW9mIGUmJnQuX3JlbW92ZVBhcmVudCh0aGlzKX0sZS5FTVBUWT1mdW5jdGlvbigpe3ZhciB0PW5ldyBlO3JldHVybiB0LmNsb3NlZD0hMCx0fSgpLGV9KCk7dmFyIFRyPVVlLkVNUFRZO2Z1bmN0aW9uIHF0KGUpe3JldHVybiBlIGluc3RhbmNlb2YgVWV8fGUmJiJjbG9zZWQiaW4gZSYmSChlLnJlbW92ZSkmJkgoZS5hZGQpJiZIKGUudW5zdWJzY3JpYmUpfWZ1bmN0aW9uIGhvKGUpe0goZSk/ZSgpOmUudW5zdWJzY3JpYmUoKX12YXIgUGU9e29uVW5oYW5kbGVkRXJyb3I6bnVsbCxvblN0b3BwZWROb3RpZmljYXRpb246bnVsbCxQcm9taXNlOnZvaWQgMCx1c2VEZXByZWNhdGVkU3luY2hyb25vdXNFcnJvckhhbmRsaW5nOiExLHVzZURlcHJlY2F0ZWROZXh0Q29udGV4dDohMX07dmFyIGR0PXtzZXRUaW1lb3V0OmZ1bmN0aW9uKGUsdCl7Zm9yKHZhciByPVtdLG89MjtvPGFyZ3VtZW50cy5sZW5ndGg7bysrKXJbby0yXT1hcmd1bWVudHNbb107dmFyIG49ZHQuZGVsZWdhdGU7cmV0dXJuIG4hPW51bGwmJm4uc2V0VGltZW91dD9uLnNldFRpbWVvdXQuYXBwbHkobixxKFtlLHRdLE4ocikpKTpzZXRUaW1lb3V0LmFwcGx5KHZvaWQgMCxxKFtlLHRdLE4ocikpKX0sY2xlYXJUaW1lb3V0OmZ1bmN0aW9uKGUpe3ZhciB0PWR0LmRlbGVnYXRlO3JldHVybigodD09bnVsbD92b2lkIDA6dC5jbGVhclRpbWVvdXQpfHxjbGVhclRpbWVvdXQpKGUpfSxkZWxlZ2F0ZTp2b2lkIDB9O2Z1bmN0aW9uIFF0KGUpe2R0LnNldFRpbWVvdXQoZnVuY3Rpb24oKXt2YXIgdD1QZS5vblVuaGFuZGxlZEVycm9yO2lmKHQpdChlKTtlbHNlIHRocm93IGV9KX1mdW5jdGlvbiBiZSgpe312YXIgYm89ZnVuY3Rpb24oKXtyZXR1cm4gU3IoIkMiLHZvaWQgMCx2b2lkIDApfSgpO2Z1bmN0aW9uIHZvKGUpe3JldHVybiBTcigiRSIsdm9pZCAwLGUpfWZ1bmN0aW9uIGdvKGUpe3JldHVybiBTcigiTiIsZSx2b2lkIDApfWZ1bmN0aW9uIFNyKGUsdCxyKXtyZXR1cm57a2luZDplLHZhbHVlOnQsZXJyb3I6cn19dmFyIGl0PW51bGw7ZnVuY3Rpb24gaHQoZSl7aWYoUGUudXNlRGVwcmVjYXRlZFN5bmNocm9ub3VzRXJyb3JIYW5kbGluZyl7dmFyIHQ9IWl0O2lmKHQmJihpdD17ZXJyb3JUaHJvd246ITEsZXJyb3I6bnVsbH0pLGUoKSx0KXt2YXIgcj1pdCxvPXIuZXJyb3JUaHJvd24sbj1yLmVycm9yO2lmKGl0PW51bGwsbyl0aHJvdyBufX1lbHNlIGUoKX1mdW5jdGlvbiB5byhlKXtQZS51c2VEZXByZWNhdGVkU3luY2hyb25vdXNFcnJvckhhbmRsaW5nJiZpdCYmKGl0LmVycm9yVGhyb3duPSEwLGl0LmVycm9yPWUpfXZhciBfdD1mdW5jdGlvbihlKXtvZSh0LGUpO2Z1bmN0aW9uIHQocil7dmFyIG89ZS5jYWxsKHRoaXMpfHx0aGlzO3JldHVybiBvLmlzU3RvcHBlZD0hMSxyPyhvLmRlc3RpbmF0aW9uPXIscXQocikmJnIuYWRkKG8pKTpvLmRlc3RpbmF0aW9uPVlpLG99cmV0dXJuIHQuY3JlYXRlPWZ1bmN0aW9uKHIsbyxuKXtyZXR1cm4gbmV3IGF0KHIsbyxuKX0sdC5wcm90b3R5cGUubmV4dD1mdW5jdGlvbihyKXt0aGlzLmlzU3RvcHBlZD9McihnbyhyKSx0aGlzKTp0aGlzLl9uZXh0KHIpfSx0LnByb3RvdHlwZS5lcnJvcj1mdW5jdGlvbihyKXt0aGlzLmlzU3RvcHBlZD9Mcih2byhyKSx0aGlzKToodGhpcy5pc1N0b3BwZWQ9ITAsdGhpcy5fZXJyb3IocikpfSx0LnByb3RvdHlwZS5jb21wbGV0ZT1mdW5jdGlvbigpe3RoaXMuaXNTdG9wcGVkP0xyKGJvLHRoaXMpOih0aGlzLmlzU3RvcHBlZD0hMCx0aGlzLl9jb21wbGV0ZSgpKX0sdC5wcm90b3R5cGUudW5zdWJzY3JpYmU9ZnVuY3Rpb24oKXt0aGlzLmNsb3NlZHx8KHRoaXMuaXNTdG9wcGVkPSEwLGUucHJvdG90eXBlLnVuc3Vic2NyaWJlLmNhbGwodGhpcyksdGhpcy5kZXN0aW5hdGlvbj1udWxsKX0sdC5wcm90b3R5cGUuX25leHQ9ZnVuY3Rpb24ocil7dGhpcy5kZXN0aW5hdGlvbi5uZXh0KHIpfSx0LnByb3RvdHlwZS5fZXJyb3I9ZnVuY3Rpb24ocil7dHJ5e3RoaXMuZGVzdGluYXRpb24uZXJyb3Iocil9ZmluYWxseXt0aGlzLnVuc3Vic2NyaWJlKCl9fSx0LnByb3RvdHlwZS5fY29tcGxldGU9ZnVuY3Rpb24oKXt0cnl7dGhpcy5kZXN0aW5hdGlvbi5jb21wbGV0ZSgpfWZpbmFsbHl7dGhpcy51bnN1YnNjcmliZSgpfX0sdH0oVWUpO3ZhciBxaT1GdW5jdGlvbi5wcm90b3R5cGUuYmluZDtmdW5jdGlvbiBPcihlLHQpe3JldHVybiBxaS5jYWxsKGUsdCl9dmFyIFFpPWZ1bmN0aW9uKCl7ZnVuY3Rpb24gZSh0KXt0aGlzLnBhcnRpYWxPYnNlcnZlcj10fXJldHVybiBlLnByb3RvdHlwZS5uZXh0PWZ1bmN0aW9uKHQpe3ZhciByPXRoaXMucGFydGlhbE9ic2VydmVyO2lmKHIubmV4dCl0cnl7ci5uZXh0KHQpfWNhdGNoKG8pe0t0KG8pfX0sZS5wcm90b3R5cGUuZXJyb3I9ZnVuY3Rpb24odCl7dmFyIHI9dGhpcy5wYXJ0aWFsT2JzZXJ2ZXI7aWYoci5lcnJvcil0cnl7ci5lcnJvcih0KX1jYXRjaChvKXtLdChvKX1lbHNlIEt0KHQpfSxlLnByb3RvdHlwZS5jb21wbGV0ZT1mdW5jdGlvbigpe3ZhciB0PXRoaXMucGFydGlhbE9ic2VydmVyO2lmKHQuY29tcGxldGUpdHJ5e3QuY29tcGxldGUoKX1jYXRjaChyKXtLdChyKX19LGV9KCksYXQ9ZnVuY3Rpb24oZSl7b2UodCxlKTtmdW5jdGlvbiB0KHIsbyxuKXt2YXIgaT1lLmNhbGwodGhpcyl8fHRoaXMsYTtpZihIKHIpfHwhcilhPXtuZXh0OnIhPW51bGw/cjp2b2lkIDAsZXJyb3I6byE9bnVsbD9vOnZvaWQgMCxjb21wbGV0ZTpuIT1udWxsP246dm9pZCAwfTtlbHNle3ZhciBzO2kmJlBlLnVzZURlcHJlY2F0ZWROZXh0Q29udGV4dD8ocz1PYmplY3QuY3JlYXRlKHIpLHMudW5zdWJzY3JpYmU9ZnVuY3Rpb24oKXtyZXR1cm4gaS51bnN1YnNjcmliZSgpfSxhPXtuZXh0OnIubmV4dCYmT3Ioci5uZXh0LHMpLGVycm9yOnIuZXJyb3ImJk9yKHIuZXJyb3IscyksY29tcGxldGU6ci5jb21wbGV0ZSYmT3Ioci5jb21wbGV0ZSxzKX0pOmE9cn1yZXR1cm4gaS5kZXN0aW5hdGlvbj1uZXcgUWkoYSksaX1yZXR1cm4gdH0oX3QpO2Z1bmN0aW9uIEt0KGUpe1BlLnVzZURlcHJlY2F0ZWRTeW5jaHJvbm91c0Vycm9ySGFuZGxpbmc/eW8oZSk6UXQoZSl9ZnVuY3Rpb24gS2koZSl7dGhyb3cgZX1mdW5jdGlvbiBMcihlLHQpe3ZhciByPVBlLm9uU3RvcHBlZE5vdGlmaWNhdGlvbjtyJiZkdC5zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7cmV0dXJuIHIoZSx0KX0pfXZhciBZaT17Y2xvc2VkOiEwLG5leHQ6YmUsZXJyb3I6S2ksY29tcGxldGU6YmV9O3ZhciBidD1mdW5jdGlvbigpe3JldHVybiB0eXBlb2YgU3ltYm9sPT0iZnVuY3Rpb24iJiZTeW1ib2wub2JzZXJ2YWJsZXx8IkBAb2JzZXJ2YWJsZSJ9KCk7ZnVuY3Rpb24gbGUoZSl7cmV0dXJuIGV9ZnVuY3Rpb24geG8oKXtmb3IodmFyIGU9W10sdD0wO3Q8YXJndW1lbnRzLmxlbmd0aDt0KyspZVt0XT1hcmd1bWVudHNbdF07cmV0dXJuIE1yKGUpfWZ1bmN0aW9uIE1yKGUpe3JldHVybiBlLmxlbmd0aD09PTA/bGU6ZS5sZW5ndGg9PT0xP2VbMF06ZnVuY3Rpb24ocil7cmV0dXJuIGUucmVkdWNlKGZ1bmN0aW9uKG8sbil7cmV0dXJuIG4obyl9LHIpfX12YXIgaj1mdW5jdGlvbigpe2Z1bmN0aW9uIGUodCl7dCYmKHRoaXMuX3N1YnNjcmliZT10KX1yZXR1cm4gZS5wcm90b3R5cGUubGlmdD1mdW5jdGlvbih0KXt2YXIgcj1uZXcgZTtyZXR1cm4gci5zb3VyY2U9dGhpcyxyLm9wZXJhdG9yPXQscn0sZS5wcm90b3R5cGUuc3Vic2NyaWJlPWZ1bmN0aW9uKHQscixvKXt2YXIgbj10aGlzLGk9R2kodCk/dDpuZXcgYXQodCxyLG8pO3JldHVybiBodChmdW5jdGlvbigpe3ZhciBhPW4scz1hLm9wZXJhdG9yLHA9YS5zb3VyY2U7aS5hZGQocz9zLmNhbGwoaSxwKTpwP24uX3N1YnNjcmliZShpKTpuLl90cnlTdWJzY3JpYmUoaSkpfSksaX0sZS5wcm90b3R5cGUuX3RyeVN1YnNjcmliZT1mdW5jdGlvbih0KXt0cnl7cmV0dXJuIHRoaXMuX3N1YnNjcmliZSh0KX1jYXRjaChyKXt0LmVycm9yKHIpfX0sZS5wcm90b3R5cGUuZm9yRWFjaD1mdW5jdGlvbih0LHIpe3ZhciBvPXRoaXM7cmV0dXJuIHI9RW8ociksbmV3IHIoZnVuY3Rpb24obixpKXt2YXIgYT1uZXcgYXQoe25leHQ6ZnVuY3Rpb24ocyl7dHJ5e3Qocyl9Y2F0Y2gocCl7aShwKSxhLnVuc3Vic2NyaWJlKCl9fSxlcnJvcjppLGNvbXBsZXRlOm59KTtvLnN1YnNjcmliZShhKX0pfSxlLnByb3RvdHlwZS5fc3Vic2NyaWJlPWZ1bmN0aW9uKHQpe3ZhciByO3JldHVybihyPXRoaXMuc291cmNlKT09PW51bGx8fHI9PT12b2lkIDA/dm9pZCAwOnIuc3Vic2NyaWJlKHQpfSxlLnByb3RvdHlwZVtidF09ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sZS5wcm90b3R5cGUucGlwZT1mdW5jdGlvbigpe2Zvcih2YXIgdD1bXSxyPTA7cjxhcmd1bWVudHMubGVuZ3RoO3IrKyl0W3JdPWFyZ3VtZW50c1tyXTtyZXR1cm4gTXIodCkodGhpcyl9LGUucHJvdG90eXBlLnRvUHJvbWlzZT1mdW5jdGlvbih0KXt2YXIgcj10aGlzO3JldHVybiB0PUVvKHQpLG5ldyB0KGZ1bmN0aW9uKG8sbil7dmFyIGk7ci5zdWJzY3JpYmUoZnVuY3Rpb24oYSl7cmV0dXJuIGk9YX0sZnVuY3Rpb24oYSl7cmV0dXJuIG4oYSl9LGZ1bmN0aW9uKCl7cmV0dXJuIG8oaSl9KX0pfSxlLmNyZWF0ZT1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IGUodCl9LGV9KCk7ZnVuY3Rpb24gRW8oZSl7dmFyIHQ7cmV0dXJuKHQ9ZSE9bnVsbD9lOlBlLlByb21pc2UpIT09bnVsbCYmdCE9PXZvaWQgMD90OlByb21pc2V9ZnVuY3Rpb24gQmkoZSl7cmV0dXJuIGUmJkgoZS5uZXh0KSYmSChlLmVycm9yKSYmSChlLmNvbXBsZXRlKX1mdW5jdGlvbiBHaShlKXtyZXR1cm4gZSYmZSBpbnN0YW5jZW9mIF90fHxCaShlKSYmcXQoZSl9ZnVuY3Rpb24gSmkoZSl7cmV0dXJuIEgoZT09bnVsbD92b2lkIDA6ZS5saWZ0KX1mdW5jdGlvbiBFKGUpe3JldHVybiBmdW5jdGlvbih0KXtpZihKaSh0KSlyZXR1cm4gdC5saWZ0KGZ1bmN0aW9uKHIpe3RyeXtyZXR1cm4gZShyLHRoaXMpfWNhdGNoKG8pe3RoaXMuZXJyb3Iobyl9fSk7dGhyb3cgbmV3IFR5cGVFcnJvcigiVW5hYmxlIHRvIGxpZnQgdW5rbm93biBPYnNlcnZhYmxlIHR5cGUiKX19ZnVuY3Rpb24gVChlLHQscixvLG4pe3JldHVybiBuZXcgWGkoZSx0LHIsbyxuKX12YXIgWGk9ZnVuY3Rpb24oZSl7b2UodCxlKTtmdW5jdGlvbiB0KHIsbyxuLGksYSxzKXt2YXIgcD1lLmNhbGwodGhpcyxyKXx8dGhpcztyZXR1cm4gcC5vbkZpbmFsaXplPWEscC5zaG91bGRVbnN1YnNjcmliZT1zLHAuX25leHQ9bz9mdW5jdGlvbihjKXt0cnl7byhjKX1jYXRjaChsKXtyLmVycm9yKGwpfX06ZS5wcm90b3R5cGUuX25leHQscC5fZXJyb3I9aT9mdW5jdGlvbihjKXt0cnl7aShjKX1jYXRjaChsKXtyLmVycm9yKGwpfWZpbmFsbHl7dGhpcy51bnN1YnNjcmliZSgpfX06ZS5wcm90b3R5cGUuX2Vycm9yLHAuX2NvbXBsZXRlPW4/ZnVuY3Rpb24oKXt0cnl7bigpfWNhdGNoKGMpe3IuZXJyb3IoYyl9ZmluYWxseXt0aGlzLnVuc3Vic2NyaWJlKCl9fTplLnByb3RvdHlwZS5fY29tcGxldGUscH1yZXR1cm4gdC5wcm90b3R5cGUudW5zdWJzY3JpYmU9ZnVuY3Rpb24oKXt2YXIgcjtpZighdGhpcy5zaG91bGRVbnN1YnNjcmliZXx8dGhpcy5zaG91bGRVbnN1YnNjcmliZSgpKXt2YXIgbz10aGlzLmNsb3NlZDtlLnByb3RvdHlwZS51bnN1YnNjcmliZS5jYWxsKHRoaXMpLCFvJiYoKHI9dGhpcy5vbkZpbmFsaXplKT09PW51bGx8fHI9PT12b2lkIDB8fHIuY2FsbCh0aGlzKSl9fSx0fShfdCk7dmFyIHZ0PXtzY2hlZHVsZTpmdW5jdGlvbihlKXt2YXIgdD1yZXF1ZXN0QW5pbWF0aW9uRnJhbWUscj1jYW5jZWxBbmltYXRpb25GcmFtZSxvPXZ0LmRlbGVnYXRlO28mJih0PW8ucmVxdWVzdEFuaW1hdGlvbkZyYW1lLHI9by5jYW5jZWxBbmltYXRpb25GcmFtZSk7dmFyIG49dChmdW5jdGlvbihpKXtyPXZvaWQgMCxlKGkpfSk7cmV0dXJuIG5ldyBVZShmdW5jdGlvbigpe3JldHVybiByPT1udWxsP3ZvaWQgMDpyKG4pfSl9LHJlcXVlc3RBbmltYXRpb25GcmFtZTpmdW5jdGlvbigpe2Zvcih2YXIgZT1bXSx0PTA7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyllW3RdPWFyZ3VtZW50c1t0XTt2YXIgcj12dC5kZWxlZ2F0ZTtyZXR1cm4oKHI9PW51bGw/dm9pZCAwOnIucmVxdWVzdEFuaW1hdGlvbkZyYW1lKXx8cmVxdWVzdEFuaW1hdGlvbkZyYW1lKS5hcHBseSh2b2lkIDAscShbXSxOKGUpKSl9LGNhbmNlbEFuaW1hdGlvbkZyYW1lOmZ1bmN0aW9uKCl7Zm9yKHZhciBlPVtdLHQ9MDt0PGFyZ3VtZW50cy5sZW5ndGg7dCsrKWVbdF09YXJndW1lbnRzW3RdO3ZhciByPXZ0LmRlbGVnYXRlO3JldHVybigocj09bnVsbD92b2lkIDA6ci5jYW5jZWxBbmltYXRpb25GcmFtZSl8fGNhbmNlbEFuaW1hdGlvbkZyYW1lKS5hcHBseSh2b2lkIDAscShbXSxOKGUpKSl9LGRlbGVnYXRlOnZvaWQgMH07dmFyIHdvPXV0KGZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbigpe2UodGhpcyksdGhpcy5uYW1lPSJPYmplY3RVbnN1YnNjcmliZWRFcnJvciIsdGhpcy5tZXNzYWdlPSJvYmplY3QgdW5zdWJzY3JpYmVkIn19KTt2YXIgZz1mdW5jdGlvbihlKXtvZSh0LGUpO2Z1bmN0aW9uIHQoKXt2YXIgcj1lLmNhbGwodGhpcyl8fHRoaXM7cmV0dXJuIHIuY2xvc2VkPSExLHIuY3VycmVudE9ic2VydmVycz1udWxsLHIub2JzZXJ2ZXJzPVtdLHIuaXNTdG9wcGVkPSExLHIuaGFzRXJyb3I9ITEsci50aHJvd25FcnJvcj1udWxsLHJ9cmV0dXJuIHQucHJvdG90eXBlLmxpZnQ9ZnVuY3Rpb24ocil7dmFyIG89bmV3IFRvKHRoaXMsdGhpcyk7cmV0dXJuIG8ub3BlcmF0b3I9cixvfSx0LnByb3RvdHlwZS5fdGhyb3dJZkNsb3NlZD1mdW5jdGlvbigpe2lmKHRoaXMuY2xvc2VkKXRocm93IG5ldyB3b30sdC5wcm90b3R5cGUubmV4dD1mdW5jdGlvbihyKXt2YXIgbz10aGlzO2h0KGZ1bmN0aW9uKCl7dmFyIG4saTtpZihvLl90aHJvd0lmQ2xvc2VkKCksIW8uaXNTdG9wcGVkKXtvLmN1cnJlbnRPYnNlcnZlcnN8fChvLmN1cnJlbnRPYnNlcnZlcnM9QXJyYXkuZnJvbShvLm9ic2VydmVycykpO3RyeXtmb3IodmFyIGE9aGUoby5jdXJyZW50T2JzZXJ2ZXJzKSxzPWEubmV4dCgpOyFzLmRvbmU7cz1hLm5leHQoKSl7dmFyIHA9cy52YWx1ZTtwLm5leHQocil9fWNhdGNoKGMpe249e2Vycm9yOmN9fWZpbmFsbHl7dHJ5e3MmJiFzLmRvbmUmJihpPWEucmV0dXJuKSYmaS5jYWxsKGEpfWZpbmFsbHl7aWYobil0aHJvdyBuLmVycm9yfX19fSl9LHQucHJvdG90eXBlLmVycm9yPWZ1bmN0aW9uKHIpe3ZhciBvPXRoaXM7aHQoZnVuY3Rpb24oKXtpZihvLl90aHJvd0lmQ2xvc2VkKCksIW8uaXNTdG9wcGVkKXtvLmhhc0Vycm9yPW8uaXNTdG9wcGVkPSEwLG8udGhyb3duRXJyb3I9cjtmb3IodmFyIG49by5vYnNlcnZlcnM7bi5sZW5ndGg7KW4uc2hpZnQoKS5lcnJvcihyKX19KX0sdC5wcm90b3R5cGUuY29tcGxldGU9ZnVuY3Rpb24oKXt2YXIgcj10aGlzO2h0KGZ1bmN0aW9uKCl7aWYoci5fdGhyb3dJZkNsb3NlZCgpLCFyLmlzU3RvcHBlZCl7ci5pc1N0b3BwZWQ9ITA7Zm9yKHZhciBvPXIub2JzZXJ2ZXJzO28ubGVuZ3RoOylvLnNoaWZ0KCkuY29tcGxldGUoKX19KX0sdC5wcm90b3R5cGUudW5zdWJzY3JpYmU9ZnVuY3Rpb24oKXt0aGlzLmlzU3RvcHBlZD10aGlzLmNsb3NlZD0hMCx0aGlzLm9ic2VydmVycz10aGlzLmN1cnJlbnRPYnNlcnZlcnM9bnVsbH0sT2JqZWN0LmRlZmluZVByb3BlcnR5KHQucHJvdG90eXBlLCJvYnNlcnZlZCIse2dldDpmdW5jdGlvbigpe3ZhciByO3JldHVybigocj10aGlzLm9ic2VydmVycyk9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmxlbmd0aCk+MH0sZW51bWVyYWJsZTohMSxjb25maWd1cmFibGU6ITB9KSx0LnByb3RvdHlwZS5fdHJ5U3Vic2NyaWJlPWZ1bmN0aW9uKHIpe3JldHVybiB0aGlzLl90aHJvd0lmQ2xvc2VkKCksZS5wcm90b3R5cGUuX3RyeVN1YnNjcmliZS5jYWxsKHRoaXMscil9LHQucHJvdG90eXBlLl9zdWJzY3JpYmU9ZnVuY3Rpb24ocil7cmV0dXJuIHRoaXMuX3Rocm93SWZDbG9zZWQoKSx0aGlzLl9jaGVja0ZpbmFsaXplZFN0YXR1c2VzKHIpLHRoaXMuX2lubmVyU3Vic2NyaWJlKHIpfSx0LnByb3RvdHlwZS5faW5uZXJTdWJzY3JpYmU9ZnVuY3Rpb24ocil7dmFyIG89dGhpcyxuPXRoaXMsaT1uLmhhc0Vycm9yLGE9bi5pc1N0b3BwZWQscz1uLm9ic2VydmVycztyZXR1cm4gaXx8YT9UcjoodGhpcy5jdXJyZW50T2JzZXJ2ZXJzPW51bGwscy5wdXNoKHIpLG5ldyBVZShmdW5jdGlvbigpe28uY3VycmVudE9ic2VydmVycz1udWxsLFFlKHMscil9KSl9LHQucHJvdG90eXBlLl9jaGVja0ZpbmFsaXplZFN0YXR1c2VzPWZ1bmN0aW9uKHIpe3ZhciBvPXRoaXMsbj1vLmhhc0Vycm9yLGk9by50aHJvd25FcnJvcixhPW8uaXNTdG9wcGVkO24/ci5lcnJvcihpKTphJiZyLmNvbXBsZXRlKCl9LHQucHJvdG90eXBlLmFzT2JzZXJ2YWJsZT1mdW5jdGlvbigpe3ZhciByPW5ldyBqO3JldHVybiByLnNvdXJjZT10aGlzLHJ9LHQuY3JlYXRlPWZ1bmN0aW9uKHIsbyl7cmV0dXJuIG5ldyBUbyhyLG8pfSx0fShqKTt2YXIgVG89ZnVuY3Rpb24oZSl7b2UodCxlKTtmdW5jdGlvbiB0KHIsbyl7dmFyIG49ZS5jYWxsKHRoaXMpfHx0aGlzO3JldHVybiBuLmRlc3RpbmF0aW9uPXIsbi5zb3VyY2U9byxufXJldHVybiB0LnByb3RvdHlwZS5uZXh0PWZ1bmN0aW9uKHIpe3ZhciBvLG47KG49KG89dGhpcy5kZXN0aW5hdGlvbik9PT1udWxsfHxvPT09dm9pZCAwP3ZvaWQgMDpvLm5leHQpPT09bnVsbHx8bj09PXZvaWQgMHx8bi5jYWxsKG8scil9LHQucHJvdG90eXBlLmVycm9yPWZ1bmN0aW9uKHIpe3ZhciBvLG47KG49KG89dGhpcy5kZXN0aW5hdGlvbik9PT1udWxsfHxvPT09dm9pZCAwP3ZvaWQgMDpvLmVycm9yKT09PW51bGx8fG49PT12b2lkIDB8fG4uY2FsbChvLHIpfSx0LnByb3RvdHlwZS5jb21wbGV0ZT1mdW5jdGlvbigpe3ZhciByLG87KG89KHI9dGhpcy5kZXN0aW5hdGlvbik9PT1udWxsfHxyPT09dm9pZCAwP3ZvaWQgMDpyLmNvbXBsZXRlKT09PW51bGx8fG89PT12b2lkIDB8fG8uY2FsbChyKX0sdC5wcm90b3R5cGUuX3N1YnNjcmliZT1mdW5jdGlvbihyKXt2YXIgbyxuO3JldHVybihuPShvPXRoaXMuc291cmNlKT09PW51bGx8fG89PT12b2lkIDA/dm9pZCAwOm8uc3Vic2NyaWJlKHIpKSE9PW51bGwmJm4hPT12b2lkIDA/bjpUcn0sdH0oZyk7dmFyIF9yPWZ1bmN0aW9uKGUpe29lKHQsZSk7ZnVuY3Rpb24gdChyKXt2YXIgbz1lLmNhbGwodGhpcyl8fHRoaXM7cmV0dXJuIG8uX3ZhbHVlPXIsb31yZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KHQucHJvdG90eXBlLCJ2YWx1ZSIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmdldFZhbHVlKCl9LGVudW1lcmFibGU6ITEsY29uZmlndXJhYmxlOiEwfSksdC5wcm90b3R5cGUuX3N1YnNjcmliZT1mdW5jdGlvbihyKXt2YXIgbz1lLnByb3RvdHlwZS5fc3Vic2NyaWJlLmNhbGwodGhpcyxyKTtyZXR1cm4hby5jbG9zZWQmJnIubmV4dCh0aGlzLl92YWx1ZSksb30sdC5wcm90b3R5cGUuZ2V0VmFsdWU9ZnVuY3Rpb24oKXt2YXIgcj10aGlzLG89ci5oYXNFcnJvcixuPXIudGhyb3duRXJyb3IsaT1yLl92YWx1ZTtpZihvKXRocm93IG47cmV0dXJuIHRoaXMuX3Rocm93SWZDbG9zZWQoKSxpfSx0LnByb3RvdHlwZS5uZXh0PWZ1bmN0aW9uKHIpe2UucHJvdG90eXBlLm5leHQuY2FsbCh0aGlzLHRoaXMuX3ZhbHVlPXIpfSx0fShnKTt2YXIgQXQ9e25vdzpmdW5jdGlvbigpe3JldHVybihBdC5kZWxlZ2F0ZXx8RGF0ZSkubm93KCl9LGRlbGVnYXRlOnZvaWQgMH07dmFyIEN0PWZ1bmN0aW9uKGUpe29lKHQsZSk7ZnVuY3Rpb24gdChyLG8sbil7cj09PXZvaWQgMCYmKHI9MS8wKSxvPT09dm9pZCAwJiYobz0xLzApLG49PT12b2lkIDAmJihuPUF0KTt2YXIgaT1lLmNhbGwodGhpcyl8fHRoaXM7cmV0dXJuIGkuX2J1ZmZlclNpemU9cixpLl93aW5kb3dUaW1lPW8saS5fdGltZXN0YW1wUHJvdmlkZXI9bixpLl9idWZmZXI9W10saS5faW5maW5pdGVUaW1lV2luZG93PSEwLGkuX2luZmluaXRlVGltZVdpbmRvdz1vPT09MS8wLGkuX2J1ZmZlclNpemU9TWF0aC5tYXgoMSxyKSxpLl93aW5kb3dUaW1lPU1hdGgubWF4KDEsbyksaX1yZXR1cm4gdC5wcm90b3R5cGUubmV4dD1mdW5jdGlvbihyKXt2YXIgbz10aGlzLG49by5pc1N0b3BwZWQsaT1vLl9idWZmZXIsYT1vLl9pbmZpbml0ZVRpbWVXaW5kb3cscz1vLl90aW1lc3RhbXBQcm92aWRlcixwPW8uX3dpbmRvd1RpbWU7bnx8KGkucHVzaChyKSwhYSYmaS5wdXNoKHMubm93KCkrcCkpLHRoaXMuX3RyaW1CdWZmZXIoKSxlLnByb3RvdHlwZS5uZXh0LmNhbGwodGhpcyxyKX0sdC5wcm90b3R5cGUuX3N1YnNjcmliZT1mdW5jdGlvbihyKXt0aGlzLl90aHJvd0lmQ2xvc2VkKCksdGhpcy5fdHJpbUJ1ZmZlcigpO2Zvcih2YXIgbz10aGlzLl9pbm5lclN1YnNjcmliZShyKSxuPXRoaXMsaT1uLl9pbmZpbml0ZVRpbWVXaW5kb3csYT1uLl9idWZmZXIscz1hLnNsaWNlKCkscD0wO3A8cy5sZW5ndGgmJiFyLmNsb3NlZDtwKz1pPzE6MilyLm5leHQoc1twXSk7cmV0dXJuIHRoaXMuX2NoZWNrRmluYWxpemVkU3RhdHVzZXMociksb30sdC5wcm90b3R5cGUuX3RyaW1CdWZmZXI9ZnVuY3Rpb24oKXt2YXIgcj10aGlzLG89ci5fYnVmZmVyU2l6ZSxuPXIuX3RpbWVzdGFtcFByb3ZpZGVyLGk9ci5fYnVmZmVyLGE9ci5faW5maW5pdGVUaW1lV2luZG93LHM9KGE/MToyKSpvO2lmKG88MS8wJiZzPGkubGVuZ3RoJiZpLnNwbGljZSgwLGkubGVuZ3RoLXMpLCFhKXtmb3IodmFyIHA9bi5ub3coKSxjPTAsbD0xO2w8aS5sZW5ndGgmJmlbbF08PXA7bCs9MiljPWw7YyYmaS5zcGxpY2UoMCxjKzEpfX0sdH0oZyk7dmFyIFNvPWZ1bmN0aW9uKGUpe29lKHQsZSk7ZnVuY3Rpb24gdChyLG8pe3JldHVybiBlLmNhbGwodGhpcyl8fHRoaXN9cmV0dXJuIHQucHJvdG90eXBlLnNjaGVkdWxlPWZ1bmN0aW9uKHIsbyl7cmV0dXJuIG89PT12b2lkIDAmJihvPTApLHRoaXN9LHR9KFVlKTt2YXIga3Q9e3NldEludGVydmFsOmZ1bmN0aW9uKGUsdCl7Zm9yKHZhciByPVtdLG89MjtvPGFyZ3VtZW50cy5sZW5ndGg7bysrKXJbby0yXT1hcmd1bWVudHNbb107dmFyIG49a3QuZGVsZWdhdGU7cmV0dXJuIG4hPW51bGwmJm4uc2V0SW50ZXJ2YWw/bi5zZXRJbnRlcnZhbC5hcHBseShuLHEoW2UsdF0sTihyKSkpOnNldEludGVydmFsLmFwcGx5KHZvaWQgMCxxKFtlLHRdLE4ocikpKX0sY2xlYXJJbnRlcnZhbDpmdW5jdGlvbihlKXt2YXIgdD1rdC5kZWxlZ2F0ZTtyZXR1cm4oKHQ9PW51bGw/dm9pZCAwOnQuY2xlYXJJbnRlcnZhbCl8fGNsZWFySW50ZXJ2YWwpKGUpfSxkZWxlZ2F0ZTp2b2lkIDB9O3ZhciBndD1mdW5jdGlvbihlKXtvZSh0LGUpO2Z1bmN0aW9uIHQocixvKXt2YXIgbj1lLmNhbGwodGhpcyxyLG8pfHx0aGlzO3JldHVybiBuLnNjaGVkdWxlcj1yLG4ud29yaz1vLG4ucGVuZGluZz0hMSxufXJldHVybiB0LnByb3RvdHlwZS5zY2hlZHVsZT1mdW5jdGlvbihyLG8pe3ZhciBuO2lmKG89PT12b2lkIDAmJihvPTApLHRoaXMuY2xvc2VkKXJldHVybiB0aGlzO3RoaXMuc3RhdGU9cjt2YXIgaT10aGlzLmlkLGE9dGhpcy5zY2hlZHVsZXI7cmV0dXJuIGkhPW51bGwmJih0aGlzLmlkPXRoaXMucmVjeWNsZUFzeW5jSWQoYSxpLG8pKSx0aGlzLnBlbmRpbmc9ITAsdGhpcy5kZWxheT1vLHRoaXMuaWQ9KG49dGhpcy5pZCkhPT1udWxsJiZuIT09dm9pZCAwP246dGhpcy5yZXF1ZXN0QXN5bmNJZChhLHRoaXMuaWQsbyksdGhpc30sdC5wcm90b3R5cGUucmVxdWVzdEFzeW5jSWQ9ZnVuY3Rpb24ocixvLG4pe3JldHVybiBuPT09dm9pZCAwJiYobj0wKSxrdC5zZXRJbnRlcnZhbChyLmZsdXNoLmJpbmQocix0aGlzKSxuKX0sdC5wcm90b3R5cGUucmVjeWNsZUFzeW5jSWQ9ZnVuY3Rpb24ocixvLG4pe2lmKG49PT12b2lkIDAmJihuPTApLG4hPW51bGwmJnRoaXMuZGVsYXk9PT1uJiZ0aGlzLnBlbmRpbmc9PT0hMSlyZXR1cm4gbztvIT1udWxsJiZrdC5jbGVhckludGVydmFsKG8pfSx0LnByb3RvdHlwZS5leGVjdXRlPWZ1bmN0aW9uKHIsbyl7aWYodGhpcy5jbG9zZWQpcmV0dXJuIG5ldyBFcnJvcigiZXhlY3V0aW5nIGEgY2FuY2VsbGVkIGFjdGlvbiIpO3RoaXMucGVuZGluZz0hMTt2YXIgbj10aGlzLl9leGVjdXRlKHIsbyk7aWYobilyZXR1cm4gbjt0aGlzLnBlbmRpbmc9PT0hMSYmdGhpcy5pZCE9bnVsbCYmKHRoaXMuaWQ9dGhpcy5yZWN5Y2xlQXN5bmNJZCh0aGlzLnNjaGVkdWxlcix0aGlzLmlkLG51bGwpKX0sdC5wcm90b3R5cGUuX2V4ZWN1dGU9ZnVuY3Rpb24ocixvKXt2YXIgbj0hMSxpO3RyeXt0aGlzLndvcmsocil9Y2F0Y2goYSl7bj0hMCxpPWF8fG5ldyBFcnJvcigiU2NoZWR1bGVkIGFjdGlvbiB0aHJldyBmYWxzeSBlcnJvciIpfWlmKG4pcmV0dXJuIHRoaXMudW5zdWJzY3JpYmUoKSxpfSx0LnByb3RvdHlwZS51bnN1YnNjcmliZT1mdW5jdGlvbigpe2lmKCF0aGlzLmNsb3NlZCl7dmFyIHI9dGhpcyxvPXIuaWQsbj1yLnNjaGVkdWxlcixpPW4uYWN0aW9uczt0aGlzLndvcms9dGhpcy5zdGF0ZT10aGlzLnNjaGVkdWxlcj1udWxsLHRoaXMucGVuZGluZz0hMSxRZShpLHRoaXMpLG8hPW51bGwmJih0aGlzLmlkPXRoaXMucmVjeWNsZUFzeW5jSWQobixvLG51bGwpKSx0aGlzLmRlbGF5PW51bGwsZS5wcm90b3R5cGUudW5zdWJzY3JpYmUuY2FsbCh0aGlzKX19LHR9KFNvKTt2YXIgQXI9ZnVuY3Rpb24oKXtmdW5jdGlvbiBlKHQscil7cj09PXZvaWQgMCYmKHI9ZS5ub3cpLHRoaXMuc2NoZWR1bGVyQWN0aW9uQ3Rvcj10LHRoaXMubm93PXJ9cmV0dXJuIGUucHJvdG90eXBlLnNjaGVkdWxlPWZ1bmN0aW9uKHQscixvKXtyZXR1cm4gcj09PXZvaWQgMCYmKHI9MCksbmV3IHRoaXMuc2NoZWR1bGVyQWN0aW9uQ3Rvcih0aGlzLHQpLnNjaGVkdWxlKG8scil9LGUubm93PUF0Lm5vdyxlfSgpO3ZhciB5dD1mdW5jdGlvbihlKXtvZSh0LGUpO2Z1bmN0aW9uIHQocixvKXtvPT09dm9pZCAwJiYobz1Bci5ub3cpO3ZhciBuPWUuY2FsbCh0aGlzLHIsbyl8fHRoaXM7cmV0dXJuIG4uYWN0aW9ucz1bXSxuLl9hY3RpdmU9ITEsbn1yZXR1cm4gdC5wcm90b3R5cGUuZmx1c2g9ZnVuY3Rpb24ocil7dmFyIG89dGhpcy5hY3Rpb25zO2lmKHRoaXMuX2FjdGl2ZSl7by5wdXNoKHIpO3JldHVybn12YXIgbjt0aGlzLl9hY3RpdmU9ITA7ZG8gaWYobj1yLmV4ZWN1dGUoci5zdGF0ZSxyLmRlbGF5KSlicmVhazt3aGlsZShyPW8uc2hpZnQoKSk7aWYodGhpcy5fYWN0aXZlPSExLG4pe2Zvcig7cj1vLnNoaWZ0KCk7KXIudW5zdWJzY3JpYmUoKTt0aHJvdyBufX0sdH0oQXIpO3ZhciBzZT1uZXcgeXQoZ3QpLENyPXNlO3ZhciBPbz1mdW5jdGlvbihlKXtvZSh0LGUpO2Z1bmN0aW9uIHQocixvKXt2YXIgbj1lLmNhbGwodGhpcyxyLG8pfHx0aGlzO3JldHVybiBuLnNjaGVkdWxlcj1yLG4ud29yaz1vLG59cmV0dXJuIHQucHJvdG90eXBlLnNjaGVkdWxlPWZ1bmN0aW9uKHIsbyl7cmV0dXJuIG89PT12b2lkIDAmJihvPTApLG8+MD9lLnByb3RvdHlwZS5zY2hlZHVsZS5jYWxsKHRoaXMscixvKToodGhpcy5kZWxheT1vLHRoaXMuc3RhdGU9cix0aGlzLnNjaGVkdWxlci5mbHVzaCh0aGlzKSx0aGlzKX0sdC5wcm90b3R5cGUuZXhlY3V0ZT1mdW5jdGlvbihyLG8pe3JldHVybiBvPjB8fHRoaXMuY2xvc2VkP2UucHJvdG90eXBlLmV4ZWN1dGUuY2FsbCh0aGlzLHIsbyk6dGhpcy5fZXhlY3V0ZShyLG8pfSx0LnByb3RvdHlwZS5yZXF1ZXN0QXN5bmNJZD1mdW5jdGlvbihyLG8sbil7cmV0dXJuIG49PT12b2lkIDAmJihuPTApLG4hPW51bGwmJm4+MHx8bj09bnVsbCYmdGhpcy5kZWxheT4wP2UucHJvdG90eXBlLnJlcXVlc3RBc3luY0lkLmNhbGwodGhpcyxyLG8sbik6KHIuZmx1c2godGhpcyksMCl9LHR9KGd0KTt2YXIgTG89ZnVuY3Rpb24oZSl7b2UodCxlKTtmdW5jdGlvbiB0KCl7cmV0dXJuIGUhPT1udWxsJiZlLmFwcGx5KHRoaXMsYXJndW1lbnRzKXx8dGhpc31yZXR1cm4gdH0oeXQpO3ZhciBrcj1uZXcgTG8oT28pO3ZhciBNbz1mdW5jdGlvbihlKXtvZSh0LGUpO2Z1bmN0aW9uIHQocixvKXt2YXIgbj1lLmNhbGwodGhpcyxyLG8pfHx0aGlzO3JldHVybiBuLnNjaGVkdWxlcj1yLG4ud29yaz1vLG59cmV0dXJuIHQucHJvdG90eXBlLnJlcXVlc3RBc3luY0lkPWZ1bmN0aW9uKHIsbyxuKXtyZXR1cm4gbj09PXZvaWQgMCYmKG49MCksbiE9PW51bGwmJm4+MD9lLnByb3RvdHlwZS5yZXF1ZXN0QXN5bmNJZC5jYWxsKHRoaXMscixvLG4pOihyLmFjdGlvbnMucHVzaCh0aGlzKSxyLl9zY2hlZHVsZWR8fChyLl9zY2hlZHVsZWQ9dnQucmVxdWVzdEFuaW1hdGlvbkZyYW1lKGZ1bmN0aW9uKCl7cmV0dXJuIHIuZmx1c2godm9pZCAwKX0pKSl9LHQucHJvdG90eXBlLnJlY3ljbGVBc3luY0lkPWZ1bmN0aW9uKHIsbyxuKXt2YXIgaTtpZihuPT09dm9pZCAwJiYobj0wKSxuIT1udWxsP24+MDp0aGlzLmRlbGF5PjApcmV0dXJuIGUucHJvdG90eXBlLnJlY3ljbGVBc3luY0lkLmNhbGwodGhpcyxyLG8sbik7dmFyIGE9ci5hY3Rpb25zO28hPW51bGwmJigoaT1hW2EubGVuZ3RoLTFdKT09PW51bGx8fGk9PT12b2lkIDA/dm9pZCAwOmkuaWQpIT09byYmKHZ0LmNhbmNlbEFuaW1hdGlvbkZyYW1lKG8pLHIuX3NjaGVkdWxlZD12b2lkIDApfSx0fShndCk7dmFyIF9vPWZ1bmN0aW9uKGUpe29lKHQsZSk7ZnVuY3Rpb24gdCgpe3JldHVybiBlIT09bnVsbCYmZS5hcHBseSh0aGlzLGFyZ3VtZW50cyl8fHRoaXN9cmV0dXJuIHQucHJvdG90eXBlLmZsdXNoPWZ1bmN0aW9uKHIpe3RoaXMuX2FjdGl2ZT0hMDt2YXIgbz10aGlzLl9zY2hlZHVsZWQ7dGhpcy5fc2NoZWR1bGVkPXZvaWQgMDt2YXIgbj10aGlzLmFjdGlvbnMsaTtyPXJ8fG4uc2hpZnQoKTtkbyBpZihpPXIuZXhlY3V0ZShyLnN0YXRlLHIuZGVsYXkpKWJyZWFrO3doaWxlKChyPW5bMF0pJiZyLmlkPT09byYmbi5zaGlmdCgpKTtpZih0aGlzLl9hY3RpdmU9ITEsaSl7Zm9yKDsocj1uWzBdKSYmci5pZD09PW8mJm4uc2hpZnQoKTspci51bnN1YnNjcmliZSgpO3Rocm93IGl9fSx0fSh5dCk7dmFyIG1lPW5ldyBfbyhNbyk7dmFyIFM9bmV3IGooZnVuY3Rpb24oZSl7cmV0dXJuIGUuY29tcGxldGUoKX0pO2Z1bmN0aW9uIFl0KGUpe3JldHVybiBlJiZIKGUuc2NoZWR1bGUpfWZ1bmN0aW9uIEhyKGUpe3JldHVybiBlW2UubGVuZ3RoLTFdfWZ1bmN0aW9uIFhlKGUpe3JldHVybiBIKEhyKGUpKT9lLnBvcCgpOnZvaWQgMH1mdW5jdGlvbiBrZShlKXtyZXR1cm4gWXQoSHIoZSkpP2UucG9wKCk6dm9pZCAwfWZ1bmN0aW9uIEJ0KGUsdCl7cmV0dXJuIHR5cGVvZiBIcihlKT09Im51bWJlciI/ZS5wb3AoKTp0fXZhciB4dD1mdW5jdGlvbihlKXtyZXR1cm4gZSYmdHlwZW9mIGUubGVuZ3RoPT0ibnVtYmVyIiYmdHlwZW9mIGUhPSJmdW5jdGlvbiJ9O2Z1bmN0aW9uIEd0KGUpe3JldHVybiBIKGU9PW51bGw/dm9pZCAwOmUudGhlbil9ZnVuY3Rpb24gSnQoZSl7cmV0dXJuIEgoZVtidF0pfWZ1bmN0aW9uIFh0KGUpe3JldHVybiBTeW1ib2wuYXN5bmNJdGVyYXRvciYmSChlPT1udWxsP3ZvaWQgMDplW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSl9ZnVuY3Rpb24gWnQoZSl7cmV0dXJuIG5ldyBUeXBlRXJyb3IoIllvdSBwcm92aWRlZCAiKyhlIT09bnVsbCYmdHlwZW9mIGU9PSJvYmplY3QiPyJhbiBpbnZhbGlkIG9iamVjdCI6IiciK2UrIiciKSsiIHdoZXJlIGEgc3RyZWFtIHdhcyBleHBlY3RlZC4gWW91IGNhbiBwcm92aWRlIGFuIE9ic2VydmFibGUsIFByb21pc2UsIFJlYWRhYmxlU3RyZWFtLCBBcnJheSwgQXN5bmNJdGVyYWJsZSwgb3IgSXRlcmFibGUuIil9ZnVuY3Rpb24gWmkoKXtyZXR1cm4gdHlwZW9mIFN5bWJvbCE9ImZ1bmN0aW9uInx8IVN5bWJvbC5pdGVyYXRvcj8iQEBpdGVyYXRvciI6U3ltYm9sLml0ZXJhdG9yfXZhciBlcj1aaSgpO2Z1bmN0aW9uIHRyKGUpe3JldHVybiBIKGU9PW51bGw/dm9pZCAwOmVbZXJdKX1mdW5jdGlvbiBycihlKXtyZXR1cm4gZm8odGhpcyxhcmd1bWVudHMsZnVuY3Rpb24oKXt2YXIgcixvLG4saTtyZXR1cm4gTnQodGhpcyxmdW5jdGlvbihhKXtzd2l0Y2goYS5sYWJlbCl7Y2FzZSAwOnI9ZS5nZXRSZWFkZXIoKSxhLmxhYmVsPTE7Y2FzZSAxOmEudHJ5cy5wdXNoKFsxLCw5LDEwXSksYS5sYWJlbD0yO2Nhc2UgMjpyZXR1cm5bNCxudChyLnJlYWQoKSldO2Nhc2UgMzpyZXR1cm4gbz1hLnNlbnQoKSxuPW8udmFsdWUsaT1vLmRvbmUsaT9bNCxudCh2b2lkIDApXTpbMyw1XTtjYXNlIDQ6cmV0dXJuWzIsYS5zZW50KCldO2Nhc2UgNTpyZXR1cm5bNCxudChuKV07Y2FzZSA2OnJldHVybls0LGEuc2VudCgpXTtjYXNlIDc6cmV0dXJuIGEuc2VudCgpLFszLDJdO2Nhc2UgODpyZXR1cm5bMywxMF07Y2FzZSA5OnJldHVybiByLnJlbGVhc2VMb2NrKCksWzddO2Nhc2UgMTA6cmV0dXJuWzJdfX0pfSl9ZnVuY3Rpb24gb3IoZSl7cmV0dXJuIEgoZT09bnVsbD92b2lkIDA6ZS5nZXRSZWFkZXIpfWZ1bmN0aW9uIFUoZSl7aWYoZSBpbnN0YW5jZW9mIGopcmV0dXJuIGU7aWYoZSE9bnVsbCl7aWYoSnQoZSkpcmV0dXJuIGVhKGUpO2lmKHh0KGUpKXJldHVybiB0YShlKTtpZihHdChlKSlyZXR1cm4gcmEoZSk7aWYoWHQoZSkpcmV0dXJuIEFvKGUpO2lmKHRyKGUpKXJldHVybiBvYShlKTtpZihvcihlKSlyZXR1cm4gbmEoZSl9dGhyb3cgWnQoZSl9ZnVuY3Rpb24gZWEoZSl7cmV0dXJuIG5ldyBqKGZ1bmN0aW9uKHQpe3ZhciByPWVbYnRdKCk7aWYoSChyLnN1YnNjcmliZSkpcmV0dXJuIHIuc3Vic2NyaWJlKHQpO3Rocm93IG5ldyBUeXBlRXJyb3IoIlByb3ZpZGVkIG9iamVjdCBkb2VzIG5vdCBjb3JyZWN0bHkgaW1wbGVtZW50IFN5bWJvbC5vYnNlcnZhYmxlIil9KX1mdW5jdGlvbiB0YShlKXtyZXR1cm4gbmV3IGooZnVuY3Rpb24odCl7Zm9yKHZhciByPTA7cjxlLmxlbmd0aCYmIXQuY2xvc2VkO3IrKyl0Lm5leHQoZVtyXSk7dC5jb21wbGV0ZSgpfSl9ZnVuY3Rpb24gcmEoZSl7cmV0dXJuIG5ldyBqKGZ1bmN0aW9uKHQpe2UudGhlbihmdW5jdGlvbihyKXt0LmNsb3NlZHx8KHQubmV4dChyKSx0LmNvbXBsZXRlKCkpfSxmdW5jdGlvbihyKXtyZXR1cm4gdC5lcnJvcihyKX0pLnRoZW4obnVsbCxRdCl9KX1mdW5jdGlvbiBvYShlKXtyZXR1cm4gbmV3IGooZnVuY3Rpb24odCl7dmFyIHIsbzt0cnl7Zm9yKHZhciBuPWhlKGUpLGk9bi5uZXh0KCk7IWkuZG9uZTtpPW4ubmV4dCgpKXt2YXIgYT1pLnZhbHVlO2lmKHQubmV4dChhKSx0LmNsb3NlZClyZXR1cm59fWNhdGNoKHMpe3I9e2Vycm9yOnN9fWZpbmFsbHl7dHJ5e2kmJiFpLmRvbmUmJihvPW4ucmV0dXJuKSYmby5jYWxsKG4pfWZpbmFsbHl7aWYocil0aHJvdyByLmVycm9yfX10LmNvbXBsZXRlKCl9KX1mdW5jdGlvbiBBbyhlKXtyZXR1cm4gbmV3IGooZnVuY3Rpb24odCl7aWEoZSx0KS5jYXRjaChmdW5jdGlvbihyKXtyZXR1cm4gdC5lcnJvcihyKX0pfSl9ZnVuY3Rpb24gbmEoZSl7cmV0dXJuIEFvKHJyKGUpKX1mdW5jdGlvbiBpYShlLHQpe3ZhciByLG8sbixpO3JldHVybiBtbyh0aGlzLHZvaWQgMCx2b2lkIDAsZnVuY3Rpb24oKXt2YXIgYSxzO3JldHVybiBOdCh0aGlzLGZ1bmN0aW9uKHApe3N3aXRjaChwLmxhYmVsKXtjYXNlIDA6cC50cnlzLnB1c2goWzAsNSw2LDExXSkscj11byhlKSxwLmxhYmVsPTE7Y2FzZSAxOnJldHVybls0LHIubmV4dCgpXTtjYXNlIDI6aWYobz1wLnNlbnQoKSwhIW8uZG9uZSlyZXR1cm5bMyw0XTtpZihhPW8udmFsdWUsdC5uZXh0KGEpLHQuY2xvc2VkKXJldHVyblsyXTtwLmxhYmVsPTM7Y2FzZSAzOnJldHVyblszLDFdO2Nhc2UgNDpyZXR1cm5bMywxMV07Y2FzZSA1OnJldHVybiBzPXAuc2VudCgpLG49e2Vycm9yOnN9LFszLDExXTtjYXNlIDY6cmV0dXJuIHAudHJ5cy5wdXNoKFs2LCw5LDEwXSksbyYmIW8uZG9uZSYmKGk9ci5yZXR1cm4pP1s0LGkuY2FsbChyKV06WzMsOF07Y2FzZSA3OnAuc2VudCgpLHAubGFiZWw9ODtjYXNlIDg6cmV0dXJuWzMsMTBdO2Nhc2UgOTppZihuKXRocm93IG4uZXJyb3I7cmV0dXJuWzddO2Nhc2UgMTA6cmV0dXJuWzddO2Nhc2UgMTE6cmV0dXJuIHQuY29tcGxldGUoKSxbMl19fSl9KX1mdW5jdGlvbiB3ZShlLHQscixvLG4pe289PT12b2lkIDAmJihvPTApLG49PT12b2lkIDAmJihuPSExKTt2YXIgaT10LnNjaGVkdWxlKGZ1bmN0aW9uKCl7cigpLG4/ZS5hZGQodGhpcy5zY2hlZHVsZShudWxsLG8pKTp0aGlzLnVuc3Vic2NyaWJlKCl9LG8pO2lmKGUuYWRkKGkpLCFuKXJldHVybiBpfWZ1bmN0aW9uIHZlKGUsdCl7cmV0dXJuIHQ9PT12b2lkIDAmJih0PTApLEUoZnVuY3Rpb24ocixvKXtyLnN1YnNjcmliZShUKG8sZnVuY3Rpb24obil7cmV0dXJuIHdlKG8sZSxmdW5jdGlvbigpe3JldHVybiBvLm5leHQobil9LHQpfSxmdW5jdGlvbigpe3JldHVybiB3ZShvLGUsZnVuY3Rpb24oKXtyZXR1cm4gby5jb21wbGV0ZSgpfSx0KX0sZnVuY3Rpb24obil7cmV0dXJuIHdlKG8sZSxmdW5jdGlvbigpe3JldHVybiBvLmVycm9yKG4pfSx0KX0pKX0pfWZ1bmN0aW9uIEtlKGUsdCl7cmV0dXJuIHQ9PT12b2lkIDAmJih0PTApLEUoZnVuY3Rpb24ocixvKXtvLmFkZChlLnNjaGVkdWxlKGZ1bmN0aW9uKCl7cmV0dXJuIHIuc3Vic2NyaWJlKG8pfSx0KSl9KX1mdW5jdGlvbiBDbyhlLHQpe3JldHVybiBVKGUpLnBpcGUoS2UodCksdmUodCkpfWZ1bmN0aW9uIGtvKGUsdCl7cmV0dXJuIFUoZSkucGlwZShLZSh0KSx2ZSh0KSl9ZnVuY3Rpb24gSG8oZSx0KXtyZXR1cm4gbmV3IGooZnVuY3Rpb24ocil7dmFyIG89MDtyZXR1cm4gdC5zY2hlZHVsZShmdW5jdGlvbigpe289PT1lLmxlbmd0aD9yLmNvbXBsZXRlKCk6KHIubmV4dChlW28rK10pLHIuY2xvc2VkfHx0aGlzLnNjaGVkdWxlKCkpfSl9KX1mdW5jdGlvbiAkbyhlLHQpe3JldHVybiBuZXcgaihmdW5jdGlvbihyKXt2YXIgbztyZXR1cm4gd2Uocix0LGZ1bmN0aW9uKCl7bz1lW2VyXSgpLHdlKHIsdCxmdW5jdGlvbigpe3ZhciBuLGksYTt0cnl7bj1vLm5leHQoKSxpPW4udmFsdWUsYT1uLmRvbmV9Y2F0Y2gocyl7ci5lcnJvcihzKTtyZXR1cm59YT9yLmNvbXBsZXRlKCk6ci5uZXh0KGkpfSwwLCEwKX0pLGZ1bmN0aW9uKCl7cmV0dXJuIEgobz09bnVsbD92b2lkIDA6by5yZXR1cm4pJiZvLnJldHVybigpfX0pfWZ1bmN0aW9uIG5yKGUsdCl7aWYoIWUpdGhyb3cgbmV3IEVycm9yKCJJdGVyYWJsZSBjYW5ub3QgYmUgbnVsbCIpO3JldHVybiBuZXcgaihmdW5jdGlvbihyKXt3ZShyLHQsZnVuY3Rpb24oKXt2YXIgbz1lW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSgpO3dlKHIsdCxmdW5jdGlvbigpe28ubmV4dCgpLnRoZW4oZnVuY3Rpb24obil7bi5kb25lP3IuY29tcGxldGUoKTpyLm5leHQobi52YWx1ZSl9KX0sMCwhMCl9KX0pfWZ1bmN0aW9uIFBvKGUsdCl7cmV0dXJuIG5yKHJyKGUpLHQpfWZ1bmN0aW9uIFJvKGUsdCl7aWYoZSE9bnVsbCl7aWYoSnQoZSkpcmV0dXJuIENvKGUsdCk7aWYoeHQoZSkpcmV0dXJuIEhvKGUsdCk7aWYoR3QoZSkpcmV0dXJuIGtvKGUsdCk7aWYoWHQoZSkpcmV0dXJuIG5yKGUsdCk7aWYodHIoZSkpcmV0dXJuICRvKGUsdCk7aWYob3IoZSkpcmV0dXJuIFBvKGUsdCl9dGhyb3cgWnQoZSl9ZnVuY3Rpb24gdWUoZSx0KXtyZXR1cm4gdD9SbyhlLHQpOlUoZSl9ZnVuY3Rpb24gSSgpe2Zvcih2YXIgZT1bXSx0PTA7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyllW3RdPWFyZ3VtZW50c1t0XTt2YXIgcj1rZShlKTtyZXR1cm4gdWUoZSxyKX1mdW5jdGlvbiAkcihlLHQpe3ZhciByPUgoZSk/ZTpmdW5jdGlvbigpe3JldHVybiBlfSxvPWZ1bmN0aW9uKG4pe3JldHVybiBuLmVycm9yKHIoKSl9O3JldHVybiBuZXcgaih0P2Z1bmN0aW9uKG4pe3JldHVybiB0LnNjaGVkdWxlKG8sMCxuKX06byl9dmFyIGlyPXV0KGZ1bmN0aW9uKGUpe3JldHVybiBmdW5jdGlvbigpe2UodGhpcyksdGhpcy5uYW1lPSJFbXB0eUVycm9yIix0aGlzLm1lc3NhZ2U9Im5vIGVsZW1lbnRzIGluIHNlcXVlbmNlIn19KTtmdW5jdGlvbiBJbyhlKXtyZXR1cm4gZSBpbnN0YW5jZW9mIERhdGUmJiFpc05hTihlKX1mdW5jdGlvbiBtKGUsdCl7cmV0dXJuIEUoZnVuY3Rpb24ocixvKXt2YXIgbj0wO3Iuc3Vic2NyaWJlKFQobyxmdW5jdGlvbihpKXtvLm5leHQoZS5jYWxsKHQsaSxuKyspKX0pKX0pfXZhciBhYT1BcnJheS5pc0FycmF5O2Z1bmN0aW9uIHNhKGUsdCl7cmV0dXJuIGFhKHQpP2UuYXBwbHkodm9pZCAwLHEoW10sTih0KSkpOmUodCl9ZnVuY3Rpb24gWmUoZSl7cmV0dXJuIG0oZnVuY3Rpb24odCl7cmV0dXJuIHNhKGUsdCl9KX12YXIgY2E9QXJyYXkuaXNBcnJheSxwYT1PYmplY3QuZ2V0UHJvdG90eXBlT2YsbGE9T2JqZWN0LnByb3RvdHlwZSxtYT1PYmplY3Qua2V5cztmdW5jdGlvbiBqbyhlKXtpZihlLmxlbmd0aD09PTEpe3ZhciB0PWVbMF07aWYoY2EodCkpcmV0dXJue2FyZ3M6dCxrZXlzOm51bGx9O2lmKGZhKHQpKXt2YXIgcj1tYSh0KTtyZXR1cm57YXJnczpyLm1hcChmdW5jdGlvbihvKXtyZXR1cm4gdFtvXX0pLGtleXM6cn19fXJldHVybnthcmdzOmUsa2V5czpudWxsfX1mdW5jdGlvbiBmYShlKXtyZXR1cm4gZSYmdHlwZW9mIGU9PSJvYmplY3QiJiZwYShlKT09PWxhfWZ1bmN0aW9uIEZvKGUsdCl7cmV0dXJuIGUucmVkdWNlKGZ1bmN0aW9uKHIsbyxuKXtyZXR1cm4gcltvXT10W25dLHJ9LHt9KX1mdW5jdGlvbiB6KCl7Zm9yKHZhciBlPVtdLHQ9MDt0PGFyZ3VtZW50cy5sZW5ndGg7dCsrKWVbdF09YXJndW1lbnRzW3RdO3ZhciByPWtlKGUpLG89WGUoZSksbj1qbyhlKSxpPW4uYXJncyxhPW4ua2V5cztpZihpLmxlbmd0aD09PTApcmV0dXJuIHVlKFtdLHIpO3ZhciBzPW5ldyBqKFByKGkscixhP2Z1bmN0aW9uKHApe3JldHVybiBGbyhhLHApfTpsZSkpO3JldHVybiBvP3MucGlwZShaZShvKSk6c31mdW5jdGlvbiBQcihlLHQscil7cmV0dXJuIHI9PT12b2lkIDAmJihyPWxlKSxmdW5jdGlvbihvKXtVbyh0LGZ1bmN0aW9uKCl7Zm9yKHZhciBuPWUubGVuZ3RoLGk9bmV3IEFycmF5KG4pLGE9bixzPW4scD1mdW5jdGlvbihsKXtVbyh0LGZ1bmN0aW9uKCl7dmFyIGY9dWUoZVtsXSx0KSx1PSExO2Yuc3Vic2NyaWJlKFQobyxmdW5jdGlvbihkKXtpW2xdPWQsdXx8KHU9ITAscy0tKSxzfHxvLm5leHQocihpLnNsaWNlKCkpKX0sZnVuY3Rpb24oKXstLWF8fG8uY29tcGxldGUoKX0pKX0sbyl9LGM9MDtjPG47YysrKXAoYyl9LG8pfX1mdW5jdGlvbiBVbyhlLHQscil7ZT93ZShyLGUsdCk6dCgpfWZ1bmN0aW9uIFdvKGUsdCxyLG8sbixpLGEscyl7dmFyIHA9W10sYz0wLGw9MCxmPSExLHU9ZnVuY3Rpb24oKXtmJiYhcC5sZW5ndGgmJiFjJiZ0LmNvbXBsZXRlKCl9LGQ9ZnVuY3Rpb24oTCl7cmV0dXJuIGM8bz95KEwpOnAucHVzaChMKX0seT1mdW5jdGlvbihMKXtpJiZ0Lm5leHQoTCksYysrO3ZhciBYPSExO1UocihMLGwrKykpLnN1YnNjcmliZShUKHQsZnVuY3Rpb24odGUpe249PW51bGx8fG4odGUpLGk/ZCh0ZSk6dC5uZXh0KHRlKX0sZnVuY3Rpb24oKXtYPSEwfSx2b2lkIDAsZnVuY3Rpb24oKXtpZihYKXRyeXtjLS07Zm9yKHZhciB0ZT1mdW5jdGlvbigpe3ZhciBKPXAuc2hpZnQoKTthP3dlKHQsYSxmdW5jdGlvbigpe3JldHVybiB5KEopfSk6eShKKX07cC5sZW5ndGgmJmM8bzspdGUoKTt1KCl9Y2F0Y2goSil7dC5lcnJvcihKKX19KSl9O3JldHVybiBlLnN1YnNjcmliZShUKHQsZCxmdW5jdGlvbigpe2Y9ITAsdSgpfSkpLGZ1bmN0aW9uKCl7cz09bnVsbHx8cygpfX1mdW5jdGlvbiBuZShlLHQscil7cmV0dXJuIHI9PT12b2lkIDAmJihyPTEvMCksSCh0KT9uZShmdW5jdGlvbihvLG4pe3JldHVybiBtKGZ1bmN0aW9uKGksYSl7cmV0dXJuIHQobyxpLG4sYSl9KShVKGUobyxuKSkpfSxyKToodHlwZW9mIHQ9PSJudW1iZXIiJiYocj10KSxFKGZ1bmN0aW9uKG8sbil7cmV0dXJuIFdvKG8sbixlLHIpfSkpfWZ1bmN0aW9uIEV0KGUpe3JldHVybiBlPT09dm9pZCAwJiYoZT0xLzApLG5lKGxlLGUpfWZ1bmN0aW9uIERvKCl7cmV0dXJuIEV0KDEpfWZ1bmN0aW9uIFdlKCl7Zm9yKHZhciBlPVtdLHQ9MDt0PGFyZ3VtZW50cy5sZW5ndGg7dCsrKWVbdF09YXJndW1lbnRzW3RdO3JldHVybiBEbygpKHVlKGUsa2UoZSkpKX1mdW5jdGlvbiBDKGUpe3JldHVybiBuZXcgaihmdW5jdGlvbih0KXtVKGUoKSkuc3Vic2NyaWJlKHQpfSl9dmFyIHVhPVsiYWRkTGlzdGVuZXIiLCJyZW1vdmVMaXN0ZW5lciJdLGRhPVsiYWRkRXZlbnRMaXN0ZW5lciIsInJlbW92ZUV2ZW50TGlzdGVuZXIiXSxoYT1bIm9uIiwib2ZmIl07ZnVuY3Rpb24gaChlLHQscixvKXtpZihIKHIpJiYobz1yLHI9dm9pZCAwKSxvKXJldHVybiBoKGUsdCxyKS5waXBlKFplKG8pKTt2YXIgbj1OKGdhKGUpP2RhLm1hcChmdW5jdGlvbihzKXtyZXR1cm4gZnVuY3Rpb24ocCl7cmV0dXJuIGVbc10odCxwLHIpfX0pOmJhKGUpP3VhLm1hcChWbyhlLHQpKTp2YShlKT9oYS5tYXAoVm8oZSx0KSk6W10sMiksaT1uWzBdLGE9blsxXTtpZighaSYmeHQoZSkpcmV0dXJuIG5lKGZ1bmN0aW9uKHMpe3JldHVybiBoKHMsdCxyKX0pKFUoZSkpO2lmKCFpKXRocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgZXZlbnQgdGFyZ2V0Iik7cmV0dXJuIG5ldyBqKGZ1bmN0aW9uKHMpe3ZhciBwPWZ1bmN0aW9uKCl7Zm9yKHZhciBjPVtdLGw9MDtsPGFyZ3VtZW50cy5sZW5ndGg7bCsrKWNbbF09YXJndW1lbnRzW2xdO3JldHVybiBzLm5leHQoMTxjLmxlbmd0aD9jOmNbMF0pfTtyZXR1cm4gaShwKSxmdW5jdGlvbigpe3JldHVybiBhKHApfX0pfWZ1bmN0aW9uIFZvKGUsdCl7cmV0dXJuIGZ1bmN0aW9uKHIpe3JldHVybiBmdW5jdGlvbihvKXtyZXR1cm4gZVtyXSh0LG8pfX19ZnVuY3Rpb24gYmEoZSl7cmV0dXJuIEgoZS5hZGRMaXN0ZW5lcikmJkgoZS5yZW1vdmVMaXN0ZW5lcil9ZnVuY3Rpb24gdmEoZSl7cmV0dXJuIEgoZS5vbikmJkgoZS5vZmYpfWZ1bmN0aW9uIGdhKGUpe3JldHVybiBIKGUuYWRkRXZlbnRMaXN0ZW5lcikmJkgoZS5yZW1vdmVFdmVudExpc3RlbmVyKX1mdW5jdGlvbiBhcihlLHQscil7cmV0dXJuIHI/YXIoZSx0KS5waXBlKFplKHIpKTpuZXcgaihmdW5jdGlvbihvKXt2YXIgbj1mdW5jdGlvbigpe2Zvcih2YXIgYT1bXSxzPTA7czxhcmd1bWVudHMubGVuZ3RoO3MrKylhW3NdPWFyZ3VtZW50c1tzXTtyZXR1cm4gby5uZXh0KGEubGVuZ3RoPT09MT9hWzBdOmEpfSxpPWUobik7cmV0dXJuIEgodCk/ZnVuY3Rpb24oKXtyZXR1cm4gdChuLGkpfTp2b2lkIDB9KX1mdW5jdGlvbiBMZShlLHQscil7ZT09PXZvaWQgMCYmKGU9MCkscj09PXZvaWQgMCYmKHI9Q3IpO3ZhciBvPS0xO3JldHVybiB0IT1udWxsJiYoWXQodCk/cj10Om89dCksbmV3IGooZnVuY3Rpb24obil7dmFyIGk9SW8oZSk/K2Utci5ub3coKTplO2k8MCYmKGk9MCk7dmFyIGE9MDtyZXR1cm4gci5zY2hlZHVsZShmdW5jdGlvbigpe24uY2xvc2VkfHwobi5uZXh0KGErKyksMDw9bz90aGlzLnNjaGVkdWxlKHZvaWQgMCxvKTpuLmNvbXBsZXRlKCkpfSxpKX0pfWZ1bmN0aW9uIE8oKXtmb3IodmFyIGU9W10sdD0wO3Q8YXJndW1lbnRzLmxlbmd0aDt0KyspZVt0XT1hcmd1bWVudHNbdF07dmFyIHI9a2UoZSksbz1CdChlLDEvMCksbj1lO3JldHVybiBuLmxlbmd0aD9uLmxlbmd0aD09PTE/VShuWzBdKTpFdChvKSh1ZShuLHIpKTpTfXZhciBZZT1uZXcgaihiZSk7dmFyIHlhPUFycmF5LmlzQXJyYXk7ZnVuY3Rpb24gd3QoZSl7cmV0dXJuIGUubGVuZ3RoPT09MSYmeWEoZVswXSk/ZVswXTplfWZ1bmN0aW9uIGIoZSx0KXtyZXR1cm4gRShmdW5jdGlvbihyLG8pe3ZhciBuPTA7ci5zdWJzY3JpYmUoVChvLGZ1bmN0aW9uKGkpe3JldHVybiBlLmNhbGwodCxpLG4rKykmJm8ubmV4dChpKX0pKX0pfWZ1bmN0aW9uIHN0KCl7Zm9yKHZhciBlPVtdLHQ9MDt0PGFyZ3VtZW50cy5sZW5ndGg7dCsrKWVbdF09YXJndW1lbnRzW3RdO3ZhciByPVhlKGUpLG89d3QoZSk7cmV0dXJuIG8ubGVuZ3RoP25ldyBqKGZ1bmN0aW9uKG4pe3ZhciBpPW8ubWFwKGZ1bmN0aW9uKCl7cmV0dXJuW119KSxhPW8ubWFwKGZ1bmN0aW9uKCl7cmV0dXJuITF9KTtuLmFkZChmdW5jdGlvbigpe2k9YT1udWxsfSk7Zm9yKHZhciBzPWZ1bmN0aW9uKGMpe1Uob1tjXSkuc3Vic2NyaWJlKFQobixmdW5jdGlvbihsKXtpZihpW2NdLnB1c2gobCksaS5ldmVyeShmdW5jdGlvbih1KXtyZXR1cm4gdS5sZW5ndGh9KSl7dmFyIGY9aS5tYXAoZnVuY3Rpb24odSl7cmV0dXJuIHUuc2hpZnQoKX0pO24ubmV4dChyP3IuYXBwbHkodm9pZCAwLHEoW10sTihmKSkpOmYpLGkuc29tZShmdW5jdGlvbih1LGQpe3JldHVybiF1Lmxlbmd0aCYmYVtkXX0pJiZuLmNvbXBsZXRlKCl9fSxmdW5jdGlvbigpe2FbY109ITAsIWlbY10ubGVuZ3RoJiZuLmNvbXBsZXRlKCl9KSl9LHA9MDshbi5jbG9zZWQmJnA8by5sZW5ndGg7cCsrKXMocCk7cmV0dXJuIGZ1bmN0aW9uKCl7aT1hPW51bGx9fSk6U31mdW5jdGlvbiBObyhlKXtyZXR1cm4gRShmdW5jdGlvbih0LHIpe3ZhciBvPSExLG49bnVsbCxpPW51bGwsYT0hMSxzPWZ1bmN0aW9uKCl7aWYoaT09bnVsbHx8aS51bnN1YnNjcmliZSgpLGk9bnVsbCxvKXtvPSExO3ZhciBjPW47bj1udWxsLHIubmV4dChjKX1hJiZyLmNvbXBsZXRlKCl9LHA9ZnVuY3Rpb24oKXtpPW51bGwsYSYmci5jb21wbGV0ZSgpfTt0LnN1YnNjcmliZShUKHIsZnVuY3Rpb24oYyl7bz0hMCxuPWMsaXx8VShlKGMpKS5zdWJzY3JpYmUoaT1UKHIscyxwKSl9LGZ1bmN0aW9uKCl7YT0hMCwoIW98fCFpfHxpLmNsb3NlZCkmJnIuY29tcGxldGUoKX0pKX0pfWZ1bmN0aW9uIE1lKGUsdCl7cmV0dXJuIHQ9PT12b2lkIDAmJih0PXNlKSxObyhmdW5jdGlvbigpe3JldHVybiBMZShlLHQpfSl9ZnVuY3Rpb24gQmUoZSx0KXtyZXR1cm4gdD09PXZvaWQgMCYmKHQ9bnVsbCksdD10IT1udWxsP3Q6ZSxFKGZ1bmN0aW9uKHIsbyl7dmFyIG49W10saT0wO3Iuc3Vic2NyaWJlKFQobyxmdW5jdGlvbihhKXt2YXIgcyxwLGMsbCxmPW51bGw7aSsrJXQ9PT0wJiZuLnB1c2goW10pO3RyeXtmb3IodmFyIHU9aGUobiksZD11Lm5leHQoKTshZC5kb25lO2Q9dS5uZXh0KCkpe3ZhciB5PWQudmFsdWU7eS5wdXNoKGEpLGU8PXkubGVuZ3RoJiYoZj1mIT1udWxsP2Y6W10sZi5wdXNoKHkpKX19Y2F0Y2godGUpe3M9e2Vycm9yOnRlfX1maW5hbGx5e3RyeXtkJiYhZC5kb25lJiYocD11LnJldHVybikmJnAuY2FsbCh1KX1maW5hbGx5e2lmKHMpdGhyb3cgcy5lcnJvcn19aWYoZil0cnl7Zm9yKHZhciBMPWhlKGYpLFg9TC5uZXh0KCk7IVguZG9uZTtYPUwubmV4dCgpKXt2YXIgeT1YLnZhbHVlO1FlKG4seSksby5uZXh0KHkpfX1jYXRjaCh0ZSl7Yz17ZXJyb3I6dGV9fWZpbmFsbHl7dHJ5e1gmJiFYLmRvbmUmJihsPUwucmV0dXJuKSYmbC5jYWxsKEwpfWZpbmFsbHl7aWYoYyl0aHJvdyBjLmVycm9yfX19LGZ1bmN0aW9uKCl7dmFyIGEsczt0cnl7Zm9yKHZhciBwPWhlKG4pLGM9cC5uZXh0KCk7IWMuZG9uZTtjPXAubmV4dCgpKXt2YXIgbD1jLnZhbHVlO28ubmV4dChsKX19Y2F0Y2goZil7YT17ZXJyb3I6Zn19ZmluYWxseXt0cnl7YyYmIWMuZG9uZSYmKHM9cC5yZXR1cm4pJiZzLmNhbGwocCl9ZmluYWxseXtpZihhKXRocm93IGEuZXJyb3J9fW8uY29tcGxldGUoKX0sdm9pZCAwLGZ1bmN0aW9uKCl7bj1udWxsfSkpfSl9ZnVuY3Rpb24gZGUoZSl7cmV0dXJuIEUoZnVuY3Rpb24odCxyKXt2YXIgbz1udWxsLG49ITEsaTtvPXQuc3Vic2NyaWJlKFQocix2b2lkIDAsdm9pZCAwLGZ1bmN0aW9uKGEpe2k9VShlKGEsZGUoZSkodCkpKSxvPyhvLnVuc3Vic2NyaWJlKCksbz1udWxsLGkuc3Vic2NyaWJlKHIpKTpuPSEwfSkpLG4mJihvLnVuc3Vic2NyaWJlKCksbz1udWxsLGkuc3Vic2NyaWJlKHIpKX0pfWZ1bmN0aW9uIHpvKGUsdCxyLG8sbil7cmV0dXJuIGZ1bmN0aW9uKGksYSl7dmFyIHM9cixwPXQsYz0wO2kuc3Vic2NyaWJlKFQoYSxmdW5jdGlvbihsKXt2YXIgZj1jKys7cD1zP2UocCxsLGYpOihzPSEwLGwpLG8mJmEubmV4dChwKX0sbiYmZnVuY3Rpb24oKXtzJiZhLm5leHQocCksYS5jb21wbGV0ZSgpfSkpfX1mdW5jdGlvbiBScigpe2Zvcih2YXIgZT1bXSx0PTA7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyllW3RdPWFyZ3VtZW50c1t0XTt2YXIgcj1YZShlKTtyZXR1cm4gcj94byhSci5hcHBseSh2b2lkIDAscShbXSxOKGUpKSksWmUocikpOkUoZnVuY3Rpb24obyxuKXtQcihxKFtvXSxOKHd0KGUpKSkpKG4pfSl9ZnVuY3Rpb24gSGUoKXtmb3IodmFyIGU9W10sdD0wO3Q8YXJndW1lbnRzLmxlbmd0aDt0KyspZVt0XT1hcmd1bWVudHNbdF07cmV0dXJuIFJyLmFwcGx5KHZvaWQgMCxxKFtdLE4oZSkpKX1mdW5jdGlvbiBIdChlKXtyZXR1cm4gRShmdW5jdGlvbih0LHIpe3ZhciBvPSExLG49bnVsbCxpPW51bGwsYT1mdW5jdGlvbigpe2lmKGk9PW51bGx8fGkudW5zdWJzY3JpYmUoKSxpPW51bGwsbyl7bz0hMTt2YXIgcz1uO249bnVsbCxyLm5leHQocyl9fTt0LnN1YnNjcmliZShUKHIsZnVuY3Rpb24ocyl7aT09bnVsbHx8aS51bnN1YnNjcmliZSgpLG89ITAsbj1zLGk9VChyLGEsYmUpLFUoZShzKSkuc3Vic2NyaWJlKGkpfSxmdW5jdGlvbigpe2EoKSxyLmNvbXBsZXRlKCl9LHZvaWQgMCxmdW5jdGlvbigpe249aT1udWxsfSkpfSl9ZnVuY3Rpb24gX2UoZSx0KXtyZXR1cm4gdD09PXZvaWQgMCYmKHQ9c2UpLEUoZnVuY3Rpb24ocixvKXt2YXIgbj1udWxsLGk9bnVsbCxhPW51bGwscz1mdW5jdGlvbigpe2lmKG4pe24udW5zdWJzY3JpYmUoKSxuPW51bGw7dmFyIGM9aTtpPW51bGwsby5uZXh0KGMpfX07ZnVuY3Rpb24gcCgpe3ZhciBjPWErZSxsPXQubm93KCk7aWYobDxjKXtuPXRoaXMuc2NoZWR1bGUodm9pZCAwLGMtbCksby5hZGQobik7cmV0dXJufXMoKX1yLnN1YnNjcmliZShUKG8sZnVuY3Rpb24oYyl7aT1jLGE9dC5ub3coKSxufHwobj10LnNjaGVkdWxlKHAsZSksby5hZGQobikpfSxmdW5jdGlvbigpe3MoKSxvLmNvbXBsZXRlKCl9LHZvaWQgMCxmdW5jdGlvbigpe2k9bj1udWxsfSkpfSl9ZnVuY3Rpb24gRGUoZSl7cmV0dXJuIEUoZnVuY3Rpb24odCxyKXt2YXIgbz0hMTt0LnN1YnNjcmliZShUKHIsZnVuY3Rpb24obil7bz0hMCxyLm5leHQobil9LGZ1bmN0aW9uKCl7b3x8ci5uZXh0KGUpLHIuY29tcGxldGUoKX0pKX0pfWZ1bmN0aW9uIFRlKGUpe3JldHVybiBlPD0wP2Z1bmN0aW9uKCl7cmV0dXJuIFN9OkUoZnVuY3Rpb24odCxyKXt2YXIgbz0wO3Quc3Vic2NyaWJlKFQocixmdW5jdGlvbihuKXsrK288PWUmJihyLm5leHQobiksZTw9byYmci5jb21wbGV0ZSgpKX0pKX0pfWZ1bmN0aW9uIFooKXtyZXR1cm4gRShmdW5jdGlvbihlLHQpe2Uuc3Vic2NyaWJlKFQodCxiZSkpfSl9ZnVuY3Rpb24gcW8oZSl7cmV0dXJuIG0oZnVuY3Rpb24oKXtyZXR1cm4gZX0pfWZ1bmN0aW9uIElyKGUsdCl7cmV0dXJuIHQ/ZnVuY3Rpb24ocil7cmV0dXJuIFdlKHQucGlwZShUZSgxKSxaKCkpLHIucGlwZShJcihlKSkpfTpuZShmdW5jdGlvbihyLG8pe3JldHVybiBVKGUocixvKSkucGlwZShUZSgxKSxxbyhyKSl9KX1mdW5jdGlvbiBHZShlLHQpe3Q9PT12b2lkIDAmJih0PXNlKTt2YXIgcj1MZShlLHQpO3JldHVybiBJcihmdW5jdGlvbigpe3JldHVybiByfSl9ZnVuY3Rpb24gSyhlLHQpe3JldHVybiB0PT09dm9pZCAwJiYodD1sZSksZT1lIT1udWxsP2U6eGEsRShmdW5jdGlvbihyLG8pe3ZhciBuLGk9ITA7ci5zdWJzY3JpYmUoVChvLGZ1bmN0aW9uKGEpe3ZhciBzPXQoYSk7KGl8fCFlKG4scykpJiYoaT0hMSxuPXMsby5uZXh0KGEpKX0pKX0pfWZ1bmN0aW9uIHhhKGUsdCl7cmV0dXJuIGU9PT10fWZ1bmN0aW9uIGVlKGUsdCl7cmV0dXJuIEsoZnVuY3Rpb24ocixvKXtyZXR1cm4gdD90KHJbZV0sb1tlXSk6cltlXT09PW9bZV19KX1mdW5jdGlvbiBRbyhlKXtyZXR1cm4gZT09PXZvaWQgMCYmKGU9RWEpLEUoZnVuY3Rpb24odCxyKXt2YXIgbz0hMTt0LnN1YnNjcmliZShUKHIsZnVuY3Rpb24obil7bz0hMCxyLm5leHQobil9LGZ1bmN0aW9uKCl7cmV0dXJuIG8/ci5jb21wbGV0ZSgpOnIuZXJyb3IoZSgpKX0pKX0pfWZ1bmN0aW9uIEVhKCl7cmV0dXJuIG5ldyBpcn1mdW5jdGlvbiBpZSgpe2Zvcih2YXIgZT1bXSx0PTA7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyllW3RdPWFyZ3VtZW50c1t0XTtyZXR1cm4gZnVuY3Rpb24ocil7cmV0dXJuIFdlKHIsSS5hcHBseSh2b2lkIDAscShbXSxOKGUpKSkpfX1mdW5jdGlvbiBfKGUpe3JldHVybiBFKGZ1bmN0aW9uKHQscil7dHJ5e3Quc3Vic2NyaWJlKHIpfWZpbmFsbHl7ci5hZGQoZSl9fSl9ZnVuY3Rpb24gQWUoZSx0KXt2YXIgcj1hcmd1bWVudHMubGVuZ3RoPj0yO3JldHVybiBmdW5jdGlvbihvKXtyZXR1cm4gby5waXBlKGU/YihmdW5jdGlvbihuLGkpe3JldHVybiBlKG4saSxvKX0pOmxlLFRlKDEpLHI/RGUodCk6UW8oZnVuY3Rpb24oKXtyZXR1cm4gbmV3IGlyfSkpfX1mdW5jdGlvbiBqcihlKXtyZXR1cm4gZTw9MD9mdW5jdGlvbigpe3JldHVybiBTfTpFKGZ1bmN0aW9uKHQscil7dmFyIG89W107dC5zdWJzY3JpYmUoVChyLGZ1bmN0aW9uKG4pe28ucHVzaChuKSxlPG8ubGVuZ3RoJiZvLnNoaWZ0KCl9LGZ1bmN0aW9uKCl7dmFyIG4saTt0cnl7Zm9yKHZhciBhPWhlKG8pLHM9YS5uZXh0KCk7IXMuZG9uZTtzPWEubmV4dCgpKXt2YXIgcD1zLnZhbHVlO3IubmV4dChwKX19Y2F0Y2goYyl7bj17ZXJyb3I6Y319ZmluYWxseXt0cnl7cyYmIXMuZG9uZSYmKGk9YS5yZXR1cm4pJiZpLmNhbGwoYSl9ZmluYWxseXtpZihuKXRocm93IG4uZXJyb3J9fXIuY29tcGxldGUoKX0sdm9pZCAwLGZ1bmN0aW9uKCl7bz1udWxsfSkpfSl9ZnVuY3Rpb24gS28oKXtmb3IodmFyIGU9W10sdD0wO3Q8YXJndW1lbnRzLmxlbmd0aDt0KyspZVt0XT1hcmd1bWVudHNbdF07dmFyIHI9a2UoZSksbz1CdChlLDEvMCk7cmV0dXJuIGU9d3QoZSksRShmdW5jdGlvbihuLGkpe0V0KG8pKHVlKHEoW25dLE4oZSkpLHIpKS5zdWJzY3JpYmUoaSl9KX1mdW5jdGlvbiBSZSgpe2Zvcih2YXIgZT1bXSx0PTA7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyllW3RdPWFyZ3VtZW50c1t0XTtyZXR1cm4gS28uYXBwbHkodm9pZCAwLHEoW10sTihlKSkpfWZ1bmN0aW9uIGN0KGUpe3ZhciB0LHI9MS8wLG87cmV0dXJuIGUhPW51bGwmJih0eXBlb2YgZT09Im9iamVjdCI/KHQ9ZS5jb3VudCxyPXQ9PT12b2lkIDA/MS8wOnQsbz1lLmRlbGF5KTpyPWUpLHI8PTA/ZnVuY3Rpb24oKXtyZXR1cm4gU306RShmdW5jdGlvbihuLGkpe3ZhciBhPTAscyxwPWZ1bmN0aW9uKCl7aWYocz09bnVsbHx8cy51bnN1YnNjcmliZSgpLHM9bnVsbCxvIT1udWxsKXt2YXIgbD10eXBlb2Ygbz09Im51bWJlciI/TGUobyk6VShvKGEpKSxmPVQoaSxmdW5jdGlvbigpe2YudW5zdWJzY3JpYmUoKSxjKCl9KTtsLnN1YnNjcmliZShmKX1lbHNlIGMoKX0sYz1mdW5jdGlvbigpe3ZhciBsPSExO3M9bi5zdWJzY3JpYmUoVChpLHZvaWQgMCxmdW5jdGlvbigpeysrYTxyP3M/cCgpOmw9ITA6aS5jb21wbGV0ZSgpfSkpLGwmJnAoKX07YygpfSl9ZnVuY3Rpb24gRnIoZSx0KXtyZXR1cm4gRSh6byhlLHQsYXJndW1lbnRzLmxlbmd0aD49MiwhMCkpfWZ1bmN0aW9uIHBlKGUpe2U9PT12b2lkIDAmJihlPXt9KTt2YXIgdD1lLmNvbm5lY3RvcixyPXQ9PT12b2lkIDA/ZnVuY3Rpb24oKXtyZXR1cm4gbmV3IGd9OnQsbz1lLnJlc2V0T25FcnJvcixuPW89PT12b2lkIDA/ITA6byxpPWUucmVzZXRPbkNvbXBsZXRlLGE9aT09PXZvaWQgMD8hMDppLHM9ZS5yZXNldE9uUmVmQ291bnRaZXJvLHA9cz09PXZvaWQgMD8hMDpzO3JldHVybiBmdW5jdGlvbihjKXt2YXIgbCxmLHUsZD0wLHk9ITEsTD0hMSxYPWZ1bmN0aW9uKCl7Zj09bnVsbHx8Zi51bnN1YnNjcmliZSgpLGY9dm9pZCAwfSx0ZT1mdW5jdGlvbigpe1goKSxsPXU9dm9pZCAwLHk9TD0hMX0sSj1mdW5jdGlvbigpe3ZhciBrPWw7dGUoKSxrPT1udWxsfHxrLnVuc3Vic2NyaWJlKCl9O3JldHVybiBFKGZ1bmN0aW9uKGssZnQpe2QrKywhTCYmIXkmJlgoKTt2YXIgcWU9dT11IT1udWxsP3U6cigpO2Z0LmFkZChmdW5jdGlvbigpe2QtLSxkPT09MCYmIUwmJiF5JiYoZj1VcihKLHApKX0pLHFlLnN1YnNjcmliZShmdCksIWwmJmQ+MCYmKGw9bmV3IGF0KHtuZXh0OmZ1bmN0aW9uKEZlKXtyZXR1cm4gcWUubmV4dChGZSl9LGVycm9yOmZ1bmN0aW9uKEZlKXtMPSEwLFgoKSxmPVVyKHRlLG4sRmUpLHFlLmVycm9yKEZlKX0sY29tcGxldGU6ZnVuY3Rpb24oKXt5PSEwLFgoKSxmPVVyKHRlLGEpLHFlLmNvbXBsZXRlKCl9fSksVShrKS5zdWJzY3JpYmUobCkpfSkoYyl9fWZ1bmN0aW9uIFVyKGUsdCl7Zm9yKHZhciByPVtdLG89MjtvPGFyZ3VtZW50cy5sZW5ndGg7bysrKXJbby0yXT1hcmd1bWVudHNbb107aWYodD09PSEwKXtlKCk7cmV0dXJufWlmKHQhPT0hMSl7dmFyIG49bmV3IGF0KHtuZXh0OmZ1bmN0aW9uKCl7bi51bnN1YnNjcmliZSgpLGUoKX19KTtyZXR1cm4gVSh0LmFwcGx5KHZvaWQgMCxxKFtdLE4ocikpKSkuc3Vic2NyaWJlKG4pfX1mdW5jdGlvbiBHKGUsdCxyKXt2YXIgbyxuLGksYSxzPSExO3JldHVybiBlJiZ0eXBlb2YgZT09Im9iamVjdCI/KG89ZS5idWZmZXJTaXplLGE9bz09PXZvaWQgMD8xLzA6byxuPWUud2luZG93VGltZSx0PW49PT12b2lkIDA/MS8wOm4saT1lLnJlZkNvdW50LHM9aT09PXZvaWQgMD8hMTppLHI9ZS5zY2hlZHVsZXIpOmE9ZSE9bnVsbD9lOjEvMCxwZSh7Y29ubmVjdG9yOmZ1bmN0aW9uKCl7cmV0dXJuIG5ldyBDdChhLHQscil9LHJlc2V0T25FcnJvcjohMCxyZXNldE9uQ29tcGxldGU6ITEscmVzZXRPblJlZkNvdW50WmVybzpzfSl9ZnVuY3Rpb24gQ2UoZSl7cmV0dXJuIGIoZnVuY3Rpb24odCxyKXtyZXR1cm4gZTw9cn0pfWZ1bmN0aW9uIFdyKGUpe3JldHVybiBFKGZ1bmN0aW9uKHQscil7dmFyIG89ITEsbj1UKHIsZnVuY3Rpb24oKXtuPT1udWxsfHxuLnVuc3Vic2NyaWJlKCksbz0hMH0sYmUpO1UoZSkuc3Vic2NyaWJlKG4pLHQuc3Vic2NyaWJlKFQocixmdW5jdGlvbihpKXtyZXR1cm4gbyYmci5uZXh0KGkpfSkpfSl9ZnVuY3Rpb24gUSgpe2Zvcih2YXIgZT1bXSx0PTA7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyllW3RdPWFyZ3VtZW50c1t0XTt2YXIgcj1rZShlKTtyZXR1cm4gRShmdW5jdGlvbihvLG4peyhyP1dlKGUsbyxyKTpXZShlLG8pKS5zdWJzY3JpYmUobil9KX1mdW5jdGlvbiB2KGUsdCl7cmV0dXJuIEUoZnVuY3Rpb24ocixvKXt2YXIgbj1udWxsLGk9MCxhPSExLHM9ZnVuY3Rpb24oKXtyZXR1cm4gYSYmIW4mJm8uY29tcGxldGUoKX07ci5zdWJzY3JpYmUoVChvLGZ1bmN0aW9uKHApe249PW51bGx8fG4udW5zdWJzY3JpYmUoKTt2YXIgYz0wLGw9aSsrO1UoZShwLGwpKS5zdWJzY3JpYmUobj1UKG8sZnVuY3Rpb24oZil7cmV0dXJuIG8ubmV4dCh0P3QocCxmLGwsYysrKTpmKX0sZnVuY3Rpb24oKXtuPW51bGwscygpfSkpfSxmdW5jdGlvbigpe2E9ITAscygpfSkpfSl9ZnVuY3Rpb24gVyhlKXtyZXR1cm4gRShmdW5jdGlvbih0LHIpe1UoZSkuc3Vic2NyaWJlKFQocixmdW5jdGlvbigpe3JldHVybiByLmNvbXBsZXRlKCl9LGJlKSksIXIuY2xvc2VkJiZ0LnN1YnNjcmliZShyKX0pfWZ1bmN0aW9uIERyKGUsdCl7cmV0dXJuIHQ9PT12b2lkIDAmJih0PSExKSxFKGZ1bmN0aW9uKHIsbyl7dmFyIG49MDtyLnN1YnNjcmliZShUKG8sZnVuY3Rpb24oaSl7dmFyIGE9ZShpLG4rKyk7KGF8fHQpJiZvLm5leHQoaSksIWEmJm8uY29tcGxldGUoKX0pKX0pfWZ1bmN0aW9uIHcoZSx0LHIpe3ZhciBvPUgoZSl8fHR8fHI/e25leHQ6ZSxlcnJvcjp0LGNvbXBsZXRlOnJ9OmU7cmV0dXJuIG8/RShmdW5jdGlvbihuLGkpe3ZhciBhOyhhPW8uc3Vic2NyaWJlKT09PW51bGx8fGE9PT12b2lkIDB8fGEuY2FsbChvKTt2YXIgcz0hMDtuLnN1YnNjcmliZShUKGksZnVuY3Rpb24ocCl7dmFyIGM7KGM9by5uZXh0KT09PW51bGx8fGM9PT12b2lkIDB8fGMuY2FsbChvLHApLGkubmV4dChwKX0sZnVuY3Rpb24oKXt2YXIgcDtzPSExLChwPW8uY29tcGxldGUpPT09bnVsbHx8cD09PXZvaWQgMHx8cC5jYWxsKG8pLGkuY29tcGxldGUoKX0sZnVuY3Rpb24ocCl7dmFyIGM7cz0hMSwoYz1vLmVycm9yKT09PW51bGx8fGM9PT12b2lkIDB8fGMuY2FsbChvLHApLGkuZXJyb3IocCl9LGZ1bmN0aW9uKCl7dmFyIHAsYztzJiYoKHA9by51bnN1YnNjcmliZSk9PT1udWxsfHxwPT09dm9pZCAwfHxwLmNhbGwobykpLChjPW8uZmluYWxpemUpPT09bnVsbHx8Yz09PXZvaWQgMHx8Yy5jYWxsKG8pfSkpfSk6bGV9ZnVuY3Rpb24gWW8oZSx0KXtyZXR1cm4gRShmdW5jdGlvbihyLG8pe3ZhciBuPXQhPW51bGw/dDp7fSxpPW4ubGVhZGluZyxhPWk9PT12b2lkIDA/ITA6aSxzPW4udHJhaWxpbmcscD1zPT09dm9pZCAwPyExOnMsYz0hMSxsPW51bGwsZj1udWxsLHU9ITEsZD1mdW5jdGlvbigpe2Y9PW51bGx8fGYudW5zdWJzY3JpYmUoKSxmPW51bGwscCYmKFgoKSx1JiZvLmNvbXBsZXRlKCkpfSx5PWZ1bmN0aW9uKCl7Zj1udWxsLHUmJm8uY29tcGxldGUoKX0sTD1mdW5jdGlvbih0ZSl7cmV0dXJuIGY9VShlKHRlKSkuc3Vic2NyaWJlKFQobyxkLHkpKX0sWD1mdW5jdGlvbigpe2lmKGMpe2M9ITE7dmFyIHRlPWw7bD1udWxsLG8ubmV4dCh0ZSksIXUmJkwodGUpfX07ci5zdWJzY3JpYmUoVChvLGZ1bmN0aW9uKHRlKXtjPSEwLGw9dGUsIShmJiYhZi5jbG9zZWQpJiYoYT9YKCk6TCh0ZSkpfSxmdW5jdGlvbigpe3U9ITAsIShwJiZjJiZmJiYhZi5jbG9zZWQpJiZvLmNvbXBsZXRlKCl9KSl9KX1mdW5jdGlvbiBwdChlLHQscil7dD09PXZvaWQgMCYmKHQ9c2UpO3ZhciBvPUxlKGUsdCk7cmV0dXJuIFlvKGZ1bmN0aW9uKCl7cmV0dXJuIG99LHIpfWZ1bmN0aW9uIHJlKCl7Zm9yKHZhciBlPVtdLHQ9MDt0PGFyZ3VtZW50cy5sZW5ndGg7dCsrKWVbdF09YXJndW1lbnRzW3RdO3ZhciByPVhlKGUpO3JldHVybiBFKGZ1bmN0aW9uKG8sbil7Zm9yKHZhciBpPWUubGVuZ3RoLGE9bmV3IEFycmF5KGkpLHM9ZS5tYXAoZnVuY3Rpb24oKXtyZXR1cm4hMX0pLHA9ITEsYz1mdW5jdGlvbihmKXtVKGVbZl0pLnN1YnNjcmliZShUKG4sZnVuY3Rpb24odSl7YVtmXT11LCFwJiYhc1tmXSYmKHNbZl09ITAsKHA9cy5ldmVyeShsZSkpJiYocz1udWxsKSl9LGJlKSl9LGw9MDtsPGk7bCsrKWMobCk7by5zdWJzY3JpYmUoVChuLGZ1bmN0aW9uKGYpe2lmKHApe3ZhciB1PXEoW2ZdLE4oYSkpO24ubmV4dChyP3IuYXBwbHkodm9pZCAwLHEoW10sTih1KSkpOnUpfX0pKX0pfWZ1bmN0aW9uIEJvKCl7Zm9yKHZhciBlPVtdLHQ9MDt0PGFyZ3VtZW50cy5sZW5ndGg7dCsrKWVbdF09YXJndW1lbnRzW3RdO3JldHVybiBFKGZ1bmN0aW9uKHIsbyl7c3QuYXBwbHkodm9pZCAwLHEoW3JdLE4oZSkpKS5zdWJzY3JpYmUobyl9KX1mdW5jdGlvbiBWcigpe2Zvcih2YXIgZT1bXSx0PTA7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyllW3RdPWFyZ3VtZW50c1t0XTtyZXR1cm4gQm8uYXBwbHkodm9pZCAwLHEoW10sTihlKSkpfWZ1bmN0aW9uIEdvKCl7bGV0IGU9bmV3IEN0KDEpO3JldHVybiBoKGRvY3VtZW50LCJET01Db250ZW50TG9hZGVkIix7b25jZTohMH0pLnN1YnNjcmliZSgoKT0+ZS5uZXh0KGRvY3VtZW50KSksZX1mdW5jdGlvbiBQKGUsdD1kb2N1bWVudCl7cmV0dXJuIEFycmF5LmZyb20odC5xdWVyeVNlbGVjdG9yQWxsKGUpKX1mdW5jdGlvbiBSKGUsdD1kb2N1bWVudCl7bGV0IHI9ZmUoZSx0KTtpZih0eXBlb2Ygcj09InVuZGVmaW5lZCIpdGhyb3cgbmV3IFJlZmVyZW5jZUVycm9yKGBNaXNzaW5nIGVsZW1lbnQ6IGV4cGVjdGVkICIke2V9IiB0byBiZSBwcmVzZW50YCk7cmV0dXJuIHJ9ZnVuY3Rpb24gZmUoZSx0PWRvY3VtZW50KXtyZXR1cm4gdC5xdWVyeVNlbGVjdG9yKGUpfHx2b2lkIDB9ZnVuY3Rpb24gSWUoKXt2YXIgZSx0LHIsbztyZXR1cm4obz0ocj0odD0oZT1kb2N1bWVudC5hY3RpdmVFbGVtZW50KT09bnVsbD92b2lkIDA6ZS5zaGFkb3dSb290KT09bnVsbD92b2lkIDA6dC5hY3RpdmVFbGVtZW50KSE9bnVsbD9yOmRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpIT1udWxsP286dm9pZCAwfXZhciB3YT1PKGgoZG9jdW1lbnQuYm9keSwiZm9jdXNpbiIpLGgoZG9jdW1lbnQuYm9keSwiZm9jdXNvdXQiKSkucGlwZShfZSgxKSxRKHZvaWQgMCksbSgoKT0+SWUoKXx8ZG9jdW1lbnQuYm9keSksRygxKSk7ZnVuY3Rpb24gZXQoZSl7cmV0dXJuIHdhLnBpcGUobSh0PT5lLmNvbnRhaW5zKHQpKSxLKCkpfWZ1bmN0aW9uICR0KGUsdCl7cmV0dXJuIEMoKCk9Pk8oaChlLCJtb3VzZWVudGVyIikucGlwZShtKCgpPT4hMCkpLGgoZSwibW91c2VsZWF2ZSIpLnBpcGUobSgoKT0+ITEpKSkucGlwZSh0P0h0KHI9PkxlKCshcip0KSk6bGUsUShlLm1hdGNoZXMoIjpob3ZlciIpKSkpfWZ1bmN0aW9uIEpvKGUsdCl7aWYodHlwZW9mIHQ9PSJzdHJpbmcifHx0eXBlb2YgdD09Im51bWJlciIpZS5pbm5lckhUTUwrPXQudG9TdHJpbmcoKTtlbHNlIGlmKHQgaW5zdGFuY2VvZiBOb2RlKWUuYXBwZW5kQ2hpbGQodCk7ZWxzZSBpZihBcnJheS5pc0FycmF5KHQpKWZvcihsZXQgciBvZiB0KUpvKGUscil9ZnVuY3Rpb24geChlLHQsLi4ucil7bGV0IG89ZG9jdW1lbnQuY3JlYXRlRWxlbWVudChlKTtpZih0KWZvcihsZXQgbiBvZiBPYmplY3Qua2V5cyh0KSl0eXBlb2YgdFtuXSE9InVuZGVmaW5lZCImJih0eXBlb2YgdFtuXSE9ImJvb2xlYW4iP28uc2V0QXR0cmlidXRlKG4sdFtuXSk6by5zZXRBdHRyaWJ1dGUobiwiIikpO2ZvcihsZXQgbiBvZiByKUpvKG8sbik7cmV0dXJuIG99ZnVuY3Rpb24gc3IoZSl7aWYoZT45OTkpe2xldCB0PSsoKGUtOTUwKSUxZTM+OTkpO3JldHVybmAkeygoZSsxZS02KS8xZTMpLnRvRml4ZWQodCl9a2B9ZWxzZSByZXR1cm4gZS50b1N0cmluZygpfWZ1bmN0aW9uIFR0KGUpe2xldCB0PXgoInNjcmlwdCIse3NyYzplfSk7cmV0dXJuIEMoKCk9Pihkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHQpLE8oaCh0LCJsb2FkIiksaCh0LCJlcnJvciIpLnBpcGUodigoKT0+JHIoKCk9Pm5ldyBSZWZlcmVuY2VFcnJvcihgSW52YWxpZCBzY3JpcHQ6ICR7ZX1gKSkpKSkucGlwZShtKCgpPT57fSksXygoKT0+ZG9jdW1lbnQuaGVhZC5yZW1vdmVDaGlsZCh0KSksVGUoMSkpKSl9dmFyIFhvPW5ldyBnLFRhPUMoKCk9PnR5cGVvZiBSZXNpemVPYnNlcnZlcj09InVuZGVmaW5lZCI/VHQoImh0dHBzOi8vdW5wa2cuY29tL3Jlc2l6ZS1vYnNlcnZlci1wb2x5ZmlsbCIpOkkodm9pZCAwKSkucGlwZShtKCgpPT5uZXcgUmVzaXplT2JzZXJ2ZXIoZT0+ZS5mb3JFYWNoKHQ9PlhvLm5leHQodCkpKSksdihlPT5PKFllLEkoZSkpLnBpcGUoXygoKT0+ZS5kaXNjb25uZWN0KCkpKSksRygxKSk7ZnVuY3Rpb24gY2UoZSl7cmV0dXJue3dpZHRoOmUub2Zmc2V0V2lkdGgsaGVpZ2h0OmUub2Zmc2V0SGVpZ2h0fX1mdW5jdGlvbiBnZShlKXtsZXQgdD1lO2Zvcig7dC5jbGllbnRXaWR0aD09PTAmJnQucGFyZW50RWxlbWVudDspdD10LnBhcmVudEVsZW1lbnQ7cmV0dXJuIFRhLnBpcGUodyhyPT5yLm9ic2VydmUodCkpLHYocj0+WG8ucGlwZShiKG89Pm8udGFyZ2V0PT09dCksXygoKT0+ci51bm9ic2VydmUodCkpKSksbSgoKT0+Y2UoZSkpLFEoY2UoZSkpKX1mdW5jdGlvbiBTdChlKXtyZXR1cm57d2lkdGg6ZS5zY3JvbGxXaWR0aCxoZWlnaHQ6ZS5zY3JvbGxIZWlnaHR9fWZ1bmN0aW9uIGNyKGUpe2xldCB0PWUucGFyZW50RWxlbWVudDtmb3IoO3QmJihlLnNjcm9sbFdpZHRoPD10LnNjcm9sbFdpZHRoJiZlLnNjcm9sbEhlaWdodDw9dC5zY3JvbGxIZWlnaHQpOyl0PShlPXQpLnBhcmVudEVsZW1lbnQ7cmV0dXJuIHQ/ZTp2b2lkIDB9ZnVuY3Rpb24gWm8oZSl7bGV0IHQ9W10scj1lLnBhcmVudEVsZW1lbnQ7Zm9yKDtyOykoZS5jbGllbnRXaWR0aD5yLmNsaWVudFdpZHRofHxlLmNsaWVudEhlaWdodD5yLmNsaWVudEhlaWdodCkmJnQucHVzaChyKSxyPShlPXIpLnBhcmVudEVsZW1lbnQ7cmV0dXJuIHQubGVuZ3RoPT09MCYmdC5wdXNoKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCksdH1mdW5jdGlvbiBWZShlKXtyZXR1cm57eDplLm9mZnNldExlZnQseTplLm9mZnNldFRvcH19ZnVuY3Rpb24gZW4oZSl7bGV0IHQ9ZS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtyZXR1cm57eDp0Lngrd2luZG93LnNjcm9sbFgseTp0Lnkrd2luZG93LnNjcm9sbFl9fWZ1bmN0aW9uIHRuKGUpe3JldHVybiBPKGgod2luZG93LCJsb2FkIiksaCh3aW5kb3csInJlc2l6ZSIpKS5waXBlKE1lKDAsbWUpLG0oKCk9PlZlKGUpKSxRKFZlKGUpKSl9ZnVuY3Rpb24gcHIoZSl7cmV0dXJue3g6ZS5zY3JvbGxMZWZ0LHk6ZS5zY3JvbGxUb3B9fWZ1bmN0aW9uIE5lKGUpe3JldHVybiBPKGgoZSwic2Nyb2xsIiksaCh3aW5kb3csInNjcm9sbCIpLGgod2luZG93LCJyZXNpemUiKSkucGlwZShNZSgwLG1lKSxtKCgpPT5wcihlKSksUShwcihlKSkpfXZhciBybj1uZXcgZyxTYT1DKCgpPT5JKG5ldyBJbnRlcnNlY3Rpb25PYnNlcnZlcihlPT57Zm9yKGxldCB0IG9mIGUpcm4ubmV4dCh0KX0se3RocmVzaG9sZDowfSkpKS5waXBlKHYoZT0+TyhZZSxJKGUpKS5waXBlKF8oKCk9PmUuZGlzY29ubmVjdCgpKSkpLEcoMSkpO2Z1bmN0aW9uIHR0KGUpe3JldHVybiBTYS5waXBlKHcodD0+dC5vYnNlcnZlKGUpKSx2KHQ9PnJuLnBpcGUoYigoe3RhcmdldDpyfSk9PnI9PT1lKSxfKCgpPT50LnVub2JzZXJ2ZShlKSksbSgoe2lzSW50ZXJzZWN0aW5nOnJ9KT0+cikpKSl9ZnVuY3Rpb24gb24oZSx0PTE2KXtyZXR1cm4gTmUoZSkucGlwZShtKCh7eTpyfSk9PntsZXQgbz1jZShlKSxuPVN0KGUpO3JldHVybiByPj1uLmhlaWdodC1vLmhlaWdodC10fSksSygpKX12YXIgbHI9e2RyYXdlcjpSKCJbZGF0YS1tZC10b2dnbGU9ZHJhd2VyXSIpLHNlYXJjaDpSKCJbZGF0YS1tZC10b2dnbGU9c2VhcmNoXSIpfTtmdW5jdGlvbiBubihlKXtyZXR1cm4gbHJbZV0uY2hlY2tlZH1mdW5jdGlvbiBKZShlLHQpe2xyW2VdLmNoZWNrZWQhPT10JiZscltlXS5jbGljaygpfWZ1bmN0aW9uIHplKGUpe2xldCB0PWxyW2VdO3JldHVybiBoKHQsImNoYW5nZSIpLnBpcGUobSgoKT0+dC5jaGVja2VkKSxRKHQuY2hlY2tlZCkpfWZ1bmN0aW9uIE9hKGUsdCl7c3dpdGNoKGUuY29uc3RydWN0b3Ipe2Nhc2UgSFRNTElucHV0RWxlbWVudDpyZXR1cm4gZS50eXBlPT09InJhZGlvIj8vXkFycm93Ly50ZXN0KHQpOiEwO2Nhc2UgSFRNTFNlbGVjdEVsZW1lbnQ6Y2FzZSBIVE1MVGV4dEFyZWFFbGVtZW50OnJldHVybiEwO2RlZmF1bHQ6cmV0dXJuIGUuaXNDb250ZW50RWRpdGFibGV9fWZ1bmN0aW9uIExhKCl7cmV0dXJuIE8oaCh3aW5kb3csImNvbXBvc2l0aW9uc3RhcnQiKS5waXBlKG0oKCk9PiEwKSksaCh3aW5kb3csImNvbXBvc2l0aW9uZW5kIikucGlwZShtKCgpPT4hMSkpKS5waXBlKFEoITEpKX1mdW5jdGlvbiBhbigpe2xldCBlPWgod2luZG93LCJrZXlkb3duIikucGlwZShiKHQ9PiEodC5tZXRhS2V5fHx0LmN0cmxLZXkpKSxtKHQ9Pih7bW9kZTpubigic2VhcmNoIik/InNlYXJjaCI6Imdsb2JhbCIsdHlwZTp0LmtleSxjbGFpbSgpe3QucHJldmVudERlZmF1bHQoKSx0LnN0b3BQcm9wYWdhdGlvbigpfX0pKSxiKCh7bW9kZTp0LHR5cGU6cn0pPT57aWYodD09PSJnbG9iYWwiKXtsZXQgbz1JZSgpO2lmKHR5cGVvZiBvIT0idW5kZWZpbmVkIilyZXR1cm4hT2EobyxyKX1yZXR1cm4hMH0pLHBlKCkpO3JldHVybiBMYSgpLnBpcGUodih0PT50P1M6ZSkpfWZ1bmN0aW9uIHllKCl7cmV0dXJuIG5ldyBVUkwobG9jYXRpb24uaHJlZil9ZnVuY3Rpb24gbHQoZSx0PSExKXtpZihCKCJuYXZpZ2F0aW9uLmluc3RhbnQiKSYmIXQpe2xldCByPXgoImEiLHtocmVmOmUuaHJlZn0pO2RvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQociksci5jbGljaygpLHIucmVtb3ZlKCl9ZWxzZSBsb2NhdGlvbi5ocmVmPWUuaHJlZn1mdW5jdGlvbiBzbigpe3JldHVybiBuZXcgZ31mdW5jdGlvbiBjbigpe3JldHVybiBsb2NhdGlvbi5oYXNoLnNsaWNlKDEpfWZ1bmN0aW9uIHBuKGUpe2xldCB0PXgoImEiLHtocmVmOmV9KTt0LmFkZEV2ZW50TGlzdGVuZXIoImNsaWNrIixyPT5yLnN0b3BQcm9wYWdhdGlvbigpKSx0LmNsaWNrKCl9ZnVuY3Rpb24gTWEoZSl7cmV0dXJuIE8oaCh3aW5kb3csImhhc2hjaGFuZ2UiKSxlKS5waXBlKG0oY24pLFEoY24oKSksYih0PT50Lmxlbmd0aD4wKSxHKDEpKX1mdW5jdGlvbiBsbihlKXtyZXR1cm4gTWEoZSkucGlwZShtKHQ9PmZlKGBbaWQ9IiR7dH0iXWApKSxiKHQ9PnR5cGVvZiB0IT0idW5kZWZpbmVkIikpfWZ1bmN0aW9uIFB0KGUpe2xldCB0PW1hdGNoTWVkaWEoZSk7cmV0dXJuIGFyKHI9PnQuYWRkTGlzdGVuZXIoKCk9PnIodC5tYXRjaGVzKSkpLnBpcGUoUSh0Lm1hdGNoZXMpKX1mdW5jdGlvbiBtbigpe2xldCBlPW1hdGNoTWVkaWEoInByaW50Iik7cmV0dXJuIE8oaCh3aW5kb3csImJlZm9yZXByaW50IikucGlwZShtKCgpPT4hMCkpLGgod2luZG93LCJhZnRlcnByaW50IikucGlwZShtKCgpPT4hMSkpKS5waXBlKFEoZS5tYXRjaGVzKSl9ZnVuY3Rpb24gTnIoZSx0KXtyZXR1cm4gZS5waXBlKHYocj0+cj90KCk6UykpfWZ1bmN0aW9uIHpyKGUsdCl7cmV0dXJuIG5ldyBqKHI9PntsZXQgbz1uZXcgWE1MSHR0cFJlcXVlc3Q7cmV0dXJuIG8ub3BlbigiR0VUIixgJHtlfWApLG8ucmVzcG9uc2VUeXBlPSJibG9iIixvLmFkZEV2ZW50TGlzdGVuZXIoImxvYWQiLCgpPT57by5zdGF0dXM+PTIwMCYmby5zdGF0dXM8MzAwPyhyLm5leHQoby5yZXNwb25zZSksci5jb21wbGV0ZSgpKTpyLmVycm9yKG5ldyBFcnJvcihvLnN0YXR1c1RleHQpKX0pLG8uYWRkRXZlbnRMaXN0ZW5lcigiZXJyb3IiLCgpPT57ci5lcnJvcihuZXcgRXJyb3IoIk5ldHdvcmsgZXJyb3IiKSl9KSxvLmFkZEV2ZW50TGlzdGVuZXIoImFib3J0IiwoKT0+e3IuY29tcGxldGUoKX0pLHR5cGVvZih0PT1udWxsP3ZvaWQgMDp0LnByb2dyZXNzJCkhPSJ1bmRlZmluZWQiJiYoby5hZGRFdmVudExpc3RlbmVyKCJwcm9ncmVzcyIsbj0+e3ZhciBpO2lmKG4ubGVuZ3RoQ29tcHV0YWJsZSl0LnByb2dyZXNzJC5uZXh0KG4ubG9hZGVkL24udG90YWwqMTAwKTtlbHNle2xldCBhPShpPW8uZ2V0UmVzcG9uc2VIZWFkZXIoIkNvbnRlbnQtTGVuZ3RoIikpIT1udWxsP2k6MDt0LnByb2dyZXNzJC5uZXh0KG4ubG9hZGVkLythKjEwMCl9fSksdC5wcm9ncmVzcyQubmV4dCg1KSksby5zZW5kKCksKCk9Pm8uYWJvcnQoKX0pfWZ1bmN0aW9uIGplKGUsdCl7cmV0dXJuIHpyKGUsdCkucGlwZSh2KHI9PnIudGV4dCgpKSxtKHI9PkpTT04ucGFyc2UocikpLEcoMSkpfWZ1bmN0aW9uIGZuKGUsdCl7bGV0IHI9bmV3IERPTVBhcnNlcjtyZXR1cm4genIoZSx0KS5waXBlKHYobz0+by50ZXh0KCkpLG0obz0+ci5wYXJzZUZyb21TdHJpbmcobywidGV4dC9odG1sIikpLEcoMSkpfWZ1bmN0aW9uIHVuKGUsdCl7bGV0IHI9bmV3IERPTVBhcnNlcjtyZXR1cm4genIoZSx0KS5waXBlKHYobz0+by50ZXh0KCkpLG0obz0+ci5wYXJzZUZyb21TdHJpbmcobywidGV4dC94bWwiKSksRygxKSl9ZnVuY3Rpb24gZG4oKXtyZXR1cm57eDpNYXRoLm1heCgwLHNjcm9sbFgpLHk6TWF0aC5tYXgoMCxzY3JvbGxZKX19ZnVuY3Rpb24gaG4oKXtyZXR1cm4gTyhoKHdpbmRvdywic2Nyb2xsIix7cGFzc2l2ZTohMH0pLGgod2luZG93LCJyZXNpemUiLHtwYXNzaXZlOiEwfSkpLnBpcGUobShkbiksUShkbigpKSl9ZnVuY3Rpb24gYm4oKXtyZXR1cm57d2lkdGg6aW5uZXJXaWR0aCxoZWlnaHQ6aW5uZXJIZWlnaHR9fWZ1bmN0aW9uIHZuKCl7cmV0dXJuIGgod2luZG93LCJyZXNpemUiLHtwYXNzaXZlOiEwfSkucGlwZShtKGJuKSxRKGJuKCkpKX1mdW5jdGlvbiBnbigpe3JldHVybiB6KFtobigpLHZuKCldKS5waXBlKG0oKFtlLHRdKT0+KHtvZmZzZXQ6ZSxzaXplOnR9KSksRygxKSl9ZnVuY3Rpb24gbXIoZSx7dmlld3BvcnQkOnQsaGVhZGVyJDpyfSl7bGV0IG89dC5waXBlKGVlKCJzaXplIikpLG49eihbbyxyXSkucGlwZShtKCgpPT5WZShlKSkpO3JldHVybiB6KFtyLHQsbl0pLnBpcGUobSgoW3toZWlnaHQ6aX0se29mZnNldDphLHNpemU6c30se3g6cCx5OmN9XSk9Pih7b2Zmc2V0Ont4OmEueC1wLHk6YS55LWMraX0sc2l6ZTpzfSkpKX1mdW5jdGlvbiBfYShlKXtyZXR1cm4gaChlLCJtZXNzYWdlIix0PT50LmRhdGEpfWZ1bmN0aW9uIEFhKGUpe2xldCB0PW5ldyBnO3JldHVybiB0LnN1YnNjcmliZShyPT5lLnBvc3RNZXNzYWdlKHIpKSx0fWZ1bmN0aW9uIHluKGUsdD1uZXcgV29ya2VyKGUpKXtsZXQgcj1fYSh0KSxvPUFhKHQpLG49bmV3IGc7bi5zdWJzY3JpYmUobyk7bGV0IGk9by5waXBlKFooKSxpZSghMCkpO3JldHVybiBuLnBpcGUoWigpLFJlKHIucGlwZShXKGkpKSkscGUoKSl9dmFyIENhPVIoIiNfX2NvbmZpZyIpLE90PUpTT04ucGFyc2UoQ2EudGV4dENvbnRlbnQpO090LmJhc2U9YCR7bmV3IFVSTChPdC5iYXNlLHllKCkpfWA7ZnVuY3Rpb24geGUoKXtyZXR1cm4gT3R9ZnVuY3Rpb24gQihlKXtyZXR1cm4gT3QuZmVhdHVyZXMuaW5jbHVkZXMoZSl9ZnVuY3Rpb24gRWUoZSx0KXtyZXR1cm4gdHlwZW9mIHQhPSJ1bmRlZmluZWQiP090LnRyYW5zbGF0aW9uc1tlXS5yZXBsYWNlKCIjIix0LnRvU3RyaW5nKCkpOk90LnRyYW5zbGF0aW9uc1tlXX1mdW5jdGlvbiBTZShlLHQ9ZG9jdW1lbnQpe3JldHVybiBSKGBbZGF0YS1tZC1jb21wb25lbnQ9JHtlfV1gLHQpfWZ1bmN0aW9uIGFlKGUsdD1kb2N1bWVudCl7cmV0dXJuIFAoYFtkYXRhLW1kLWNvbXBvbmVudD0ke2V9XWAsdCl9ZnVuY3Rpb24ga2EoZSl7bGV0IHQ9UigiLm1kLXR5cGVzZXQgPiA6Zmlyc3QtY2hpbGQiLGUpO3JldHVybiBoKHQsImNsaWNrIix7b25jZTohMH0pLnBpcGUobSgoKT0+UigiLm1kLXR5cGVzZXQiLGUpKSxtKHI9Pih7aGFzaDpfX21kX2hhc2goci5pbm5lckhUTUwpfSkpKX1mdW5jdGlvbiB4bihlKXtpZighQigiYW5ub3VuY2UuZGlzbWlzcyIpfHwhZS5jaGlsZEVsZW1lbnRDb3VudClyZXR1cm4gUztpZighZS5oaWRkZW4pe2xldCB0PVIoIi5tZC10eXBlc2V0IixlKTtfX21kX2hhc2godC5pbm5lckhUTUwpPT09X19tZF9nZXQoIl9fYW5ub3VuY2UiKSYmKGUuaGlkZGVuPSEwKX1yZXR1cm4gQygoKT0+e2xldCB0PW5ldyBnO3JldHVybiB0LnN1YnNjcmliZSgoe2hhc2g6cn0pPT57ZS5oaWRkZW49ITAsX19tZF9zZXQoIl9fYW5ub3VuY2UiLHIpfSksa2EoZSkucGlwZSh3KHI9PnQubmV4dChyKSksXygoKT0+dC5jb21wbGV0ZSgpKSxtKHI9PiQoe3JlZjplfSxyKSkpfSl9ZnVuY3Rpb24gSGEoZSx7dGFyZ2V0JDp0fSl7cmV0dXJuIHQucGlwZShtKHI9Pih7aGlkZGVuOnIhPT1lfSkpKX1mdW5jdGlvbiBFbihlLHQpe2xldCByPW5ldyBnO3JldHVybiByLnN1YnNjcmliZSgoe2hpZGRlbjpvfSk9PntlLmhpZGRlbj1vfSksSGEoZSx0KS5waXBlKHcobz0+ci5uZXh0KG8pKSxfKCgpPT5yLmNvbXBsZXRlKCkpLG0obz0+JCh7cmVmOmV9LG8pKSl9ZnVuY3Rpb24gUnQoZSx0KXtyZXR1cm4gdD09PSJpbmxpbmUiP3goImRpdiIse2NsYXNzOiJtZC10b29sdGlwIG1kLXRvb2x0aXAtLWlubGluZSIsaWQ6ZSxyb2xlOiJ0b29sdGlwIn0seCgiZGl2Iix7Y2xhc3M6Im1kLXRvb2x0aXBfX2lubmVyIG1kLXR5cGVzZXQifSkpOngoImRpdiIse2NsYXNzOiJtZC10b29sdGlwIixpZDplLHJvbGU6InRvb2x0aXAifSx4KCJkaXYiLHtjbGFzczoibWQtdG9vbHRpcF9faW5uZXIgbWQtdHlwZXNldCJ9KSl9ZnVuY3Rpb24gd24oLi4uZSl7cmV0dXJuIHgoImRpdiIse2NsYXNzOiJtZC10b29sdGlwMiIscm9sZToidG9vbHRpcCJ9LHgoImRpdiIse2NsYXNzOiJtZC10b29sdGlwMl9faW5uZXIgbWQtdHlwZXNldCJ9LGUpKX1mdW5jdGlvbiBUbihlLHQpe2lmKHQ9dD9gJHt0fV9hbm5vdGF0aW9uXyR7ZX1gOnZvaWQgMCx0KXtsZXQgcj10P2AjJHt0fWA6dm9pZCAwO3JldHVybiB4KCJhc2lkZSIse2NsYXNzOiJtZC1hbm5vdGF0aW9uIix0YWJJbmRleDowfSxSdCh0KSx4KCJhIix7aHJlZjpyLGNsYXNzOiJtZC1hbm5vdGF0aW9uX19pbmRleCIsdGFiSW5kZXg6LTF9LHgoInNwYW4iLHsiZGF0YS1tZC1hbm5vdGF0aW9uLWlkIjplfSkpKX1lbHNlIHJldHVybiB4KCJhc2lkZSIse2NsYXNzOiJtZC1hbm5vdGF0aW9uIix0YWJJbmRleDowfSxSdCh0KSx4KCJzcGFuIix7Y2xhc3M6Im1kLWFubm90YXRpb25fX2luZGV4Iix0YWJJbmRleDotMX0seCgic3BhbiIseyJkYXRhLW1kLWFubm90YXRpb24taWQiOmV9KSkpfWZ1bmN0aW9uIFNuKGUpe3JldHVybiB4KCJidXR0b24iLHtjbGFzczoibWQtY2xpcGJvYXJkIG1kLWljb24iLHRpdGxlOkVlKCJjbGlwYm9hcmQuY29weSIpLCJkYXRhLWNsaXBib2FyZC10YXJnZXQiOmAjJHtlfSA+IGNvZGVgfSl9dmFyIExuPU10KHFyKCkpO2Z1bmN0aW9uIFFyKGUsdCl7bGV0IHI9dCYyLG89dCYxLG49T2JqZWN0LmtleXMoZS50ZXJtcykuZmlsdGVyKHA9PiFlLnRlcm1zW3BdKS5yZWR1Y2UoKHAsYyk9PlsuLi5wLHgoImRlbCIsbnVsbCwoMCxMbi5kZWZhdWx0KShjKSksIiAiXSxbXSkuc2xpY2UoMCwtMSksaT14ZSgpLGE9bmV3IFVSTChlLmxvY2F0aW9uLGkuYmFzZSk7Qigic2VhcmNoLmhpZ2hsaWdodCIpJiZhLnNlYXJjaFBhcmFtcy5zZXQoImgiLE9iamVjdC5lbnRyaWVzKGUudGVybXMpLmZpbHRlcigoWyxwXSk9PnApLnJlZHVjZSgocCxbY10pPT5gJHtwfSAke2N9YC50cmltKCksIiIpKTtsZXR7dGFnczpzfT14ZSgpO3JldHVybiB4KCJhIix7aHJlZjpgJHthfWAsY2xhc3M6Im1kLXNlYXJjaC1yZXN1bHRfX2xpbmsiLHRhYkluZGV4Oi0xfSx4KCJhcnRpY2xlIix7Y2xhc3M6Im1kLXNlYXJjaC1yZXN1bHRfX2FydGljbGUgbWQtdHlwZXNldCIsImRhdGEtbWQtc2NvcmUiOmUuc2NvcmUudG9GaXhlZCgyKX0scj4wJiZ4KCJkaXYiLHtjbGFzczoibWQtc2VhcmNoLXJlc3VsdF9faWNvbiBtZC1pY29uIn0pLHI+MCYmeCgiaDEiLG51bGwsZS50aXRsZSkscjw9MCYmeCgiaDIiLG51bGwsZS50aXRsZSksbz4wJiZlLnRleHQubGVuZ3RoPjAmJmUudGV4dCxlLnRhZ3MmJngoIm5hdiIse2NsYXNzOiJtZC10YWdzIn0sZS50YWdzLm1hcChwPT57bGV0IGM9cz9wIGluIHM/YG1kLXRhZy1pY29uIG1kLXRhZy0tJHtzW3BdfWA6Im1kLXRhZy1pY29uIjoiIjtyZXR1cm4geCgic3BhbiIse2NsYXNzOmBtZC10YWcgJHtjfWB9LHApfSkpLG8+MCYmbi5sZW5ndGg+MCYmeCgicCIse2NsYXNzOiJtZC1zZWFyY2gtcmVzdWx0X190ZXJtcyJ9LEVlKCJzZWFyY2gucmVzdWx0LnRlcm0ubWlzc2luZyIpLCI6ICIsLi4ubikpKX1mdW5jdGlvbiBNbihlKXtsZXQgdD1lWzBdLnNjb3JlLHI9Wy4uLmVdLG89eGUoKSxuPXIuZmluZEluZGV4KGw9PiFgJHtuZXcgVVJMKGwubG9jYXRpb24sby5iYXNlKX1gLmluY2x1ZGVzKCIjIikpLFtpXT1yLnNwbGljZShuLDEpLGE9ci5maW5kSW5kZXgobD0+bC5zY29yZTx0KTthPT09LTEmJihhPXIubGVuZ3RoKTtsZXQgcz1yLnNsaWNlKDAsYSkscD1yLnNsaWNlKGEpLGM9W1FyKGksMnwrKCFuJiZhPT09MCkpLC4uLnMubWFwKGw9PlFyKGwsMSkpLC4uLnAubGVuZ3RoP1t4KCJkZXRhaWxzIix7Y2xhc3M6Im1kLXNlYXJjaC1yZXN1bHRfX21vcmUifSx4KCJzdW1tYXJ5Iix7dGFiSW5kZXg6LTF9LHgoImRpdiIsbnVsbCxwLmxlbmd0aD4wJiZwLmxlbmd0aD09PTE/RWUoInNlYXJjaC5yZXN1bHQubW9yZS5vbmUiKTpFZSgic2VhcmNoLnJlc3VsdC5tb3JlLm90aGVyIixwLmxlbmd0aCkpKSwuLi5wLm1hcChsPT5RcihsLDEpKSldOltdXTtyZXR1cm4geCgibGkiLHtjbGFzczoibWQtc2VhcmNoLXJlc3VsdF9faXRlbSJ9LGMpfWZ1bmN0aW9uIF9uKGUpe3JldHVybiB4KCJ1bCIse2NsYXNzOiJtZC1zb3VyY2VfX2ZhY3RzIn0sT2JqZWN0LmVudHJpZXMoZSkubWFwKChbdCxyXSk9PngoImxpIix7Y2xhc3M6YG1kLXNvdXJjZV9fZmFjdCBtZC1zb3VyY2VfX2ZhY3QtLSR7dH1gfSx0eXBlb2Ygcj09Im51bWJlciI/c3Iocik6cikpKX1mdW5jdGlvbiBLcihlKXtsZXQgdD1gdGFiYmVkLWNvbnRyb2wgdGFiYmVkLWNvbnRyb2wtLSR7ZX1gO3JldHVybiB4KCJkaXYiLHtjbGFzczp0LGhpZGRlbjohMH0seCgiYnV0dG9uIix7Y2xhc3M6InRhYmJlZC1idXR0b24iLHRhYkluZGV4Oi0xLCJhcmlhLWhpZGRlbiI6InRydWUifSkpfWZ1bmN0aW9uIEFuKGUpe3JldHVybiB4KCJkaXYiLHtjbGFzczoibWQtdHlwZXNldF9fc2Nyb2xsd3JhcCJ9LHgoImRpdiIse2NsYXNzOiJtZC10eXBlc2V0X190YWJsZSJ9LGUpKX1mdW5jdGlvbiBSYShlKXt2YXIgbztsZXQgdD14ZSgpLHI9bmV3IFVSTChgLi4vJHtlLnZlcnNpb259L2AsdC5iYXNlKTtyZXR1cm4geCgibGkiLHtjbGFzczoibWQtdmVyc2lvbl9faXRlbSJ9LHgoImEiLHtocmVmOmAke3J9YCxjbGFzczoibWQtdmVyc2lvbl9fbGluayJ9LGUudGl0bGUsKChvPXQudmVyc2lvbik9PW51bGw/dm9pZCAwOm8uYWxpYXMpJiZlLmFsaWFzZXMubGVuZ3RoPjAmJngoInNwYW4iLHtjbGFzczoibWQtdmVyc2lvbl9fYWxpYXMifSxlLmFsaWFzZXNbMF0pKSl9ZnVuY3Rpb24gQ24oZSx0KXt2YXIgbztsZXQgcj14ZSgpO3JldHVybiBlPWUuZmlsdGVyKG49Pnt2YXIgaTtyZXR1cm4hKChpPW4ucHJvcGVydGllcykhPW51bGwmJmkuaGlkZGVuKX0pLHgoImRpdiIse2NsYXNzOiJtZC12ZXJzaW9uIn0seCgiYnV0dG9uIix7Y2xhc3M6Im1kLXZlcnNpb25fX2N1cnJlbnQiLCJhcmlhLWxhYmVsIjpFZSgic2VsZWN0LnZlcnNpb24iKX0sdC50aXRsZSwoKG89ci52ZXJzaW9uKT09bnVsbD92b2lkIDA6by5hbGlhcykmJnQuYWxpYXNlcy5sZW5ndGg+MCYmeCgic3BhbiIse2NsYXNzOiJtZC12ZXJzaW9uX19hbGlhcyJ9LHQuYWxpYXNlc1swXSkpLHgoInVsIix7Y2xhc3M6Im1kLXZlcnNpb25fX2xpc3QifSxlLm1hcChSYSkpKX12YXIgSWE9MDtmdW5jdGlvbiBqYShlKXtsZXQgdD16KFtldChlKSwkdChlKV0pLnBpcGUobSgoW28sbl0pPT5vfHxuKSxLKCkpLHI9QygoKT0+Wm8oZSkpLnBpcGUobmUoTmUpLHB0KDEpLEhlKHQpLG0oKCk9PmVuKGUpKSk7cmV0dXJuIHQucGlwZShBZShvPT5vKSx2KCgpPT56KFt0LHJdKSksbSgoW28sbl0pPT4oe2FjdGl2ZTpvLG9mZnNldDpufSkpLHBlKCkpfWZ1bmN0aW9uIEZhKGUsdCl7bGV0e2NvbnRlbnQkOnIsdmlld3BvcnQkOm99PXQsbj1gX190b29sdGlwMl8ke0lhKyt9YDtyZXR1cm4gQygoKT0+e2xldCBpPW5ldyBnLGE9bmV3IF9yKCExKTtpLnBpcGUoWigpLGllKCExKSkuc3Vic2NyaWJlKGEpO2xldCBzPWEucGlwZShIdChjPT5MZSgrIWMqMjUwLGtyKSksSygpLHYoYz0+Yz9yOlMpLHcoYz0+Yy5pZD1uKSxwZSgpKTt6KFtpLnBpcGUobSgoe2FjdGl2ZTpjfSk9PmMpKSxzLnBpcGUodihjPT4kdChjLDI1MCkpLFEoITEpKV0pLnBpcGUobShjPT5jLnNvbWUobD0+bCkpKS5zdWJzY3JpYmUoYSk7bGV0IHA9YS5waXBlKGIoYz0+YykscmUocyxvKSxtKChbYyxsLHtzaXplOmZ9XSk9PntsZXQgdT1lLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLGQ9dS53aWR0aC8yO2lmKGwucm9sZT09PSJ0b29sdGlwIilyZXR1cm57eDpkLHk6OCt1LmhlaWdodH07aWYodS55Pj1mLmhlaWdodC8yKXtsZXR7aGVpZ2h0Onl9PWNlKGwpO3JldHVybnt4OmQseTotMTYteX19ZWxzZSByZXR1cm57eDpkLHk6MTYrdS5oZWlnaHR9fSkpO3JldHVybiB6KFtzLGkscF0pLnN1YnNjcmliZSgoW2Mse29mZnNldDpsfSxmXSk9PntjLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLXRvb2x0aXAtaG9zdC14IixgJHtsLnh9cHhgKSxjLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLXRvb2x0aXAtaG9zdC15IixgJHtsLnl9cHhgKSxjLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLXRvb2x0aXAteCIsYCR7Zi54fXB4YCksYy5zdHlsZS5zZXRQcm9wZXJ0eSgiLS1tZC10b29sdGlwLXkiLGAke2YueX1weGApLGMuY2xhc3NMaXN0LnRvZ2dsZSgibWQtdG9vbHRpcDItLXRvcCIsZi55PDApLGMuY2xhc3NMaXN0LnRvZ2dsZSgibWQtdG9vbHRpcDItLWJvdHRvbSIsZi55Pj0wKX0pLGEucGlwZShiKGM9PmMpLHJlKHMsKGMsbCk9PmwpLGIoYz0+Yy5yb2xlPT09InRvb2x0aXAiKSkuc3Vic2NyaWJlKGM9PntsZXQgbD1jZShSKCI6c2NvcGUgPiAqIixjKSk7Yy5zdHlsZS5zZXRQcm9wZXJ0eSgiLS1tZC10b29sdGlwLXdpZHRoIixgJHtsLndpZHRofXB4YCksYy5zdHlsZS5zZXRQcm9wZXJ0eSgiLS1tZC10b29sdGlwLXRhaWwiLCIwcHgiKX0pLGEucGlwZShLKCksdmUobWUpLHJlKHMpKS5zdWJzY3JpYmUoKFtjLGxdKT0+e2wuY2xhc3NMaXN0LnRvZ2dsZSgibWQtdG9vbHRpcDItLWFjdGl2ZSIsYyl9KSx6KFthLnBpcGUoYihjPT5jKSksc10pLnN1YnNjcmliZSgoW2MsbF0pPT57bC5yb2xlPT09ImRpYWxvZyI/KGUuc2V0QXR0cmlidXRlKCJhcmlhLWNvbnRyb2xzIixuKSxlLnNldEF0dHJpYnV0ZSgiYXJpYS1oYXNwb3B1cCIsImRpYWxvZyIpKTplLnNldEF0dHJpYnV0ZSgiYXJpYS1kZXNjcmliZWRieSIsbil9KSxhLnBpcGUoYihjPT4hYykpLnN1YnNjcmliZSgoKT0+e2UucmVtb3ZlQXR0cmlidXRlKCJhcmlhLWNvbnRyb2xzIiksZS5yZW1vdmVBdHRyaWJ1dGUoImFyaWEtZGVzY3JpYmVkYnkiKSxlLnJlbW92ZUF0dHJpYnV0ZSgiYXJpYS1oYXNwb3B1cCIpfSksamEoZSkucGlwZSh3KGM9PmkubmV4dChjKSksXygoKT0+aS5jb21wbGV0ZSgpKSxtKGM9PiQoe3JlZjplfSxjKSkpfSl9ZnVuY3Rpb24gbXQoZSx7dmlld3BvcnQkOnR9LHI9ZG9jdW1lbnQuYm9keSl7cmV0dXJuIEZhKGUse2NvbnRlbnQkOm5ldyBqKG89PntsZXQgbj1lLnRpdGxlLGk9d24obik7cmV0dXJuIG8ubmV4dChpKSxlLnJlbW92ZUF0dHJpYnV0ZSgidGl0bGUiKSxyLmFwcGVuZChpKSwoKT0+e2kucmVtb3ZlKCksZS5zZXRBdHRyaWJ1dGUoInRpdGxlIixuKX19KSx2aWV3cG9ydCQ6dH0pfWZ1bmN0aW9uIFVhKGUsdCl7bGV0IHI9QygoKT0+eihbdG4oZSksTmUodCldKSkucGlwZShtKChbe3g6byx5Om59LGldKT0+e2xldHt3aWR0aDphLGhlaWdodDpzfT1jZShlKTtyZXR1cm57eDpvLWkueCthLzIseTpuLWkueStzLzJ9fSkpO3JldHVybiBldChlKS5waXBlKHYobz0+ci5waXBlKG0obj0+KHthY3RpdmU6byxvZmZzZXQ6bn0pKSxUZSgrIW98fDEvMCkpKSl9ZnVuY3Rpb24ga24oZSx0LHt0YXJnZXQkOnJ9KXtsZXRbbyxuXT1BcnJheS5mcm9tKGUuY2hpbGRyZW4pO3JldHVybiBDKCgpPT57bGV0IGk9bmV3IGcsYT1pLnBpcGUoWigpLGllKCEwKSk7cmV0dXJuIGkuc3Vic2NyaWJlKHtuZXh0KHtvZmZzZXQ6c30pe2Uuc3R5bGUuc2V0UHJvcGVydHkoIi0tbWQtdG9vbHRpcC14IixgJHtzLnh9cHhgKSxlLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLXRvb2x0aXAteSIsYCR7cy55fXB4YCl9LGNvbXBsZXRlKCl7ZS5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgiLS1tZC10b29sdGlwLXgiKSxlLnN0eWxlLnJlbW92ZVByb3BlcnR5KCItLW1kLXRvb2x0aXAteSIpfX0pLHR0KGUpLnBpcGUoVyhhKSkuc3Vic2NyaWJlKHM9PntlLnRvZ2dsZUF0dHJpYnV0ZSgiZGF0YS1tZC12aXNpYmxlIixzKX0pLE8oaS5waXBlKGIoKHthY3RpdmU6c30pPT5zKSksaS5waXBlKF9lKDI1MCksYigoe2FjdGl2ZTpzfSk9PiFzKSkpLnN1YnNjcmliZSh7bmV4dCh7YWN0aXZlOnN9KXtzP2UucHJlcGVuZChvKTpvLnJlbW92ZSgpfSxjb21wbGV0ZSgpe2UucHJlcGVuZChvKX19KSxpLnBpcGUoTWUoMTYsbWUpKS5zdWJzY3JpYmUoKHthY3RpdmU6c30pPT57by5jbGFzc0xpc3QudG9nZ2xlKCJtZC10b29sdGlwLS1hY3RpdmUiLHMpfSksaS5waXBlKHB0KDEyNSxtZSksYigoKT0+ISFlLm9mZnNldFBhcmVudCksbSgoKT0+ZS5vZmZzZXRQYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkpLG0oKHt4OnN9KT0+cykpLnN1YnNjcmliZSh7bmV4dChzKXtzP2Uuc3R5bGUuc2V0UHJvcGVydHkoIi0tbWQtdG9vbHRpcC0wIixgJHstc31weGApOmUuc3R5bGUucmVtb3ZlUHJvcGVydHkoIi0tbWQtdG9vbHRpcC0wIil9LGNvbXBsZXRlKCl7ZS5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgiLS1tZC10b29sdGlwLTAiKX19KSxoKG4sImNsaWNrIikucGlwZShXKGEpLGIocz0+IShzLm1ldGFLZXl8fHMuY3RybEtleSkpKS5zdWJzY3JpYmUocz0+e3Muc3RvcFByb3BhZ2F0aW9uKCkscy5wcmV2ZW50RGVmYXVsdCgpfSksaChuLCJtb3VzZWRvd24iKS5waXBlKFcoYSkscmUoaSkpLnN1YnNjcmliZSgoW3Mse2FjdGl2ZTpwfV0pPT57dmFyIGM7aWYocy5idXR0b24hPT0wfHxzLm1ldGFLZXl8fHMuY3RybEtleSlzLnByZXZlbnREZWZhdWx0KCk7ZWxzZSBpZihwKXtzLnByZXZlbnREZWZhdWx0KCk7bGV0IGw9ZS5wYXJlbnRFbGVtZW50LmNsb3Nlc3QoIi5tZC1hbm5vdGF0aW9uIik7bCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50P2wuZm9jdXMoKTooYz1JZSgpKT09bnVsbHx8Yy5ibHVyKCl9fSksci5waXBlKFcoYSksYihzPT5zPT09byksR2UoMTI1KSkuc3Vic2NyaWJlKCgpPT5lLmZvY3VzKCkpLFVhKGUsdCkucGlwZSh3KHM9PmkubmV4dChzKSksXygoKT0+aS5jb21wbGV0ZSgpKSxtKHM9PiQoe3JlZjplfSxzKSkpfSl9ZnVuY3Rpb24gV2EoZSl7cmV0dXJuIGUudGFnTmFtZT09PSJDT0RFIj9QKCIuYywgLmMxLCAuY20iLGUpOltlXX1mdW5jdGlvbiBEYShlKXtsZXQgdD1bXTtmb3IobGV0IHIgb2YgV2EoZSkpe2xldCBvPVtdLG49ZG9jdW1lbnQuY3JlYXRlTm9kZUl0ZXJhdG9yKHIsTm9kZUZpbHRlci5TSE9XX1RFWFQpO2ZvcihsZXQgaT1uLm5leHROb2RlKCk7aTtpPW4ubmV4dE5vZGUoKSlvLnB1c2goaSk7Zm9yKGxldCBpIG9mIG8pe2xldCBhO2Zvcig7YT0vKFwoXGQrXCkpKCEpPy8uZXhlYyhpLnRleHRDb250ZW50KTspe2xldFsscyxwXT1hO2lmKHR5cGVvZiBwPT0idW5kZWZpbmVkIil7bGV0IGM9aS5zcGxpdFRleHQoYS5pbmRleCk7aT1jLnNwbGl0VGV4dChzLmxlbmd0aCksdC5wdXNoKGMpfWVsc2V7aS50ZXh0Q29udGVudD1zLHQucHVzaChpKTticmVha319fX1yZXR1cm4gdH1mdW5jdGlvbiBIbihlLHQpe3QuYXBwZW5kKC4uLkFycmF5LmZyb20oZS5jaGlsZE5vZGVzKSl9ZnVuY3Rpb24gZnIoZSx0LHt0YXJnZXQkOnIscHJpbnQkOm99KXtsZXQgbj10LmNsb3Nlc3QoIltpZF0iKSxpPW49PW51bGw/dm9pZCAwOm4uaWQsYT1uZXcgTWFwO2ZvcihsZXQgcyBvZiBEYSh0KSl7bGV0WyxwXT1zLnRleHRDb250ZW50Lm1hdGNoKC9cKChcZCspXCkvKTtmZShgOnNjb3BlID4gbGk6bnRoLWNoaWxkKCR7cH0pYCxlKSYmKGEuc2V0KHAsVG4ocCxpKSkscy5yZXBsYWNlV2l0aChhLmdldChwKSkpfXJldHVybiBhLnNpemU9PT0wP1M6QygoKT0+e2xldCBzPW5ldyBnLHA9cy5waXBlKFooKSxpZSghMCkpLGM9W107Zm9yKGxldFtsLGZdb2YgYSljLnB1c2goW1IoIi5tZC10eXBlc2V0IixmKSxSKGA6c2NvcGUgPiBsaTpudGgtY2hpbGQoJHtsfSlgLGUpXSk7cmV0dXJuIG8ucGlwZShXKHApKS5zdWJzY3JpYmUobD0+e2UuaGlkZGVuPSFsLGUuY2xhc3NMaXN0LnRvZ2dsZSgibWQtYW5ub3RhdGlvbi1saXN0IixsKTtmb3IobGV0W2YsdV1vZiBjKWw/SG4oZix1KTpIbih1LGYpfSksTyguLi5bLi4uYV0ubWFwKChbLGxdKT0+a24obCx0LHt0YXJnZXQkOnJ9KSkpLnBpcGUoXygoKT0+cy5jb21wbGV0ZSgpKSxwZSgpKX0pfWZ1bmN0aW9uICRuKGUpe2lmKGUubmV4dEVsZW1lbnRTaWJsaW5nKXtsZXQgdD1lLm5leHRFbGVtZW50U2libGluZztpZih0LnRhZ05hbWU9PT0iT0wiKXJldHVybiB0O2lmKHQudGFnTmFtZT09PSJQIiYmIXQuY2hpbGRyZW4ubGVuZ3RoKXJldHVybiAkbih0KX19ZnVuY3Rpb24gUG4oZSx0KXtyZXR1cm4gQygoKT0+e2xldCByPSRuKGUpO3JldHVybiB0eXBlb2YgciE9InVuZGVmaW5lZCI/ZnIocixlLHQpOlN9KX12YXIgUm49TXQoQnIoKSk7dmFyIFZhPTA7ZnVuY3Rpb24gSW4oZSl7aWYoZS5uZXh0RWxlbWVudFNpYmxpbmcpe2xldCB0PWUubmV4dEVsZW1lbnRTaWJsaW5nO2lmKHQudGFnTmFtZT09PSJPTCIpcmV0dXJuIHQ7aWYodC50YWdOYW1lPT09IlAiJiYhdC5jaGlsZHJlbi5sZW5ndGgpcmV0dXJuIEluKHQpfX1mdW5jdGlvbiBOYShlKXtyZXR1cm4gZ2UoZSkucGlwZShtKCh7d2lkdGg6dH0pPT4oe3Njcm9sbGFibGU6U3QoZSkud2lkdGg+dH0pKSxlZSgic2Nyb2xsYWJsZSIpKX1mdW5jdGlvbiBqbihlLHQpe2xldHttYXRjaGVzOnJ9PW1hdGNoTWVkaWEoIihob3ZlcikiKSxvPUMoKCk9PntsZXQgbj1uZXcgZyxpPW4ucGlwZShqcigxKSk7bi5zdWJzY3JpYmUoKHtzY3JvbGxhYmxlOmN9KT0+e2MmJnI/ZS5zZXRBdHRyaWJ1dGUoInRhYmluZGV4IiwiMCIpOmUucmVtb3ZlQXR0cmlidXRlKCJ0YWJpbmRleCIpfSk7bGV0IGE9W107aWYoUm4uZGVmYXVsdC5pc1N1cHBvcnRlZCgpJiYoZS5jbG9zZXN0KCIuY29weSIpfHxCKCJjb250ZW50LmNvZGUuY29weSIpJiYhZS5jbG9zZXN0KCIubm8tY29weSIpKSl7bGV0IGM9ZS5jbG9zZXN0KCJwcmUiKTtjLmlkPWBfX2NvZGVfJHtWYSsrfWA7bGV0IGw9U24oYy5pZCk7Yy5pbnNlcnRCZWZvcmUobCxlKSxCKCJjb250ZW50LnRvb2x0aXBzIikmJmEucHVzaChtdChsLHt2aWV3cG9ydCR9KSl9bGV0IHM9ZS5jbG9zZXN0KCIuaGlnaGxpZ2h0Iik7aWYocyBpbnN0YW5jZW9mIEhUTUxFbGVtZW50KXtsZXQgYz1JbihzKTtpZih0eXBlb2YgYyE9InVuZGVmaW5lZCImJihzLmNsYXNzTGlzdC5jb250YWlucygiYW5ub3RhdGUiKXx8QigiY29udGVudC5jb2RlLmFubm90YXRlIikpKXtsZXQgbD1mcihjLGUsdCk7YS5wdXNoKGdlKHMpLnBpcGUoVyhpKSxtKCh7d2lkdGg6ZixoZWlnaHQ6dX0pPT5mJiZ1KSxLKCksdihmPT5mP2w6UykpKX19cmV0dXJuIFAoIjpzY29wZSA+IHNwYW5baWRdIixlKS5sZW5ndGgmJmUuY2xhc3NMaXN0LmFkZCgibWQtY29kZV9fY29udGVudCIpLE5hKGUpLnBpcGUodyhjPT5uLm5leHQoYykpLF8oKCk9Pm4uY29tcGxldGUoKSksbShjPT4kKHtyZWY6ZX0sYykpLFJlKC4uLmEpKX0pO3JldHVybiBCKCJjb250ZW50LmxhenkiKT90dChlKS5waXBlKGIobj0+biksVGUoMSksdigoKT0+bykpOm99ZnVuY3Rpb24gemEoZSx7dGFyZ2V0JDp0LHByaW50JDpyfSl7bGV0IG89ITA7cmV0dXJuIE8odC5waXBlKG0obj0+bi5jbG9zZXN0KCJkZXRhaWxzOm5vdChbb3Blbl0pIikpLGIobj0+ZT09PW4pLG0oKCk9Pih7YWN0aW9uOiJvcGVuIixyZXZlYWw6ITB9KSkpLHIucGlwZShiKG49Pm58fCFvKSx3KCgpPT5vPWUub3BlbiksbShuPT4oe2FjdGlvbjpuPyJvcGVuIjoiY2xvc2UifSkpKSl9ZnVuY3Rpb24gRm4oZSx0KXtyZXR1cm4gQygoKT0+e2xldCByPW5ldyBnO3JldHVybiByLnN1YnNjcmliZSgoe2FjdGlvbjpvLHJldmVhbDpufSk9PntlLnRvZ2dsZUF0dHJpYnV0ZSgib3BlbiIsbz09PSJvcGVuIiksbiYmZS5zY3JvbGxJbnRvVmlldygpfSksemEoZSx0KS5waXBlKHcobz0+ci5uZXh0KG8pKSxfKCgpPT5yLmNvbXBsZXRlKCkpLG0obz0+JCh7cmVmOmV9LG8pKSl9KX12YXIgVW49Ii5ub2RlIGNpcmNsZSwubm9kZSBlbGxpcHNlLC5ub2RlIHBhdGgsLm5vZGUgcG9seWdvbiwubm9kZSByZWN0e2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWJnLWNvbG9yKTtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWZnLWNvbG9yKX1tYXJrZXJ7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWVkZ2UtY29sb3IpIWltcG9ydGFudH0uZWRnZUxhYmVsIC5sYWJlbCByZWN0e2ZpbGw6IzAwMDB9LmxhYmVse2NvbG9yOnZhcigtLW1kLW1lcm1haWQtbGFiZWwtZmctY29sb3IpO2ZvbnQtZmFtaWx5OnZhcigtLW1kLW1lcm1haWQtZm9udC1mYW1pbHkpfS5sYWJlbCBmb3JlaWduT2JqZWN0e2xpbmUtaGVpZ2h0Om5vcm1hbDtvdmVyZmxvdzp2aXNpYmxlfS5sYWJlbCBkaXYgLmVkZ2VMYWJlbHtjb2xvcjp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWZnLWNvbG9yKX0uZWRnZUxhYmVsLC5lZGdlTGFiZWwgcCwubGFiZWwgZGl2IC5lZGdlTGFiZWx7YmFja2dyb3VuZC1jb2xvcjp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKX0uZWRnZUxhYmVsLC5lZGdlTGFiZWwgcHtmaWxsOnZhcigtLW1kLW1lcm1haWQtbGFiZWwtYmctY29sb3IpO2NvbG9yOnZhcigtLW1kLW1lcm1haWQtZWRnZS1jb2xvcil9LmVkZ2VQYXRoIC5wYXRoLC5mbG93Y2hhcnQtbGlua3tzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1lZGdlLWNvbG9yKTtzdHJva2Utd2lkdGg6LjA1cmVtfS5lZGdlUGF0aCAuYXJyb3doZWFkUGF0aHtmaWxsOnZhcigtLW1kLW1lcm1haWQtZWRnZS1jb2xvcik7c3Ryb2tlOm5vbmV9LmNsdXN0ZXIgcmVjdHtmaWxsOnZhcigtLW1kLWRlZmF1bHQtZmctY29sb3ItLWxpZ2h0ZXN0KTtzdHJva2U6dmFyKC0tbWQtZGVmYXVsdC1mZy1jb2xvci0tbGlnaHRlcil9LmNsdXN0ZXIgc3Bhbntjb2xvcjp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWZnLWNvbG9yKTtmb250LWZhbWlseTp2YXIoLS1tZC1tZXJtYWlkLWZvbnQtZmFtaWx5KX1nICNmbG93Y2hhcnQtY2lyY2xlRW5kLGcgI2Zsb3djaGFydC1jaXJjbGVTdGFydCxnICNmbG93Y2hhcnQtY3Jvc3NFbmQsZyAjZmxvd2NoYXJ0LWNyb3NzU3RhcnQsZyAjZmxvd2NoYXJ0LXBvaW50RW5kLGcgI2Zsb3djaGFydC1wb2ludFN0YXJ0e3N0cm9rZTpub25lfWcuY2xhc3NHcm91cCBsaW5lLGcuY2xhc3NHcm91cCByZWN0e2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWJnLWNvbG9yKTtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWZnLWNvbG9yKX1nLmNsYXNzR3JvdXAgdGV4dHtmaWxsOnZhcigtLW1kLW1lcm1haWQtbGFiZWwtZmctY29sb3IpO2ZvbnQtZmFtaWx5OnZhcigtLW1kLW1lcm1haWQtZm9udC1mYW1pbHkpfS5jbGFzc0xhYmVsIC5ib3h7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKTtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLW1kLW1lcm1haWQtbGFiZWwtYmctY29sb3IpO29wYWNpdHk6MX0uY2xhc3NMYWJlbCAubGFiZWx7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWZnLWNvbG9yKTtmb250LWZhbWlseTp2YXIoLS1tZC1tZXJtYWlkLWZvbnQtZmFtaWx5KX0ubm9kZSAuZGl2aWRlcntzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWZnLWNvbG9yKX0ucmVsYXRpb257c3Ryb2tlOnZhcigtLW1kLW1lcm1haWQtZWRnZS1jb2xvcil9LmNhcmRpbmFsaXR5e2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1sYWJlbC1mZy1jb2xvcik7Zm9udC1mYW1pbHk6dmFyKC0tbWQtbWVybWFpZC1mb250LWZhbWlseSl9LmNhcmRpbmFsaXR5IHRleHR7ZmlsbDppbmhlcml0IWltcG9ydGFudH1kZWZzICNjbGFzc0RpYWdyYW0tY29tcG9zaXRpb25FbmQsZGVmcyAjY2xhc3NEaWFncmFtLWNvbXBvc2l0aW9uU3RhcnQsZGVmcyAjY2xhc3NEaWFncmFtLWRlcGVuZGVuY3lFbmQsZGVmcyAjY2xhc3NEaWFncmFtLWRlcGVuZGVuY3lTdGFydCxkZWZzICNjbGFzc0RpYWdyYW0tZXh0ZW5zaW9uRW5kLGRlZnMgI2NsYXNzRGlhZ3JhbS1leHRlbnNpb25TdGFydHtmaWxsOnZhcigtLW1kLW1lcm1haWQtZWRnZS1jb2xvcikhaW1wb3J0YW50O3N0cm9rZTp2YXIoLS1tZC1tZXJtYWlkLWVkZ2UtY29sb3IpIWltcG9ydGFudH1kZWZzICNjbGFzc0RpYWdyYW0tYWdncmVnYXRpb25FbmQsZGVmcyAjY2xhc3NEaWFncmFtLWFnZ3JlZ2F0aW9uU3RhcnR7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKSFpbXBvcnRhbnQ7c3Ryb2tlOnZhcigtLW1kLW1lcm1haWQtZWRnZS1jb2xvcikhaW1wb3J0YW50fWcuc3RhdGVHcm91cCByZWN0e2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWJnLWNvbG9yKTtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWZnLWNvbG9yKX1nLnN0YXRlR3JvdXAgLnN0YXRlLXRpdGxle2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1sYWJlbC1mZy1jb2xvcikhaW1wb3J0YW50O2ZvbnQtZmFtaWx5OnZhcigtLW1kLW1lcm1haWQtZm9udC1mYW1pbHkpfWcuc3RhdGVHcm91cCAuY29tcG9zaXR7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKX0ubm9kZUxhYmVsLC5ub2RlTGFiZWwgcHtjb2xvcjp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWZnLWNvbG9yKTtmb250LWZhbWlseTp2YXIoLS1tZC1tZXJtYWlkLWZvbnQtZmFtaWx5KX1hIC5ub2RlTGFiZWx7dGV4dC1kZWNvcmF0aW9uOnVuZGVybGluZX0ubm9kZSBjaXJjbGUuc3RhdGUtZW5kLC5ub2RlIGNpcmNsZS5zdGF0ZS1zdGFydCwuc3RhcnQtc3RhdGV7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWVkZ2UtY29sb3IpO3N0cm9rZTpub25lfS5lbmQtc3RhdGUtaW5uZXIsLmVuZC1zdGF0ZS1vdXRlcntmaWxsOnZhcigtLW1kLW1lcm1haWQtZWRnZS1jb2xvcil9LmVuZC1zdGF0ZS1pbm5lciwubm9kZSBjaXJjbGUuc3RhdGUtZW5ke3N0cm9rZTp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKX0udHJhbnNpdGlvbntzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1lZGdlLWNvbG9yKX1baWRePXN0YXRlLWZvcmtdIHJlY3QsW2lkXj1zdGF0ZS1qb2luXSByZWN0e2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1lZGdlLWNvbG9yKSFpbXBvcnRhbnQ7c3Ryb2tlOm5vbmUhaW1wb3J0YW50fS5zdGF0ZWRpYWdyYW0tY2x1c3Rlci5zdGF0ZWRpYWdyYW0tY2x1c3RlciAuaW5uZXJ7ZmlsbDp2YXIoLS1tZC1kZWZhdWx0LWJnLWNvbG9yKX0uc3RhdGVkaWFncmFtLWNsdXN0ZXIgcmVjdHtmaWxsOnZhcigtLW1kLW1lcm1haWQtbm9kZS1iZy1jb2xvcik7c3Ryb2tlOnZhcigtLW1kLW1lcm1haWQtbm9kZS1mZy1jb2xvcil9LnN0YXRlZGlhZ3JhbS1zdGF0ZSByZWN0LmRpdmlkZXJ7ZmlsbDp2YXIoLS1tZC1kZWZhdWx0LWZnLWNvbG9yLS1saWdodGVzdCk7c3Ryb2tlOnZhcigtLW1kLWRlZmF1bHQtZmctY29sb3ItLWxpZ2h0ZXIpfWRlZnMgI3N0YXRlZGlhZ3JhbS1iYXJiRW5ke3N0cm9rZTp2YXIoLS1tZC1tZXJtYWlkLWVkZ2UtY29sb3IpfS5hdHRyaWJ1dGVCb3hFdmVuLC5hdHRyaWJ1dGVCb3hPZGR7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLW5vZGUtYmctY29sb3IpO3N0cm9rZTp2YXIoLS1tZC1tZXJtYWlkLW5vZGUtZmctY29sb3IpfS5lbnRpdHlCb3h7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKTtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1ub2RlLWZnLWNvbG9yKX0uZW50aXR5TGFiZWx7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWZnLWNvbG9yKTtmb250LWZhbWlseTp2YXIoLS1tZC1tZXJtYWlkLWZvbnQtZmFtaWx5KX0ucmVsYXRpb25zaGlwTGFiZWxCb3h7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKTtmaWxsLW9wYWNpdHk6MTtiYWNrZ3JvdW5kLWNvbG9yOnZhcigtLW1kLW1lcm1haWQtbGFiZWwtYmctY29sb3IpO29wYWNpdHk6MX0ucmVsYXRpb25zaGlwTGFiZWx7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWZnLWNvbG9yKX0ucmVsYXRpb25zaGlwTGluZXtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1lZGdlLWNvbG9yKX1kZWZzICNPTkVfT1JfTU9SRV9FTkQgKixkZWZzICNPTkVfT1JfTU9SRV9TVEFSVCAqLGRlZnMgI09OTFlfT05FX0VORCAqLGRlZnMgI09OTFlfT05FX1NUQVJUICosZGVmcyAjWkVST19PUl9NT1JFX0VORCAqLGRlZnMgI1pFUk9fT1JfTU9SRV9TVEFSVCAqLGRlZnMgI1pFUk9fT1JfT05FX0VORCAqLGRlZnMgI1pFUk9fT1JfT05FX1NUQVJUICp7c3Ryb2tlOnZhcigtLW1kLW1lcm1haWQtZWRnZS1jb2xvcikhaW1wb3J0YW50fWRlZnMgI1pFUk9fT1JfTU9SRV9FTkQgY2lyY2xlLGRlZnMgI1pFUk9fT1JfTU9SRV9TVEFSVCBjaXJjbGV7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLWxhYmVsLWJnLWNvbG9yKX0uYWN0b3J7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLXNlcXVlbmNlLWFjdG9yLWJnLWNvbG9yKTtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1hY3Rvci1ib3JkZXItY29sb3IpfXRleHQuYWN0b3I+dHNwYW57ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLXNlcXVlbmNlLWFjdG9yLWZnLWNvbG9yKTtmb250LWZhbWlseTp2YXIoLS1tZC1tZXJtYWlkLWZvbnQtZmFtaWx5KX1saW5le3N0cm9rZTp2YXIoLS1tZC1tZXJtYWlkLXNlcXVlbmNlLWFjdG9yLWxpbmUtY29sb3IpfS5hY3Rvci1tYW4gY2lyY2xlLC5hY3Rvci1tYW4gbGluZXtmaWxsOnZhcigtLW1kLW1lcm1haWQtc2VxdWVuY2UtYWN0b3JtYW4tYmctY29sb3IpO3N0cm9rZTp2YXIoLS1tZC1tZXJtYWlkLXNlcXVlbmNlLWFjdG9ybWFuLWxpbmUtY29sb3IpfS5tZXNzYWdlTGluZTAsLm1lc3NhZ2VMaW5lMXtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1tZXNzYWdlLWxpbmUtY29sb3IpfS5ub3Rle2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1ub3RlLWJnLWNvbG9yKTtzdHJva2U6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1ub3RlLWJvcmRlci1jb2xvcil9Lmxvb3BUZXh0LC5sb29wVGV4dD50c3BhbiwubWVzc2FnZVRleHQsLm5vdGVUZXh0PnRzcGFue3N0cm9rZTpub25lO2ZvbnQtZmFtaWx5OnZhcigtLW1kLW1lcm1haWQtZm9udC1mYW1pbHkpIWltcG9ydGFudH0ubWVzc2FnZVRleHR7ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLXNlcXVlbmNlLW1lc3NhZ2UtZmctY29sb3IpfS5sb29wVGV4dCwubG9vcFRleHQ+dHNwYW57ZmlsbDp2YXIoLS1tZC1tZXJtYWlkLXNlcXVlbmNlLWxvb3AtZmctY29sb3IpfS5ub3RlVGV4dD50c3BhbntmaWxsOnZhcigtLW1kLW1lcm1haWQtc2VxdWVuY2Utbm90ZS1mZy1jb2xvcil9I2Fycm93aGVhZCBwYXRoe2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1tZXNzYWdlLWxpbmUtY29sb3IpO3N0cm9rZTpub25lfS5sb29wTGluZXtmaWxsOnZhcigtLW1kLW1lcm1haWQtc2VxdWVuY2UtbG9vcC1iZy1jb2xvcik7c3Ryb2tlOnZhcigtLW1kLW1lcm1haWQtc2VxdWVuY2UtbG9vcC1ib3JkZXItY29sb3IpfS5sYWJlbEJveHtmaWxsOnZhcigtLW1kLW1lcm1haWQtc2VxdWVuY2UtbGFiZWwtYmctY29sb3IpO3N0cm9rZTpub25lfS5sYWJlbFRleHQsLmxhYmVsVGV4dD5zcGFue2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1sYWJlbC1mZy1jb2xvcik7Zm9udC1mYW1pbHk6dmFyKC0tbWQtbWVybWFpZC1mb250LWZhbWlseSl9LnNlcXVlbmNlTnVtYmVye2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1udW1iZXItZmctY29sb3IpfXJlY3QucmVjdHtmaWxsOnZhcigtLW1kLW1lcm1haWQtc2VxdWVuY2UtYm94LWJnLWNvbG9yKTtzdHJva2U6bm9uZX1yZWN0LnJlY3QrdGV4dC50ZXh0e2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1ib3gtZmctY29sb3IpfWRlZnMgI3NlcXVlbmNlbnVtYmVye2ZpbGw6dmFyKC0tbWQtbWVybWFpZC1zZXF1ZW5jZS1udW1iZXItYmctY29sb3IpIWltcG9ydGFudH0iO3ZhciBHcixRYT0wO2Z1bmN0aW9uIEthKCl7cmV0dXJuIHR5cGVvZiBtZXJtYWlkPT0idW5kZWZpbmVkInx8bWVybWFpZCBpbnN0YW5jZW9mIEVsZW1lbnQ/VHQoImh0dHBzOi8vdW5wa2cuY29tL21lcm1haWRAMTEvZGlzdC9tZXJtYWlkLm1pbi5qcyIpOkkodm9pZCAwKX1mdW5jdGlvbiBXbihlKXtyZXR1cm4gZS5jbGFzc0xpc3QucmVtb3ZlKCJtZXJtYWlkIiksR3J8fChHcj1LYSgpLnBpcGUodygoKT0+bWVybWFpZC5pbml0aWFsaXplKHtzdGFydE9uTG9hZDohMSx0aGVtZUNTUzpVbixzZXF1ZW5jZTp7YWN0b3JGb250U2l6ZToiMTZweCIsbWVzc2FnZUZvbnRTaXplOiIxNnB4Iixub3RlRm9udFNpemU6IjE2cHgifX0pKSxtKCgpPT57fSksRygxKSkpLEdyLnN1YnNjcmliZSgoKT0+Y28odGhpcyxudWxsLGZ1bmN0aW9uKigpe2UuY2xhc3NMaXN0LmFkZCgibWVybWFpZCIpO2xldCB0PWBfX21lcm1haWRfJHtRYSsrfWAscj14KCJkaXYiLHtjbGFzczoibWVybWFpZCJ9KSxvPWUudGV4dENvbnRlbnQse3N2ZzpuLGZuOml9PXlpZWxkIG1lcm1haWQucmVuZGVyKHQsbyksYT1yLmF0dGFjaFNoYWRvdyh7bW9kZToiY2xvc2VkIn0pO2EuaW5uZXJIVE1MPW4sZS5yZXBsYWNlV2l0aChyKSxpPT1udWxsfHxpKGEpfSkpLEdyLnBpcGUobSgoKT0+KHtyZWY6ZX0pKSl9dmFyIERuPXgoInRhYmxlIik7ZnVuY3Rpb24gVm4oZSl7cmV0dXJuIGUucmVwbGFjZVdpdGgoRG4pLERuLnJlcGxhY2VXaXRoKEFuKGUpKSxJKHtyZWY6ZX0pfWZ1bmN0aW9uIFlhKGUpe2xldCB0PWUuZmluZChyPT5yLmNoZWNrZWQpfHxlWzBdO3JldHVybiBPKC4uLmUubWFwKHI9PmgociwiY2hhbmdlIikucGlwZShtKCgpPT5SKGBsYWJlbFtmb3I9IiR7ci5pZH0iXWApKSkpKS5waXBlKFEoUihgbGFiZWxbZm9yPSIke3QuaWR9Il1gKSksbShyPT4oe2FjdGl2ZTpyfSkpKX1mdW5jdGlvbiBObihlLHt2aWV3cG9ydCQ6dCx0YXJnZXQkOnJ9KXtsZXQgbz1SKCIudGFiYmVkLWxhYmVscyIsZSksbj1QKCI6c2NvcGUgPiBpbnB1dCIsZSksaT1LcigicHJldiIpO2UuYXBwZW5kKGkpO2xldCBhPUtyKCJuZXh0Iik7cmV0dXJuIGUuYXBwZW5kKGEpLEMoKCk9PntsZXQgcz1uZXcgZyxwPXMucGlwZShaKCksaWUoITApKTt6KFtzLGdlKGUpLHR0KGUpXSkucGlwZShXKHApLE1lKDEsbWUpKS5zdWJzY3JpYmUoe25leHQoW3thY3RpdmU6Y30sbF0pe2xldCBmPVZlKGMpLHt3aWR0aDp1fT1jZShjKTtlLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLWluZGljYXRvci14IixgJHtmLnh9cHhgKSxlLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLWluZGljYXRvci13aWR0aCIsYCR7dX1weGApO2xldCBkPXByKG8pOyhmLng8ZC54fHxmLngrdT5kLngrbC53aWR0aCkmJm8uc2Nyb2xsVG8oe2xlZnQ6TWF0aC5tYXgoMCxmLngtMTYpLGJlaGF2aW9yOiJzbW9vdGgifSl9LGNvbXBsZXRlKCl7ZS5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgiLS1tZC1pbmRpY2F0b3IteCIpLGUuc3R5bGUucmVtb3ZlUHJvcGVydHkoIi0tbWQtaW5kaWNhdG9yLXdpZHRoIil9fSkseihbTmUobyksZ2UobyldKS5waXBlKFcocCkpLnN1YnNjcmliZSgoW2MsbF0pPT57bGV0IGY9U3Qobyk7aS5oaWRkZW49Yy54PDE2LGEuaGlkZGVuPWMueD5mLndpZHRoLWwud2lkdGgtMTZ9KSxPKGgoaSwiY2xpY2siKS5waXBlKG0oKCk9Pi0xKSksaChhLCJjbGljayIpLnBpcGUobSgoKT0+MSkpKS5waXBlKFcocCkpLnN1YnNjcmliZShjPT57bGV0e3dpZHRoOmx9PWNlKG8pO28uc2Nyb2xsQnkoe2xlZnQ6bCpjLGJlaGF2aW9yOiJzbW9vdGgifSl9KSxyLnBpcGUoVyhwKSxiKGM9Pm4uaW5jbHVkZXMoYykpKS5zdWJzY3JpYmUoYz0+Yy5jbGljaygpKSxvLmNsYXNzTGlzdC5hZGQoInRhYmJlZC1sYWJlbHMtLWxpbmtlZCIpO2ZvcihsZXQgYyBvZiBuKXtsZXQgbD1SKGBsYWJlbFtmb3I9IiR7Yy5pZH0iXWApO2wucmVwbGFjZUNoaWxkcmVuKHgoImEiLHtocmVmOmAjJHtsLmh0bWxGb3J9YCx0YWJJbmRleDotMX0sLi4uQXJyYXkuZnJvbShsLmNoaWxkTm9kZXMpKSksaChsLmZpcnN0RWxlbWVudENoaWxkLCJjbGljayIpLnBpcGUoVyhwKSxiKGY9PiEoZi5tZXRhS2V5fHxmLmN0cmxLZXkpKSx3KGY9PntmLnByZXZlbnREZWZhdWx0KCksZi5zdG9wUHJvcGFnYXRpb24oKX0pKS5zdWJzY3JpYmUoKCk9PntoaXN0b3J5LnJlcGxhY2VTdGF0ZSh7fSwiIixgIyR7bC5odG1sRm9yfWApLGwuY2xpY2soKX0pfXJldHVybiBCKCJjb250ZW50LnRhYnMubGluayIpJiZzLnBpcGUoQ2UoMSkscmUodCkpLnN1YnNjcmliZSgoW3thY3RpdmU6Y30se29mZnNldDpsfV0pPT57bGV0IGY9Yy5pbm5lclRleHQudHJpbSgpO2lmKGMuaGFzQXR0cmlidXRlKCJkYXRhLW1kLXN3aXRjaGluZyIpKWMucmVtb3ZlQXR0cmlidXRlKCJkYXRhLW1kLXN3aXRjaGluZyIpO2Vsc2V7bGV0IHU9ZS5vZmZzZXRUb3AtbC55O2ZvcihsZXQgeSBvZiBQKCJbZGF0YS10YWJzXSIpKWZvcihsZXQgTCBvZiBQKCI6c2NvcGUgPiBpbnB1dCIseSkpe2xldCBYPVIoYGxhYmVsW2Zvcj0iJHtMLmlkfSJdYCk7aWYoWCE9PWMmJlguaW5uZXJUZXh0LnRyaW0oKT09PWYpe1guc2V0QXR0cmlidXRlKCJkYXRhLW1kLXN3aXRjaGluZyIsIiIpLEwuY2xpY2soKTticmVha319d2luZG93LnNjcm9sbFRvKHt0b3A6ZS5vZmZzZXRUb3AtdX0pO2xldCBkPV9fbWRfZ2V0KCJfX3RhYnMiKXx8W107X19tZF9zZXQoIl9fdGFicyIsWy4uLm5ldyBTZXQoW2YsLi4uZF0pXSl9fSkscy5waXBlKFcocCkpLnN1YnNjcmliZSgoKT0+e2ZvcihsZXQgYyBvZiBQKCJhdWRpbywgdmlkZW8iLGUpKWMucGF1c2UoKX0pLFlhKG4pLnBpcGUodyhjPT5zLm5leHQoYykpLF8oKCk9PnMuY29tcGxldGUoKSksbShjPT4kKHtyZWY6ZX0sYykpKX0pLnBpcGUoS2Uoc2UpKX1mdW5jdGlvbiB6bihlLHt2aWV3cG9ydCQ6dCx0YXJnZXQkOnIscHJpbnQkOm99KXtyZXR1cm4gTyguLi5QKCIuYW5ub3RhdGU6bm90KC5oaWdobGlnaHQpIixlKS5tYXAobj0+UG4obix7dGFyZ2V0JDpyLHByaW50JDpvfSkpLC4uLlAoInByZTpub3QoLm1lcm1haWQpID4gY29kZSIsZSkubWFwKG49PmpuKG4se3RhcmdldCQ6cixwcmludCQ6b30pKSwuLi5QKCJwcmUubWVybWFpZCIsZSkubWFwKG49PlduKG4pKSwuLi5QKCJ0YWJsZTpub3QoW2NsYXNzXSkiLGUpLm1hcChuPT5WbihuKSksLi4uUCgiZGV0YWlscyIsZSkubWFwKG49PkZuKG4se3RhcmdldCQ6cixwcmludCQ6b30pKSwuLi5QKCJbZGF0YS10YWJzXSIsZSkubWFwKG49Pk5uKG4se3ZpZXdwb3J0JDp0LHRhcmdldCQ6cn0pKSwuLi5QKCJbdGl0bGVdIixlKS5maWx0ZXIoKCk9PkIoImNvbnRlbnQudG9vbHRpcHMiKSkubWFwKG49Pm10KG4se3ZpZXdwb3J0JDp0fSkpKX1mdW5jdGlvbiBCYShlLHthbGVydCQ6dH0pe3JldHVybiB0LnBpcGUodihyPT5PKEkoITApLEkoITEpLnBpcGUoR2UoMmUzKSkpLnBpcGUobShvPT4oe21lc3NhZ2U6cixhY3RpdmU6b30pKSkpKX1mdW5jdGlvbiBxbihlLHQpe2xldCByPVIoIi5tZC10eXBlc2V0IixlKTtyZXR1cm4gQygoKT0+e2xldCBvPW5ldyBnO3JldHVybiBvLnN1YnNjcmliZSgoe21lc3NhZ2U6bixhY3RpdmU6aX0pPT57ZS5jbGFzc0xpc3QudG9nZ2xlKCJtZC1kaWFsb2ctLWFjdGl2ZSIsaSksci50ZXh0Q29udGVudD1ufSksQmEoZSx0KS5waXBlKHcobj0+by5uZXh0KG4pKSxfKCgpPT5vLmNvbXBsZXRlKCkpLG0obj0+JCh7cmVmOmV9LG4pKSl9KX12YXIgR2E9MDtmdW5jdGlvbiBKYShlLHQpe2RvY3VtZW50LmJvZHkuYXBwZW5kKGUpO2xldHt3aWR0aDpyfT1jZShlKTtlLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLXRvb2x0aXAtd2lkdGgiLGAke3J9cHhgKSxlLnJlbW92ZSgpO2xldCBvPWNyKHQpLG49dHlwZW9mIG8hPSJ1bmRlZmluZWQiP05lKG8pOkkoe3g6MCx5OjB9KSxpPU8oZXQodCksJHQodCkpLnBpcGUoSygpKTtyZXR1cm4geihbaSxuXSkucGlwZShtKChbYSxzXSk9PntsZXR7eDpwLHk6Y309VmUodCksbD1jZSh0KSxmPXQuY2xvc2VzdCgidGFibGUiKTtyZXR1cm4gZiYmdC5wYXJlbnRFbGVtZW50JiYocCs9Zi5vZmZzZXRMZWZ0K3QucGFyZW50RWxlbWVudC5vZmZzZXRMZWZ0LGMrPWYub2Zmc2V0VG9wK3QucGFyZW50RWxlbWVudC5vZmZzZXRUb3ApLHthY3RpdmU6YSxvZmZzZXQ6e3g6cC1zLngrbC53aWR0aC8yLXIvMix5OmMtcy55K2wuaGVpZ2h0Kzh9fX0pKX1mdW5jdGlvbiBRbihlKXtsZXQgdD1lLnRpdGxlO2lmKCF0Lmxlbmd0aClyZXR1cm4gUztsZXQgcj1gX190b29sdGlwXyR7R2ErK31gLG89UnQociwiaW5saW5lIiksbj1SKCIubWQtdHlwZXNldCIsbyk7cmV0dXJuIG4uaW5uZXJIVE1MPXQsQygoKT0+e2xldCBpPW5ldyBnO3JldHVybiBpLnN1YnNjcmliZSh7bmV4dCh7b2Zmc2V0OmF9KXtvLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLXRvb2x0aXAteCIsYCR7YS54fXB4YCksby5zdHlsZS5zZXRQcm9wZXJ0eSgiLS1tZC10b29sdGlwLXkiLGAke2EueX1weGApfSxjb21wbGV0ZSgpe28uc3R5bGUucmVtb3ZlUHJvcGVydHkoIi0tbWQtdG9vbHRpcC14Iiksby5zdHlsZS5yZW1vdmVQcm9wZXJ0eSgiLS1tZC10b29sdGlwLXkiKX19KSxPKGkucGlwZShiKCh7YWN0aXZlOmF9KT0+YSkpLGkucGlwZShfZSgyNTApLGIoKHthY3RpdmU6YX0pPT4hYSkpKS5zdWJzY3JpYmUoe25leHQoe2FjdGl2ZTphfSl7YT8oZS5pbnNlcnRBZGphY2VudEVsZW1lbnQoImFmdGVyZW5kIixvKSxlLnNldEF0dHJpYnV0ZSgiYXJpYS1kZXNjcmliZWRieSIsciksZS5yZW1vdmVBdHRyaWJ1dGUoInRpdGxlIikpOihvLnJlbW92ZSgpLGUucmVtb3ZlQXR0cmlidXRlKCJhcmlhLWRlc2NyaWJlZGJ5IiksZS5zZXRBdHRyaWJ1dGUoInRpdGxlIix0KSl9LGNvbXBsZXRlKCl7by5yZW1vdmUoKSxlLnJlbW92ZUF0dHJpYnV0ZSgiYXJpYS1kZXNjcmliZWRieSIpLGUuc2V0QXR0cmlidXRlKCJ0aXRsZSIsdCl9fSksaS5waXBlKE1lKDE2LG1lKSkuc3Vic2NyaWJlKCh7YWN0aXZlOmF9KT0+e28uY2xhc3NMaXN0LnRvZ2dsZSgibWQtdG9vbHRpcC0tYWN0aXZlIixhKX0pLGkucGlwZShwdCgxMjUsbWUpLGIoKCk9PiEhZS5vZmZzZXRQYXJlbnQpLG0oKCk9PmUub2Zmc2V0UGFyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpKSxtKCh7eDphfSk9PmEpKS5zdWJzY3JpYmUoe25leHQoYSl7YT9vLnN0eWxlLnNldFByb3BlcnR5KCItLW1kLXRvb2x0aXAtMCIsYCR7LWF9cHhgKTpvLnN0eWxlLnJlbW92ZVByb3BlcnR5KCItLW1kLXRvb2x0aXAtMCIpfSxjb21wbGV0ZSgpe28uc3R5bGUucmVtb3ZlUHJvcGVydHkoIi0tbWQtdG9vbHRpcC0wIil9fSksSmEobyxlKS5waXBlKHcoYT0+aS5uZXh0KGEpKSxfKCgpPT5pLmNvbXBsZXRlKCkpLG0oYT0+JCh7cmVmOmV9LGEpKSl9KS5waXBlKEtlKHNlKSl9ZnVuY3Rpb24gWGEoe3ZpZXdwb3J0JDplfSl7aWYoIUIoImhlYWRlci5hdXRvaGlkZSIpKXJldHVybiBJKCExKTtsZXQgdD1lLnBpcGUobSgoe29mZnNldDp7eTpufX0pPT5uKSxCZSgyLDEpLG0oKFtuLGldKT0+W248aSxpXSksZWUoMCkpLHI9eihbZSx0XSkucGlwZShiKChbe29mZnNldDpufSxbLGldXSk9Pk1hdGguYWJzKGktbi55KT4xMDApLG0oKFssW25dXSk9Pm4pLEsoKSksbz16ZSgic2VhcmNoIik7cmV0dXJuIHooW2Usb10pLnBpcGUobSgoW3tvZmZzZXQ6bn0saV0pPT5uLnk+NDAwJiYhaSksSygpLHYobj0+bj9yOkkoITEpKSxRKCExKSl9ZnVuY3Rpb24gS24oZSx0KXtyZXR1cm4gQygoKT0+eihbZ2UoZSksWGEodCldKSkucGlwZShtKChbe2hlaWdodDpyfSxvXSk9Pih7aGVpZ2h0OnIsaGlkZGVuOm99KSksSygocixvKT0+ci5oZWlnaHQ9PT1vLmhlaWdodCYmci5oaWRkZW49PT1vLmhpZGRlbiksRygxKSl9ZnVuY3Rpb24gWW4oZSx7aGVhZGVyJDp0LG1haW4kOnJ9KXtyZXR1cm4gQygoKT0+e2xldCBvPW5ldyBnLG49by5waXBlKFooKSxpZSghMCkpO28ucGlwZShlZSgiYWN0aXZlIiksSGUodCkpLnN1YnNjcmliZSgoW3thY3RpdmU6YX0se2hpZGRlbjpzfV0pPT57ZS5jbGFzc0xpc3QudG9nZ2xlKCJtZC1oZWFkZXItLXNoYWRvdyIsYSYmIXMpLGUuaGlkZGVuPXN9KTtsZXQgaT11ZShQKCJbdGl0bGVdIixlKSkucGlwZShiKCgpPT5CKCJjb250ZW50LnRvb2x0aXBzIikpLG5lKGE9PlFuKGEpKSk7cmV0dXJuIHIuc3Vic2NyaWJlKG8pLHQucGlwZShXKG4pLG0oYT0+JCh7cmVmOmV9LGEpKSxSZShpLnBpcGUoVyhuKSkpKX0pfWZ1bmN0aW9uIFphKGUse3ZpZXdwb3J0JDp0LGhlYWRlciQ6cn0pe3JldHVybiBtcihlLHt2aWV3cG9ydCQ6dCxoZWFkZXIkOnJ9KS5waXBlKG0oKHtvZmZzZXQ6e3k6b319KT0+e2xldHtoZWlnaHQ6bn09Y2UoZSk7cmV0dXJue2FjdGl2ZTpvPj1ufX0pLGVlKCJhY3RpdmUiKSl9ZnVuY3Rpb24gQm4oZSx0KXtyZXR1cm4gQygoKT0+e2xldCByPW5ldyBnO3Iuc3Vic2NyaWJlKHtuZXh0KHthY3RpdmU6bn0pe2UuY2xhc3NMaXN0LnRvZ2dsZSgibWQtaGVhZGVyX190aXRsZS0tYWN0aXZlIixuKX0sY29tcGxldGUoKXtlLmNsYXNzTGlzdC5yZW1vdmUoIm1kLWhlYWRlcl9fdGl0bGUtLWFjdGl2ZSIpfX0pO2xldCBvPWZlKCIubWQtY29udGVudCBoMSIpO3JldHVybiB0eXBlb2Ygbz09InVuZGVmaW5lZCI/UzpaYShvLHQpLnBpcGUodyhuPT5yLm5leHQobikpLF8oKCk9PnIuY29tcGxldGUoKSksbShuPT4kKHtyZWY6ZX0sbikpKX0pfWZ1bmN0aW9uIEduKGUse3ZpZXdwb3J0JDp0LGhlYWRlciQ6cn0pe2xldCBvPXIucGlwZShtKCh7aGVpZ2h0Oml9KT0+aSksSygpKSxuPW8ucGlwZSh2KCgpPT5nZShlKS5waXBlKG0oKHtoZWlnaHQ6aX0pPT4oe3RvcDplLm9mZnNldFRvcCxib3R0b206ZS5vZmZzZXRUb3AraX0pKSxlZSgiYm90dG9tIikpKSk7cmV0dXJuIHooW28sbix0XSkucGlwZShtKChbaSx7dG9wOmEsYm90dG9tOnN9LHtvZmZzZXQ6e3k6cH0sc2l6ZTp7aGVpZ2h0OmN9fV0pPT4oYz1NYXRoLm1heCgwLGMtTWF0aC5tYXgoMCxhLXAsaSktTWF0aC5tYXgoMCxjK3AtcykpLHtvZmZzZXQ6YS1pLGhlaWdodDpjLGFjdGl2ZTphLWk8PXB9KSksSygoaSxhKT0+aS5vZmZzZXQ9PT1hLm9mZnNldCYmaS5oZWlnaHQ9PT1hLmhlaWdodCYmaS5hY3RpdmU9PT1hLmFjdGl2ZSkpfWZ1bmN0aW9uIGVzKGUpe2xldCB0PV9fbWRfZ2V0KCJfX3BhbGV0dGUiKXx8e2luZGV4OmUuZmluZEluZGV4KG89Pm1hdGNoTWVkaWEoby5nZXRBdHRyaWJ1dGUoImRhdGEtbWQtY29sb3ItbWVkaWEiKSkubWF0Y2hlcyl9LHI9TWF0aC5tYXgoMCxNYXRoLm1pbih0LmluZGV4LGUubGVuZ3RoLTEpKTtyZXR1cm4gSSguLi5lKS5waXBlKG5lKG89PmgobywiY2hhbmdlIikucGlwZShtKCgpPT5vKSkpLFEoZVtyXSksbShvPT4oe2luZGV4OmUuaW5kZXhPZihvKSxjb2xvcjp7bWVkaWE6by5nZXRBdHRyaWJ1dGUoImRhdGEtbWQtY29sb3ItbWVkaWEiKSxzY2hlbWU6by5nZXRBdHRyaWJ1dGUoImRhdGEtbWQtY29sb3Itc2NoZW1lIikscHJpbWFyeTpvLmdldEF0dHJpYnV0ZSgiZGF0YS1tZC1jb2xvci1wcmltYXJ5IiksYWNjZW50Om8uZ2V0QXR0cmlidXRlKCJkYXRhLW1kLWNvbG9yLWFjY2VudCIpfX0pKSxHKDEpKX1mdW5jdGlvbiBKbihlKXtsZXQgdD1QKCJpbnB1dCIsZSkscj14KCJtZXRhIix7bmFtZToidGhlbWUtY29sb3IifSk7ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChyKTtsZXQgbz14KCJtZXRhIix7bmFtZToiY29sb3Itc2NoZW1lIn0pO2RvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQobyk7bGV0IG49UHQoIihwcmVmZXJzLWNvbG9yLXNjaGVtZTogbGlnaHQpIik7cmV0dXJuIEMoKCk9PntsZXQgaT1uZXcgZztyZXR1cm4gaS5zdWJzY3JpYmUoYT0+e2lmKGRvY3VtZW50LmJvZHkuc2V0QXR0cmlidXRlKCJkYXRhLW1kLWNvbG9yLXN3aXRjaGluZyIsIiIpLGEuY29sb3IubWVkaWE9PT0iKHByZWZlcnMtY29sb3Itc2NoZW1lKSIpe2xldCBzPW1hdGNoTWVkaWEoIihwcmVmZXJzLWNvbG9yLXNjaGVtZTogbGlnaHQpIikscD1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKHMubWF0Y2hlcz8iW2RhdGEtbWQtY29sb3ItbWVkaWE9JyhwcmVmZXJzLWNvbG9yLXNjaGVtZTogbGlnaHQpJ10iOiJbZGF0YS1tZC1jb2xvci1tZWRpYT0nKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKSddIik7YS5jb2xvci5zY2hlbWU9cC5nZXRBdHRyaWJ1dGUoImRhdGEtbWQtY29sb3Itc2NoZW1lIiksYS5jb2xvci5wcmltYXJ5PXAuZ2V0QXR0cmlidXRlKCJkYXRhLW1kLWNvbG9yLXByaW1hcnkiKSxhLmNvbG9yLmFjY2VudD1wLmdldEF0dHJpYnV0ZSgiZGF0YS1tZC1jb2xvci1hY2NlbnQiKX1mb3IobGV0W3MscF1vZiBPYmplY3QuZW50cmllcyhhLmNvbG9yKSlkb2N1bWVudC5ib2R5LnNldEF0dHJpYnV0ZShgZGF0YS1tZC1jb2xvci0ke3N9YCxwKTtmb3IobGV0IHM9MDtzPHQubGVuZ3RoO3MrKyl7bGV0IHA9dFtzXS5uZXh0RWxlbWVudFNpYmxpbmc7cCBpbnN0YW5jZW9mIEhUTUxFbGVtZW50JiYocC5oaWRkZW49YS5pbmRleCE9PXMpfV9fbWRfc2V0KCJfX3BhbGV0dGUiLGEpfSksaChlLCJrZXlkb3duIikucGlwZShiKGE9PmEua2V5PT09IkVudGVyIikscmUoaSwoYSxzKT0+cykpLnN1YnNjcmliZSgoe2luZGV4OmF9KT0+e2E9KGErMSkldC5sZW5ndGgsdFthXS5jbGljaygpLHRbYV0uZm9jdXMoKX0pLGkucGlwZShtKCgpPT57bGV0IGE9U2UoImhlYWRlciIpLHM9d2luZG93LmdldENvbXB1dGVkU3R5bGUoYSk7cmV0dXJuIG8uY29udGVudD1zLmNvbG9yU2NoZW1lLHMuYmFja2dyb3VuZENvbG9yLm1hdGNoKC9cZCsvZykubWFwKHA9PigrcCkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsIjAiKSkuam9pbigiIil9KSkuc3Vic2NyaWJlKGE9PnIuY29udGVudD1gIyR7YX1gKSxpLnBpcGUodmUoc2UpKS5zdWJzY3JpYmUoKCk9Pntkb2N1bWVudC5ib2R5LnJlbW92ZUF0dHJpYnV0ZSgiZGF0YS1tZC1jb2xvci1zd2l0Y2hpbmciKX0pLGVzKHQpLnBpcGUoVyhuLnBpcGUoQ2UoMSkpKSxjdCgpLHcoYT0+aS5uZXh0KGEpKSxfKCgpPT5pLmNvbXBsZXRlKCkpLG0oYT0+JCh7cmVmOmV9LGEpKSl9KX1mdW5jdGlvbiBYbihlLHtwcm9ncmVzcyQ6dH0pe3JldHVybiBDKCgpPT57bGV0IHI9bmV3IGc7cmV0dXJuIHIuc3Vic2NyaWJlKCh7dmFsdWU6b30pPT57ZS5zdHlsZS5zZXRQcm9wZXJ0eSgiLS1tZC1wcm9ncmVzcy12YWx1ZSIsYCR7b31gKX0pLHQucGlwZSh3KG89PnIubmV4dCh7dmFsdWU6b30pKSxfKCgpPT5yLmNvbXBsZXRlKCkpLG0obz0+KHtyZWY6ZSx2YWx1ZTpvfSkpKX0pfXZhciBKcj1NdChCcigpKTtmdW5jdGlvbiB0cyhlKXtlLnNldEF0dHJpYnV0ZSgiZGF0YS1tZC1jb3B5aW5nIiwiIik7bGV0IHQ9ZS5jbG9zZXN0KCJbZGF0YS1jb3B5XSIpLHI9dD90LmdldEF0dHJpYnV0ZSgiZGF0YS1jb3B5Iik6ZS5pbm5lclRleHQ7cmV0dXJuIGUucmVtb3ZlQXR0cmlidXRlKCJkYXRhLW1kLWNvcHlpbmciKSxyLnRyaW1FbmQoKX1mdW5jdGlvbiBabih7YWxlcnQkOmV9KXtKci5kZWZhdWx0LmlzU3VwcG9ydGVkKCkmJm5ldyBqKHQ9PntuZXcgSnIuZGVmYXVsdCgiW2RhdGEtY2xpcGJvYXJkLXRhcmdldF0sIFtkYXRhLWNsaXBib2FyZC10ZXh0XSIse3RleHQ6cj0+ci5nZXRBdHRyaWJ1dGUoImRhdGEtY2xpcGJvYXJkLXRleHQiKXx8dHMoUihyLmdldEF0dHJpYnV0ZSgiZGF0YS1jbGlwYm9hcmQtdGFyZ2V0IikpKX0pLm9uKCJzdWNjZXNzIixyPT50Lm5leHQocikpfSkucGlwZSh3KHQ9Pnt0LnRyaWdnZXIuZm9jdXMoKX0pLG0oKCk9PkVlKCJjbGlwYm9hcmQuY29waWVkIikpKS5zdWJzY3JpYmUoZSl9ZnVuY3Rpb24gZWkoZSx0KXtyZXR1cm4gZS5wcm90b2NvbD10LnByb3RvY29sLGUuaG9zdG5hbWU9dC5ob3N0bmFtZSxlfWZ1bmN0aW9uIHJzKGUsdCl7bGV0IHI9bmV3IE1hcDtmb3IobGV0IG8gb2YgUCgidXJsIixlKSl7bGV0IG49UigibG9jIixvKSxpPVtlaShuZXcgVVJMKG4udGV4dENvbnRlbnQpLHQpXTtyLnNldChgJHtpWzBdfWAsaSk7Zm9yKGxldCBhIG9mIFAoIltyZWw9YWx0ZXJuYXRlXSIsbykpe2xldCBzPWEuZ2V0QXR0cmlidXRlKCJocmVmIik7cyE9bnVsbCYmaS5wdXNoKGVpKG5ldyBVUkwocyksdCkpfX1yZXR1cm4gcn1mdW5jdGlvbiB1cihlKXtyZXR1cm4gdW4obmV3IFVSTCgic2l0ZW1hcC54bWwiLGUpKS5waXBlKG0odD0+cnModCxuZXcgVVJMKGUpKSksZGUoKCk9PkkobmV3IE1hcCkpKX1mdW5jdGlvbiBvcyhlLHQpe2lmKCEoZS50YXJnZXQgaW5zdGFuY2VvZiBFbGVtZW50KSlyZXR1cm4gUztsZXQgcj1lLnRhcmdldC5jbG9zZXN0KCJhIik7aWYocj09PW51bGwpcmV0dXJuIFM7aWYoci50YXJnZXR8fGUubWV0YUtleXx8ZS5jdHJsS2V5KXJldHVybiBTO2xldCBvPW5ldyBVUkwoci5ocmVmKTtyZXR1cm4gby5zZWFyY2g9by5oYXNoPSIiLHQuaGFzKGAke299YCk/KGUucHJldmVudERlZmF1bHQoKSxJKG5ldyBVUkwoci5ocmVmKSkpOlN9ZnVuY3Rpb24gdGkoZSl7bGV0IHQ9bmV3IE1hcDtmb3IobGV0IHIgb2YgUCgiOnNjb3BlID4gKiIsZS5oZWFkKSl0LnNldChyLm91dGVySFRNTCxyKTtyZXR1cm4gdH1mdW5jdGlvbiByaShlKXtmb3IobGV0IHQgb2YgUCgiW2hyZWZdLCBbc3JjXSIsZSkpZm9yKGxldCByIG9mWyJocmVmIiwic3JjIl0pe2xldCBvPXQuZ2V0QXR0cmlidXRlKHIpO2lmKG8mJiEvXig/OlthLXpdKzopP1wvXC8vaS50ZXN0KG8pKXt0W3JdPXRbcl07YnJlYWt9fXJldHVybiBJKGUpfWZ1bmN0aW9uIG5zKGUpe2ZvcihsZXQgbyBvZlsiW2RhdGEtbWQtY29tcG9uZW50PWFubm91bmNlXSIsIltkYXRhLW1kLWNvbXBvbmVudD1jb250YWluZXJdIiwiW2RhdGEtbWQtY29tcG9uZW50PWhlYWRlci10b3BpY10iLCJbZGF0YS1tZC1jb21wb25lbnQ9b3V0ZGF0ZWRdIiwiW2RhdGEtbWQtY29tcG9uZW50PWxvZ29dIiwiW2RhdGEtbWQtY29tcG9uZW50PXNraXBdIiwuLi5CKCJuYXZpZ2F0aW9uLnRhYnMuc3RpY2t5Iik/WyJbZGF0YS1tZC1jb21wb25lbnQ9dGFic10iXTpbXV0pe2xldCBuPWZlKG8pLGk9ZmUobyxlKTt0eXBlb2YgbiE9InVuZGVmaW5lZCImJnR5cGVvZiBpIT0idW5kZWZpbmVkIiYmbi5yZXBsYWNlV2l0aChpKX1sZXQgdD10aShkb2N1bWVudCk7Zm9yKGxldFtvLG5db2YgdGkoZSkpdC5oYXMobyk/dC5kZWxldGUobyk6ZG9jdW1lbnQuaGVhZC5hcHBlbmRDaGlsZChuKTtmb3IobGV0IG8gb2YgdC52YWx1ZXMoKSl7bGV0IG49by5nZXRBdHRyaWJ1dGUoIm5hbWUiKTtuIT09InRoZW1lLWNvbG9yIiYmbiE9PSJjb2xvci1zY2hlbWUiJiZvLnJlbW92ZSgpfWxldCByPVNlKCJjb250YWluZXIiKTtyZXR1cm4gV2UoUCgic2NyaXB0IixyKSkucGlwZSh2KG89PntsZXQgbj1lLmNyZWF0ZUVsZW1lbnQoInNjcmlwdCIpO2lmKG8uc3JjKXtmb3IobGV0IGkgb2Ygby5nZXRBdHRyaWJ1dGVOYW1lcygpKW4uc2V0QXR0cmlidXRlKGksby5nZXRBdHRyaWJ1dGUoaSkpO3JldHVybiBvLnJlcGxhY2VXaXRoKG4pLG5ldyBqKGk9PntuLm9ubG9hZD0oKT0+aS5jb21wbGV0ZSgpfSl9ZWxzZSByZXR1cm4gbi50ZXh0Q29udGVudD1vLnRleHRDb250ZW50LG8ucmVwbGFjZVdpdGgobiksU30pLFooKSxpZShkb2N1bWVudCkpfWZ1bmN0aW9uIG9pKHtsb2NhdGlvbiQ6ZSx2aWV3cG9ydCQ6dCxwcm9ncmVzcyQ6cn0pe2xldCBvPXhlKCk7aWYobG9jYXRpb24ucHJvdG9jb2w9PT0iZmlsZToiKXJldHVybiBTO2xldCBuPXVyKG8uYmFzZSk7SShkb2N1bWVudCkuc3Vic2NyaWJlKHJpKTtsZXQgaT1oKGRvY3VtZW50LmJvZHksImNsaWNrIikucGlwZShIZShuKSx2KChbcCxjXSk9Pm9zKHAsYykpLHBlKCkpLGE9aCh3aW5kb3csInBvcHN0YXRlIikucGlwZShtKHllKSxwZSgpKTtpLnBpcGUocmUodCkpLnN1YnNjcmliZSgoW3Ase29mZnNldDpjfV0pPT57aGlzdG9yeS5yZXBsYWNlU3RhdGUoYywiIiksaGlzdG9yeS5wdXNoU3RhdGUobnVsbCwiIixwKX0pLE8oaSxhKS5zdWJzY3JpYmUoZSk7bGV0IHM9ZS5waXBlKGVlKCJwYXRobmFtZSIpLHYocD0+Zm4ocCx7cHJvZ3Jlc3MkOnJ9KS5waXBlKGRlKCgpPT4obHQocCwhMCksUykpKSksdihyaSksdihucykscGUoKSk7cmV0dXJuIE8ocy5waXBlKHJlKGUsKHAsYyk9PmMpKSxzLnBpcGUodigoKT0+ZSksZWUoInBhdGhuYW1lIiksdigoKT0+ZSksZWUoImhhc2giKSksZS5waXBlKEsoKHAsYyk9PnAucGF0aG5hbWU9PT1jLnBhdGhuYW1lJiZwLmhhc2g9PT1jLmhhc2gpLHYoKCk9PmkpLHcoKCk9Pmhpc3RvcnkuYmFjaygpKSkpLnN1YnNjcmliZShwPT57dmFyIGMsbDtoaXN0b3J5LnN0YXRlIT09bnVsbHx8IXAuaGFzaD93aW5kb3cuc2Nyb2xsVG8oMCwobD0oYz1oaXN0b3J5LnN0YXRlKT09bnVsbD92b2lkIDA6Yy55KSE9bnVsbD9sOjApOihoaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uPSJhdXRvIixwbihwLmhhc2gpLGhpc3Rvcnkuc2Nyb2xsUmVzdG9yYXRpb249Im1hbnVhbCIpfSksZS5zdWJzY3JpYmUoKCk9PntoaXN0b3J5LnNjcm9sbFJlc3RvcmF0aW9uPSJtYW51YWwifSksaCh3aW5kb3csImJlZm9yZXVubG9hZCIpLnN1YnNjcmliZSgoKT0+e2hpc3Rvcnkuc2Nyb2xsUmVzdG9yYXRpb249ImF1dG8ifSksdC5waXBlKGVlKCJvZmZzZXQiKSxfZSgxMDApKS5zdWJzY3JpYmUoKHtvZmZzZXQ6cH0pPT57aGlzdG9yeS5yZXBsYWNlU3RhdGUocCwiIil9KSxzfXZhciBuaT1NdChxcigpKTtmdW5jdGlvbiBpaShlKXtsZXQgdD1lLnNlcGFyYXRvci5zcGxpdCgifCIpLm1hcChuPT5uLnJlcGxhY2UoLyhcKFw/WyE9PF1bXildK1wpKS9nLCIiKS5sZW5ndGg9PT0wPyJcdUZGRkQiOm4pLmpvaW4oInwiKSxyPW5ldyBSZWdFeHAodCwiaW1nIiksbz0obixpLGEpPT5gJHtpfTxtYXJrIGRhdGEtbWQtaGlnaGxpZ2h0PiR7YX08L21hcms+YDtyZXR1cm4gbj0+e249bi5yZXBsYWNlKC9bXHMqK1wtOn5eXSsvZywiICIpLnRyaW0oKTtsZXQgaT1uZXcgUmVnRXhwKGAoXnwke2Uuc2VwYXJhdG9yfXwpKCR7bi5yZXBsYWNlKC9bfFxce30oKVtcXV4kKyo/Li1dL2csIlxcJCYiKS5yZXBsYWNlKHIsInwiKX0pYCwiaW1nIik7cmV0dXJuIGE9PigwLG5pLmRlZmF1bHQpKGEpLnJlcGxhY2UoaSxvKS5yZXBsYWNlKC88XC9tYXJrPihccyspPG1hcmtbXj5dKj4vaW1nLCIkMSIpfX1mdW5jdGlvbiBqdChlKXtyZXR1cm4gZS50eXBlPT09MX1mdW5jdGlvbiBkcihlKXtyZXR1cm4gZS50eXBlPT09M31mdW5jdGlvbiBhaShlLHQpe2xldCByPXluKGUpO3JldHVybiBPKEkobG9jYXRpb24ucHJvdG9jb2whPT0iZmlsZToiKSx6ZSgic2VhcmNoIikpLnBpcGUoQWUobz0+byksdigoKT0+dCkpLnN1YnNjcmliZSgoe2NvbmZpZzpvLGRvY3M6bn0pPT5yLm5leHQoe3R5cGU6MCxkYXRhOntjb25maWc6byxkb2NzOm4sb3B0aW9uczp7c3VnZ2VzdDpCKCJzZWFyY2guc3VnZ2VzdCIpfX19KSkscn1mdW5jdGlvbiBzaShlKXt2YXIgbDtsZXR7c2VsZWN0ZWRWZXJzaW9uU2l0ZW1hcDp0LHNlbGVjdGVkVmVyc2lvbkJhc2VVUkw6cixjdXJyZW50TG9jYXRpb246byxjdXJyZW50QmFzZVVSTDpufT1lLGk9KGw9WHIobikpPT1udWxsP3ZvaWQgMDpsLnBhdGhuYW1lO2lmKGk9PT12b2lkIDApcmV0dXJuO2xldCBhPXNzKG8ucGF0aG5hbWUsaSk7aWYoYT09PXZvaWQgMClyZXR1cm47bGV0IHM9cHModC5rZXlzKCkpO2lmKCF0LmhhcyhzKSlyZXR1cm47bGV0IHA9WHIoYSxzKTtpZighcHx8IXQuaGFzKHAuaHJlZikpcmV0dXJuO2xldCBjPVhyKGEscik7aWYoYylyZXR1cm4gYy5oYXNoPW8uaGFzaCxjLnNlYXJjaD1vLnNlYXJjaCxjfWZ1bmN0aW9uIFhyKGUsdCl7dHJ5e3JldHVybiBuZXcgVVJMKGUsdCl9Y2F0Y2gocil7cmV0dXJufX1mdW5jdGlvbiBzcyhlLHQpe2lmKGUuc3RhcnRzV2l0aCh0KSlyZXR1cm4gZS5zbGljZSh0Lmxlbmd0aCl9ZnVuY3Rpb24gY3MoZSx0KXtsZXQgcj1NYXRoLm1pbihlLmxlbmd0aCx0Lmxlbmd0aCksbztmb3Iobz0wO288ciYmZVtvXT09PXRbb107KytvKTtyZXR1cm4gb31mdW5jdGlvbiBwcyhlKXtsZXQgdDtmb3IobGV0IHIgb2YgZSl0PT09dm9pZCAwP3Q9cjp0PXQuc2xpY2UoMCxjcyh0LHIpKTtyZXR1cm4gdCE9bnVsbD90OiIifWZ1bmN0aW9uIGNpKHtkb2N1bWVudCQ6ZX0pe2xldCB0PXhlKCkscj1qZShuZXcgVVJMKCIuLi92ZXJzaW9ucy5qc29uIix0LmJhc2UpKS5waXBlKGRlKCgpPT5TKSksbz1yLnBpcGUobShuPT57bGV0WyxpXT10LmJhc2UubWF0Y2goLyhbXi9dKylcLz8kLyk7cmV0dXJuIG4uZmluZCgoe3ZlcnNpb246YSxhbGlhc2VzOnN9KT0+YT09PWl8fHMuaW5jbHVkZXMoaSkpfHxuWzBdfSkpO3IucGlwZShtKG49Pm5ldyBNYXAobi5tYXAoaT0+W2Ake25ldyBVUkwoYC4uLyR7aS52ZXJzaW9ufS9gLHQuYmFzZSl9YCxpXSkpKSx2KG49PmgoZG9jdW1lbnQuYm9keSwiY2xpY2siKS5waXBlKGIoaT0+IWkubWV0YUtleSYmIWkuY3RybEtleSkscmUobyksdigoW2ksYV0pPT57aWYoaS50YXJnZXQgaW5zdGFuY2VvZiBFbGVtZW50KXtsZXQgcz1pLnRhcmdldC5jbG9zZXN0KCJhIik7aWYocyYmIXMudGFyZ2V0JiZuLmhhcyhzLmhyZWYpKXtsZXQgcD1zLmhyZWY7cmV0dXJuIWkudGFyZ2V0LmNsb3Nlc3QoIi5tZC12ZXJzaW9uIikmJm4uZ2V0KHApPT09YT9TOihpLnByZXZlbnREZWZhdWx0KCksSShuZXcgVVJMKHApKSl9fXJldHVybiBTfSksdihpPT51cihpKS5waXBlKG0oYT0+e3ZhciBzO3JldHVybihzPXNpKHtzZWxlY3RlZFZlcnNpb25TaXRlbWFwOmEsc2VsZWN0ZWRWZXJzaW9uQmFzZVVSTDppLGN1cnJlbnRMb2NhdGlvbjp5ZSgpLGN1cnJlbnRCYXNlVVJMOnQuYmFzZX0pKSE9bnVsbD9zOml9KSkpKSkpLnN1YnNjcmliZShuPT5sdChuLCEwKSkseihbcixvXSkuc3Vic2NyaWJlKChbbixpXSk9PntSKCIubWQtaGVhZGVyX190b3BpYyIpLmFwcGVuZENoaWxkKENuKG4saSkpfSksZS5waXBlKHYoKCk9Pm8pKS5zdWJzY3JpYmUobj0+e3ZhciBhO2xldCBpPV9fbWRfZ2V0KCJfX291dGRhdGVkIixzZXNzaW9uU3RvcmFnZSk7aWYoaT09PW51bGwpe2k9ITA7bGV0IHM9KChhPXQudmVyc2lvbik9PW51bGw/dm9pZCAwOmEuZGVmYXVsdCl8fCJsYXRlc3QiO0FycmF5LmlzQXJyYXkocyl8fChzPVtzXSk7ZTpmb3IobGV0IHAgb2Ygcylmb3IobGV0IGMgb2Ygbi5hbGlhc2VzLmNvbmNhdChuLnZlcnNpb24pKWlmKG5ldyBSZWdFeHAocCwiaSIpLnRlc3QoYykpe2k9ITE7YnJlYWsgZX1fX21kX3NldCgiX19vdXRkYXRlZCIsaSxzZXNzaW9uU3RvcmFnZSl9aWYoaSlmb3IobGV0IHMgb2YgYWUoIm91dGRhdGVkIikpcy5oaWRkZW49ITF9KX1mdW5jdGlvbiBscyhlLHt3b3JrZXIkOnR9KXtsZXR7c2VhcmNoUGFyYW1zOnJ9PXllKCk7ci5oYXMoInEiKSYmKEplKCJzZWFyY2giLCEwKSxlLnZhbHVlPXIuZ2V0KCJxIiksZS5mb2N1cygpLHplKCJzZWFyY2giKS5waXBlKEFlKGk9PiFpKSkuc3Vic2NyaWJlKCgpPT57bGV0IGk9eWUoKTtpLnNlYXJjaFBhcmFtcy5kZWxldGUoInEiKSxoaXN0b3J5LnJlcGxhY2VTdGF0ZSh7fSwiIixgJHtpfWApfSkpO2xldCBvPWV0KGUpLG49Tyh0LnBpcGUoQWUoanQpKSxoKGUsImtleXVwIiksbykucGlwZShtKCgpPT5lLnZhbHVlKSxLKCkpO3JldHVybiB6KFtuLG9dKS5waXBlKG0oKFtpLGFdKT0+KHt2YWx1ZTppLGZvY3VzOmF9KSksRygxKSl9ZnVuY3Rpb24gcGkoZSx7d29ya2VyJDp0fSl7bGV0IHI9bmV3IGcsbz1yLnBpcGUoWigpLGllKCEwKSk7eihbdC5waXBlKEFlKGp0KSkscl0sKGksYSk9PmEpLnBpcGUoZWUoInZhbHVlIikpLnN1YnNjcmliZSgoe3ZhbHVlOml9KT0+dC5uZXh0KHt0eXBlOjIsZGF0YTppfSkpLHIucGlwZShlZSgiZm9jdXMiKSkuc3Vic2NyaWJlKCh7Zm9jdXM6aX0pPT57aSYmSmUoInNlYXJjaCIsaSl9KSxoKGUuZm9ybSwicmVzZXQiKS5waXBlKFcobykpLnN1YnNjcmliZSgoKT0+ZS5mb2N1cygpKTtsZXQgbj1SKCJoZWFkZXIgW2Zvcj1fX3NlYXJjaF0iKTtyZXR1cm4gaChuLCJjbGljayIpLnN1YnNjcmliZSgoKT0+ZS5mb2N1cygpKSxscyhlLHt3b3JrZXIkOnR9KS5waXBlKHcoaT0+ci5uZXh0KGkpKSxfKCgpPT5yLmNvbXBsZXRlKCkpLG0oaT0+JCh7cmVmOmV9LGkpKSxHKDEpKX1mdW5jdGlvbiBsaShlLHt3b3JrZXIkOnQscXVlcnkkOnJ9KXtsZXQgbz1uZXcgZyxuPW9uKGUucGFyZW50RWxlbWVudCkucGlwZShiKEJvb2xlYW4pKSxpPWUucGFyZW50RWxlbWVudCxhPVIoIjpzY29wZSA+IDpmaXJzdC1jaGlsZCIsZSkscz1SKCI6c2NvcGUgPiA6bGFzdC1jaGlsZCIsZSk7emUoInNlYXJjaCIpLnN1YnNjcmliZShsPT5zLnNldEF0dHJpYnV0ZSgicm9sZSIsbD8ibGlzdCI6InByZXNlbnRhdGlvbiIpKSxvLnBpcGUocmUociksV3IodC5waXBlKEFlKGp0KSkpKS5zdWJzY3JpYmUoKFt7aXRlbXM6bH0se3ZhbHVlOmZ9XSk9Pntzd2l0Y2gobC5sZW5ndGgpe2Nhc2UgMDphLnRleHRDb250ZW50PWYubGVuZ3RoP0VlKCJzZWFyY2gucmVzdWx0Lm5vbmUiKTpFZSgic2VhcmNoLnJlc3VsdC5wbGFjZWhvbGRlciIpO2JyZWFrO2Nhc2UgMTphLnRleHRDb250ZW50PUVlKCJzZWFyY2gucmVzdWx0Lm9uZSIpO2JyZWFrO2RlZmF1bHQ6bGV0IHU9c3IobC5sZW5ndGgpO2EudGV4dENvbnRlbnQ9RWUoInNlYXJjaC5yZXN1bHQub3RoZXIiLHUpfX0pO2xldCBwPW8ucGlwZSh3KCgpPT5zLmlubmVySFRNTD0iIiksdigoe2l0ZW1zOmx9KT0+TyhJKC4uLmwuc2xpY2UoMCwxMCkpLEkoLi4ubC5zbGljZSgxMCkpLnBpcGUoQmUoNCksVnIobiksdigoW2ZdKT0+ZikpKSksbShNbikscGUoKSk7cmV0dXJuIHAuc3Vic2NyaWJlKGw9PnMuYXBwZW5kQ2hpbGQobCkpLHAucGlwZShuZShsPT57bGV0IGY9ZmUoImRldGFpbHMiLGwpO3JldHVybiB0eXBlb2YgZj09InVuZGVmaW5lZCI/UzpoKGYsInRvZ2dsZSIpLnBpcGUoVyhvKSxtKCgpPT5mKSl9KSkuc3Vic2NyaWJlKGw9PntsLm9wZW49PT0hMSYmbC5vZmZzZXRUb3A8PWkuc2Nyb2xsVG9wJiZpLnNjcm9sbFRvKHt0b3A6bC5vZmZzZXRUb3B9KX0pLHQucGlwZShiKGRyKSxtKCh7ZGF0YTpsfSk9PmwpKS5waXBlKHcobD0+by5uZXh0KGwpKSxfKCgpPT5vLmNvbXBsZXRlKCkpLG0obD0+JCh7cmVmOmV9LGwpKSl9ZnVuY3Rpb24gbXMoZSx7cXVlcnkkOnR9KXtyZXR1cm4gdC5waXBlKG0oKHt2YWx1ZTpyfSk9PntsZXQgbz15ZSgpO3JldHVybiBvLmhhc2g9IiIscj1yLnJlcGxhY2UoL1xzKy9nLCIrIikucmVwbGFjZSgvJi9nLCIlMjYiKS5yZXBsYWNlKC89L2csIiUzRCIpLG8uc2VhcmNoPWBxPSR7cn1gLHt1cmw6b319KSl9ZnVuY3Rpb24gbWkoZSx0KXtsZXQgcj1uZXcgZyxvPXIucGlwZShaKCksaWUoITApKTtyZXR1cm4gci5zdWJzY3JpYmUoKHt1cmw6bn0pPT57ZS5zZXRBdHRyaWJ1dGUoImRhdGEtY2xpcGJvYXJkLXRleHQiLGUuaHJlZiksZS5ocmVmPWAke259YH0pLGgoZSwiY2xpY2siKS5waXBlKFcobykpLnN1YnNjcmliZShuPT5uLnByZXZlbnREZWZhdWx0KCkpLG1zKGUsdCkucGlwZSh3KG49PnIubmV4dChuKSksXygoKT0+ci5jb21wbGV0ZSgpKSxtKG49PiQoe3JlZjplfSxuKSkpfWZ1bmN0aW9uIGZpKGUse3dvcmtlciQ6dCxrZXlib2FyZCQ6cn0pe2xldCBvPW5ldyBnLG49U2UoInNlYXJjaC1xdWVyeSIpLGk9TyhoKG4sImtleWRvd24iKSxoKG4sImZvY3VzIikpLnBpcGUodmUoc2UpLG0oKCk9Pm4udmFsdWUpLEsoKSk7cmV0dXJuIG8ucGlwZShIZShpKSxtKChbe3N1Z2dlc3Q6c30scF0pPT57bGV0IGM9cC5zcGxpdCgvKFtccy1dKykvKTtpZihzIT1udWxsJiZzLmxlbmd0aCYmY1tjLmxlbmd0aC0xXSl7bGV0IGw9c1tzLmxlbmd0aC0xXTtsLnN0YXJ0c1dpdGgoY1tjLmxlbmd0aC0xXSkmJihjW2MubGVuZ3RoLTFdPWwpfWVsc2UgYy5sZW5ndGg9MDtyZXR1cm4gY30pKS5zdWJzY3JpYmUocz0+ZS5pbm5lckhUTUw9cy5qb2luKCIiKS5yZXBsYWNlKC9ccy9nLCImbmJzcDsiKSksci5waXBlKGIoKHttb2RlOnN9KT0+cz09PSJzZWFyY2giKSkuc3Vic2NyaWJlKHM9Pntzd2l0Y2gocy50eXBlKXtjYXNlIkFycm93UmlnaHQiOmUuaW5uZXJUZXh0Lmxlbmd0aCYmbi5zZWxlY3Rpb25TdGFydD09PW4udmFsdWUubGVuZ3RoJiYobi52YWx1ZT1lLmlubmVyVGV4dCk7YnJlYWt9fSksdC5waXBlKGIoZHIpLG0oKHtkYXRhOnN9KT0+cykpLnBpcGUodyhzPT5vLm5leHQocykpLF8oKCk9Pm8uY29tcGxldGUoKSksbSgoKT0+KHtyZWY6ZX0pKSl9ZnVuY3Rpb24gdWkoZSx7aW5kZXgkOnQsa2V5Ym9hcmQkOnJ9KXtsZXQgbz14ZSgpO3RyeXtsZXQgbj1haShvLnNlYXJjaCx0KSxpPVNlKCJzZWFyY2gtcXVlcnkiLGUpLGE9U2UoInNlYXJjaC1yZXN1bHQiLGUpO2goZSwiY2xpY2siKS5waXBlKGIoKHt0YXJnZXQ6cH0pPT5wIGluc3RhbmNlb2YgRWxlbWVudCYmISFwLmNsb3Nlc3QoImEiKSkpLnN1YnNjcmliZSgoKT0+SmUoInNlYXJjaCIsITEpKSxyLnBpcGUoYigoe21vZGU6cH0pPT5wPT09InNlYXJjaCIpKS5zdWJzY3JpYmUocD0+e2xldCBjPUllKCk7c3dpdGNoKHAudHlwZSl7Y2FzZSJFbnRlciI6aWYoYz09PWkpe2xldCBsPW5ldyBNYXA7Zm9yKGxldCBmIG9mIFAoIjpmaXJzdC1jaGlsZCBbaHJlZl0iLGEpKXtsZXQgdT1mLmZpcnN0RWxlbWVudENoaWxkO2wuc2V0KGYscGFyc2VGbG9hdCh1LmdldEF0dHJpYnV0ZSgiZGF0YS1tZC1zY29yZSIpKSl9aWYobC5zaXplKXtsZXRbW2ZdXT1bLi4ubF0uc29ydCgoWyx1XSxbLGRdKT0+ZC11KTtmLmNsaWNrKCl9cC5jbGFpbSgpfWJyZWFrO2Nhc2UiRXNjYXBlIjpjYXNlIlRhYiI6SmUoInNlYXJjaCIsITEpLGkuYmx1cigpO2JyZWFrO2Nhc2UiQXJyb3dVcCI6Y2FzZSJBcnJvd0Rvd24iOmlmKHR5cGVvZiBjPT0idW5kZWZpbmVkIilpLmZvY3VzKCk7ZWxzZXtsZXQgbD1baSwuLi5QKCI6bm90KGRldGFpbHMpID4gW2hyZWZdLCBzdW1tYXJ5LCBkZXRhaWxzW29wZW5dIFtocmVmXSIsYSldLGY9TWF0aC5tYXgoMCwoTWF0aC5tYXgoMCxsLmluZGV4T2YoYykpK2wubGVuZ3RoKyhwLnR5cGU9PT0iQXJyb3dVcCI/LTE6MSkpJWwubGVuZ3RoKTtsW2ZdLmZvY3VzKCl9cC5jbGFpbSgpO2JyZWFrO2RlZmF1bHQ6aSE9PUllKCkmJmkuZm9jdXMoKX19KSxyLnBpcGUoYigoe21vZGU6cH0pPT5wPT09Imdsb2JhbCIpKS5zdWJzY3JpYmUocD0+e3N3aXRjaChwLnR5cGUpe2Nhc2UiZiI6Y2FzZSJzIjpjYXNlIi8iOmkuZm9jdXMoKSxpLnNlbGVjdCgpLHAuY2xhaW0oKTticmVha319KTtsZXQgcz1waShpLHt3b3JrZXIkOm59KTtyZXR1cm4gTyhzLGxpKGEse3dvcmtlciQ6bixxdWVyeSQ6c30pKS5waXBlKFJlKC4uLmFlKCJzZWFyY2gtc2hhcmUiLGUpLm1hcChwPT5taShwLHtxdWVyeSQ6c30pKSwuLi5hZSgic2VhcmNoLXN1Z2dlc3QiLGUpLm1hcChwPT5maShwLHt3b3JrZXIkOm4sa2V5Ym9hcmQkOnJ9KSkpKX1jYXRjaChuKXtyZXR1cm4gZS5oaWRkZW49ITAsWWV9fWZ1bmN0aW9uIGRpKGUse2luZGV4JDp0LGxvY2F0aW9uJDpyfSl7cmV0dXJuIHooW3Qsci5waXBlKFEoeWUoKSksYihvPT4hIW8uc2VhcmNoUGFyYW1zLmdldCgiaCIpKSldKS5waXBlKG0oKFtvLG5dKT0+aWkoby5jb25maWcpKG4uc2VhcmNoUGFyYW1zLmdldCgiaCIpKSksbShvPT57dmFyIGE7bGV0IG49bmV3IE1hcCxpPWRvY3VtZW50LmNyZWF0ZU5vZGVJdGVyYXRvcihlLE5vZGVGaWx0ZXIuU0hPV19URVhUKTtmb3IobGV0IHM9aS5uZXh0Tm9kZSgpO3M7cz1pLm5leHROb2RlKCkpaWYoKGE9cy5wYXJlbnRFbGVtZW50KSE9bnVsbCYmYS5vZmZzZXRIZWlnaHQpe2xldCBwPXMudGV4dENvbnRlbnQsYz1vKHApO2MubGVuZ3RoPnAubGVuZ3RoJiZuLnNldChzLGMpfWZvcihsZXRbcyxwXW9mIG4pe2xldHtjaGlsZE5vZGVzOmN9PXgoInNwYW4iLG51bGwscCk7cy5yZXBsYWNlV2l0aCguLi5BcnJheS5mcm9tKGMpKX1yZXR1cm57cmVmOmUsbm9kZXM6bn19KSl9ZnVuY3Rpb24gZnMoZSx7dmlld3BvcnQkOnQsbWFpbiQ6cn0pe2xldCBvPWUuY2xvc2VzdCgiLm1kLWdyaWQiKSxuPW8ub2Zmc2V0VG9wLW8ucGFyZW50RWxlbWVudC5vZmZzZXRUb3A7cmV0dXJuIHooW3IsdF0pLnBpcGUobSgoW3tvZmZzZXQ6aSxoZWlnaHQ6YX0se29mZnNldDp7eTpzfX1dKT0+KGE9YStNYXRoLm1pbihuLE1hdGgubWF4KDAscy1pKSktbix7aGVpZ2h0OmEsbG9ja2VkOnM+PWkrbn0pKSxLKChpLGEpPT5pLmhlaWdodD09PWEuaGVpZ2h0JiZpLmxvY2tlZD09PWEubG9ja2VkKSl9ZnVuY3Rpb24gWnIoZSxvKXt2YXIgbj1vLHtoZWFkZXIkOnR9PW4scj1zbyhuLFsiaGVhZGVyJCJdKTtsZXQgaT1SKCIubWQtc2lkZWJhcl9fc2Nyb2xsd3JhcCIsZSkse3k6YX09VmUoaSk7cmV0dXJuIEMoKCk9PntsZXQgcz1uZXcgZyxwPXMucGlwZShaKCksaWUoITApKSxjPXMucGlwZShNZSgwLG1lKSk7cmV0dXJuIGMucGlwZShyZSh0KSkuc3Vic2NyaWJlKHtuZXh0KFt7aGVpZ2h0Omx9LHtoZWlnaHQ6Zn1dKXtpLnN0eWxlLmhlaWdodD1gJHtsLTIqYX1weGAsZS5zdHlsZS50b3A9YCR7Zn1weGB9LGNvbXBsZXRlKCl7aS5zdHlsZS5oZWlnaHQ9IiIsZS5zdHlsZS50b3A9IiJ9fSksYy5waXBlKEFlKCkpLnN1YnNjcmliZSgoKT0+e2ZvcihsZXQgbCBvZiBQKCIubWQtbmF2X19saW5rLS1hY3RpdmVbaHJlZl0iLGUpKXtpZighbC5jbGllbnRIZWlnaHQpY29udGludWU7bGV0IGY9bC5jbG9zZXN0KCIubWQtc2lkZWJhcl9fc2Nyb2xsd3JhcCIpO2lmKHR5cGVvZiBmIT0idW5kZWZpbmVkIil7bGV0IHU9bC5vZmZzZXRUb3AtZi5vZmZzZXRUb3Ase2hlaWdodDpkfT1jZShmKTtmLnNjcm9sbFRvKHt0b3A6dS1kLzJ9KX19fSksdWUoUCgibGFiZWxbdGFiaW5kZXhdIixlKSkucGlwZShuZShsPT5oKGwsImNsaWNrIikucGlwZSh2ZShzZSksbSgoKT0+bCksVyhwKSkpKS5zdWJzY3JpYmUobD0+e2xldCBmPVIoYFtpZD0iJHtsLmh0bWxGb3J9Il1gKTtSKGBbYXJpYS1sYWJlbGxlZGJ5PSIke2wuaWR9Il1gKS5zZXRBdHRyaWJ1dGUoImFyaWEtZXhwYW5kZWQiLGAke2YuY2hlY2tlZH1gKX0pLGZzKGUscikucGlwZSh3KGw9PnMubmV4dChsKSksXygoKT0+cy5jb21wbGV0ZSgpKSxtKGw9PiQoe3JlZjplfSxsKSkpfSl9ZnVuY3Rpb24gaGkoZSx0KXtpZih0eXBlb2YgdCE9InVuZGVmaW5lZCIpe2xldCByPWBodHRwczovL2FwaS5naXRodWIuY29tL3JlcG9zLyR7ZX0vJHt0fWA7cmV0dXJuIHN0KGplKGAke3J9L3JlbGVhc2VzL2xhdGVzdGApLnBpcGUoZGUoKCk9PlMpLG0obz0+KHt2ZXJzaW9uOm8udGFnX25hbWV9KSksRGUoe30pKSxqZShyKS5waXBlKGRlKCgpPT5TKSxtKG89Pih7c3RhcnM6by5zdGFyZ2F6ZXJzX2NvdW50LGZvcmtzOm8uZm9ya3NfY291bnR9KSksRGUoe30pKSkucGlwZShtKChbbyxuXSk9PiQoJCh7fSxvKSxuKSkpfWVsc2V7bGV0IHI9YGh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vdXNlcnMvJHtlfWA7cmV0dXJuIGplKHIpLnBpcGUobShvPT4oe3JlcG9zaXRvcmllczpvLnB1YmxpY19yZXBvc30pKSxEZSh7fSkpfX1mdW5jdGlvbiBiaShlLHQpe2xldCByPWBodHRwczovLyR7ZX0vYXBpL3Y0L3Byb2plY3RzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KHQpfWA7cmV0dXJuIHN0KGplKGAke3J9L3JlbGVhc2VzL3Blcm1hbGluay9sYXRlc3RgKS5waXBlKGRlKCgpPT5TKSxtKCh7dGFnX25hbWU6b30pPT4oe3ZlcnNpb246b30pKSxEZSh7fSkpLGplKHIpLnBpcGUoZGUoKCk9PlMpLG0oKHtzdGFyX2NvdW50Om8sZm9ya3NfY291bnQ6bn0pPT4oe3N0YXJzOm8sZm9ya3M6bn0pKSxEZSh7fSkpKS5waXBlKG0oKFtvLG5dKT0+JCgkKHt9LG8pLG4pKSl9ZnVuY3Rpb24gdmkoZSl7bGV0IHQ9ZS5tYXRjaCgvXi4rZ2l0aHViXC5jb21cLyhbXi9dKylcLz8oW14vXSspPy9pKTtpZih0KXtsZXRbLHIsb109dDtyZXR1cm4gaGkocixvKX1pZih0PWUubWF0Y2goL14uKz8oW14vXSpnaXRsYWJbXi9dKylcLyguKz8pXC8/JC9pKSx0KXtsZXRbLHIsb109dDtyZXR1cm4gYmkocixvKX1yZXR1cm4gU312YXIgdXM7ZnVuY3Rpb24gZHMoZSl7cmV0dXJuIHVzfHwodXM9QygoKT0+e2xldCB0PV9fbWRfZ2V0KCJfX3NvdXJjZSIsc2Vzc2lvblN0b3JhZ2UpO2lmKHQpcmV0dXJuIEkodCk7aWYoYWUoImNvbnNlbnQiKS5sZW5ndGgpe2xldCBvPV9fbWRfZ2V0KCJfX2NvbnNlbnQiKTtpZighKG8mJm8uZ2l0aHViKSlyZXR1cm4gU31yZXR1cm4gdmkoZS5ocmVmKS5waXBlKHcobz0+X19tZF9zZXQoIl9fc291cmNlIixvLHNlc3Npb25TdG9yYWdlKSkpfSkucGlwZShkZSgoKT0+UyksYih0PT5PYmplY3Qua2V5cyh0KS5sZW5ndGg+MCksbSh0PT4oe2ZhY3RzOnR9KSksRygxKSkpfWZ1bmN0aW9uIGdpKGUpe2xldCB0PVIoIjpzY29wZSA+IDpsYXN0LWNoaWxkIixlKTtyZXR1cm4gQygoKT0+e2xldCByPW5ldyBnO3JldHVybiByLnN1YnNjcmliZSgoe2ZhY3RzOm99KT0+e3QuYXBwZW5kQ2hpbGQoX24obykpLHQuY2xhc3NMaXN0LmFkZCgibWQtc291cmNlX19yZXBvc2l0b3J5LS1hY3RpdmUiKX0pLGRzKGUpLnBpcGUodyhvPT5yLm5leHQobykpLF8oKCk9PnIuY29tcGxldGUoKSksbShvPT4kKHtyZWY6ZX0sbykpKX0pfWZ1bmN0aW9uIGhzKGUse3ZpZXdwb3J0JDp0LGhlYWRlciQ6cn0pe3JldHVybiBnZShkb2N1bWVudC5ib2R5KS5waXBlKHYoKCk9Pm1yKGUse2hlYWRlciQ6cix2aWV3cG9ydCQ6dH0pKSxtKCh7b2Zmc2V0Ont5Om99fSk9Pih7aGlkZGVuOm8+PTEwfSkpLGVlKCJoaWRkZW4iKSl9ZnVuY3Rpb24geWkoZSx0KXtyZXR1cm4gQygoKT0+e2xldCByPW5ldyBnO3JldHVybiByLnN1YnNjcmliZSh7bmV4dCh7aGlkZGVuOm99KXtlLmhpZGRlbj1vfSxjb21wbGV0ZSgpe2UuaGlkZGVuPSExfX0pLChCKCJuYXZpZ2F0aW9uLnRhYnMuc3RpY2t5Iik/SSh7aGlkZGVuOiExfSk6aHMoZSx0KSkucGlwZSh3KG89PnIubmV4dChvKSksXygoKT0+ci5jb21wbGV0ZSgpKSxtKG89PiQoe3JlZjplfSxvKSkpfSl9ZnVuY3Rpb24gYnMoZSx7dmlld3BvcnQkOnQsaGVhZGVyJDpyfSl7bGV0IG89bmV3IE1hcCxuPVAoIi5tZC1uYXZfX2xpbmsiLGUpO2ZvcihsZXQgcyBvZiBuKXtsZXQgcD1kZWNvZGVVUklDb21wb25lbnQocy5oYXNoLnN1YnN0cmluZygxKSksYz1mZShgW2lkPSIke3B9Il1gKTt0eXBlb2YgYyE9InVuZGVmaW5lZCImJm8uc2V0KHMsYyl9bGV0IGk9ci5waXBlKGVlKCJoZWlnaHQiKSxtKCh7aGVpZ2h0OnN9KT0+e2xldCBwPVNlKCJtYWluIiksYz1SKCI6c2NvcGUgPiA6Zmlyc3QtY2hpbGQiLHApO3JldHVybiBzKy44KihjLm9mZnNldFRvcC1wLm9mZnNldFRvcCl9KSxwZSgpKTtyZXR1cm4gZ2UoZG9jdW1lbnQuYm9keSkucGlwZShlZSgiaGVpZ2h0IiksdihzPT5DKCgpPT57bGV0IHA9W107cmV0dXJuIEkoWy4uLm9dLnJlZHVjZSgoYyxbbCxmXSk9Pntmb3IoO3AubGVuZ3RoJiZvLmdldChwW3AubGVuZ3RoLTFdKS50YWdOYW1lPj1mLnRhZ05hbWU7KXAucG9wKCk7bGV0IHU9Zi5vZmZzZXRUb3A7Zm9yKDshdSYmZi5wYXJlbnRFbGVtZW50OylmPWYucGFyZW50RWxlbWVudCx1PWYub2Zmc2V0VG9wO2xldCBkPWYub2Zmc2V0UGFyZW50O2Zvcig7ZDtkPWQub2Zmc2V0UGFyZW50KXUrPWQub2Zmc2V0VG9wO3JldHVybiBjLnNldChbLi4ucD1bLi4ucCxsXV0ucmV2ZXJzZSgpLHUpfSxuZXcgTWFwKSl9KS5waXBlKG0ocD0+bmV3IE1hcChbLi4ucF0uc29ydCgoWyxjXSxbLGxdKT0+Yy1sKSkpLEhlKGkpLHYoKFtwLGNdKT0+dC5waXBlKEZyKChbbCxmXSx7b2Zmc2V0Ont5OnV9LHNpemU6ZH0pPT57bGV0IHk9dStkLmhlaWdodD49TWF0aC5mbG9vcihzLmhlaWdodCk7Zm9yKDtmLmxlbmd0aDspe2xldFssTF09ZlswXTtpZihMLWM8dXx8eSlsPVsuLi5sLGYuc2hpZnQoKV07ZWxzZSBicmVha31mb3IoO2wubGVuZ3RoOyl7bGV0WyxMXT1sW2wubGVuZ3RoLTFdO2lmKEwtYz49dSYmIXkpZj1bbC5wb3AoKSwuLi5mXTtlbHNlIGJyZWFrfXJldHVybltsLGZdfSxbW10sWy4uLnBdXSksSygobCxmKT0+bFswXT09PWZbMF0mJmxbMV09PT1mWzFdKSkpKSkpLnBpcGUobSgoW3MscF0pPT4oe3ByZXY6cy5tYXAoKFtjXSk9PmMpLG5leHQ6cC5tYXAoKFtjXSk9PmMpfSkpLFEoe3ByZXY6W10sbmV4dDpbXX0pLEJlKDIsMSksbSgoW3MscF0pPT5zLnByZXYubGVuZ3RoPHAucHJldi5sZW5ndGg/e3ByZXY6cC5wcmV2LnNsaWNlKE1hdGgubWF4KDAscy5wcmV2Lmxlbmd0aC0xKSxwLnByZXYubGVuZ3RoKSxuZXh0OltdfTp7cHJldjpwLnByZXYuc2xpY2UoLTEpLG5leHQ6cC5uZXh0LnNsaWNlKDAscC5uZXh0Lmxlbmd0aC1zLm5leHQubGVuZ3RoKX0pKX1mdW5jdGlvbiB4aShlLHt2aWV3cG9ydCQ6dCxoZWFkZXIkOnIsbWFpbiQ6byx0YXJnZXQkOm59KXtyZXR1cm4gQygoKT0+e2xldCBpPW5ldyBnLGE9aS5waXBlKFooKSxpZSghMCkpO2lmKGkuc3Vic2NyaWJlKCh7cHJldjpzLG5leHQ6cH0pPT57Zm9yKGxldFtjXW9mIHApYy5jbGFzc0xpc3QucmVtb3ZlKCJtZC1uYXZfX2xpbmstLXBhc3NlZCIpLGMuY2xhc3NMaXN0LnJlbW92ZSgibWQtbmF2X19saW5rLS1hY3RpdmUiKTtmb3IobGV0W2MsW2xdXW9mIHMuZW50cmllcygpKWwuY2xhc3NMaXN0LmFkZCgibWQtbmF2X19saW5rLS1wYXNzZWQiKSxsLmNsYXNzTGlzdC50b2dnbGUoIm1kLW5hdl9fbGluay0tYWN0aXZlIixjPT09cy5sZW5ndGgtMSl9KSxCKCJ0b2MuZm9sbG93Iikpe2xldCBzPU8odC5waXBlKF9lKDEpLG0oKCk9Pnt9KSksdC5waXBlKF9lKDI1MCksbSgoKT0+InNtb290aCIpKSk7aS5waXBlKGIoKHtwcmV2OnB9KT0+cC5sZW5ndGg+MCksSGUoby5waXBlKHZlKHNlKSkpLHJlKHMpKS5zdWJzY3JpYmUoKFtbe3ByZXY6cH1dLGNdKT0+e2xldFtsXT1wW3AubGVuZ3RoLTFdO2lmKGwub2Zmc2V0SGVpZ2h0KXtsZXQgZj1jcihsKTtpZih0eXBlb2YgZiE9InVuZGVmaW5lZCIpe2xldCB1PWwub2Zmc2V0VG9wLWYub2Zmc2V0VG9wLHtoZWlnaHQ6ZH09Y2UoZik7Zi5zY3JvbGxUbyh7dG9wOnUtZC8yLGJlaGF2aW9yOmN9KX19fSl9cmV0dXJuIEIoIm5hdmlnYXRpb24udHJhY2tpbmciKSYmdC5waXBlKFcoYSksZWUoIm9mZnNldCIpLF9lKDI1MCksQ2UoMSksVyhuLnBpcGUoQ2UoMSkpKSxjdCh7ZGVsYXk6MjUwfSkscmUoaSkpLnN1YnNjcmliZSgoWyx7cHJldjpzfV0pPT57bGV0IHA9eWUoKSxjPXNbcy5sZW5ndGgtMV07aWYoYyYmYy5sZW5ndGgpe2xldFtsXT1jLHtoYXNoOmZ9PW5ldyBVUkwobC5ocmVmKTtwLmhhc2ghPT1mJiYocC5oYXNoPWYsaGlzdG9yeS5yZXBsYWNlU3RhdGUoe30sIiIsYCR7cH1gKSl9ZWxzZSBwLmhhc2g9IiIsaGlzdG9yeS5yZXBsYWNlU3RhdGUoe30sIiIsYCR7cH1gKX0pLGJzKGUse3ZpZXdwb3J0JDp0LGhlYWRlciQ6cn0pLnBpcGUodyhzPT5pLm5leHQocykpLF8oKCk9PmkuY29tcGxldGUoKSksbShzPT4kKHtyZWY6ZX0scykpKX0pfWZ1bmN0aW9uIHZzKGUse3ZpZXdwb3J0JDp0LG1haW4kOnIsdGFyZ2V0JDpvfSl7bGV0IG49dC5waXBlKG0oKHtvZmZzZXQ6e3k6YX19KT0+YSksQmUoMiwxKSxtKChbYSxzXSk9PmE+cyYmcz4wKSxLKCkpLGk9ci5waXBlKG0oKHthY3RpdmU6YX0pPT5hKSk7cmV0dXJuIHooW2ksbl0pLnBpcGUobSgoW2Esc10pPT4hKGEmJnMpKSxLKCksVyhvLnBpcGUoQ2UoMSkpKSxpZSghMCksY3Qoe2RlbGF5OjI1MH0pLG0oYT0+KHtoaWRkZW46YX0pKSl9ZnVuY3Rpb24gRWkoZSx7dmlld3BvcnQkOnQsaGVhZGVyJDpyLG1haW4kOm8sdGFyZ2V0JDpufSl7bGV0IGk9bmV3IGcsYT1pLnBpcGUoWigpLGllKCEwKSk7cmV0dXJuIGkuc3Vic2NyaWJlKHtuZXh0KHtoaWRkZW46c30pe2UuaGlkZGVuPXMscz8oZS5zZXRBdHRyaWJ1dGUoInRhYmluZGV4IiwiLTEiKSxlLmJsdXIoKSk6ZS5yZW1vdmVBdHRyaWJ1dGUoInRhYmluZGV4Iil9LGNvbXBsZXRlKCl7ZS5zdHlsZS50b3A9IiIsZS5oaWRkZW49ITAsZS5yZW1vdmVBdHRyaWJ1dGUoInRhYmluZGV4Iil9fSksci5waXBlKFcoYSksZWUoImhlaWdodCIpKS5zdWJzY3JpYmUoKHtoZWlnaHQ6c30pPT57ZS5zdHlsZS50b3A9YCR7cysxNn1weGB9KSxoKGUsImNsaWNrIikuc3Vic2NyaWJlKHM9PntzLnByZXZlbnREZWZhdWx0KCksd2luZG93LnNjcm9sbFRvKHt0b3A6MH0pfSksdnMoZSx7dmlld3BvcnQkOnQsbWFpbiQ6byx0YXJnZXQkOm59KS5waXBlKHcocz0+aS5uZXh0KHMpKSxfKCgpPT5pLmNvbXBsZXRlKCkpLG0ocz0+JCh7cmVmOmV9LHMpKSl9ZnVuY3Rpb24gd2koe2RvY3VtZW50JDplLHZpZXdwb3J0JDp0fSl7ZS5waXBlKHYoKCk9PlAoIi5tZC1lbGxpcHNpcyIpKSxuZShyPT50dChyKS5waXBlKFcoZS5waXBlKENlKDEpKSksYihvPT5vKSxtKCgpPT5yKSxUZSgxKSkpLGIocj0+ci5vZmZzZXRXaWR0aDxyLnNjcm9sbFdpZHRoKSxuZShyPT57bGV0IG89ci5pbm5lclRleHQsbj1yLmNsb3Nlc3QoImEiKXx8cjtyZXR1cm4gbi50aXRsZT1vLEIoImNvbnRlbnQudG9vbHRpcHMiKT9tdChuLHt2aWV3cG9ydCQ6dH0pLnBpcGUoVyhlLnBpcGUoQ2UoMSkpKSxfKCgpPT5uLnJlbW92ZUF0dHJpYnV0ZSgidGl0bGUiKSkpOlN9KSkuc3Vic2NyaWJlKCksQigiY29udGVudC50b29sdGlwcyIpJiZlLnBpcGUodigoKT0+UCgiLm1kLXN0YXR1cyIpKSxuZShyPT5tdChyLHt2aWV3cG9ydCQ6dH0pKSkuc3Vic2NyaWJlKCl9ZnVuY3Rpb24gVGkoe2RvY3VtZW50JDplLHRhYmxldCQ6dH0pe2UucGlwZSh2KCgpPT5QKCIubWQtdG9nZ2xlLS1pbmRldGVybWluYXRlIikpLHcocj0+e3IuaW5kZXRlcm1pbmF0ZT0hMCxyLmNoZWNrZWQ9ITF9KSxuZShyPT5oKHIsImNoYW5nZSIpLnBpcGUoRHIoKCk9PnIuY2xhc3NMaXN0LmNvbnRhaW5zKCJtZC10b2dnbGUtLWluZGV0ZXJtaW5hdGUiKSksbSgoKT0+cikpKSxyZSh0KSkuc3Vic2NyaWJlKChbcixvXSk9PntyLmNsYXNzTGlzdC5yZW1vdmUoIm1kLXRvZ2dsZS0taW5kZXRlcm1pbmF0ZSIpLG8mJihyLmNoZWNrZWQ9ITEpfSl9ZnVuY3Rpb24gZ3MoKXtyZXR1cm4vKGlQYWR8aVBob25lfGlQb2QpLy50ZXN0KG5hdmlnYXRvci51c2VyQWdlbnQpfWZ1bmN0aW9uIFNpKHtkb2N1bWVudCQ6ZX0pe2UucGlwZSh2KCgpPT5QKCJbZGF0YS1tZC1zY3JvbGxmaXhdIikpLHcodD0+dC5yZW1vdmVBdHRyaWJ1dGUoImRhdGEtbWQtc2Nyb2xsZml4IikpLGIoZ3MpLG5lKHQ9PmgodCwidG91Y2hzdGFydCIpLnBpcGUobSgoKT0+dCkpKSkuc3Vic2NyaWJlKHQ9PntsZXQgcj10LnNjcm9sbFRvcDtyPT09MD90LnNjcm9sbFRvcD0xOnIrdC5vZmZzZXRIZWlnaHQ9PT10LnNjcm9sbEhlaWdodCYmKHQuc2Nyb2xsVG9wPXItMSl9KX1mdW5jdGlvbiBPaSh7dmlld3BvcnQkOmUsdGFibGV0JDp0fSl7eihbemUoInNlYXJjaCIpLHRdKS5waXBlKG0oKFtyLG9dKT0+ciYmIW8pLHYocj0+SShyKS5waXBlKEdlKHI/NDAwOjEwMCkpKSxyZShlKSkuc3Vic2NyaWJlKChbcix7b2Zmc2V0Ont5Om99fV0pPT57aWYocilkb2N1bWVudC5ib2R5LnNldEF0dHJpYnV0ZSgiZGF0YS1tZC1zY3JvbGxsb2NrIiwiIiksZG9jdW1lbnQuYm9keS5zdHlsZS50b3A9YC0ke299cHhgO2Vsc2V7bGV0IG49LTEqcGFyc2VJbnQoZG9jdW1lbnQuYm9keS5zdHlsZS50b3AsMTApO2RvY3VtZW50LmJvZHkucmVtb3ZlQXR0cmlidXRlKCJkYXRhLW1kLXNjcm9sbGxvY2siKSxkb2N1bWVudC5ib2R5LnN0eWxlLnRvcD0iIixuJiZ3aW5kb3cuc2Nyb2xsVG8oMCxuKX19KX1PYmplY3QuZW50cmllc3x8KE9iamVjdC5lbnRyaWVzPWZ1bmN0aW9uKGUpe2xldCB0PVtdO2ZvcihsZXQgciBvZiBPYmplY3Qua2V5cyhlKSl0LnB1c2goW3IsZVtyXV0pO3JldHVybiB0fSk7T2JqZWN0LnZhbHVlc3x8KE9iamVjdC52YWx1ZXM9ZnVuY3Rpb24oZSl7bGV0IHQ9W107Zm9yKGxldCByIG9mIE9iamVjdC5rZXlzKGUpKXQucHVzaChlW3JdKTtyZXR1cm4gdH0pO3R5cGVvZiBFbGVtZW50IT0idW5kZWZpbmVkIiYmKEVsZW1lbnQucHJvdG90eXBlLnNjcm9sbFRvfHwoRWxlbWVudC5wcm90b3R5cGUuc2Nyb2xsVG89ZnVuY3Rpb24oZSx0KXt0eXBlb2YgZT09Im9iamVjdCI/KHRoaXMuc2Nyb2xsTGVmdD1lLmxlZnQsdGhpcy5zY3JvbGxUb3A9ZS50b3ApOih0aGlzLnNjcm9sbExlZnQ9ZSx0aGlzLnNjcm9sbFRvcD10KX0pLEVsZW1lbnQucHJvdG90eXBlLnJlcGxhY2VXaXRofHwoRWxlbWVudC5wcm90b3R5cGUucmVwbGFjZVdpdGg9ZnVuY3Rpb24oLi4uZSl7bGV0IHQ9dGhpcy5wYXJlbnROb2RlO2lmKHQpe2UubGVuZ3RoPT09MCYmdC5yZW1vdmVDaGlsZCh0aGlzKTtmb3IobGV0IHI9ZS5sZW5ndGgtMTtyPj0wO3ItLSl7bGV0IG89ZVtyXTt0eXBlb2Ygbz09InN0cmluZyI/bz1kb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShvKTpvLnBhcmVudE5vZGUmJm8ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChvKSxyP3QuaW5zZXJ0QmVmb3JlKHRoaXMucHJldmlvdXNTaWJsaW5nLG8pOnQucmVwbGFjZUNoaWxkKG8sdGhpcyl9fX0pKTtmdW5jdGlvbiB5cygpe3JldHVybiBsb2NhdGlvbi5wcm90b2NvbD09PSJmaWxlOiI/VHQoYCR7bmV3IFVSTCgic2VhcmNoL3NlYXJjaF9pbmRleC5qcyIsZW8uYmFzZSl9YCkucGlwZShtKCgpPT5fX2luZGV4KSxHKDEpKTpqZShuZXcgVVJMKCJzZWFyY2gvc2VhcmNoX2luZGV4Lmpzb24iLGVvLmJhc2UpKX1kb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZSgibm8tanMiKTtkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xhc3NMaXN0LmFkZCgianMiKTt2YXIgb3Q9R28oKSxVdD1zbigpLEx0PWxuKFV0KSx0bz1hbigpLE9lPWduKCksaHI9UHQoIihtaW4td2lkdGg6IDk2MHB4KSIpLE1pPVB0KCIobWluLXdpZHRoOiAxMjIwcHgpIiksX2k9bW4oKSxlbz14ZSgpLEFpPWRvY3VtZW50LmZvcm1zLm5hbWVkSXRlbSgic2VhcmNoIik/eXMoKTpZZSxybz1uZXcgZztabih7YWxlcnQkOnJvfSk7dmFyIG9vPW5ldyBnO0IoIm5hdmlnYXRpb24uaW5zdGFudCIpJiZvaSh7bG9jYXRpb24kOlV0LHZpZXdwb3J0JDpPZSxwcm9ncmVzcyQ6b299KS5zdWJzY3JpYmUob3QpO3ZhciBMaTsoKExpPWVvLnZlcnNpb24pPT1udWxsP3ZvaWQgMDpMaS5wcm92aWRlcik9PT0ibWlrZSImJmNpKHtkb2N1bWVudCQ6b3R9KTtPKFV0LEx0KS5waXBlKEdlKDEyNSkpLnN1YnNjcmliZSgoKT0+e0plKCJkcmF3ZXIiLCExKSxKZSgic2VhcmNoIiwhMSl9KTt0by5waXBlKGIoKHttb2RlOmV9KT0+ZT09PSJnbG9iYWwiKSkuc3Vic2NyaWJlKGU9Pntzd2l0Y2goZS50eXBlKXtjYXNlInAiOmNhc2UiLCI6bGV0IHQ9ZmUoImxpbmtbcmVsPXByZXZdIik7dHlwZW9mIHQhPSJ1bmRlZmluZWQiJiZsdCh0KTticmVhaztjYXNlIm4iOmNhc2UiLiI6bGV0IHI9ZmUoImxpbmtbcmVsPW5leHRdIik7dHlwZW9mIHIhPSJ1bmRlZmluZWQiJiZsdChyKTticmVhaztjYXNlIkVudGVyIjpsZXQgbz1JZSgpO28gaW5zdGFuY2VvZiBIVE1MTGFiZWxFbGVtZW50JiZvLmNsaWNrKCl9fSk7d2koe3ZpZXdwb3J0JDpPZSxkb2N1bWVudCQ6b3R9KTtUaSh7ZG9jdW1lbnQkOm90LHRhYmxldCQ6aHJ9KTtTaSh7ZG9jdW1lbnQkOm90fSk7T2koe3ZpZXdwb3J0JDpPZSx0YWJsZXQkOmhyfSk7dmFyIHJ0PUtuKFNlKCJoZWFkZXIiKSx7dmlld3BvcnQkOk9lfSksRnQ9b3QucGlwZShtKCgpPT5TZSgibWFpbiIpKSx2KGU9PkduKGUse3ZpZXdwb3J0JDpPZSxoZWFkZXIkOnJ0fSkpLEcoMSkpLHhzPU8oLi4uYWUoImNvbnNlbnQiKS5tYXAoZT0+RW4oZSx7dGFyZ2V0JDpMdH0pKSwuLi5hZSgiZGlhbG9nIikubWFwKGU9PnFuKGUse2FsZXJ0JDpyb30pKSwuLi5hZSgicGFsZXR0ZSIpLm1hcChlPT5KbihlKSksLi4uYWUoInByb2dyZXNzIikubWFwKGU9PlhuKGUse3Byb2dyZXNzJDpvb30pKSwuLi5hZSgic2VhcmNoIikubWFwKGU9PnVpKGUse2luZGV4JDpBaSxrZXlib2FyZCQ6dG99KSksLi4uYWUoInNvdXJjZSIpLm1hcChlPT5naShlKSkpLEVzPUMoKCk9Pk8oLi4uYWUoImFubm91bmNlIikubWFwKGU9PnhuKGUpKSwuLi5hZSgiY29udGVudCIpLm1hcChlPT56bihlLHt2aWV3cG9ydCQ6T2UsdGFyZ2V0JDpMdCxwcmludCQ6X2l9KSksLi4uYWUoImNvbnRlbnQiKS5tYXAoZT0+Qigic2VhcmNoLmhpZ2hsaWdodCIpP2RpKGUse2luZGV4JDpBaSxsb2NhdGlvbiQ6VXR9KTpTKSwuLi5hZSgiaGVhZGVyIikubWFwKGU9PlluKGUse3ZpZXdwb3J0JDpPZSxoZWFkZXIkOnJ0LG1haW4kOkZ0fSkpLC4uLmFlKCJoZWFkZXItdGl0bGUiKS5tYXAoZT0+Qm4oZSx7dmlld3BvcnQkOk9lLGhlYWRlciQ6cnR9KSksLi4uYWUoInNpZGViYXIiKS5tYXAoZT0+ZS5nZXRBdHRyaWJ1dGUoImRhdGEtbWQtdHlwZSIpPT09Im5hdmlnYXRpb24iP05yKE1pLCgpPT5acihlLHt2aWV3cG9ydCQ6T2UsaGVhZGVyJDpydCxtYWluJDpGdH0pKTpOcihociwoKT0+WnIoZSx7dmlld3BvcnQkOk9lLGhlYWRlciQ6cnQsbWFpbiQ6RnR9KSkpLC4uLmFlKCJ0YWJzIikubWFwKGU9PnlpKGUse3ZpZXdwb3J0JDpPZSxoZWFkZXIkOnJ0fSkpLC4uLmFlKCJ0b2MiKS5tYXAoZT0+eGkoZSx7dmlld3BvcnQkOk9lLGhlYWRlciQ6cnQsbWFpbiQ6RnQsdGFyZ2V0JDpMdH0pKSwuLi5hZSgidG9wIikubWFwKGU9PkVpKGUse3ZpZXdwb3J0JDpPZSxoZWFkZXIkOnJ0LG1haW4kOkZ0LHRhcmdldCQ6THR9KSkpKSxDaT1vdC5waXBlKHYoKCk9PkVzKSxSZSh4cyksRygxKSk7Q2kuc3Vic2NyaWJlKCk7d2luZG93LmRvY3VtZW50JD1vdDt3aW5kb3cubG9jYXRpb24kPVV0O3dpbmRvdy50YXJnZXQkPUx0O3dpbmRvdy5rZXlib2FyZCQ9dG87d2luZG93LnZpZXdwb3J0JD1PZTt3aW5kb3cudGFibGV0JD1ocjt3aW5kb3cuc2NyZWVuJD1NaTt3aW5kb3cucHJpbnQkPV9pO3dpbmRvdy5hbGVydCQ9cm87d2luZG93LnByb2dyZXNzJD1vbzt3aW5kb3cuY29tcG9uZW50JD1DaTt9KSgpOwovLyMgc291cmNlTWFwcGluZ1VSTD1idW5kbGUuODNmNzNiNDMubWluLmpzLm1hcAoK"></script><!--URL:../assets/javascripts/bundle.83f73b43.min.js-->
|
||
<script src="data:text/javascript;base64,LyogCkphdmFzY3JpcHQgZnVuY3Rpb25zIHRvIGhlbHAgbWFrZSB0aGUgcHJpbnQgcGFnZSBtb3JlIFBERiBmcmllbmRseQoqLwoKLyoKR2VuZXJhdGVzIGEgdGFibGUgb2YgY29udGVudHMgZm9yIHRoZSBwcmludCBzaXRlIHBhZ2UuCk9ubHkgY2FsbGVkIHdoZW4gcHJpbnQtc2l0ZS1wbHVnaW4gb3B0aW9uICdhZGRfdGFibGVfb2ZfY29udGVudHMnIGlzIHNldCB0byB0cnVlCiovCmZ1bmN0aW9uIGdlbmVyYXRlX3RvYygpIHsKCiAgdmFyIFRvQyA9ICIiCgogIHZhciBuZXdMaW5lLCBlbCwgdGl0bGUsIGxpbms7CgogIGNvbnN0IHRvY19lbGVtZW50cyA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoCiAgICAiI3ByaW50LXNpdGUtcGFnZSBoMS5uYXYtc2VjdGlvbi10aXRsZSwgI3ByaW50LXNpdGUtcGFnZSBoMS5uYXYtc2VjdGlvbi10aXRsZS1lbmQsIiArCiAgICAiI3ByaW50LXNpdGUtcGFnZSBoMi5uYXYtc2VjdGlvbi10aXRsZSwgI3ByaW50LXNpdGUtcGFnZSBoMi5uYXYtc2VjdGlvbi10aXRsZS1lbmQsIiArCiAgICAiI3ByaW50LXNpdGUtcGFnZSBoMy5uYXYtc2VjdGlvbi10aXRsZSwgI3ByaW50LXNpdGUtcGFnZSBoMy5uYXYtc2VjdGlvbi10aXRsZS1lbmQsIiArCiAgICAiI3ByaW50LXNpdGUtcGFnZSBoNC5uYXYtc2VjdGlvbi10aXRsZSwgI3ByaW50LXNpdGUtcGFnZSBoNC5uYXYtc2VjdGlvbi10aXRsZS1lbmQsIiArCiAgICAiI3ByaW50LXNpdGUtcGFnZSBoNS5uYXYtc2VjdGlvbi10aXRsZSwgI3ByaW50LXNpdGUtcGFnZSBoNS5uYXYtc2VjdGlvbi10aXRsZS1lbmQsIiArCiAgICAiI3ByaW50LXNpdGUtcGFnZSBoNi5uYXYtc2VjdGlvbi10aXRsZSwgI3ByaW50LXNpdGUtcGFnZSBoNi5uYXYtc2VjdGlvbi10aXRsZS1lbmQsIiArCiAgICAic2VjdGlvbi5wcmludC1wYWdlIGgxLHNlY3Rpb24ucHJpbnQtcGFnZSBoMixzZWN0aW9uLnByaW50LXBhZ2UgaDMsIiArCiAgICAic2VjdGlvbi5wcmludC1wYWdlIGg0LHNlY3Rpb24ucHJpbnQtcGFnZSBoNSxzZWN0aW9uLnByaW50LXBhZ2UgaDYiKQogIAogIHZhciBjdXJyZW50X2hlYWRpbmdfZGVwdGggPSAwOwogIHZhciBjdXJyZW50X3NlY3Rpb25fZGVwdGggPSAwOwoKICAvLyBFeHRyYWN0IHRhYmxlIG9mIGNvbnRlbnRzIGRlcHRoCiAgLy8gYmFzaWNhbGx5IHBsdWdpbiBzZXR0aW5nLCBwYXNzZWQgdmlhIGEgZGF0YSBhdHRyaWJ1dGUKICB2YXIgdG9jX2RlcHRoID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoInByaW50LXBhZ2UtdG9jIikuZ2V0QXR0cmlidXRlKCJkYXRhLXRvYy1kZXB0aCIpCgogIGZvciAodmFyIGkgPSAwOyBpIDwgdG9jX2VsZW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAKICAgIC8vIEdldCB0aGUgaW5mbyBmcm9tIHRoZSBlbGVtZW50CiAgICBlbCA9IHRvY19lbGVtZW50c1tpXQogICAgbGluayA9ICIjIiArIGVsLmlkOwogICAgdGFnID0gZWwudGFnTmFtZQogICAgdGFnX2xldmVsID0gdGFnLnN1YnN0cmluZygxKQogICAgLy8gR2V0IHRoZSB0ZXh0IG9mIGEgaGVhZGluZwogICAgLy8gV2UgdXNlIC5maXJzdENoaWxkLm5vZGVWYWx1ZSBpbnN0ZWFkIG9mIC5pbm5lclRleHQKICAgIC8vIGJlY2F1c2Ugb2YgZWxlbWVudHMgbGlrZToKICAgIC8vIDxoMSBpZD0iaW5kZXgtbWtkb2NzLXByaW50LXNpdGUtcGx1Z2luIj4KICAgIC8vICAgICBta2RvY3MtcHJpbnQtc2l0ZS1wbHVnaW48YSBjbGFzcz0iaGVhZGVybGluayIgaHJlZj0iI2luZGV4LW1rZG9jcy1wcmludC1zaXRlLXBsdWdpbiIgdGl0bGU9IlBlcm1hbmVudCBsaW5rIj7ihrU8L2E+CiAgICAvLyAgPC9oMT4KICAgIHRpdGxlID0gZWwuZmlyc3RDaGlsZC5ub2RlVmFsdWU7CiAgICBpZiAoICEgdGl0bGUgKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQoKICAgIC8vIERvbid0IHB1dCB0aGUgdG9jIGgxIGluIHRoZSB0b2MKICAgIGlmICggZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCdwcmludC1wYWdlLXRvYy10aXRsZScpICkgewogICAgICBjb250aW51ZTsKICAgIH0KICAgIC8vIElnbm9yZSB0aGUgTWtEb2NzIGtleWJvYXJkIE1vZGVsCiAgICBpZiAoIGVsLmlkLmluZGV4T2YoImtleWJvYXJkTW9kYWxMYWJlbCIpID4gLTEgKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQoKICAgIC8vIHByaW50LXNpdGUtcGx1Z2luIGhhcyBhIHNldHRpbmcgdG8gY29udHJvbCBUT0MgZGVwdGgKICAgIGlmICggdGFnX2xldmVsID4gdG9jX2RlcHRoICkgewogICAgICBjb250aW51ZTsKICAgIH0KCiAgICBpZiAoZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCduYXYtc2VjdGlvbi10aXRsZScpICkgewogICAgICAvLyBVc2UgdGhlIHRhZyBsZXZlbCBvZiB0aGUgZmlyc3QgaXRlbSBpbiB0aGUgc2VjdGlvbiB0byBjbG9zZSBvZmYgYW55IG5lc3RlZCA8dWw+CiAgICAgIGVsID0gdG9jX2VsZW1lbnRzW2krMV0KICAgICAgbGluayA9ICIjIiArIGVsLmlkOwogICAgICB0YWcgPSBlbC50YWdOYW1lCiAgICAgIHRhZ19sZXZlbCA9IHRhZy5zdWJzdHJpbmcoMSkKICAgICAgd2hpbGUgKHRhZ19sZXZlbCA+IGN1cnJlbnRfaGVhZGluZ19kZXB0aCkgewogICAgICAgIGN1cnJlbnRfaGVhZGluZ19kZXB0aCsrOwogICAgICAgIFRvQyArPSAiPHVsIGNsYXNzPSdwcmludC1zaXRlLXRvYy1sZXZlbC0iICsgY3VycmVudF9oZWFkaW5nX2RlcHRoICsgIic+IjsKICAgICAgfQogICAgICB3aGlsZSAodGFnX2xldmVsIDwgY3VycmVudF9oZWFkaW5nX2RlcHRoKSB7CiAgICAgICAgY3VycmVudF9oZWFkaW5nX2RlcHRoLS07CiAgICAgICAgVG9DICs9ICI8L3VsPiI7IAogICAgICB9CgogICAgICAvLyBJbnNlcnQgYSBzZWN0aW9uIGhlYWRpbmcgPGxpPiBpdGVtLCBob3dldmVyIGRlZXBseSB3ZSBhcmUgbmVzdGVkLgogICAgICBjdXJyZW50X3NlY3Rpb25fZGVwdGgrKzsKICAgICAgLy8gSW5zZXJ0IGl0ZW0gYXMgYSBzZWN0aW9uIHRpdGxlIGluIHRoZSBjdXJyZW50IGxpc3QKICAgICAgVG9DICs9ICI8bGkgY2xhc3M9J3RvYy1uYXYtc2VjdGlvbi10aXRsZSB0b2MtbmF2LXNlY3Rpb24tdGl0bGUtbGV2ZWwtIiArIChjdXJyZW50X3NlY3Rpb25fZGVwdGgpICsgIic+IiArIHRpdGxlICsgIjwvbGk+IjsKICAgICAgCiAgICAgIC8vIFN0YXJ0IGEgbmV3IHVsIGZvciB0aGUgc2VjdGlvbgogICAgICBUb0MgKz0gIjx1bCBjbGFzcz0ncHJpbnQtc2l0ZS10b2MtbGV2ZWwtIiArIGN1cnJlbnRfaGVhZGluZ19kZXB0aCArICIgdG9jLXNlY3Rpb24tbGluZS1ib3JkZXInPiI7CiAgICAgIGNvbnRpbnVlOwogICAgfQoKCiAgICBpZiAoZWwuY2xhc3NMaXN0LmNvbnRhaW5zKCduYXYtc2VjdGlvbi10aXRsZS1lbmQnKSApIHsKCiAgICAgIGN1cnJlbnRfc2VjdGlvbl9kZXB0aC0tOwogICAgICAvLyBDbG9zZSB0aGUgc3BlY2lhbCBzZWN0aW9uIHVsCiAgICAgIFRvQyArPSAiPC91bD4iOwoKICAgICAgY29udGludWU7CiAgICB9CgogICAgd2hpbGUgKHRhZ19sZXZlbCA+IGN1cnJlbnRfaGVhZGluZ19kZXB0aCkgewogICAgICBjdXJyZW50X2hlYWRpbmdfZGVwdGgrKzsKICAgICAgVG9DICs9ICI8dWwgY2xhc3M9J3ByaW50LXNpdGUtdG9jLWxldmVsLSIgKyBjdXJyZW50X2hlYWRpbmdfZGVwdGggKyAiJz4iOwogICAgfQogICAgd2hpbGUgKHRhZ19sZXZlbCA8IGN1cnJlbnRfaGVhZGluZ19kZXB0aCkgewogICAgICBjdXJyZW50X2hlYWRpbmdfZGVwdGgtLTsKICAgICAgVG9DICs9ICI8L3VsPiI7IAogICAgfQoKCiAgICBuZXdMaW5lID0gIjxsaT4iICsKICAgICAgIjxhIGhyZWY9JyIgKyBsaW5rICsgIic+IiArCiAgICAgICAgdGl0bGUgKwogICAgICAiPC9hPiIgKwogICAgIjwvbGk+IjsKCiAgICBUb0MgKz0gbmV3TGluZTsKCiAgfTsKCiAgVG9DICs9ICI8L3VsPiIKCiAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgiI3ByaW50LXBhZ2UtdG9jIG5hdiIpWzBdLmluc2VydEFkamFjZW50SFRNTCgiYmVmb3JlZW5kIiwgVG9DKTsKCn0="></script><!--URL:../js/print-site.js-->
|
||
</body></html><!--Generated by HTMLArk 2024-11-20 23:55:21.099099. Original URL public_html/print_page/index.html--> |