From dc23a7b766f548bba3b43771ec6a4236d8a52547 Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Sat, 19 Nov 2016 19:20:44 +0100 Subject: [PATCH] new wildcard mechanism --- lam/HISTORY | 1 + lam/docs/manual-sources/howto.xml | 94 ++++++++++++++++++ .../manual-sources/images/mod_personal5.png | Bin 0 -> 20626 bytes .../manual-sources/images/mod_personal6.png | Bin 0 -> 19912 bytes lam/lib/baseModule.inc | 10 ++ lam/lib/modules.inc | 56 +++++++++++ lam/lib/modules/inetOrgPerson.inc | 92 +++++++++++------ lam/lib/modules/posixAccount.inc | 34 +++++-- 8 files changed, 250 insertions(+), 37 deletions(-) create mode 100644 lam/docs/manual-sources/images/mod_personal5.png create mode 100644 lam/docs/manual-sources/images/mod_personal6.png diff --git a/lam/HISTORY b/lam/HISTORY index 773fbf34..73aba618 100644 --- a/lam/HISTORY +++ b/lam/HISTORY @@ -1,4 +1,5 @@ December 2016 5.6 + - New mechanism to replace wildcards in user edit screen. Personal/Unix support more wildcards like "$firstname". - Windows: added support for pager, otherPager, mobile, otherMobile, company and proxyAddresses (disabled by default in server profile) - Mail routing: enable for groups and allow to add/remove the extension - LAM Pro: diff --git a/lam/docs/manual-sources/howto.xml b/lam/docs/manual-sources/howto.xml index e25333f3..1b2d319b 100644 --- a/lam/docs/manual-sources/howto.xml +++ b/lam/docs/manual-sources/howto.xml @@ -1005,6 +1005,9 @@ Have fun! Mail routing: No longer added by default. Use profile editor to activate by default for new users/groups. + + Personal: no more replacement of $user/$group on user + upload
@@ -3306,6 +3309,12 @@ mysql> GRANT ALL PRIVILEGES ON lam_cron.* TO 'lam_cron'@'localhost'; Location + + labeledURI + + Web site + + mail/rfc822Mailbox @@ -3330,6 +3339,12 @@ mysql> GRANT ALL PRIVILEGES ON lam_cron.* TO 'lam_cron'@'localhost'; Organisation + + ou + + Organizational unit + + pager @@ -3422,6 +3437,85 @@ mysql> GRANT ALL PRIVILEGES ON lam_cron.* TO 'lam_cron'@'localhost'; + + Wildcards + + This module provides the following wildcards (others may be + provided by other modules): + + + + $firstname: First name + + + + $lastname: Last name + + + + $user: User name + + + + $commonname: Common name + + + + $email: Email address + + + + You can use them in the following input fields on user edit + screen: + + + + Common name + + + + Description + + + + Mail + + + + Postal address + + + + Registered address + + + + Web site + + + + Use this when some of your data always follows the same schema. + E.g. using "$firstname $lastname" in common name field can be used + like this to get "First Last". You can set the wildcards in profile + editor so they are automatically applied for new users. + + + + + + + + + + + + + + + + + +
diff --git a/lam/docs/manual-sources/images/mod_personal5.png b/lam/docs/manual-sources/images/mod_personal5.png new file mode 100644 index 0000000000000000000000000000000000000000..35be0271553e42f09a201f788d6cd8cc8b5027af GIT binary patch literal 20626 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 nlHAek|97Q!Slwq z{48b#FbGK<9`lp<7JMak2)I`42D*_(TBOvVQA>8a*O`|iNJW*46430^1kKM6b98g_ zX|DoYuYVrBVO733b1J!lc+9K?Hu%;QqN3A%)%fB?48&R)&1u@x_v+oJJ)}7&&7v3u zkVGfyXA!h0Ndt%gJ#`f1rIaKkE`$wR>S=}SOWr6+X}>lGtQ@+y<42f2Z#XG9IQ*f* z`jShB9sA~aVR|P+pTD}9r|>wu5xi@xnGYm)4JTam8{$SR9^M&&ua}Np3=KaG2>V)3 zsUKhx9`_bbBrq&0F`E@%n%rf4a-bLXF^A_Lpm`T>94oZ8In!3H@E{?d-)@H@yc<_+ z)zuU1)$A+m_`EO6wkEoLny$Y@;vwc27tba}xCH(bil*)@y7BxN^6#BS5)VsqUFqbt zzB$HS>UJh4CFXWLie?@%tIB0%$T|qd+3-B|z75XTYcfv(OhedCc7MWN38I21;6ggz z=eMyO>F@VF%B@=^3$|Z8ulOmJE;Z{nIfuwE@iJWr2yAm_J`F<|zr4;bl zmhjifW9F9%VeL>TE^0BvAonpn)x($v$3;uN11G+Yeh#+Go7;r_n(vcRtD{JgU2ksA zO84WfT%Ru)5$2DFa@o)Fd#%TmXa`B=V%yta02Xnx+MQl5DEK!8tRf#hd2n>lrJ%5 zE3B$gzO5JCV9wFz9`f7B9UimIQ3{rZvkCbgcFCykxLO_lF&mPAOv0@`Jkxbo^2+rrx_aP7STl;n z+V$7sk-psKVv}}1%!LNA!0I{Kes#c9buR3;&d{HPjHw##V_zx}f3EV`T+6 z59AnU9YSJSi_@^5l~*`$0f`SLQ_anTlONw8X#bidkMGoC&Q+S0th?+W!6 zHq6V%E+JuugNU)`s78>pfLS^>R6H9u7$O#QO30TJ znR|3|Hs7k-(g{4NHA-S~VVliE^Yrfm{gsyI#pWrg@ZsU(ezBH>LoG?k*H{3WnD?y9 zNS#;L2@>{L8cRG|m&t0nWw2LEFJc8YQawR2dh719$O0sW3H0flPl z3A0AL^MPB|UG32X;}d`#qd$n-;YfKw*4DS)KwOv_;xjptO~GmI;CLuaAeH!QZ0PEh z_0{_ZKA)aVS3NzlGq2M>1_*X@X6<*$i~@p--9q;SSh%=_2tl_()1LD3cBhRA&n}l* zSAI94AvWf6&o*-5n-x@mmGP$S?Vw2D-#UA?V**N*x4*j(L--21(UcAM4IymceBpVw zsdeVqSUpGh%)2FQ2EknyJ~xt-sy1`6)jOfg+|4XLN^PwbFj!jTd8!8d11>_)KvC|& z14%yl^q$X!m8W-PoJ`nmlqS8DCM$vz9K5-3Rb8`W>*sQ=%tUnb>6`w#zI3p&8RHB`o^$z%J5fBs)PqdTr z5*76g2IkK_S4*}`}zmZSl2_n*Lb zxzBKXs$*Ck!qyJFMlH|Y)kl_uo)f*FqX5&;5K^4f#}3GtphT{nRsJF|mQ-2JrWkxy zs*D`jE>iaFT5W+Tb-tPJrm$rG+^@wd^!0O6e#rSQp-D~M=215HQCb_noSSz_3gk}qoe-n=E75@wwHI^6`n5B%0)A`CYt!zMA$4g8VA`u z@-q{OqEplgL~)1r$M4Bo2?;in6FpY%p3l*tb1J@Y_BJ}+ z+~ZeD^YASGX>hyTliG&xwOVu=*cbM8d4;lJ+?GznRc$Zc?XpAnQhV|rBjQ2JE6j~E z650iLI&dHaLc`XjMd2VoamT++IP^KasUo0%y5T;oeX*cIc|3k~wWmwXE-XBpDr>c; z=(mM$xMrn8%RwBiWKf=p!iOO4tbh||e>YN@VD<{P0n;pN8#Uuu@_s?VDk z-S*e6uC8R$xg5qjqvFpe@|8Cb8>`jT)@Wks#gYUZ<=g-X*5*9>gPfb1I6M#V3;4Ge z;dqP!g>znPOI3Z>$DP4WCx|KretsGr9)s)ZU?E1?g#%1fl=0;yD8m!r zZ{;w?VS;*^@Z2dy0~uZ{2kO<&G`S37!ShntG~mW0U8bl*YxDTuLK$~6$gl8sl+Mk+ z240^u8?Yq~nMF+O3~3UYeHpV^A2egf!Xeo7+I5$AsF;IwJuu%K#Z<~DxonNzVrAdH z3#g8VOIQv#U{~e5Bp%kClBT@vx2%DBP7lW!}e*3P-LS@!yFdSay#o=lV9r0uWatcD(=56m~gyJfkWOE=IK!4 zDQsm|-684F^V8%fbIaJ7C5S_wIFisrK?#AOhr_$ zt5p8060NH_AgQz%%wa1WGf*j-qKoSX5_OTGCuua`z{0LONK)`68T?4F|70>NY{3zX za=|*^%CJi2dQW)~DQsWg*!X=&0IQ?2ScNW%cL1(l#zTlUTvwTr0(Wc}JjQ*@mN+>- ze`949-1n9F#Z&*Akms0`SW$-yE&@2*mPmBHSsQ+whBmc4R8XnOq5z$iaweEsEkk@l|di3tFjmZc5scS zeI*|~j;%Os8?VvdDysBCf%5rh2)I%}Kv3Iksc~y>4<=H#gyf$$JU_oU5Hm(BM?!=5 zq<96{ViKStgLx8FMk?zGmi&RNnMtodPPz*croj+Bkn7kG1EGsD$qD97!>v-$5Mg-1 z_G07&Nc|fp6Pq(@Vo^*(}!9E2cv6KtvQ#I zVdk)B3#_kD<&RwMHrp3HhGaDm}>Ko)-elhXOqg&9f$>7COKq z*;VBQnh?P;s;l1EWgum%Z<*Dx{AAk;CAx^~J7j$*3i-?J^4gE|Nr``50Aem^)PLI$ zmZrflz9WYzgaPaTO*R3uOHc1d@y^vh@43JKv_)5+^-X zW33Ke;nDH65&^u;pATWrD6rmaKjOee8^Dfw&2rAv8TCf`uP3GyV4Ah_)acXO-htiR z;#Hr0fEU~bb8@!mHa+)J2T&b`^@Zj8aR>O>JNba{%I0LmfXzft6eFmu|V=9{0wivc z#4$Ig$v~A!7)bM4ZZNdxswyk>y|?!2C04ZSd~ARKs&r0XbB?gwN&CK^-E>9})4bE3 zpno??WoFVv8f&xS9zLzny z#oFOT7rmQgk~CvE?r7rQh?T6n%`Eqk%@OpcyRB!vnz{Vx(70EKvZd6Do|Z*AyW zzkBzXn`+Ol_ry-TnEdz|@-v{`)pGjl)U_lV{7wv7@LCw5@3ejj-6FywI$m3o8bDk) zbm@LZLSn%5QpEs8FmBbeaVd>%5`K|7{17sw#pfCzZ#o{#frM4~Dk}v$1Y>=gL}gBh zdYp`dKi=ALS|ZNJY{avBR&#%6{xdXI8b4f|9y>S?W6SBasZaQ7+dmSK4i*5Qb0r^? zrq4C_Oerfw0A91Ho=3sU*T~m5ss^!BCb+S^&1U58_vPnhcZwyzJmI?C`rg$>Q9R?} z?ORw>U0n?-x$)gWO7nFxMmL|zsqPFQZxt|JpG7U)N(9VddXSKm-$meXK2zCzM3CKO z`_tVG<03=)vf1KbtpM4&CP;)`QG>d_KjAH0R*x1QA5sRN7^9C>m-grqx2IBo(6C<) z^=z%!ZVkPYO4Bk~E&pDJJQTrra&mj;Q#^uC)5>`l;8D~%%VS}10Dw8XU@LdGr^xC) zQyY_olS>$PQ2;`_4WR#gII^pyuWt{ImZpNNt**L^=p`m{XEmYKwZ``4aN=R&&SDR= zYM$73B_uHE=~TN1zsr1`CHf@@jYuHplNA!EzUS<5MO7^GSVay6*sKE!433{s2+RJU z?=ffVdn2{-G!U9X85>0pq+eTU41i})eHn`Ius%JQadJD}PFc7eQ7fIW=wI^iGCRAG zrc`Y%;i5txwK@G;3$S;+GJwu3n?6})UtCwWk?ljH=D`ryaB-hS(xcy8j{oMs@Y-NG ztHM}ZLPEkVBw~MRC#sZ{^}O^sC<#^cbsCV&AuJ7{)MqRK*L2M0C!w`5QO1mZiqBO- zIU6o1@iWX66*GOv_Kwo8%1W7?=I9dIc+fE4+BNE*+T8;=v`eb5C^^}Y~2w@`A4o&>W3dxF1)ywZ^!kmSjHsy z32}O)AtoLcf1&oBbHLkKvAA!tH@PCLxRUJ`hp|Ere8YBDR#KuIS_%p}yG8#2g4qbd z3JbT&+A7-5vxQkbPR~hcwMt6sHCm2O4)O&A^QUP*H5(fn+)n4aWokYr1Ff-75k5ubZbd|6W%7BUeMA*$371w^X9C#+2 z8mG(2>3$Whwl_cHyBgxVEk_i*y%%JBuH|YSzI6sTwcT2Y&DdqH56h$o*%}S;-`cKx zT_%$AI1s`i-{apJObnF~_H3#>6SEB`XxW@JEa%dwNi8XG%1J>m$dKE1&y0Y`BqIVDPnghC{#py%!70UdXpkk9q)()@wDhnF^2DzDFV2{$4&Dr$Ls-S_x(D^L)}-z>XW zMGhjJpyY)=uF+iCFH@A=9`6WVk?nq}AgvjQT^A#+0CDDQ(g82e3|F6ZQ2nAq2Yob{ zV(6{0`?0VQm&mT4sClN9vN@dUH=CfO4}SzwvFwZeH8bO>*P3}iL>X zwli?4?4upiKTz@4zv^tG1^*q)O(swe&Gp6mE2{o)LF->9fqx+>E0?Xq;SF?gXrTcX zpzx&j6VH|iC$am?2mF?t62sPcXCAw~Gp`~R!>cL>y~{#g7I$|2a( zMFpuyP{#xYA!88F4GhdL!fJTffSTdQw^UT70}1w{R!8VNAUXe^2C{N3+Xv*MZRyAz zDCbN)hCq$bUrY+-p;0tdXE$NCTkjqxZF=Ac%HXrA;S*$Jq@z=^=UCn;A;wsLII`it z1UYhPd^cueQygCEV;ThL;^23aNEUPi@l;?@gI!(dgNVrD*M17W7$hk+?z%%COL2Hs z`N1)Pwv`PNHzzq~^=C|;nr87~en!m)$*GF2t44~E>(3tm95PPM$AN3-w6=54wB0?t zlKI&t07ANd03v#H1brF41qx7vIEhs?91n|&&6AH+GZj9*r*P*n;26>#7uW3=AVeKaZQk3h1I?Fq+ zW(3XGWb$6onbc_f3R7@=WW~tIxd@|LfWKOZa8{RA_M^X~53nNxb8~yCuk`|r?&>}U zaiIQJU`)R6V4C?;8{ELn+W%C`@8qq?BRwEC|Xh4>b$tit*(PIkrerfVp z!9-NMa4S{m80$8#EL1Y-+xiGn9T@#+*?A1|Z=CnhigKN|)M3z8=?F_qa%5|># zrh}X1D$4dHiX67cn-6J(V+QOQgZCayCXHECy1jrvJ}r8#eHDaR&3>}>drnAm_A{NN zaoX@*XzeBC40Uo0S6A0L^f`L))`G`$7-2(0L;U&Y+grb(#0iQ#YluZ}ObiVpVyP$I zbs(VSPdjL!!_EcCKU;>cG%WlThiA6|wm_^=O?-rIrgEY)ct`|77w|U!Yu1+rPUN`S z$lz*Z5lC!Y+}(h3akg3b-6hk? zkvw!kQlW~7f~*N0yF^wv1;5Qf9D3fj@RZsL+unU#&N{(o-kYr(>FF^awl33}GapJB zt5EJiY9r-yIbUE`&L{ibwlr>+h)8f@pFb|wUIhIaMHzr-USa2^^wH-oC>_;!^LYjw zOVgJ9-Yi-B2eZnf+sxRa`L<7azEK+A64M_5HAOD~A(zZ-)BajIzj!1O4`R{OZQh*5 zyAr&tv<)LHlTGAjj)IovkyqbV3p4QAhp%{}Q0sOUFDqr07e5NoPyM0RA$M-MyTSM{w1vI=2Qu+9CioNj%Nea~4rzKdDF79Pi zWaNyXm#G;Hx_>+pRK=E9eV+eR)!ll3;k(_UQKOsn6kYE`hZuYv4~xhM5TJEJhjklo zt36H{oXpkBv^Wuqh%jPdSnJedkrS*nTPAMSTrIHp>rYruR-T5OCJ@P&g-vPQQd z@W!_TKBjx+Uo2n(G83$^yc}J9?}p`ot(fbx@U!!C@9G1HjMu+llhuSHAWB_c+rD3L zqBL$5`~X-O`h_Q=&E1gsonFg)T(gs+QI-a{(6J~zeQ9vED)=p+<=V{nG+j;e0Fq+X zguDQ04G%Nb#)jF7M}&x&`n65hBak`d5)iiV7BI=6L;;0BQA_kKraJ<$Rw0p z8{QpD;Yf%})J<8r;BvozA8_tb-Q&03*0?@DbSC6}_WAQI3TmkJK61@up6$HL&UBnL z$FncXllp!`X;%tRa(1h=Rv#};Q&YaweGzHtc~?ZSLqtf3^jv+^Dvwtz8fd6%P0uvI zw7G~~lT4aMo@pGpK6&AliR~a0i|~@Z@y&PO!9pM?0Vfqp3WR9glar@2OBx2YGudF{OoW~(R}DC7PH1a3=8>UXGg%1}jSP>zRV8b>@mz0oiH7m;VPuhZhJMEno?I zjqSizm}bhF-umbPE@c~Pi0-TGXbu8GWRw^{QTBh=g#E3=`Y&W$tuja;5;-X;O+ema zxiy3SEE`ZJ`)~J}j2|Ah8;W^(cr?v7;YmE`&@ggya%`@S(X|*`4M{Uzusq~N>UVcY z*B2)S8b4uh9)`bQUmriFb zAgYg-;b3KviNs_m6*ju=Nkd421{D5*Ttoh&Fr^z7z{3Wy1a8+~{71R0bBhSW%cmZR zEwMU_&j7ZpK+DR?v&j|fL6!$fDqPIRmFkI`L8ZL6qYm8E`b612!9iPU<1Fi88}x4O z%Q_Vh(5Ftn)H*}c5BqZ`eQFi~jmn=#mgus-%ti)v@?SW-8<7;X|KpKHiS1-odgv0e zlg54w*eq_P7K34Tv!FjBlCv71ruxHy9-%Y-ErECgGt2HHSY{4IiEW@K(C2<*7~QMd zJ)*gzS@bCCJR=b$bQ7qbuL<2zzlWSfTCp1dNM!mvM3}ynGOM_F7hm6#e?RJS+LoLc za3QgG5(k8?{~4Zd@3YA>3gPA^ zC;4FK0dkc29td#5);$ri_Ug=1P0a{^OsX=YQCTo)`0mDe_eW6u%&aA8w8^b5wq-~D zzQOpk;1l2rTt~hGNBsx9P$9YlkXb$dlfpQiEjiA~dB&9|^K#9%Zz5nKj`F%$n~8V% z{~Ws;^1mo;WsO<92af@P8(@BvBc}kc*+I{MV+xls`t`M0DLSNc=6Fkq3m%8<(0%SJ zfR#GWxnir;P4`>zw zE<8&|05XHtOUDk>37WGV;+?&{D~qMz3+K(HvW@+-AJrlqwW6KMI}S&^}1ulJ2jGQRxmi|0C0J^gyale*Pab6ROGQx1BvbEtC06 zYa!vms2jdlQ-P(6;zOwkJU(+RH5ZvwGDa9zx43YUR{Oz|9cO=5~r%CMf$Wh76;3mjmcf9 zpDngNmBSO9RWu97e$nP?CWW4@;&1(z+%~*7nl?a*P`5QxT~aoUZmT=H8qO1}sRTve zD7B)(_Jvn#K?EPTg$IZ8{tZs6XQsiw1(0mfWd<5-X-+t}!d;qtv6DyF78&wD*n{Jw z!k=Ypm8cb}JjhzDs1F6OSY;XaX~tzcFWyETD5mA(nXbj-DAq^Lo|_V0h&-HxjYS5i z6giohM^p<tHr#i?aPiuj*6F%(2*q zC{_NV<2hR)45s>T88-~Jua_1EvsmG&cwqXGK|eZJK1+7?<#@(-wXprQs)mQ?pNc*# zg@F9_pVrg-7ct^LiH_@+9v0__P^fB9H|o8{gMMxv)a&Q-4IujKIFalsz&UNzAA5f4 zTpH?psZ0OuiF*=tS6p}mZQ0%jNw3k}*m$e>GL0(pgXI+?7YmC&^vntm8kLq%z0{Jyji?gplfO~Q{weii_gqrH!tedXPRzf`N5i{bj{PSYnUf$Q{t+mn z^nW4w0vOb!1pV{d+T)1}`r6L3-EsEXD)`klrxc*31BwaIO+f#n=6!6tlGP9|ClQe% z@U2qF6fwrV!9*lfyp;KcIP&g(rg-*+I@4ZVt{5l9!SAT!y=|(WKOfyFMW~RJXVKjZ zdU6`Be8nPX_6phvIGDcU0Mg1x^i5M4R_(eyAV1)7w1|<z(nWb($!%+uQo91wNj*NqOc9!?kC*KPWHZ)_8N{@k&$Vfs!Nz@0IHzp@P zzBy8!7Ak8yPbn%IfG*#mKU*bs%4?|S!2}ddHtROKABK7lsG9Mxv3pqt1(DQLOw)mw zBzU$)U~b+J8hTQ_L9@PrKdUi#u~QdL!rBg~rS?mS0JYTOh4#+*fXx~}eZ?~`eY}6i z2jCWE6BYu1&`T3^)BQu}HFJCjh+Hd=sib*h)TJA8SFEp`Pf_4;N_rJz+I=`d>B^YLbR7)tjiOJyJa`7yEX!nN{Abwoeyn{lr=*Jt@OWO)Lj3ma2UK-q>FFolMOr;i>nmN06S?6;S-MH0Z$?;|AeK8sLK2;fu`Bm5}AxbCn<^4j*(XKv6@Id@Lh3y&c>G}DSu~r;ghQQU!Q2cW~tKO={zd60P z|0rCB=Y_2%DXIavsR#8&I_l%jmvY;NC}*mA!|V9AG!#8r_xVf@(UU8C=`{%J>|o|( z=1ZG`$F_s@Ktw8Slk1(;gRbY^)D*tIPY0%BoPu`M>QR;{iiI@;A`#O0)>@rL8HJG_ za;*Q*{s>{}i5Z)55ClJ0#LU<-(ujvX$;3-va}2l&q~Az2x~a6mb(-qG=Xqm?`}V?C z(?gkbx4A`l@f#o>7dYyC{wd7MyC@Tr$Lzn2((_^uQQAh=7+C8u+AM%r`1+u30kYJm zPrHc1U2h_MWQ4A-&t}rHmKy&xhmF4>0V`z#a`^QAC0xf45u{IpJvyQ zH-FCq^OSEBeghU9GRvn=bJ11mCQoBFhhG5*}>J#s`fD$Aq3f z+Nb7zs!3dhIyiDM^IM3T;v=`!ZfrID5?C@5M{I0-U|Y;M(0m+HH9%jha&LLXtUfP< zhl?mukGLJR03@4g_p8Vsvi~l4&~X7pQIFnFB~QEeR=| zna96Ui4%)fSK4~FP|#JR&86k00KYGTqJ_!+#;yBP_T6ev6@zuK=cB!OWe?uC1bsoT zT<7j0UA^ze{xytkw?59HY0ua+$hcA2^&;K3AN5qbo5m%mNql02Lpl?~P}5>7(WvZb z!qcFeR;~?@UuCJ9MmPTTwaB1|5d#)VCavH6r8HPBR!er>1I#`rXEV6`IlD3*TX6L? zM_#Nc#%qpsdK1pH`!5!QG#Eo6$~O99Bce}}+g`Uspf%$81cuhy4#Hwp$|)L*CYxM^ z1ifx!^u(@(FR`9R%p_I2k()7&OwFfm14aDU{>@|bmUl+SDpK5Jxr{whgVFD7c-&O! zqkzPI3cQV_W(g8;I)wSb(4RkFs5Lg986FFYAmayC3#R*2u3T+Rl#ohGhXCv3Na<}p zaHa|QBN=E;n-5;{3&3p=rSH?1b7ro)&l_rv_*-BqtlNtO+`Ok-FCIN=b>ZpsL)_-X zS?2_A@US_2)?_*!O>}<7Mj%;6(^1wX!M!g74tx?XNqHL6!?=Ghzc~EgW4n5-rO0P9 z=b-i@s)GgIvxW_UmS(7At`a&Kn@LaU;&jQ+PmhSgsd-r1ugh!m|F0GEikf_QzRSg* zc7N235d~lksjID)gqwx%Nn8RdDoU}$LP|9)Q>_HVLQ-~PxXNr0SiM=IF}R*1*Aawa zNs1+8^2eA)Aw{Fg)1^%)Qam6CsPVC#Y)^%3ob7x<$_~T~MML$;F(28RubtXErEkRv9R;Sc_; zyq(DzzY_*05}Re_6(%1iZKWKk-%Lu|PIS$DKbIcJj_J+^XtL_=n+(nd$JK-IoB5hQ z?%Bv4H)rud1mDde`LByCuT*X%=g57`W4ujKs?%I-ykZyd(5^7CYQk7f!x zdVDVq4^t4s!bOI)cR-~tAaq#2x!Qb5h@3o~x2#3$DC0(1>AudW>nb#XjGWu@DZli+#OBbR)>e+3`hnsDK{3)xrKz!7w? z0QA~tk>vJdoJZ65f;m%Kj(RN+K`>jAoL1HOen-v}QB45+saNU2)#mNWk{zi*IGV8u z0fn*0JDof4r;`6H94nVbBH}L|_irq$mo}cCE@CNkbC7Bm-e^7GewDu}6uQPnHVb1N6Urs6 zUd&8YebpvMD--z&xcIn5Q&hkLY@1R~$2wp=PnR4M6BE&p@P!VK-~K|zBgB%dQ&hor zlk2?u_0+3rhyqDce%9JzW846}xZrqfP-BA$wXbuBD&g_zC7=F0zsp8vU>Nz}=h;E^ z%WP}vc!D%2fl;tKHt;{RFyGqi>@mRJB|X*GU)so5Kpfm0?A@D=0Az5!Fk<1rFRftj zb%#XQ=0fg(LNa$cznkmX57m>UyOH{%RomH$m5Z4cPB%N*Iy=_IrWz~UwXNk$N2e-T zlw#kqerAs}#Lg+r&rDxHQy$< zOtWOapCRrkW@ew7VYXn#Sw#0%w1LDry~TP#5|ws+bM_sJ*EYDbkWMX^-HPL&_PP*bCP5 zag_~=H#Ai+wYkyDMVIU2{oO?^P4PHD1989c)#-2bp`xOKsHmu%PQ(u#9dYR*V?HT zO~HwV?2$2rI6WNW1Z@TGtWX~8c_`$1=8Nfo@DJ~*I1FZmTufM#Rt^oR!s7rZl8Y5> z&15&hODw{)H(<9!udiMz#3Qv#MhQf275ERNq<2iZJDbNwgoIZYmg4R29>Co$dGD0) zg|Sa3Chs=8#d0iFOw-jZb>+YOi&~DNBAk*F z7Z+CbSRITNBp{e3q#OG)1llX9vNoUfd!oe`qhA^+uH>Dr*nEARi(RKBrnO^c1yJoO zNY?Uk(qbPQR3J~v(kkg=Y)oEa&P;>MTmzyuR7sK}3#&?uMC_!yV05s#kAQmKbhMF6|5SS}$i>Us2!GQRQO zGTh8xgW+cPyk_jeJ{DSka~@O8&z}DX0yvsK-vcrBrdqrr3@z5xskQCV;=9&z}-T>18`cqDz_U$3v zc?$ARHH7_-epBRs#(`X}S0iR%smR=#>kc4ZJSChlcGWO^rQ#el+enY1;!I1yREo+MPlp#@^tsm5koI*5O%RD-HAz5xJeOc} zv;A@F$UPPs8Vgm|yQI3M5fi?Ho3*}^`*F)8`?L!{v;Y#}SDk;WGHJo9=v+^;0A5;n z4czJ{=TnQm_D@Hj9w_j+)V-yo6ATSHD`!EzCc?2u&c-yueM{PK%!S2;xd-K@ad0@f z1N?^?eevKh3BTFzl6f7?zI{AC6WK(cU5m{0RDge=_y}ci64UTd?TvjUltbj6$!j28pP!~Sk4{KoWjmM zF;fY?X=#cflax za2W^I{reIN8Iz1iz+}9GJuQzu58HTEq8Py=OnddSb4kwo%6>NM?bUvGIQg>np{v>} z_>f<*lzgJV;mpO*_bZ?_soE+kq?Io0y;gnsRq+Lq_)_CH;0IwoRo-cz^!0x`H5uv> z=dDequ5DU=hm=~HD{p3KP%Ro8TTMA}<$2f5Ja``&EZ8tQ7Ea1OxZ2>nu#-3R6bnli zfE~ZLoN@OSE*xOzLHP=lS-ei{>SpEfL^Z${@6>BcN(6sWH*fmvcoU_;`Ch z_W@M=LYh0IYuRU4O|I*6d*SM~7DIE*3n{q3isPcCtB;z~+wYl&Xz6Et7F+79r`I)0 z;&u4})q(lq`fl6-qi$up*UWUu`-76c?TLJI!!a0eRRxlHk0M{@A0PCWzPFWJnn(q3 z>mi9WnX+uIu6TwkkP?v@qB=7^ig#;|UWnvw;CS}QtzvT*W6tk0bhG%q?7n?@Qb6>H z_Xl#1Jv*6e13%0^9Sdabro1~`OTvcElF*-KRYI|>_g_-vV6LH5)rEa;p1<3!UxpP( zK=_3g1=nF-&U|~9lUS|54yTPlw#2Z-CJ8;x%U^A`yi81UCT#NQu87t<{kjj`f#Lkr zf;`g}XskqHz_ON$t55dcZY?QS&VaCuz*s#{rM~p~x*M0?5tE!&6wv%2Ac}mR)w?%h zxH^WPN~ykC5eK9*Z8C_fEsCh3&yh2aw&JKPicGmEeSQBXt4ul$9eFcI`ff{0w?_BS zNn>#Dk&c?4uhpooWvl8J(F0wL+S34&|4i?39G}vuICL~=sW=u1p&c0;QnorIJE1soS)HcC zSsdotSd>m?xn*)9npWoQ%q12}WCyt&VKHaS=tvr4ZksLl^Hu#3=kfUb@_BqNkI&=t z!{`0_Jl?PO^HC~=!q(|1G9j|8pD`F+G2XOe4!(2o$m*4lX3b>QdZG%o*Q&$|U)Z6N znA0y+WKoU5JC|wB85CQZ3OK(RK_&X?j4G)^ca}mWsM!3_fGntiW61}$)Mtu;RCcCx5#QzQAB*qX>gLvIX&z4@s{-~XB<)0% zaFSc{Oz5iLXe+K1^-Ow}3l?(_#+<=X-@b|2yaho@mfD78YMYuD%Nho&U^3lv?BofE zE*JOy#SYqBik92nsq~3Z#Pw4?mA@JKjFQA7d`bktPClcZNLEw3LqZ%zBLA$ewlI|- zsS(?^!+TDc2=Cec+*J@HhgE`J7RHl)C~?Q@>cOc zr|v#=v1Z2j!ZSjEi^7ER%CyhppVb-EvLV*{fZF$*IT zJFX5~cpqjvDVbsocjYd&+5fssVzQ47)OU=|<(JyebOb1WfUI&IuoSwyUE$9R&KM5! zy@QRLe4Q)POtw-sm8QfDjf8xyVSO*h%dhUoguw2J-h-h+zkefN6?qImc>A+&gL$LD_*`2ke z4_2~(OR4d1W-A;q*Az8^5016A@M`6J30D+W%ht=yhXum5iqiBa>{=CbtqjcRb+Fd{ zwd={{V!lZ*V4}d(7$?D^yLq+iHIjSSl_x47{u%e|D;cQwbZ2@S`lQ06tC3D6t#rzspY&CeQNk3U&C%J#D4ZHalR_8z1`cUT1PBW z%7i)i1XBtDOscDs3M^1|-T?vEr8F$BL5UMxSJx@|mR{sjzV*d7pjq$BNd@G?k2Fe2 z|58Q~Nzi1nA@SE@yeln*7Ot*V=XQm=cRI|YJoFSaYpBO8frp2f4>`G6KDe48*c$f_ zCHe1t$bw4AoEMPndFThM+=fh8Cj`!5Rz;Mv$k%OJLbh=?>3-okKdYD4Fq zqz5diQ}B6!W)rpWG2ueX`A^=>Z`+*pI8CF^vlTe^tY&1)&|2Oqw%?IsRon7cU4?U# zvjG%A=F$%Im@Z%2KBn`DM0Pxr84(Z}n^&MG{z0MdDm4mRD01|(H&w5si_dhEuayg1 z$u4u#t z37D((eFQ*Sw}#VQZ&;oH(=JjBpcdeopmTiQ@xB4fmowys|GboH*Gpo_9OD+-n4@T1 zPhO)_BefCy7Q#Lh)>mcsc~jB-MsnMgrwh~kVipts2mB~+SC!@GA-P|VB#WvXfWVQ6EMjQ7oz@kV;&GmymkR;78}~?y z2GP5ab=Ck-lxK^{+k9go5iX%V{}6`Xlt0w>jxIRPK{*VQ;UI=G=||Iq0TyG*v? u0a!OxNcty$+gYp6YSj8O2k(F0U3TQl!XLtgN4tSL2f3WYpv#;t-uw@mp#PKr literal 0 HcmV?d00001 diff --git a/lam/docs/manual-sources/images/mod_personal6.png b/lam/docs/manual-sources/images/mod_personal6.png new file mode 100644 index 0000000000000000000000000000000000000000..e3648113892bbea1d0fe09e4d6e98572cd6fb5f5 GIT binary patch literal 19912 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 literal 0 HcmV?d00001 diff --git a/lam/lib/baseModule.inc b/lam/lib/baseModule.inc index b0f5a7cb..4644664f 100644 --- a/lam/lib/baseModule.inc +++ b/lam/lib/baseModule.inc @@ -1951,6 +1951,16 @@ abstract class baseModule { return ($this->moduleSettings[$optionName][0] == 'true'); } + /** + * Returns a list of wildcards that can be replaced in input fileds. + * E.g. "$firstname$" is replaced with "givenName" attribute value. + * + * @return array replacements as wildcard => value + */ + public function getWildCardReplacements() { + return array(); + } + } /** diff --git a/lam/lib/modules.inc b/lam/lib/modules.inc index f17cf003..e54bb1b1 100644 --- a/lam/lib/modules.inc +++ b/lam/lib/modules.inc @@ -2143,6 +2143,62 @@ class accountContainer { return $this->cachedOUs; } + /** + * Replaces POST data with wildcard values from modules. + * + * @param array $keyPrefixes POST keys as full name or prefix (e.g. "key" matches "key1") + */ + public function replaceWildcardsInPOST($keyPrefixes) { + $replacements = array(); + foreach ($this->module as $module) { + $replacements = array_merge($replacements, $module->getWildCardReplacements()); + } + while (true) { + if (!$this->replaceWildcards($replacements, $keyPrefixes, $_POST)) { + break; + } + } + } + + /** + * Replaces wildcards in an array. + * + * @param array $replacements replacements (key => value) + * @param array $keyPrefixes prefixes of $data array keys that should be replaced + * @param array $data data array + * @return boolean replacement done + */ + private function replaceWildcards($replacements, $keyPrefixes, &$data) { + $found = false; + foreach ($data as $key => $value) { + foreach ($keyPrefixes as $keyPrefix) { + if (strpos($key, $keyPrefix) === 0) { + $found = $this->doReplace($replacements, $data[$key]) || $found; + } + } + } + return $found; + } + + /** + * Replaces wildcards in a value. + * + * @param array $replacements replacements (key => value) + * @param String $value value to perform replacements + * @return boolean replacement done + */ + private function doReplace($replacements, &$value) { + $found = false; + foreach ($replacements as $replKey => $replValue) { + $searchString = '$' . $replKey; + if (strpos($value, $searchString) !== false) { + $found = true; + $value = str_replace($searchString, $replValue, $value); + } + } + return $found; + } + /** * Encrypts sensitive data before storing in session. * diff --git a/lam/lib/modules/inetOrgPerson.inc b/lam/lib/modules/inetOrgPerson.inc index 5e124534..15df66e0 100644 --- a/lam/lib/modules/inetOrgPerson.inc +++ b/lam/lib/modules/inetOrgPerson.inc @@ -171,6 +171,9 @@ class inetOrgPerson extends baseModule implements passwordService { 'ou', 'description', 'uid'); // profile elements $profileElements = array(); + if (!$this->isUnixActive()) { + $profileElements[] = new htmlTableExtendedInputField(_('Common name'), 'inetOrgPerson_cn', null, 'cn'); + } if (!$this->isBooleanConfigOptionSet('inetOrgPerson_hideInitials')) { $profileElements[] = new htmlTableExtendedInputField(_('Initials'), 'inetOrgPerson_initials', null, 'initials'); } @@ -243,6 +246,9 @@ class inetOrgPerson extends baseModule implements passwordService { $return['profile_options'] = $profileContainer; } // profile checks and mappings + if (!$this->isUnixActive()) { + $return['profile_mappings']['inetOrgPerson_cn'] = 'cn'; + } if (!$this->isBooleanConfigOptionSet('inetOrgPerson_hideInitials')) { $return['profile_mappings']['inetOrgPerson_initials'] = 'initials'; } @@ -740,12 +746,11 @@ class inetOrgPerson extends baseModule implements passwordService { ), 'mail' => array ( "Headline" => _("Email address"), 'attr' => 'mail', - "Text" => _("The user's email address.") . ' ' . _('You can use "$user", "$firstname" and "$lastname" as wildcards for user name, first and last name.') + "Text" => _("The user's email address.") ), 'mailList' => array ( "Headline" => _("Email address"), 'attr' => 'mail', "Text" => _("The user's email address.") . ' ' . _('Multiple values are separated by semicolon.') - . ' ' . _('You can use "$user", "$firstname" and "$lastname" as wildcards for user name, first and last name.') ), "mailPassword" => array ( "Headline" => _("Send password via mail"), @@ -934,22 +939,6 @@ class inetOrgPerson extends baseModule implements passwordService { if (!$this->getAccountContainer()->isNewAccount && !in_array('inetOrgPerson', $this->getAccountContainer()->attributes_orig['objectClass'])) { return array(); } - // replace $user in email - if (!empty($this->attributes['mail'][0])) { - $user = null; - if ($this->getAccountContainer()->getAccountModule('posixAccount') != null) { - $attrs = $this->getAccountContainer()->getAccountModule('posixAccount')->getAttributes(); - $user = $attrs['uid'][0]; - } - elseif (!empty($this->attributes['uid'][0])) { - $user = $this->attributes['uid'][0]; - } - if (!empty($user)) { - foreach ($this->attributes['mail'] as &$mail) { - $mail = str_replace('$user', $user, $mail); - } - } - } $return = $this->getAccountContainer()->save_module_attributes($this->attributes, $this->orig); // postalAddress, registeredAddress, facsimileTelephoneNumber and jpegPhoto need special removing if (isset($return[$this->getAccountContainer()->dn_orig]['remove']['postalAddress'])) { @@ -1037,7 +1026,12 @@ class inetOrgPerson extends baseModule implements passwordService { */ function process_attributes() { $errors = array(); - $replacements = array('$lastname' => 'sn', '$firstname' => 'givenName'); + $keysToReplace = array('mail', 'description', 'postalAddress', 'cn', + 'registeredAddress', 'labeledURI'); + if ($this->isUnixActive()) { + $keysToReplace[] = 'uid'; + } + $this->getAccountContainer()->replaceWildcardsInPOST($keysToReplace); // add parent object classes if ($this->getAccountContainer()->isNewAccount) { if (!in_array('organizationalPerson', $this->attributes['objectClass'])) { @@ -1069,11 +1063,6 @@ class inetOrgPerson extends baseModule implements passwordService { $this->processMultiValueInputTextField('mail', $errors, 'email'); if (!empty($this->attributes['mail'])) { foreach ($this->attributes['mail'] as &$mail) { - foreach ($replacements as $wildcard => $key) { - if (!empty($this->attributes[$key][0])) { - $mail = str_replace($wildcard, $this->attributes[$key][0], $mail); - } - } if (empty($this->orig['mail']) || !in_array($mail, $this->orig['mail'])) { if ($this->emailExists($mail)) { $msg = $this->messages['mail'][1]; @@ -2178,7 +2167,6 @@ class inetOrgPerson extends baseModule implements passwordService { */ function build_uploadAccounts($rawAccounts, $ids, &$partialAccounts, $selectedModules) { $errors = array(); - $replacements = array(); // get list of existing users $existingUsers = searchLDAPByAttribute('uid', '*', 'inetOrgPerson', array('uid'), array('user')); for ($e = 0; $e < sizeof($existingUsers); $e++) { @@ -2189,7 +2177,6 @@ class inetOrgPerson extends baseModule implements passwordService { // last name if (get_preg($rawAccounts[$i][$ids['inetOrgPerson_lastName']], 'realname')) { $partialAccounts[$i]['sn'] = trim($rawAccounts[$i][$ids['inetOrgPerson_lastName']]); - $replacements['$lastname'] = $partialAccounts[$i]['sn']; } else { $errMsg = $this->messages['lastname'][1]; @@ -2200,7 +2187,6 @@ class inetOrgPerson extends baseModule implements passwordService { if ($rawAccounts[$i][$ids['inetOrgPerson_firstName']] != "") { if (get_preg($rawAccounts[$i][$ids['inetOrgPerson_firstName']], 'realname')) { $partialAccounts[$i]['givenName'] = trim($rawAccounts[$i][$ids['inetOrgPerson_firstName']]); - $replacements['$firstname'] = $partialAccounts[$i]['givenName']; } else { $errMsg = $this->messages['givenName'][1]; @@ -2218,7 +2204,6 @@ class inetOrgPerson extends baseModule implements passwordService { } elseif (get_preg($rawAccounts[$i][$ids['inetOrgPerson_userName']], 'username')) { $partialAccounts[$i]['uid'] = $rawAccounts[$i][$ids['inetOrgPerson_userName']]; - $replacements['$user'] = $partialAccounts[$i]['uid']; } else { $errMsg = $this->messages['uid'][1]; @@ -2300,9 +2285,6 @@ class inetOrgPerson extends baseModule implements passwordService { $this->mapSimpleUploadField($rawAccounts, $ids, $partialAccounts, $i, 'inetOrgPerson_pager', 'pager', 'telephone', $this->messages['pager'][1], $errors, '/;[ ]*/'); // eMail if (isset($ids['inetOrgPerson_email']) && ($rawAccounts[$i][$ids['inetOrgPerson_email']] != "")) { - foreach ($replacements as $wildcard => $value) { - $rawAccounts[$i][$ids['inetOrgPerson_email']] = str_replace($wildcard, $value, $rawAccounts[$i][$ids['inetOrgPerson_email']]); - } $mailList = preg_split('/;[ ]*/', trim($rawAccounts[$i][$ids['inetOrgPerson_email']])); $partialAccounts[$i]['mail'] = $mailList; for ($x = 0; $x < sizeof($mailList); $x++) { @@ -3810,6 +3792,54 @@ class inetOrgPerson extends baseModule implements passwordService { return in_array('posixAccount', $modules); } + /** + * Returns a list of wildcards that can be replaced in input fileds. + * E.g. "$firstname$" is replaced with "givenName" attribute value. + * + * @return array replacements as wildcard => value + */ + public function getWildCardReplacements() { + $replacements = array(); + // first name + if (!empty($_POST['givenName'])) { + $replacements['firstname'] = $_POST['givenName']; + } + elseif (!empty($this->attributes['givenName'][0])) { + $replacements['firstname'] = $this->attributes['givenName'][0]; + } + // last name + if (!empty($_POST['sn'])) { + $replacements['lastname'] = $_POST['sn']; + } + elseif (!empty($this->attributes['sn'][0])) { + $replacements['lastname'] = $this->attributes['sn'][0]; + } + // user name + if (!$this->isUnixActive()) { + if (!empty($_POST['uid'])) { + $replacements['user'] = $_POST['uid']; + } + elseif (!empty($this->attributes['uid'][0])) { + $replacements['user'] = $this->attributes['uid'][0]; + } + } + // cn + if (!empty($_POST['cn_0'])) { + $replacements['commonname'] = $_POST['cn_0']; + } + elseif (!empty($this->attributes['cn'][0])) { + $replacements['commonname'] = $this->attributes['cn'][0]; + } + // mail + if (!empty($_POST['mail_0'])) { + $replacements['email'] = $_POST['mail_0']; + } + elseif (!empty($this->attributes['mail'][0])) { + $replacements['email'] = $this->attributes['mail'][0]; + } + return $replacements; + } + } ?> diff --git a/lam/lib/modules/posixAccount.inc b/lam/lib/modules/posixAccount.inc index 4ac81d64..04f396a4 100644 --- a/lam/lib/modules/posixAccount.inc +++ b/lam/lib/modules/posixAccount.inc @@ -471,7 +471,7 @@ class posixAccount extends baseModule implements passwordService { ), 'homeDirectory' => array( "Headline" => _("Home directory"), 'attr' => $this->getHomedirAttrName(), - "Text" => _('$user and $group will be replaced with user name and primary group name.') + "Text" => _("Please enter the path to the user's home directory.") ), 'userPassword' => array( "Headline" => _("Password"), @@ -990,6 +990,8 @@ class posixAccount extends baseModule implements passwordService { * @return array list of info/error messages */ function process_attributes() { + $keysToReplace = array('cn', 'gecos', 'homeDirectory'); + $this->getAccountContainer()->replaceWildcardsInPOST($keysToReplace); $errors = array(); if (isset($_POST['addObjectClass'])) { if (!isset($this->attributes['objectClass'])) { @@ -1160,11 +1162,6 @@ class posixAccount extends baseModule implements passwordService { if ($this->get_scope()=='host') $errors[] = $this->messages['uid'][6]; } if ($this->get_scope()=='user') { - $this->attributes[$homedirAttrName][0] = str_replace('$group', $this->getGroupName($this->attributes['gidNumber'][0]), $this->attributes[$homedirAttrName][0]); - if ($this->attributes['uid'][0] != '') { - $this->attributes[$homedirAttrName][0] = str_replace('$user', $this->attributes['uid'][0], $this->attributes[$homedirAttrName][0]); - } - if ($this->attributes[$homedirAttrName][0] != $_POST['homeDirectory']) $errors[] = array('INFO', _('Home directory'), _('Replaced $user or $group in homedir.')); // Check if Username contains only valid characters if (!get_preg($this->attributes['uid'][0], 'username')) $errors[] = $this->messages['uid'][2]; @@ -3459,6 +3456,31 @@ class posixAccount extends baseModule implements passwordService { return $this->isBooleanConfigOptionSet('posixAccount_noObjectClass'); } + /** + * Returns a list of wildcards that can be replaced in input fileds. + * E.g. "$firstname$" is replaced with "givenName" attribute value. + * + * @return array replacements as wildcard => value + */ + public function getWildCardReplacements() { + $replacements = array(); + // user name + if (!empty($_POST['uid'])) { + $replacements['user'] = $_POST['uid']; + } + elseif (!empty($this->attributes['uid'][0])) { + $replacements['user'] = $this->attributes['uid'][0]; + } + // group name + if (!empty($_POST['gidNumber'])) { + $replacements['group'] = $this->getGroupName($_POST['gidNumber']); + } + elseif (!empty($this->attributes['gidNumber'][0])) { + $replacements['group'] = $this->getGroupName($this->attributes['gidNumber'][0]); + } + return $replacements; + } + } ?>