summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/Makefile21
-rw-r--r--doc/figure-01.diag19
-rw-r--r--doc/figure-01.pngbin0 -> 29923 bytes
-rw-r--r--doc/mapping.pdf8750
-rw-r--r--doc/mapping.rst344
5 files changed, 9134 insertions, 0 deletions
diff --git a/doc/Makefile b/doc/Makefile
new file mode 100644
index 0000000..994d932
--- /dev/null
+++ b/doc/Makefile
@@ -0,0 +1,21 @@
+all: mapping.html mapping.pdf mapping.html
+
+
+images = figure-01.png
+
+mapping.html: $(images)
+
+mapping.pdf: $(images)
+
+%.html: %.rst
+ rst2html $< $@
+
+%.pdf: %.rst
+ rst2pdf --footer='-###Page###-' $< -o $@
+
+%.png: %.svg
+ inkscape -z -e $@ -w 800 $<
+
+figure-01.svg: figure-01.diag
+ blockdiag -Tsvg $<
+
diff --git a/doc/figure-01.diag b/doc/figure-01.diag
new file mode 100644
index 0000000..501d14d
--- /dev/null
+++ b/doc/figure-01.diag
@@ -0,0 +1,19 @@
+blockdiag {
+ IdP -> Assertion;
+ Assertion -> JsonAssertion [folded];
+
+ group {
+ #orientation = portrait
+ JsonAssertion -> IdPMapper;
+ IdPMapper -> JsonMapped;
+ }
+
+ JsonMapped -> Local [folded];
+
+ IdP [numbered = 1]
+ Assertion [numbered = 2]
+ JsonAssertion [numbered = 3.1]
+ IdPMapper [numbered = 3.2]
+ JsonMapped [numbered = 3.3]
+ Local [numbered = 4]
+}
diff --git a/doc/figure-01.png b/doc/figure-01.png
new file mode 100644
index 0000000..5e28180
--- /dev/null
+++ b/doc/figure-01.png
Binary files differ
diff --git a/doc/mapping.pdf b/doc/mapping.pdf
new file mode 100644
index 0000000..139c5b7
--- /dev/null
+++ b/doc/mapping.pdf
@@ -0,0 +1,8750 @@
+%PDF-1.4
+%“Œ‹ž ReportLab Generated PDF document http://www.reportlab.com
+1 0 obj
+<< /F1 2 0 R /F2 3 0 R /F3 10 0 R /F4 12 0 R /F5 15 0 R /F6 33 0 R >>
+endobj
+2 0 obj
+<< /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
+endobj
+3 0 obj
+<< /BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font >>
+endobj
+4 0 obj
+<< /Contents 139 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+5 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 32 0 R /XYZ 62.69291 260.8236 0 ] /Rect [ 270.9115 753.7736 316.0541 765.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+6 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 30 0 R /XYZ 62.69291 488.8236 0 ] /Rect [ 155.916 729.7736 211.1376 741.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+7 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 11 0 R /XYZ 277.9078 281.6969 0 ] /Rect [ 62.69291 519.7736 105.3066 531.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+8 0 obj
+<< /BitsPerComponent 8 /ColorSpace /DeviceRGB /Filter [ /ASCII85Decode /FlateDecode ] /Height 350 /Length 25648 /SMask 9 0 R
+ /Subtype /Image /Type /XObject /Width 800 >>
+stream
+Gb"/l$(O`Os2Ua7N3W;d7!9kLKHa"1f"T7,7&X'%0n^hL=9^RK@9-lpdSH]Uos9l<<(`=POBpPkR5$Mm'D)6QTBFL>c&C?"^!Ak)I,;'qbNh4`gb\-Mo6JXUo;j;k%0-A.zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!#9%&N;uLGla!KTP"6)!#hPij5oCan)rj[7+ma")Ut_9Y$!7^H9qS-NVo*/(D7B8"jf%*!!']/MXgB0V-NV2]mCt/$p!t5MR7N@A-gm[Dp]'%)srTc"?[I`)#sYeG%<B!Th>9p)0)(n;!+G,BP7/I;A/IaTP"6)!.%K_.,Nh;T`P+q`c'!o1/^D"dmrVSk[":]"8!!%!5K8@Cf7'JiDlQ`\^*[h5p)n`dm8)*%fdI1)#sYeG,V!-(&!#&,9nM^5u?YJg4>gr!!$\&NDTukk^PD18-L":@on1eTP"6)!1n_EO)KXh[IQ.Dj[MN@Oi)g"FakcH?_D$3!!(_M_gleg].,a*LJe5,JVh`*_ZE1jcbMkn"ot#,[4Y9.F3VZ])_QWP0ur,"3^UDrZ(PLOXjF_C90HWbqt#A7^=_tlUAnHh,P5e&F=S%*?l/b>r#u@SaZdK+?+@7IZW7gaPbl"@R+HZHR#gH]FBIAn;,EA<enK$DNLn&a%P1\]1jpepDsu[SMGEHe(OEM/\oe>[YW-`sTk\k=.p>$TpA'W$FRK.ukhrK&b3-cOd/d,![j8NgRfajYHCicqn'VM@cE1?$p<.Bp^##5B[5)7soP?m:$Pi_M=bM/<>:quB.IO3VHZ&`r`GHnol+V?C=.rj,2al_(cP6D^rOHC*Z6Qur!Bo0Qh6I1a=:i'Q1oO9p(&k4Ac+A)T21Z._Xk^"O'-lJta^:mGriW37J)&u@g$_DL7/'Ie>_m:Z!W];+h,rAgCZPnQe[AURh7$)96?F_:CIB6:9[VmgkGqU]81k9r[PPL[$NRCL_I`_H?1V+)CY+"MR"stWX.)6uj]0V?hWT#RZ!s28I0_u?%h%S=!+9,dbPDGcXERHZE3Sd!#P%kkUcd``%noP=0E$OPhKleYOeU`'cHa\[9qZ.*@0&Ln!6g@?g%b9`jiYoA5@=0Z"*qZ`q'bu`Np-L<1&iH`B?\MpntB^F@0&Ln!6gABh0epsnXF]Np_cN.$5NHHmmo+;rs6q`p[[%DAW-!F#P(,Dnr]iHUg321k+H/>hVKshLFQ;&**p2aHF=Y+cnb[;eDt4)`X?-laD_rAWc?L(p88!nX^"<h2Zn?C)Ykd?H>\#sI2Tc<X&$3ZSh5[SoF(^R06qk-:+i;Q_a]3.J\&T6a;`^O8'j%g=@:C7!:qC>n2sroDsqPt[d!d'+E(@,+$n4<@1>@%!)/BUO)KXh[B@Mf](ol)#AIG@DRZcSFakd#B.T7-TP'?u+[#o-bR<6,I!pB/"8^o&5,*ZD.pDS\JHNKu'?Dtqa[a]68@+DL!<B!ODCjZ$hQ&sfDC-7Ka*iA`(GB*rqqHZ!@&85R4Td5!)$"&Z]Y(n7'J>pEPXHV+V0MMbA&da3*[%(W/0@1(2TK9Q"ot#,+U83MXZnY8J"FZ_d*D7qWp*G;\pF%LmdC2IM8f#toPAS"VIomZfb&8k8qS%iE]F5[G&(?\DR#p)d>_UY/=DQlBA6le4Tb].Mn7#,j^"u5'KKPlQE+HC7XD+H_a`M>hVGbd`;j9R@**d!4kg`Fl59S0?CYpkP`ktCr4M)Hh&=eAe[AW(G0O5KWHV/"EolPfWg0Uf"pSOB+Nn07HiuUe(/*p1!+9-=^\QB^>rt#*GlIX:GSZeAY[fqLSo'B3oaCgS0A561ka&(B"G*VXA3PU:D2T_5$iht7a@E\XP5,B0[Omfp1B>5'+<T8P9BIJ_fsY!\cN!t:@aBGon%\m/]Qc0S\$g,+o'*'EWn3Rj?bRYV(N)>s2dsCIPiKl4ZC\7)\O&p;Z2iMIjibF9mQ:1Ch1EUlH3OA:)Y<*dRis[J[W(3B=hYUd(=oj,;t^!pf3VCjK9qp+V+R#-%j-8bdNpiDVJEGC50EEV4^$)U7Z<urN/EL5ocH5Ap?YF*]l`Vn0k8CJcTV$J47B]Un%'G'knsJ/C<W0.DMHsD.sapXB_UrN+X&#iZ@[^]h0>Bk`Hq>.a-67"4^Ya?V/k\?p$1(Ce>SM1s43;W8*Hin8K1l/S2`g3bLM*oeQ>Vn!!#r-dX6/#AFNY^GO?G1E+%"`4dRd,R_`@=Ct[7hmEnEGD:YeVRnqRW=>(cXGk)oVk>eQ`'eNV]pYUHJ&+@.V=)r?PU.'udp[6k>>IU8uTT^a!d`+qH0!/BhEmUIF?+P+q3csSg?+\V3s8Mn6>[6(MYJ3j0J,/2m`^(dn,JX-D]B.5&pZ^.^Pi&rg?hu3tp$+u<?*I];m4a%hr"U__)#Gsm]Jq#Vi6=4<<:;<NqWb+AF67;r^4"(a+nRR>rqY`[r_;s@p%/Xm0Jt3%7lQ:2^S6U5M%V-&^%^ATP9s;5?G0dbL,\[)c'pY1d@u?lcdkNe0-B;#nfFjpNZC3)mFmh3OMK_%qe]hi^OH,"2f;<\T8XHZs37#le&Ie3BARpsSJ*AGS3(r_i5(%1qs:XGBs("!eZ)Ug2/6+jrr#F:&J5W?+H79s])Vd,l)h4#a"CN#K`7g?@efHOiSib<L,nu=dYgGG$GGuL)hEQkrr2oXf$sC*,=YMoW)p/D\[(YZ]DMI$P$rFl09e9Ddk_!>e<i'7h'C;FMG+_0.Q+C(o&\'VbEmGH=-VNambIW]0>EGe4dph]OH:#j-XG*[0-?T#cd_RNe#30Br)Tq'7BbmuR8]tV).T%@WD]S,qWb*iq_r<AN#YoRNO*9D-9J"A\;4:oAs(&1o.nBo<N9$_b*=LBXj$`rL;,ckkR\W0%mKbRD'oQWH`Hcr2*>^4^4#:KB:jU\F6CgPp(J,Cn5fSiO2?kOkiQmY=1)hqVCK.H<nFK[Sc+h?QP]&bTE"heDV_n?_800@8-j_,+j?<.K3\Ais8GZpPEM)d'IdKRD#/i%?F]t-gII8D\TR4=A,e8n`fr)]3\W7,h7@aK`bsVDeYuIp4<<-GUmie'=$:p(2"o/5?S,KjN8?UEr4(IPS=Ei_:nbF@kGCh#<PO!2j!3U)O*>Kqo`X3V!!"'o)=u8#j6Ws!<2e_;C$WJ,hRcYbTZ+-A50EEV4]B]$hKpo4Y\cFt8sO/I]!ZkMd\TSYIItoc:H_-1VaZLZC=;"iX&iB)>1Klfa(!#FeZ2bI4mV:aB:lm7m^qAgSjS8CV+H.oFm;rdcXl.?k09AsZtN=uoG$E0PuDO2jKBVSr,H6DPUTNnD(MFSoF(^R2.k'&2ik;[HMHHS.9.7(23k,ln5nbp7ld0R#O;-:?[nmc)aAeadI]8+a:KF8+6W;1Lf:3HeYl>Til$]!)cKX4Sp^+NQX>30?4S)>R(Q7]mAh-&eX84+kV)r2kF]a0_dEB3_[lCj:I"fR[dW"^PQ&1)ac\LU.f]Rj,GrXS"bO(qHN3s<99^hj8`\<r92pE8oCIUL12/qpn`2i0c[G]aD:"r,o9Ln.Y#MK)0dJ%*gpqLLQ7Z%;8Vr:\GM[VCRaCfN-_HnnJ"BtO]QfS:Q0R2^ZY,?6^H["M_hSc#8aEd'iBh\&%/u-_;l@q%ackuaC7ppPYNTo\Fk9p$>IWJ(J,bWU7lkeX6t_[OR[OG1"TSOJ`,tgR5]HEuPg9-tl/Ume<P3Qrb&m*dq_%f38b5f>-gtbq^2W$tWD]QZ6UNYG+#IY-mFntoS2jNM=uC=p<NB.P>IJA"Y$KQpFj_Yf!if5!6D&]&l).=L5-7$Ap"*R"rncMgPq#c`<2^AAV7(%1=6._s2fDIgFQh'pmJ?X2^]4:[rVH28I=8)F<3KVVj2R'n48]fn!9=H-jWiB>R$^DZG26fi<ihXKE]eV'lM8r/;g\6)ame)UUnjel]67c]1k?;f:Aje:?g#_*]9tm0r:k9^%V?odVe6![WNfbn!kH74q$;;T/XFmB!5Q5i+5%E&js0*C[THGR!!)VBHt6G4R?+"RgL<`;!s$OQnr[doA3PU:D2T_5$iht7a@E\XP5,B0[Omfp1B>5'+<T8P9BIJ_fsY!\cN!t:Jp_*5/=DQlBA6le4Tb].$hBEsZ"-%MSo'B3oaCgS0??Yl`KL$&HF>Dke2%*?]HA<L(/*d7kh3CH;U5=Co7D@#>:c2'TP*"g8Nd.UbR=!(D6[V8Jt?h;-1qZH0JCL;[`+F*#^Wp2QII\j^q:d3fbR6C,O!gh=AmHF!:teiA6UUQO.^.?@S&]b!6biAO_q@65(]ACM^A$)!&-(I8%-C"q$;;T/XFmB!5Q5i+5%E&js0*C[THGR!!)VRrQV6dp$/^^MaA63HMIhm[Omfp1B>5'jPu7'm#5huk()ll#FGqUJcu-V(>ZGY?nug32@"@(4MYLk(+]I$ZKT$9!L'3]YW8BRk5cns[pT4:Q::Q8%@@R[K$=>P57]Fc\ciHAYUmA(DnooI(2OKErcs%9cn/?"J7[,VHNPT^[pX8BpWiq8L2Og/!%a&rgD_ga\cnQ*\pkc/13<m>!+8rOhqin*cn3lid/EP9PG)3b!!"OEq[NkTKPn3[N:($YQjMS`"TVXBh01hd-?Q:GB6=/?^eErm.fdB-ke=q81SJ$T3MZHf!bOd.=oeV(7e[o5QjMS`bo,?P&24d/eHu;\1:lpn^bk8@C9Gq^,6?8d>H.Z'l_F>@#L%a:S`U^D^Cr:+\oe>[YWfYeF2.qB(24i:rDN_1TNe2l!5"p$D?i9Bh=AcG\plEldHHlD!5Mq)^?5OC7CP2HKC7V*GV6S8#lq1M\o2r2'@Er)r1j.U".k<d<<</:MXHrUn/uh2YlN/L'*8\2[ho,G!*RG3kS@P,U\j3WRaE]P!!()rme\2I2nBae>'0eU^tn3T)up!");R5HOFM@f`tQjK9gJ^*XW7BA!!(XQ(_6TH!!%P$"o\i/!&R&%i@H4uG2_P:5Zf9;qH&$366Hj8NuM\Di1Yt.*)oar8@*LW.1(R07VFGR#R$k%K@=ohpP!3o:I/6l<S&+g7Fsu@DA?jlD_DUfVh%)U&.!rHpn3QPg3DqPh%FDNdYXaD8mMgMBbi^3WQfE,9ucnm0BJc2)hkISL\B1^+:ne]_DrERC6glKPBFJ$>%Dl[FI.]i/.EHY8mMhB"%u##f9'O63#!^f_Sjh]NjSF<5/f/5kJO"l1_9oq!b([S;QqAjLWKZ^O-;GtCkpgR]"UT@%9`,^qIV7q=n.CU^1;?QNdiHP7Z12d`>LF7+,R>pZ6k7&a#mQo&O-cmVh%)U&-uK1HLdn#bj"mI:<f#r.8<aHVNf>39/U\-3Mgl]mR#hQY&CjKXc%R@_PBb`k1=u$A&Po+E@t!37u67#7<0qLb%r"cEISJcVh%)U&.!s3_OQW23&OWdVDQQ>3eA#(Vf1\&e-MZTX]W@JAEXe.=(*/b3#*WsEK'NhA>Q"hC*];01XWiu+\H",,8+HG0%_C@($3ek)@-HIJZs2T1@H2X`0?92.8suY"ANU!P4^i'\Bi;Cc8g<E;f[Z4E[QUV>3)otLLd_+?*$HYXN2ZZNo_dV(b$*X7++bK:,sp^cSJ"1PXqBWQalDu%dg0F5TgUD]18)Z_6[^r<=Gef7%'o$=eD!c9=17Q32LXfkhKIRaJfm^rlP[0R4H=mo=4NQ/OC`-@2k^tQgJde]R4fY;e"B8dj7YE(.kbTM<n9%3)=^5VCeN_Bb'O.JNt=h#Wi9f>tVi$Jn$e]-d'r/,1A@plU9FB7-U2(32LXfka^5e3@/uR/9g%A=7L;rqgj$QQ7KNjjF5G$()LRUB18CA8t:qWk@_&.*naRVGHY[X?.?$mdBpJugJCT-+AufT4K@;YU&?eZ"WJ^m&oc;<U/",eH=7IM,:j_ZZRmAeSQ/:P8<j-KLuZuY$2V;.f%`\2_s.'2*2Z.2?+",^O<]87SHl_.(NQWjE)2.Wj#P`=E^eS+;0E#<b[Qc0(G#7a;7Ei4M5#H*6Bj-/W_q#Em@1MXTGR6-g/tYZ?_]]qU:Np'D8j#s,)>m@5SQbN:e@f9D6.B'Plc9?:QV:0rkV\p=35HB!EZ8,*7g&F$KF*c-d*caIWg#fem(u?Pj#=:,m5j=iNIL.%!&cuo$i<QpXoXUN+"rp=(dhddmMV5kMt[ceZAb`OTU=XqJ8US\mI2qD5=XS#MQ:g<M,NYe#,*+-lQ.Jd!cmhRg]oW8JHJ?=<jJO4,.RU;QkBDQ#p'6j]j>I`(H>d9o3m49');a.BW3S6J5#A4UD&0ouOsNM`UFtX;\:f7.:?*e2X%k^j\8/034DdU/3#*qeF\c2^9qrZ-=8qgO1qp(,"Z(Wf:m"(3DZ@SO<9g+DrMsQA&Jf25+Z9"Tj"Y@jlCEs&FK$b$679ParNSBZm.%WA9`;6;NlI2k5_D1h#qG=ZU!tQ:ncs-A*4^`W#RZT'8fN3+]NX)_Dua/pt=F6[K&ENSfti_Q/93%Li^9naZ&FT_-ZP(5WfNEG.QG7/he68:i*iOuT.JK\6HR[Vr+1X-n![IsT:<Ou-A7mQ!9[Md*RLe2&.q23ZL8RV]hr7U_tsbJcHCGr:YL,>/C(eMAi!$^WnQ1oMm]q%m?P)Njo[lQ#Q5i^F3hg.[C?SC+UHGl6uF;=520k:O&np6.o*1.[9J83?,T@ASLGm2N>GMbFho>fA`^-H2jOY*n']`U-`I/Z_qImKL.Q-)Gim0HC)7*F/?G6%8<_S0Z1>#@i#$M3#,i^'h,AKW17Od7sXWf)3L6c\_"^*OMFa+u_e3,UqGPcNq\soPEiLjaS:6JC6WXaR.*T2_[7PX]Od=\WTjl3%l5V.'6Eg:Qo(;)4sG*>f*nfYE$b<(aV\.o?f\t?qP'/aO_fHGMp^[?59.7JOKqCr#2BcnE2=I7Z0m8KU5aUcAFO.>I9%VP=4IK,X2nb8^Z[H7T^n.B=g\#[27U_R,2Pu*JML8GI]a\]tQ2LZ%=8JG=qC<e\e$r@>P1iPO>X8iaY+G.TTf1i^o\@9)CHH=Y!9rqDSaBaSiM][V=s-?^(;Cs7R5b=nsT%88i3,4[a1>j@:DISe9NZkh5C_1s4Y<+$:o@os!&2NEW?)Mmcu[c#$UJeg\..MWZ-b+$(H8#_1r.Ukt(TpoD=Ma5F!^Ns[NnY?]@Ba\C-U]Y2#0&*$N1ArML\$=BFkbSC)C2JPH2Q\PJtn,`q0*m"q=[WuQ<+nU^A^i4OufPBO%PN/f]^J[i::7fFb.k*rXNHGZGU."J>=7O]=^gFX0oYKoF`C]m3VoJ71)-(VJI^oBj)9Q@0lL/nDY\<3TT3Y^.+iaXWqu")"BBLium^_NR(1,^5:&0^>7qZYTUArY2m3eb]oN0r@&gTT&?iK[k1>_W[-+cBF@O4/^15'h-\kUNCm]H_Os-WOPlK[i3B+me:@gJBAW:B7HC4#eN_^%5Rl^W'"(M/K%6r3'=P.kF^48bAE\B\G-Kh6b/-]7fu71L0o>l*<+Z&=[PG9L=#0/'LA`JR.pGW3g_]4pC4cSTpG9Snqn5i*SDgA*<]@-,gc8b2/90j\cAr-TOIMI+YZ[@`V/igb'p?_"MORTp%'07S9hqXU[5MuUh%6E6XSmO69BfsY=%4brbNjB&:AO4:MNTAT-U4eQG/a%XNg=%VtV^oUu?0Y;B\ghE-*=7AaY.pp8PKUJ@cH".]hQ$^$L35`j,4MN!r;KR=`GR9L@"lKheF8%7kFu=`tM5=RmgZ91@(r+@"OLb:<(GT\npX^4B$S>W)08%$6"4CW0%24T'VMkW+7.J,(Iml$S^Y2K*%:Kt3N&esn-'f7kNpfL!?dIf:ekCucs4%Y#QE9N/^*@3cD0$Ls6dPH7S*P@Cm#SU$?hEg@T+b;EcNkLa]6ujq"F;t9,fGMF1&N[.4"FmIAG_YGJM!1(WoA0<BC^NcAk@IeabcV;rO!pii3-D)21Ka`Y$AMcY%UX#PUf``Rhk.>s/i+co@_d<g$DY5E8_6)MP=":;Gl8gfdO2Hj;16.*tEUjrFB.Pd>gbZOXS+lo[Ps3%:Q.q[Jm(phB6FE+tAqi=Zo\/X]S*$L=np`=@UUp$KsLN-rZjNLslcPkh.d)I4``4M1d9X2;'Re<Cnp*2&VRQ>$0W9Na_D`Z/T4LVg(i+Pj[M6>Ydh=FZri*.kC%g=Y#sm1[aqm`JYG,;Ogg<eYGsB@BIM*#d_O5l/I^Y*:uSpag``oVT5Z,NmfJP\.fl".P\UBBBWmRhJ\QgN,C.:GW2U7M?BJu61oZhjb=hT?.7;L[R4.qca@QFUn05e]j]cE@si]Prga"fAa[lfL^\U,32uO$NRm?-p0()@9%"%1eV?Q`?us7T\HE]GQ+P,S?^8ApZu=MFF-6BCeq.q=8lLj'?i&?%$^YFsN3`(Wm@(GaE>pQUDVf&5MaRAU\03n14MW\RZRjMgM9.b.AOoDH;br_,Z__o?H-;],o9H^J5B21:-?\TZE>mqV!Bo0bTP#";QER"<$5`7`k$R34f_H;p5MIlh]Hho,]%8tf)n8GnA@+nUgpAq;:*Gip?sT9/J)sGri3-$[J,e8ns"59KiVA7tf;r6=ki,TfpK+J3f<5'%0Fu^7=/R6iFLjFi>o]KqW&L]WA<rJ0X&[aH-r50Wh53QY11g30]Gu5U2:1sVD`?*^bCZY+qK-Ln@U%=%'11#WK_52ZrSgAX3''DHUQ@r<`G*kR(r]3Ogh@TWcG[S,\X>#HeXbCe&$!)"Z6`.<m5#lgrp%>rpBCj-li,$L%o<k8o)&/<nP>N3*6sCtZ]_EeRjBA?Be(7;EW9Eao_eE@?#D/mHH-8K12Ll,[m'G#0!(c0D#+BXH%/k7:\C/p[<iM[BCeH9DVmu)SB@!Y'IF<D4":a$[8+iP/H/]\2'eqcr[KoHrlUdBiNF/#c!c"s^MA>%<hX!;p7:d>Y:>kh5C`Z[h-V&\!@kkOmLsq6`4f&#`KZXJa<F:ms"%'28*6S7YN@M[3.!g'o27Ni<mJT^TP*it4Zc07#*#4&n6tP6]TA`>2AEbNZ_[=k&I51j6dfWg8Zt*m$`t?G%Y(=+/H"$K%qRKqGNPQ,LHf-;06ViPA6@I8S-Sm#m.dk`=1\%K:HLf=N5FJu0DNf$kf'eQX4:EhrpQ.)>BG@+O9_`^[V7/hS02uM'Y@ogVM`g\0JfQ$+0q?]SkD5-kl,ne6@OiE-7MqnS6EW2H8[E7fCK6bK(^g%H=cKis"+"R7/qIE\!V_6TkEs`H>_P(r'"G'%i0Xh'"^]_U#LT%2-1c0aQBQ0foQpl:.2G'8rSG<EZ80VX,Ad?=C8F<r<?S7?A3cPL!=Y78it?sDd'XL.o/=+?LM(%35\,[H9L.l]gW1->.KOYmgJ[jQ/Ccm'q9ioeo@4FW!MjW(&r%u.I,Vl(!k)o'NK%qVk0qhW0flsUL/E_H8[E7f5oOkT(_jI;7le)B[Q?g";na:cXqk&r6.<5dhmPj2bEiVl*C#9Yc@_paphK!m%ZAh>ese3+DZIL8(fGbO-?q[*S'&./m`\^q?M`810QTK5;4cfp\+i:K?EX]ou%BY`Ptb[KW1\6'n8_G$KiaLe]Y.rr5PZMm0P1."?b\oo%o>O'7l`l#kXXmqE(\\s0Lp=QbV>^4e!J?o98kBH'B7;nFP@_*QsW&0i@j+g!KoIj0HP@M&A(C77%.TPrm+A?O_D:(!h*thR79jmdCPS#*n)dmM90E,N@So5E6GIa)LjN.M<KQJ#;c*i"K6nq6_TC%.Vdp=$.!0H8Zkl1\>K08C*@J&ZZ.pDr-a391iAFAF5OsZRfqG2L@8c*0#WdE\gkqX2HtpXfTis2/?KWhfSIDQO_HR:>Ken]B]C$+O<m[D,jdk+!=Sn(2J]JPS>DBR(spr%nts%B3"'fr%=8[9tVG&<>0\e3RBSSCaDWu/aa6E!lb0DMQ^Qm@D`AUBsdYP*081pV8g2EPm]Q2q5Y1fn5o&:LAkr]CVm9::T2ak'Cm0;!W@ok.sBjd!Sq)uj;BG^c"`)2qM;!H`Mu4/IQ*9"^Q%>%ke64\rf[rGGH#gt5,,Y`0n5hB!9i+e5gRf`Por4S>Z:R0\+mV>pgSbUrJk!X/CkZCN@`XK3?0R!0bEZt%/;>3F$kGB*%P?6/pt=FSKA-#O._R2qYDgN]NFne"o3_lDq!u\hOENb5%7ZEXs/9Q9`-Zc;<:"jCIT2R<'2oX;:&Uif*?W12:+/OCaDWu9ra+3YDWRt`+NVchWDQ@FgCJ*LDN\s4+_aLm,(b'E;(70e9(I9GESN38rXLFh+b;Q_YGh$oYFah(EYGFN:*kUnd1T=#O^Y!G<Y4>(;7\hcteDoT13i;s3?H`]j5c[S;oEl5,&nF>23!iHF>KR1\>K08C.$3'@GXh@XZa1I,7Z#(b!rD&`4$65EFf16E3$3SA]j5'F2P7YM;e]reg+tXW%Nf+7IR,^c_;_e'=WfrMaBsL%jl_X1H%ma<sr9)r2ZLF;;-/E.*"GJ$'ml0UsX`gOj((MB"aHH,tm:e<=Ij\PYuiKq@Z=oF*le$.AEn[u7IC,3BUpmgX0"?/AqK/UU@l3.b/4H3s>"?Lq5G_r7fS7LoF_S1MNegC&KqT165'k&SHKmFJdBh."?\U"S,c;#+sQ4$Q&rW^ua=j<j(jK6X-504T8&TKOG\s-JMBaB@o%T8urJ7B`)n:ZK'[BA3GM6dJebo\?+>R,!h)%'s:#?Ga\[\5i6lGIc9iWnoL3r#%%-=:bO`jaM73YG__V5?p<WfA#''X2R6r6k1&s@J+"C[#s3[g$jH/DsqRL]4/RO"ebF5D\Y"k74u>r?Pf?W/sZ4*][k6oiuLKfSF_jt,ZoEAaX66Drg4g7H@U,&eIm2:'@8Q-CaDWuodbsj*Q5>1gk8*rL.-%N5^,)iE8tWP-nN8C*M!Caj\Bj^YEEAi0p/L@M_5Nd<@I+p,t+RbV5VD`Y$&qkc!!!(>JG3ho!GZ:jXPh4JQPF]1)T+3XG_m]9e6_2_Y``44R6b:Gb4s$a@DYq>\Qtpg#o-+=?]`b2=t_L<OoJ(cOW:e<X3r*Sui.[\R&hZe4t[=&s;"ggc'Iqm'?W',1cVbGb$ZtiGAW(S,CgNC%,2A-?&nKF;3VX%YsWW1)""/r>lW]h^WBmXrSK%4Fd?X4M/a^W:E$Y*I"L$^</SN<-["'iV=p,a784t2<@Fn=N#=Wk\N):ZoL%8.h87+M#gD.43Bh7<X*jS<eBsK[uqTY`mH%n]8'M@S!V#r3Cp4jl<$>R<?-0XL;.anH1k;eB!B%E]+A8OhoCXfmh'YuFajeW.TH3ae!B;idG;?_Iqdh`q<5VYCK&s3R#b"bI.U4%fGh[PE1XZXHF>TU1U%L6EUU%Y7Q`>U?P)2%8bOAh"Dbt!me,Ej;Z&;=rRK1bn5if7O2!a:jKG/+^To[crFg4Ac:8uKjN>m%n*gs5^Q!BsUVeG)7n9KK_NMu1FoZgm<^QV_@BCPUhD<XZ'e_]?Y/=W:g*?)gHH<k9g,5:X1&R<E;<<"4)_n<:p[;$EU;He-H9Q@#).\SOZmUM3#pUNp)sA/A$+dWhdf%_'cJ7NpTI6r)Y5Hf\ntFD!=8FV7^Ue[[ikPNmlah^U^3nU&#LA-1]6;Gf29YrJ2jYBKc]_\J/g!s4h."ZWeGfh0[53^Yq8e:UcbN/W^T&F5HVTN8n*jC#p>f4DaBs?'J#+5Cq5\Ptb"\<]aV@>&\T=Y[ikYjAFN)'P0Rirp7>hp!s8D`QO3<kCmtSTH5E'tH;<FYLDjij3F_sa;>#[#qCE8m-+.YWGrjUd6_toJ*#C6S,jc;Y*84lKpgRhFDC?T`O7cdVE.usf3MA\0[8DUk"]tD"$m+C9Sj#ckR,EId)4kf[L8kR7"6\eqF8+V^?o9$Ku8#t?+7)?e4dD:G?Rl"jMkF[69IV[,m/bE?Jn,NBJ?E[J9U5>[[e#"-HFI5(0VJ;0g]01#,]#2XR-]JW`-71qKcpP2=`/,.Fq]_U3o^$1U/6UDq7>la\-<2R\UlQKU@VhhZBsVErBY3-Ul)hGOqS3(/cY\.ArlVQ%X2!AtDdR$cjNB3kr8sJe^An30`]i_>Xm=lZ5FiG#Hg/s)[IMjUJ"8]I1)7f+UIKCler<RgF-WBG;#0\D5Q("<.\:1XSH%RZ5Q!3Iba=`'HARYRYLQ+BTnJ/TG4+-G+<Y(Vd\Xt/hgb\)^juUPp`Ue((G8rHN\Ft_N'2O]N#4:DCY,^2J,F<:W`:-ipu.nZ3l>gh[S<,C_)TN=?+\s?mlfBGgph?:cC@`N.5TDtVbWeO11^e5TAE179eE;N21)EnNtd:q3%OZ8cC)a@nkj!uj6BE)rKR+0B7Ddgrd9#d!aDm:6'!'Mr;HTOHL!0:Ier\Ng0ULAM<WKe)]tS-CDLc\m@N\3>ljTaAn#7[$PtF#YfBF4:0*OT40>dXK+C.BP,=^c_>^u-!Ik9C0VuOYKMo'a`ReFCD>*>LiSibO]6@=<`5T]@H[E5;f5BZjOX3YdUjA6q;,m0[QS*^drV'71#n.4n<id,U(#uOAQS56g<+[TDOO5gQ@;Xf0nWmBsTgR(o2_QR-Lce\+ZoUX6(4H)I\*)&-9;R!NJ,sEJW2QZS`J]rUU##.NqsL=URpNXGKsoIp<N9#tHM-Ra""-j6\8'Qo)Du7lp!cq!')GhXrI[?6p`ggWJHm6hY?@u22>SG@WjMC,gUqh'(LMQ0o]X[;.TGWaZ(lYpF)0q`KqGOs?<E/(b;UX4q'\%erDe5m4Okn%R:l4p`]ehIoI3\6#`2CRX'WJc2/(@PGk[ne*pVFbVmF.l^OJI>OfBJ'=0GZQ<NKQBrp\ma<1T]iaGL]_N&o/XoB/]h<0-hMkF\_):gqIbg;!RV$Z07`Gk'InB8qmdeuYPX[!VOb3neMerDm=@;6GJAh+S$&Q'@M$pKP4+PKZp&;N1"=U,d;WI/2ljkK]VS2Ce+mrV,3F()#'7M\joejf_5'Fm@I2G(/M78!KeYIs(8=_,!8jKI"6Oj\"]e]2TCAkF[56*&p2@&c.F*@HdqeR]<M_\o]mVn6Mua:?Cp8cTe<_jh-#^NZGKt8gW<>iNIbFVY!qh2G(n+L7Q\^^J(%NA;AZa<E>j"O='o@]r&*1hBI/chgP5:+)K]?D:bprdq#?_ebZ8`WU9Z\oeW,-!L6^KcRR!>O[G%`M,F;LKL3/4,tjQ"8Uj0YqO;E;0m:jh5NqI;*e4+X-_Ge7pcA$fhgP6)j1C6j4''&&E8a-hO[c3h.<KQ&()?RC&bk*6RbT?\e`8oM-gL8FJ%gJIGFs-=IaPF*Gj,7V\V]P@+NMY>:&26dR;llmN;6$'lQ`Eo((]3bl2HR?(%gD(*d`i\&3Y@3\<4Op5(,KjQVs4A='pCK'ic$XDV^a.gIS:r5_[;K=513&-a?N7kg6"*m7-Ne:tM7^hYGSm0E(&us.N&9YHMlNB$JD"dIt8#pX7)hH0(=GDS(lddd*SoLT6D30'gr^$gmladnd#ZK$is\J!\HK.M;:g,u$>sJkeSWDT:@:OmsQ:d4LCHX)o.Xo6TUY:29=inktVt_>NuX?YY(:9`cPN54QQ)<*>kdX1IIEImll&=u.$Pg-TD.6q+Rf_dANi99h!WVG3Nr??h#2gUM65_afh>ldVmISI%m!:n^3MRP^]?dWR)J9%&qoW,>A6.9!1+:lU+9PGII(WNo2Tgu!V]?+iZ^VX=-5F&1&L2;>TY:O`cO$D_0(Imlh_8lNp!/ZJ4X<=-6l;i.0YM6VQ\W`@S4TDTEM#U<o.qWXnW5h,,[a,a0`TNn8k9<!TeLjHaVku+fkh7@`5[VVAZW't:Ta2dB=kF\Y^)YGbKWe,kU_pb;7W([o=VLn1$KsL5MFHY+M9f(YkfWc[gS<faTNMft,c,=H^430qGEV<ILeuUSoSrf%!W?Foa7=M4brVH3PeOrR(+/Ft1q<".r?OS#?SA+"o5Q"ofke`#]7eSidmTbS]-&b$3nlKDGQMp^L^XH_k4Gd561FdlC2G&$kPNShXW<S3Y[Tk[JL(Y0ApmGcd;+IDK[;4Bk6Kb6'/ecU<RrS.'O$<E=l31"_]-?'jWOB<^oB*FP@=_s9e.1QC8:IB+1g)9#0,5QNT9eoKW%@T.gUBtN5.$%/St.reroKJR%"C]l2?mlW7*27PRAg.K^EW!?*kushi'DZ^oeS(I745)$f&FZ,l+^u\qq8;gPJL1oJ34n'a([JT_ITUbN#=u%WEMUL9,Ts\rhRiT?[4Q,oN/u9A&h-jPX.k6C=(Ib%3%jmWX(#O=re.cO='o@GqEP'o&\&od]HhOR50I[e[fnh[M#Tp:lWI3#u%20B@!0V1Y'=$TiRCh"qMbK"eSC&fr)4L"sl<ipRM$<M_EMS^N/b/8\;7BU+Ak@ELp>nB[@mP<i.XROd5.BdspW-E:Z;.NhAU*43mh?i4soOC=P)rU26+2?Vq]7g,H\f)ma8-VDKZM70S@7''5Z6<N<-+]@PYB&SKCZTd*ASJVr"6GMaDX(oXm,cF\2_@f42'D;()L8k\n[oB+:rgSk6@[=b]f0RDQT<NC<1gAR<I'nKi5MQ,FQ?O[r4bdG2e[Qr/V`n=_4rqbr?)Dt^(A;PBRi+oO0k1h1H'hkXsWqn:B/*?r<\)2Z3gpqLTSGX,XT?/OEO!9jl>.)N+?_tkn"M42#S2cWV:">50]m?[FjKCUdk[5C]W5^<:207nR[@O<%V+[.U)2Bd#Zd1gN83/dmg<\*+$l/_<k?IK-X]sbfJ.lPf<sGI>W]8J`SkK`1RgPD6:3@=%f97RX:<V3q;->,J(%+JD$5Je@18)KZ'ba2#)?)IX6qSFuhkq)WIsU5!Q'orYZbN6G4Lm-*^Wu4JGMI0Ce]<]Yk[((Q"7TAEb"!L4*]Pt$ri/np:/k"JhYQs#D_q/=g?n'qJ,\W'IuN6*_dCf,nn'.$b#@r8ZbN4s7F$[9&\Uh+N:L8`DV`g_.<A4S3n="`A&jV+3_3Gc^G:+,Lkd($pmlWc8X!kNrksH@UJ`T?Q"A.)\b>d?(?jGr3;Y5;EKOV&HS8NA1@V:^qq,D>;'"6?J).\YoL4c]4dm^Oj?.Xc@Ddh7%#3`EkVX5*&oGUF(!5i&ql=Sg[Zr7<U.'tUDnYfZ8c!uC*\bU8dQO5f&]S6.8)/7=?"rR&M@O+.p#r03p?U=k?;PKmC*a`CSWJpeB?m#ODnX]RT.Cj[cf)&m3i;ON<&$>/X+1*@f=0OUMjeBNetmBH`oM:U',(T[)W^AUYF;e8jKBsL;1ZkDo:9n)Q!&G'`>;m[c:9@pF>VN_*?QB,)OAi_UG4bQe]LTD+=_@M2JbpJ%ERkeYM[$?G?S&HMMcS`B$H>U3MMtGSc';RZcLsb:SVFJ_7dOqeR1*+WrgU;*]ouW1O3`Mb5?6lImnL*H9H#mW&-N@eaQZ4PuSQ*;6sk/B7H2up+&1gdE.s\nlNj+7P-mODC4uQ6+T4^?+ZD5X9P#'hgUic^S:\k[5sPY^Zs@Mf0^'3A:1gl]mA!'.^/5@V"nYqI5^]+6i.V>(=W%/.[>*s<\6u*8]XhmprRMQeUsrZg4p"@PnYl)Y@>J.Pq?4+I$E?6,C`/T-<1q-7a9&L)Ej?^\hd<c<2jEMP#OAAe"*Ei?aOKDqD_JZa>g.o^bk;$g9tikJ"#4D;PXTo0%Fs6fjF.$\$&`.:@rQ&/*G6NGP5+;WMsgKnHRYrqPHaB>8mF)$hBF:emigq=/s(da736V3;Y5+L+HWA<4*Z)ql9`"#!Dn[j(a(DYg@Q+J!FI?<CB5C>#s[e8@R?_DblQGQ"oj/E'_A)[>2N&S"?2LeNa*3@r*ND^%0;rBfV0fb0aSD7nD(nhWX=0L(56X]QnSk6)s>#G%Z;i@JlB/'pa.C(#@3dD4aS@a2^]@Ud@YAr]6l!N5#EQ^bl&UYJ:&\l&t2ZIn@k[E7Ko;J[9"8;V<L\7BO]3m,#E['fUb<QS.[_^H]UM>m9=.b(a&j<UQQ5cn3*tdfX[0HMPX(cP+DSIo&j+cZ/rWJ[<+3`n=_tq<+AL-+X'Tq^EiAXBC`"S?otNSj1l5AP:SARX+n*0m/g4rp%GcJ=ScGY#heJI7h0VIq:Q%P8gD,WHq9r-)lu<87qL?f</Cn3R&Yid9eoom'#We9k(a'^ACHJFI_NcHd:;O3R8eC]!JC]A=c#!N;fQ8m+o94SKsa.SLrC7NJDpYbl[JA_$r)R^P[u/XC&_+aZb@-!NsFgq'ap4cblTKIscXVo0YHqork;RctcXHTIRUC?'TuaQS6g2Wb?%t:'[T^`jA&./"_=j3Mcr6P7ek'3jkOVe_I]V1Tu;)r"Z%R[JlG[-L]/#J,HQZ_1L@HB7KNt2p)/uaeacuXI-L,kh43WFeD3`)X@";P:+o?=$Q]Z@tocPB"@ok`f1pu*BRm2GOstAC/QN]Y"?4Ml`)DtZa=#?+-Isda%M^LTjoDp,`ph[NN6dA?]e.-]`+2e=![,OXa`c0punK6B$Hc5f$9A!g@ac=;74AF(YT>6?[4Qln5mpuo?8.l]OBUeJ_NFRZ8p'7A_q>"/,,[ablBo=%5R2V(G;dcTn8`Om5ZSEQ$L"#YM=V"q$-i@ZS@6M!kLW\Z8qDUcu]2R1hfk0OsSklDm-Xh1,JE$n5o#ZrX*0@nr_0WI/%ZHSar+#?TrGeJFd8@9EFboNZ:(=g^@g]@O=ZZkd^8(i3,6^pa_FHa@F$<5gR5<^gD@Fn5g_oOH4pWJ=_=WJA:Yki3,Ch+<LV7!BgN8!Is4a^gDZZ5X#6M!dY&O!rg?KJ\M9>JU@U%"S<,("T4Nt"+LK["8N4)$0W7/$2?$s#6"s?#P&J2'$rG='(Ato%K$s^%cejB-(nmY-/bsh)u(qF*QUad8jL_<9#+eZ2Xjcj4-5MRQ%5HWQ%6X?CuDK^Fr:$gP0?E<oL(kE-3ec#<^QV_pRW&Yg5B\7<uqVE(!$lMO%-PiP<*$:O#Dq.^EF["ZN32k/&D4bU);HbN:5]o<ss>3c_\B[$\,"Fr;/"U?GFBb=WP)`FXr;GD8bLq,.]l!UEtKNlh#Ssf-G@O.f!arM"hYZaQc%:^e1R%K(;uO?,Xt=`(.MNb+S[_L6:I3pa_ora'Tj1nlO/S?We;4O2eOA+e:S7/a+LH#)Y9*`/c.RfW'=@`8paX)!.MHj<Ik/4Td3CoQLPT+MtaH\9*5.@ZZBflL7m0`ku0J,.IP$0in-$=aglW(C-jp4e^[19`D&<p$/^^MaA5h?=a_u:/#qi)kX,!0'e!m4sHn!q<4Vgo?f!3+,,S:K/k#>cP?_2#$-=.Y%j#gfMTlV.V?FJrYrXIZ7F%(]uR/04GNgbY0$07>.C9@\hHdQc5,STM/tE<[1]7RR4*&5MXNZ__o:Ntrb?[nnPh[Af\N:`?/jh3idj21ICG,]WX-3"[4@&:j[>*_7.o;&[BeeP1=tN/KSP8$Br[F1GF%>`<jS=+X+I"ed51MV)P=!LZnOam0gL-XY4u^qUY$WTb5DpJMDJki7u+t"^/2'tQq-:$?!lm-2Y:hFJ=c/-kMh1U[%Bg=8(Mu=0BuNtlV$o)OA7!oS!`fYpc*f)%''ShF[O,DjKD%2h^=:e+^B#;^N)D=q5ZM"@?*m=&ZIQTb"Tjh729.?kFA%cNl_4uIBn=o99ApdQrlLRI,7YHn0U*)LVC]nqn;12gJ<^9*YghBMV">U<ur.5*YMbJMO,FGk^r<.:tMOJ;pkOenQIa=7LKgtM!4klGiosY78J;.9Rg3hkoi7T,JJP0X;rcKNoJo(b"#^o:X;NV&l[qf)30*OA"r`U8:3Xlot2,f2KM.0p=(l971/F[;;dS5Sc^&NK:`psT,6NKnDXj2YD@IBMGO,*jTEG&K>m[qXQn%rgeGFoZIhfmLDf+8%/;>sP0mX5c4q.j7=sk>9V!J-@eo_\,5VTY@ecO9.Y=kOhm33+7kckdr\.TYH&%/0I+1g-]uh)-i"roBEl^%G^_<I2US;r_7k*lRS@(ZQlGEnR$G%WKRdi80P"QUlc_If85/e`oa0leXSO?F91%,SAfj!8&]`((^f&pK],6"1Vojq%?fdIo;a1]Sm4=M<kag0Nfc8HhLS;uYRKh'"*i6>UBH'%WP&_pdt4e"L*B7&pS\nmDUIMrA2=mC:Z;s]^g[,o7r_I"'7?PO[VilQgPAY:PK^3\7A2V?b3Lts5EY7F;?-`;g]dI:4Tj-m_D\O\!j&ZLoP@[ouNh1DV*Cu`$;PS0<H^-13/YGcoW5Er'%D]-`NkgmDic0SCISGP@nHD]HK\Fr&KmbMNp^o+]rf_7+d"Bk0L14$>pGZN0[$'=].A"ql@>dpPu4scsYm2Ug=mPQ$o]HiRdZW"uBC=2`_0!h>VW\:!)ijs3*;:CS9c$4'Okp<6/q0C+P"?0J^,tGD(kH:OtL[mS8H8]\,ch>k0Xn!Ic:SY]MZ^qCdc/rb?>;>(?1%ciq0?fQ2YK08<(aQg5b3^7GC,4Fk:?9M,qa/5PE,fp03'KbNO5Y0kJ)u")rRFM[10PrWnX+Ln=416J8op8nW^sB=6&r](Is!;oqZljkiSgG6a,,eNGpqL+J\8);#<ga/LNh_AcW![[fnM@L'dXL1^aI*O-b75bd3%=U_:Rd?0",l:V2I5'=hai418:f:eBT8<45ZGj%cEXcWYqeT(pE%rl.df*j&KPj0^!&:TKhP.9L]?9l1rD78[k<^MfmCQaTHjtVk.[*i6Zok"Wj*)4T'JB\JkJL]B'o9\\9ct:%;q)nO7rq*)qQoILQqE-L`^\IA(--<3^okq^\[+*"V"M:IuZ-b/IWKYGd,[^P^u2dCEE85F<]H8*A=t#H@3aQMp]9Vt3/M[7%p00g#SsY3E7kI*6j9%IW>U)Ic5b[amb3`9=X=jRYJHT$">GOpAk!6<tD-i6u83].TH*%U@J\A4.0h=g)hg1Yn\f0!,>YW&7S"0ubneHj6Y2XON;fne%FmOcPMtQW#g'P)R/7i<G:FhLV7m*72#Toj"s=L\B1FnAmrBmD[![GT&-$X4UMLZ7ZOsMZ[,1hn7-6I,enFAK72?ST<<$JM:-DM.nMWT"tGWjUU@t)_]V``:4B6IZb<q0#WXRZ8\C[SnE&d<K^VeMYu#X(r#S]O)PMI=%fVkeaLP@Hqh?qaJ7N,o\tVJQrh5uY'`1';EXJ<0$*'6E/dEm'l&ClKt8mYNMo03Fo4fO\`AKfiFKkaURpJ/\+oqrGNnRNZ_OCDnR%L!ri&#JPl16S..08GKd8.Ub]IAAc\s,P?_B@tj-5VAGY7>rM;hUijiq'\d'IEgHFB`Cn#=O)rA4jDDPZHODVQ?pmg\gEhHXF_nnh\aGMOseig[u-n*l?FYq)(;e\N]o@$io0KB)0;:A:"F3VC9s\IeSk#!)T]6F]RE'c3T4nn`3V\hI>hNoUJlF"r^.b%G;]4XU+B&&F\[S"N:A(f@lM?ORL(qML>[Z^muj(mX*:Xuo^>PVB3q(M?VL_IJ5$&Ogp\XqO6HkE8KIiX^D,aGm$:9bj\ps!XA-[g1*m^sgqMT1GTuSttZKZ&U]j4>p/M5=s-1j!bq0ggn5g$>#P_l$:`kSp^](Rm!EW]BQjl<=\DoiM*hWceV"U.q3Z4mM>`(ClDX`5cbkTioOZi2N8>Ra)^Ld:-&+7:cNg%A!,bmR(*\NNeF5*X!$Bj!5KnVql<0FBUh%$-^#^mq.OqM]EFP#*6$"hPA:)8N+30qj)PkcZGa@%E>/!,+J,DB5EmMsdoE8\]eG!*@oS=W!*#%i?feR5h&YJ%6.^q8/>]%C4a;JaQ!Cm8J,0ok"9.1C*i\_$S<KZ_"Pss;*h/&SaiJ7U"XSGA13-,]`ftXVaNEqmgnIOMQdRMYD"`CNmAB(DDWfAq)D2A04jT89C-aNC8Usnoc.0tQgl(g\0V6ZW)>X$sgj2QkC>T_FA=>JK(+W(KU6rrWri#*"KYMOZne[VkMW,$^>.Fc:dN"A^,L3458P,K7(kQlg<h,$-qp.i:ILf05Kf/'$DO$tF^E:b'ct&ibGagdHkrqS5Qu6RZp>U(WoA8Qf4;ZtU6!&iE&X?M1=B',:)o-kMTCijjqt#K*YD7)'1R6a&a7:6tf4;$)X3"D<LXXZ;]i?G60kA7e,:PO!acYe&;m+WM\N;-(cW1>8fnOgemg]ipVr<NSW9<$m%/Y<WZ)"#ehqRLf^O;GQ.=W>RMc.t<h]C"bMXn(?U$StC:6X-2_o;FjRHPH`ql:k7/(]o$Y2g3)BlXQS)M1D#U=>U:B/!N7+-bfhW(tD#=41GQ7IST&E?J4]OX>l96/5+(7<n2r*p^OL+Lad<4`PI+XtERSrj34%6,gkF#gWj#?0E3SQ!2\(a(`o.>LoE.oN)L]C=,*8ZisSaU<<Jl:t_8"rhR!/:6g6Keb9`O*F1.0ea!<XeeR#0[Z#p39cVNd4nYo1YI'okJOa<8dtM!AaEh/Q:jegOY1*OYIiBbaT-/:\F6gl\ah4G(&Qs*MK<L;jE2(+U3!9)D$b>E'%a<su0mEuTqcjHeAJo*$bpXmX;+4)V'ftneZA\4j$un+o+%3V?/qc[&.B3\lUfu1P?ER_]]0(7YjWJGrs)Oc7rjGoeJ:f>4#`fG+5]ij$H:sT`lM.F;iB@sUo<'/fIN4VZ/Wrn6T_nGVn;NW\@i00*S>V/6^gL(;.B;r/asqlX2lH,7bVps6g$A`&gJ-!'Ds,Jr)D6p5oK84N$=CQcQZAX%mHUTH4B#bU=ME?JjEO"o29:Zmd0Q?7s%f#l&17]i:#U1)J)t\Rs0dhHnrLF2K)9*)7*&B`j1#DRQbZ4#^R^7$K'_8W)o_IpmNn+sMFY5#.aj>K@bWm4lPQ5[]OA>FmQDV)p[&O+Ti#rH[1(Ic_S_!Y'4!7@[WLof^<=t@^)t?fWGo79%[c$/M$H_S3Y?XR[F-oC<ft;neC,m15Lc[\3NFL[dnY5O-J:t<K7][H&C@bcoR'FL%dg1Q\hNdSbtr;a=uVBF>l?WKr%'3(r\dOL+aXFnR`'K><)!ER*mRE1T:*O[qh4;UUdVsf%W:IZ:Zb9b?b$Y:'@uk"fk)XF&LP7G+%-s`/^K8nik/Nm+[NM#X!*^)icq7Y5+RI:d7)h@T>a&S.l,FTJp?hfh8-T8&*"TI\SDP`\P[a4nDI-pLb9HK27dtgbEC$ZYo:O%Le@*\M;76@?j[_)A)VeG=8=7Ajs-I9AWhG**:#T=6rdf[q2"Zj3/mOC0*HU069rk?e+;B13OGE5M^"pf8+<l@<E[s:QH^.MiZ/]Cb-3s\B:n]6#MCSRFuk\s3[G`K.)f,Zh]@Hj/,.uk=.A4i9iu+NH$h[gf^lH&>U@]3.<;-0K_,Li-,hndP]J$H*0L[e*14`7Gc*%.j*8/XVU=2T:R@YjBKlpgpjO's*20OeO0[ipF]?KHp[i24<V@j`OftY9naZ7:Y17p#K_1L>MGP[:N*!PB+3@B6d'GS2HFAm+CR*r,IMsgJFhO`BY]1(5X%bnHXL=*%Ig#?]DKMT&dr5eOaY*$QNg'%M/&u-Z\Z<`Nc0--h'94@Wie+Cn_E&>RV\%-cMfiI:UQIYn8gHpM(9JEn15;i#a5fPrLVgtoEr!#SEjiiF?nTE?qbhP_\so[l&reS6W9Zn(Niq;@R>L-rr[$/nfe;NmdnQ<pdA_q;C$8fJ5I.iZ>l"G47oi5(<Cl!ZHF?L4ch>cX*G%4;T8$"Vd.;0And.;9q&q_>=gq%FF`8gk\_8uFW]H(Dj,pl5'>rsid^h1(.R",r1UmU.D$_c6^[iG'O/Z0]e@F@TPo(lS<YW0Ie#Mo_i)T-(7rfj8Z"Z=VDZ<ZW:q(3qcc>i;Qq,j./uqW7r&PVPl![gJFnt5^ne2ccnR\PTbC069*,AfOLm64YP)j<UTm`5Q5/K;TdrJ"K$2+(kE9Pt!!Bo10c]q+BBKlsXKsRA[bL'@?9]VMlS['u9B53*UK-B%0n]u:u;Kt=Xd;kL77Afa':5M.?K<O'^PJpGEL53VcX]UE74N]fu[Q#;NMioAUZI'jhHo@.cfURh]CB[LDQZ[O62b6j5RjrT:EpT0@/P#sL'8:Gbe>8sV8jO8[Xtg/dmShLQ#rAag5>'%f@=/7OV0HAkoPCX[So(4bZN&n1IN#ALCO2:>\*]a/$_?YqiT^:;_mo[1:]uil3YTDj=%B0HJ#70OVmL?;GaL#U@JD?_/Z_C$oeB3qYcUN]/h8rJQc;XWADbAV]kHinVsQudE:C^_@2t'"3+DnuK^$CaRd/lR:OduH\Ys:`+kH;Er,p:%$cPBWQ4)p0g3PAOPXG=^\0lGpk*]f\K_$1CrSbC#a54r)UQ/+02CifKWRKO6;%e)SDn3r'9a:ACGB1C9@Z)`Y8sgqEZ?SC8#e;cmN%D=+0fmGFo0q_+$SdZ$)KB%&#X_];S?Jo3X];1@[T$f4G0mQA"+%D[Sr<JeBKlrM`aKTZic#0MWY=?-X,_jPLEIm\:>]K?7h'?j\^H0C`^'96S[7U%a:[c/j1+jWA@+<R=0A_+O_iX,A(*k4=7aL,KT.0aSs;\?c\la`BU9_2>Tcn^O$ieY\1'`aOV5Lt<693k+7MP&fJeeR25TY,b#t]UX.Tk3`.>[D01'49-qnhfgZ@^qI&5uI9.'&W;<b8`*1q8hfKC9af#[!Zg,?<F'L]Z&]6HFlZsT&L%6n20mAJp7TZ^uD?q3ZrP6lOV-Yl?-gOl#d<JHeiQn,Wj%#^D=Z51RJU?6K6:;<%JNU%m#:BU`M5TgW,_q1AFqe<PrS9(sQ:rPFapr(?L]dQgcQ%6EnLm-!h$;/&if6]!bF<M2$"9RNgiU+UXrA<:OnNe$+[.+nZnME(,GnuFK/7C(qQH=$t28$R5#Qt4fEC"j&dU,#T2+-J9X3bJ?d0PkWUtI8W,)ec0&-u&>m5[L#gb:el?mZ"+!WW3#!!!00r"T23!!#:#!e1@R!!!!qYeXTHz'J/`Tz!!Nc.'`\46!'n@%Ig#fP!!#j"^g@*B!!'f'L`<#a]NgIk^*Wg[!!(f/>e8_6hp9VALpA="25jBQ?*dQGoRd'8)u2'=0+0iQpaZ=E!!!]IA1DtTI*"H5>jpOj!CI?F[N]SE0,]@"dTa'\m7'0AdYGVF!<<*"TKnV$b,7Ob>3fe=A[YU,K6F#\kp+cc,4JY6!!!#/8Q:J<\$pQp5l[nTRrW#A<7&q_&c/0>\dRK#zE0HAF.T3eGWmHRW4"KKe&(8M_+M,<XrjgEIITqfs#64`(5X@]]_;!^+hr`(c=EG,GRLo6Ez'GP<+<G4YtRk[tokTK".MZnS6!!!"LK#6-[[m?!WGoCahbucMWgtc'+GKM9e<r`4#!4[<-*7g_)fn-c);5a]1!u%A4L&_2RJ>H*.>ijg+?!O_ps47+8rB=t%/DZTm'F_Pf$31&+Qk+[2^W6FCEbV\j%>uCie>,jQm!#3,dU@:q!`5!BegUS!!+6]nDgD_PjU1CC,A$OleLO[LnF$-5qC=TL>-BK6DSZAS!!"?2aCbnCZLOr%qbDRoG9$*]k8aF8`GHnol1P1o<To`#!!!#Wd86u^:nq'/bglP-Z`;e]mbGtX\b&r4CYkoB"TT@5>Ia_6!.a6!M6^En<]QVFeCEI.W)R>Rn2,H^97PL#=\IQd!4WTraoqbF!'D'[4+B,lj3'*aHq_6!V8$cs]N+@Q[9j+"TmHCsYZLl*!5Qi(Em[*rk)4/k]tJd%kqM8-SeP_<.[;GU0<uZ7s'WNeJqJ\uIm9#"aC:hX$NL/,\9UIp`j[=uLk#*^eje0"]ipg:-0`D*KhJcJ<98/^kKfd(qtkq,!.P.P!!!]=+tr7<jM$,*f4XUDg9P:JmdCDO5X,)\//A3c!0ALP>$j+Qre_1f[;m#<h[JQTpaZ=E!2-"+lgo+:'.k.]$4I?mrQRUaJA2-c!!!?5iI^5SH[C*XgU9iN2Zn=-rX&W*!%:*[I=*!`W-'tHe'4@43_89lFh;e`Wr"l/4Hi!Z"cENa!!$O9V+=r8T?r,f2t*s6+N93R4`K>0mdC;L%/^h?!!#j":mUbIp0JIPEAQa7547as]6NjTh;8Ft#P]eL!!&\-nac6#;Rg\[/J`d(QK#m(N#ADfH[pJFIg#fP!#.CZ%WqI=p'qPqT;SqrZnm-Kf>j6%e^^^%Fajp`:Z/DV!!!!8+llb,"uU/WE^h5>f!nK2@RZ3L>L;`P?NC-,!%pTL9OAlK[4YM@J0A'umS4_cXd0D8H$am^le3'Ug+<=&'`\46i$+]_-<VmL5<ggsN5>cVC:.p0Z<d'&:$UP5\QjE+X(p`GJUrASkK5Qq?NC-,!%oJm9No&OmGQp\q=Ee0fn.cWrX&W*!,rP'B2V@<\k`mI$MZ+O!!'f'^gGb1paZ=E!5M%=?eH4i.f]PL^dVA^?X:<hn_\irFj\#=&e`(!_c'H2>]b@[!e1@R!!'M7bPS>\jiU;d1s&/khn=@qrCTS?*-'Br>mgKE!!!#W,2fYB#5B\K!!!"0`jYk]a,V0-LCW_*[HiJP'+tojN9s]M?<sdC5sR\#kK]X=N>m*<oP*$(nDM.)P:+*hR5&3kV+[0)cL=m8!!!#?N'7-iqXs1QrV`3DD)u[r`2]!,B@!Teg9bQmUe$Uh4aP&c`R2HjnaWt@1,>"4(Mt$QH?>,b24f<sH*oI+'`\46!&A%[J(:8^Mq5"7X4J.@?G,Bc>=OVm8Zrp^>"%7oldi2k*:UGpI\V>bm+IR,Ig#fP!._/TTte0ZjbggfIq3)cZ)(0a2GZL/'YW_f^OPqAeMA<._M&@p;,NlFFaE,27p<?;l0IZI@`=3]paZ=E!!$P`%K0:AC+=Y>ji`u0>Pe$Yf<f6jHI9EQpEuPW,4e*,Iei*;m^ao"/8Y"EeJgD_+FEh8B:l$:?NC-,!$Ee.kc]f"'e9b637.G=]mB@_FQl+F`fD3K\8^EfjCIGE<I<?<++LBk]70^)qISTgzE$O`-Y6GFS[*skQkKXMU2QUr\b$TSiec5U*s2E!tdPq.$l`Y$c_hSa=04);(c^t%.mn].r#&+IYB\Kh-?sqpSbEp=I4n[<'hVR,Y<r`4#!4WVan5gLAeAiY\S<B%%?]Ak7\LE#Xs(TrZ)>gUA\#roBC@kP\$5H0t..Pb^5LIK9.p(<'=d/hhXB74J@qEfIJ\M6d!!'foYe7`nL=F`&4aZm-^3hs4>=X_qh7Im7Z-JWon%\nJEbCR;Ig#fP!4W:rq^\-<Ig#fP!4W=0/)(,T"TSN&\-Vj[gB)j.!!!#/#l#q)!e1@R!!'M7pab)#Ig#fP!4W=0/)(,T"TSN&\-Vj[gB)j.!!!#/#l#q)!e1@R!!'M7pab)#Ig#fP!4W=0/)(,T"TSN&\-Vj[gB)j.!!!#/#l#q)!e1@R!!'M7pab)#Ig#fP!4W=0/)(,T"TSN&\-Vj[gB)j.!!!#/#l#q)!e1@R!!'M7pab)#Ig#fP!4W=0/)(,T"TSN&\;9K-C%^cA?Nh4!/h[&:!!!#W$M'NlJXt2j=TAF%^sg]%X+C)nX]YW(!5R(2SZ@>;d&gFN!!'g`d@I=hq9Z6H!!!#7e'X_eJbdZp=TAF%^sg]%X+C)nX]YW(!5R(2SZ@>;d&gFN!!'g`d@I=hq9Z6H!!!#7"R&V4^eErm.f]PL?k.9kCg\T3WtbU7!&+Yh1H$p#]%%,f!!&Agh&.0!$/K>"!!!#CJaSI+9S75^!WW3#AjU^u#3J1[:&t=p!&L<1DZ^ZG>GM6!!.amlS\9SEUKa;i!!%OPd@J1+kFu1M!!!"LM:%m6JL@0rPlLdaJEbIPb^g"m>DrO^!.^omS_/L*F:/W[!!'5Y](8%'2nB_/!!!#O)Vmj_j<*43!<<*"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz!!#8Krsu!q.Ok~>endstream
+endobj
+9 0 obj
+<< /BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [ 0 1 ] /Filter [ /ASCII85Decode /FlateDecode ] /Height 350 /Length 9862
+ /Subtype /Image /Type /XObject /Width 800 >>
+stream
+Gb"0WH!D'Vrs/$8Ep^^2_CdCK/0H,B#^E"uW-BD?TVCP![i$Z-H/T?MC8Q7Z=^!.#ifS[_/+:V5YDcBN%*^$c>>oG7bq+eGrT<&4]:[cIcSD]es*PmZ)W%ZgcS!Dbs8=#>zzzzzzzzzzzz!!!"$Weco3XK;&Y#bd<s>f;pE#_ZbqY:M.S/M/NR]Ufufo[0%tf^](M?!]s>j\s,5GrhX[aL&mO(Pj=OrbYj2'2t8DoJ)bsf^](MX,QV,b5Y:8Sm`r;ELD^:ncG5<P5h$f<_8%ma(6`0b6p_$b+CODQ'LI=FNYi9]KekdplE[S@EVNH'Dg?T6#:gt9O@7qa+\ffRO@a4R=a)^!g,0s=&]&JC*P7?+>9*b-KiQ$o7ED[oRLmH?8.H+guD:8H+a])LaPZ.H%ALS:#f,Sfu/Utf%/DJLB`%?jALkM)OI1,G'(!seIRZ0'-jru5UO1KVKjV<>t,:&<%;>/1IK'=9H>>_-N/e2ncG5\d[K<pr6.4%jQ<>^Us-p4)?pCk_6dsK(]*2A'lk0J0fCr0%?/s1!h#MO=7k1=;6(COWPmG?WHit^+4@eeVWRWRo\&<nlHDq\N#<K2Q32EKPb.Jl-ZulmH@'<_N^aP<f^]*;)ZO,5T<1B[^0Y^&beVlcg))V!@`o-iCAPXJKg(P+D;aUEk,`T2?Vl`L(U<'*1,XJeO$Yp<RY;"BHb6;Cnu<L*j9:b,rk:=Np3)7O$4l_!FE(hu:lUkZZ/l-ESGt61V0rZ@=uQhin)L9GaRgD]j9=#lqL;EnIFg-G@nboj5>Po,Zf/-kA&Q$9/M@Z]pAG?^F<Dki4t\<9^ftU,E$-g$fX(!i6`\*L#:=SNM/8hp2B9`^MqIS%WEr#Zntu*$fV*`*[;HoLl`O)UNLgrkjTRD?Id8L8A(-Q)@:]BZED[n'L0Q0=hln:XR%..sS&j\M.Z94`hfnuRn`<&nm9>7oA*-3lHp:#b(W\<%@OG$[)7T+Jd.?`h8#M:dgoFq,UAur[Q->hm+/6mcACu0i.b*n#T*d^lcZ:X#D.rC`/].\'>uYj=IY]F+OKkI(R6H(%Ep&hZqI8[o06r+Bot:&s5;1&i]J;U[$Tg"F*r7%G]KjJgk%3\.iQ5A070JdtbG)7bU<3js/?0d:qNB,sG%Eru1$&R*U?b<pq;-)\j97lElUPMt8bi]XZ/c'T,4%g2A^R:F!-.''6C-)]HTrV/^MiS$D4c3g+YS%V:/85P$4MiX>hguGR/[6a5m-b3<p0bt/>jTB?\/$0YTJ+>%f\E6o`LiT_Z)lCrP7:qiI;uUITY1q9@+3cM6%enb6qk!2D8O_$Y71604N*4AAgAZ@`o-i`&98Xb6qk!2D8O_$Y71604N*4AAgAZ@`o-i`&98Xb6qk!2D8O_$Y71604N*4AAgAZ@`o-i`&98Xb6qk!2D8O_$Y1f'??iuPT\/f:)%2lLgj^-a:2KY\(L(2g@mT^<kC8$8<BX,LmA?Y-?MJnsP^)a#).m2k,ml#$h2K['m/:PriV[15:7XCLE:2M,>+@ZUnCuXF-]`3+lhQ11ant96+(<LeSJT@LeZlQJ3&k[=#"H&dP!!jQjGX78ZJPUhe`uMf*%GL&rb0j)ji\FR0qFs"f:"1-5lm6rJW,%aj=79UrUB$28HVIYQo8Tnial9]]t\$q8h-oes1RN^9,>gD3Jj*cJX\4ZR57h)"Ys+Zei(ab3.'3aNJ`Y_2g!9^l*KNc[:o*YA[GRNjR%ZmkKKGYIcS;?:,.k?FDbiI`;"eK.dtKCI"YeFG?uE0cATA0WH%Y?DB.CkBu#NZY>1XN0k]peq6ZMJpPmi^djL0*.4$u</h/Ef>O1K<edmu*4a)dFYk.\9$Y6=I+*bBn"?(!9f<+e_@ACk;QoKBV[-=rbQ9KH^CZA>`VY!OF(t1I3foE,op9rOApVTCEoCMb`4.YiQ5Xmskb_F$SPBfHRC"L&M$Rrt_N_UTR/hLp&("1OMNCeP4plGNu$(Y6Y$`ia6CcCu.k7I:''R:32VD9fdZ!uUp1)g_2>MXhV-8Fo!,kUNZIpgFW+[`4`3+YqdIXMj@Fbl"a&+]=60l/e-mY>NIrpU"#;>#1Y$\[.A\Xg[TdD\Hh(tpr1[U&'64aJIKl:m=G8VmcD>ro?PBbhcNn*R,U1><8ukJ^DG^]'[WW-\C("Ys-F?d.kJ$FSG`=2/0gdhX[?gU:nTTjoHRFR7AJI9`7Bd8?%"%K*lpS5nq!.C7ha\f[fk]6cIY@6="N(W\<%_S2\cQ-@&=p]lP,75S]se\"=-4^'\'C=]b3G\Bp(YEt`bUI&#SEb]td9TjVsFrmCCnXC?9=Qs0ho`O76m\TL_#RkGb&fO6'd#a@I#5.<XH@'<_bdal1V^23p:#<!Vak&6)2(t&rd_DI/g.UO"7uc*Ue([CUlf[_DO!=RPIQF%/Qb0<)>"(P+VTQM^$P,h0n<t.!<=b$VY#%-XS[GWgmN*F@<:OpOGLO-:Qt_[UR;pXC2N44D'BS&WM0t:t]]KAQ<ec11P=XdF$C.BM>-613;amHYWuY24Kj5t0-QX';j^#WmI#VmRjon)+J[)JdP=T5)AnDlPW\=\=i#n@XR;&q.g2)k0MeVab>=ZCs21G,u+oT3\'4YfjB.oB<U^S,0R)<?mMA[1A=q'FX1bU2tS"%SgdOKY-"[Z6c-cX/lR2IL-1:(G"D3u*UEA9o=2/@G?aFMUL5cEt7^lF@24#Ad'NiYtr^8AjPH#n"N>0)6G]KjX)WB-8iH@U,"c,npYTkaMf"_(LJJ_%Keg&/!SNPE-A'@ZlRa\\UrkC/dR07__eB+'+j!;&TBC+!>3"b2jj/d3SJrujQm2rZ:(naQIeMa7hKpOfagVE'X16VU.PX'oj^P!=9^rV$;jrUcje>nS(0_%sr>n0_anI]Zo!o7BfN)87t9X8gb$cjcslLFlF4M;d2ZEaIkio",smDME)$8aQ--afK65_"D*i+dL.i'M>2ojiFd@4MFmMg.eDA.M_=%QE.a-/7_'=ojHMtG>L=]Bq/I6Zs$O[D;<5(Jl''n[4X)W)CJ%OK:He7^*(;D6R#I-S=I!)*a[]GI=-/7g:Wj:"eg,2nYtjAjl*(ZG1-ChZ&f,ts$+TU:+B=+3P0Ugp%8h$C_.<9OC+W/b4C3]]*/Es#Rp4sXm>6:m%fk=fn'LZO2'N1`l#h]Y[LX%j/1(qRQ#0$V_>dBFZHDVRd4m,'G8nMd,2l2X&d@P\"sY7+#^QD4^>[J"%+9%7E:EnnBog(Wu%UUk0KV^4>+X_e4&'F[Uo'!QYQ0UAabQ/Y&.usZcJ4n?SD,MOV5KJ)Hh1j>(p/GjW>0XeS<%RH^,m'AS!/6Q1oJsH''K3I`p>8I%.G-^'XAYb7aB[d'$g65.u8cn(b'G<-XM>QWDAf(/LTmehd84G#s^j/^,H7?ee^[qU\(Xb:8Or*5d\e#PhMXD_mGRPaN^KXXk`9lH>qm%3I?uDdq>.kf@0*Y2%529:1/jI70$s5t&n!`IDZYrX>*1bi$Al^[SN;h_pddR3jS`/0s]M1M9CR3bcI`;1nc=kg2)ZJ^.Pre3C<AJ:^``K$Vi`4!6)#9h!#c*\:Q9.$Fn6:@YRrh[]T@/l-cWA1;f]=giGB_DgZ%S2>-%M[AcTKEZV,(D("5=B1E$<P.LIRq.laoCQ$`Q64EtEpBjk*M4N[M/UGX9p(cK(6`rJm[EKB/$]r:SN^K#$h8)&"RFjm%YFAk`_NP`Gh*7lqM\Jlr@:S@%MC/g>3Q1;6@?s89jVR;:>YAFI("1@`jHn#/snABBV/&d;r9H)JY(T=p-Y]tnIFnlb]3V3bCA5Ai':`D3e[f0f&>@Zc[7SrcV#brb59*NhsT72A*_.b=`7&0*=s;3)<gI^OpT\MHb#p&-YR-AfD2JWs!rp6ea$H_>)$ti\R#b:o2<__nfC$lo1t.Us72(B+"`s>@;&PDdi]a7UYK1CITSE)E,sDRELoA6Q/>.qd4\eqKP1t3?)\u"@9tEd;Vq!KB29Vq5Od39lW:_ZAQ3]jjrlcE-TV&)Q4X#![<HS1pWG)G5(+0,YEQJ%[E<?\7JQSdL=ZOE]Mu24][s;k^0#@>kP`$m[<hA%e/,_bL\ePC3S<'nedo1#s6Z7]?RkIU.:UmW,$T\<2-hh+o?t^Co%q'.o@i;I-]dWk/GG]o["7%B)Yq"GL$ON461#7ke*3p7I.AWkp9gs\1!pV]HXb.1'XF[MNum/mF8aP?UYkOmY^F_H.IjOWrB9cpn-[YUKuRV#EK0.b["q7%nHs[(r%N_h]_&J-]S2Cg4h,q5r3(nLCg&Rfe\OCX,O0Pf'LMN2oBi"D;-lklU4R=b^2\VSa\Q7.=B+.?U*l#ihRI\(a"OoLnE.Y4$#LmOGm`>fgh6WRr%Ael.48'SFrYc2<aJi)i7@!G8&"i\_Zc6Y-+&L;TY2Gs+oDcTIJEguOl\0AGl*Q.q>3?][;b^+`3tX/n&KMC<rci4p?9fPJtKg2qU*//Cd71mh2ga356imCZ:B,BT)7X(D6"II)*pVS&qiFl!.Rr@kM9q:Ndg_*p=iM9-H.jFmj2p;!q$>B7KEEcp?0,)kDt&kH-YDk3r6,?3M2B8Qr3\>He3a3rkfOfQ:r7JMhZ]Q[CD8WTGB&-I/h3??h\JG]4Cc:?L=0ehiGjl\:=Q:b+Cf+H1Ah(*P"h@^XSb?LU5A+kZ<?d#ge1fa/qu^&+*Q0CrU-LqU+G"oE/c(roE%?bGPj=c?j3dkW\C'"B*U-Sm*f6Ds1#5PnuWsrQ".EpT2\grT-61Ro7XpiHoMI!BO0o5.^@+R3R&;AA+S'9M%I':&:[P3T'E20T1g_7sD*irRgm_7VZrK>5GL3j5im<6U5l27=X1-EqZCa2nh@h$q:+sp$%OHn1FhHa7eOCduR5HB8u.K;a:!S>]B")c<F]XR"`6r^ZBr6@m@-Qr=dco&/=sA^ob0i+/9nXs1n9ehDM_`n'+<d!<*)s!Pkh3kV;o7^]FB6i.c[\E'lhi\=juEgs?Q3DWh<*2tR3&)u9TN%K-:bL40,A6U(R\TcX9icjp+okQ_)HoE0U_q>nA@r;bc1IK4=S56/3e*rt*C%fgM2#66^T"+V?e!Pf0=:B]U1IK4?)rS%@_;>U3O%mTkNs0jM&*mrl+$=4%0k4qE2pZ_8SWTcq=KV9(:r:#oRIQIAHm>!"LPb5jn?ZS57W#lmsjfPI01HaPts86%-T'oo;U34>7fB.Reji\l]0&O>A\>Z41m,-,:*WC4UAU:2ccnC*c7cWn4Ar'Vor8b]]bGPm>hN7F,bC/)'W@r3T4R,ARp)*_mg_Cq"3ILD7ot-8+(D`?"4d#AF&$;Y'UmP.MN*V-?%=*rQ]\rC[[%t5$chfXRSijN(h6InOokrBW^8I(kE):oVLUW.:H"G9J)gC^7?LZ"[qi;d_.Fb!2&fObE8R^SA-]]-p&n7/Oo&N@cnf"^ES=ar('GhKJIW4K8q-uX*?b9k&W*X<[#C'u'"RCiVKA,.r;,"HMBc3?)56!P@oS'>)n(`E6Sk/Q3<ZutCie-2tQsVL&-''*2I.6(nrVQ?10Io81nF5B]j>C7H)4u2H4FZq\cAbJ0o"WkhHJt)#4ki@/G\A)`L$OMX]3f5nQPWS5/BRm%n%kc3J%p$kk3]eT$n%2r&+t!an*Z`.[r:*8H/lo(lQhji^NoG%XkS&]f6F-gI&pfHnDX>X\$'-k3.>hmk*>OF)q#t>;*>Gt@/[=7QTMbB6CN*l*]7NFaph_E4*:*o_=*_n>eS.I8`iFt^3tbdbQ6P2Fn<WGCKI_;EV\&%M\e!NpmhEVitj@S])2g(&h#4R?_\MQpVsTk(CNtXq<%9kRBt?HG&%uXl`QQ.gBc5g3_VaX[6?lNj-#-lR/P=qbrbV>q!$Ffe%_G8s#Y9K044]Gmg9g%LN<4]V+VUXr-kg,\$Mu.T/q8W`/.h-S2bNZjJgU@c5%P+nK'pW1[h.Jk6k$,qsh:h+0Sj-D03OQbo>qQSX=lU&Z-Xn16mcA?t=*OJCLP+hTblkoA0:m3;@"_01V*'HK+"b;l<E`Tuh"l7S`r/r7KDho8ifops?j0#7g)ZhLPb6%N[\/j,os_7UG+<GX/ut!L*9=M;u>jftVIGk3U;PY7=3_CDp/RX-2-Bedn`Xj&n%:7Ai=:a3T,`l_D,;>IX(to':5/qgLbN/e8sdr$+oG+(f-G_#>Fis7Vqc^\VusmTmGJmbD6`SND&`g:_.fQXB2K?K9kU9tl>_PP=!dn%\gAkLPWnZfY%(h7n;1G^u-e;CYX1oH3S6l%5D3M18sPX#&li?2e9X\rE3Z[<:6e?YnW)F4[SNFO:W?p<PtXp?B?#Cu2O=_hRjMo8L/-rV?sB2gr@7?_8IEnZH-U@1`Sgn+P)9DV;7+jjJG'`hk#hNsbE"f71F`=?kl,0&?V;/_VSb3$N3[`nZ8@17,3>@+FQ/2/@9bX]nkL<[kj)bdqr-CY.XKrb0ge/)Phpq7H*-AS#EkNVVOWQbW:oMNo8-YOTo1k9DL8c'u<lkG+<cQS-@H4Eb]4c8":/FgXtbU&)TSJ0e-/giX&M>'B,WDobRcY>(QBCX1`2$Pk@@Hh!8q9:%57p'sNY_caQmal9cG]sV8I]X_t)R6>?:X:4,D5<XAeS@S7R^PTVC4*d!EUfEf"=gE;">OuIQQotAE6+skJ2@fHRE)t-6O08]M#C?KV@kSsrI_h/oEEs7T%3.:kjfrO']_^?Xa]#'39qTFo:(?o1daP*hR653CCD1"lT/LTBfWer,&/[KPgpj`]Y=q2f!r;Y>A7b#s:7XLe6<`Z16%'D-[V?`?n&8TsliakH<,Jl+AI>irb<IC;.^jblpr#@E?Q:aRA]W5,_hX9i0ll?r;,gs6BZ0E!_hJX=S<>X@i.1h*qnG[tJ,]NO"qF6CN4d0b^Ron5C/!Dk_hJR<d'$N3c>B<q2lu30W_pk(L"Te;)lu(YbW?B4g==A*0I/ERAa?i9S[rq1(>klW6I26[M+R>29MFf@OO,5dHhVD`]67V)2BMbU?+Y:GefB#BI/PoUb8;Mum+J.\f1t^BURQuAq0BSdPg$`MRlZ.;YLn;+gXrb7d<bT_#<$B4fq_dB(==^D>.'6ID;@[b/Of::e@Kd=Co^Sk0eHU!ZW[oJJ%fL;Q8-HR@-:9+P#fuNNGTCD*Rutj/1<dHl)IT8].4h9Jbl&nLom4IY&n]-orRKF?b\m'E5U&Ld'0`DN>dN"M)hk2@E^H\kVXW[?NPM0CtltY63^-9OPmnSIig=&(UZjf[BgUL*c+'nJk0DZQ'8Q*c,6TbO&"m(lg)U^Vj%,4r-\0ZUoK_H?34?>n?e8X'343of@/R+7I@%88_A=perT*JfLt<98k17gZ\saBX.+Z%V5fU&c'8f8=$p<SCu!+\6If=H[9=AZ[?Ja!0!uM(*_\fNK%R::Oi\UX8u5/AkicOh*-icNP5c#oH1UV%?&q^[;CN?$);>W?I6@`!LS5jeL=f.p;Ai,6c%/3%',!@\ZV[8Q2j]kBWlaoY.$[Ekp$E=#*r:If28mMcf%,jm&+JI\]9_U`og?e/UJ5kmKWN5CL9M]'AnqJ;^W=OUInfkiZ83qW4/s6/.#A8k5]'P`A"'YW%&M>,Gfn/sZ4!t32D`nAcr1C;b0Ce!#QX(BIK4=S56/3e*rt*C%fgM2#66^T"+V?e!OYBb8pXN=H:e=$9;3M)4+q0OY:M.S/M/NR]Ug"\f;e$>e-<LsMW2Al"'8`iVrMDqoE/iZUr),@Io'To@1k4$UE<n6X>7runPmtpndI^r,)1Ps`QKZTf!BNm1<<L%`.#D+5l^f=7D'TeJ.RmdTD^J/Ej@:JR(lZ?_pa_LR%:CAj,rjHKfYB>D$g]b.ke-ckthE)0!G''ojHXPk7K<$\[ilRGreh'ZO>g'HK_OTNJRQ;Cq'Cl:!%:ErhI\0/H8ZR'ZoFKHnZ@u9VQ52dU,8^K6Sldh[+_^5V0'Zf;#YB3n]#9B,+EI(1m%-+8Z7U#aeOY:%bHdCdN6A(70fAPn./F]'YD^eX^'o&29<4U71@E1sCtN>"M:(fa@b1]l=m9k:e^qbTaa)VLB5n/gI)QG>:`<_I'*:WJ"^+Pf1S]ck)ns*n5@9V)@q@r6.2W?[YAQ^q\(;9pJ9r<Hg&b5JZo+mK\12fR%s$%C*0(6,<,-hI"ZCK1;t@aJBL`"O*S%pZM2%jR2<W1dkr#0HKuj-M<nTGH%pff@rZnEC<+.4DOfk+FU[&"o*DS3BOMW`jS/t^sm,qIL1]lNsom`kO%E5EaUOCkQdJW:#AaBd*A"jiBdJ"Y%jfg?Ecr?K8=Jr^R[i@42aUB#PiYV33j>3Cp:_)3<)4#9)B5^[;Ha\hoAHnOC<bFB#+*>[8d"*?UDf#`kd+qc73FYAW7-7R,#%:cTnB1.EV+";.0L^g?K-5ct<l(]4]sWLK91#%SZ.%'A5XkCp;7s0TTO/QLZC$aOm27]<uMpm-CfO8C7r%$S0!b'pc,Hb+CAnIuh+<&EXFX;Q>5!0(c],g<ZdZ:#tjaQ,Q2An$@J2q!t)rp+=/H1&[3-+(,jX5O9YQ2WGRE(OH(QkNJ/8K6qa"DA;$jXHM83+(,Rp5GSXo]C2Xaci<SV92?M\]5u0b!,i[=*;olDYb6G=+$V<eF%gh,oE3=7\fZCNpZ)%-=,&)H@Jc`e5JTrDW#mfC$r?<F.O#H&!4/r/IZ3KKIXkRp*rt*C%fgM2#66^T"+V?e!Pf0C!8rT\!,t:i!4\^E!8Pp3!,h!*!&sNPJ/e=c^^^5Bi.c[\E'lhi\=juEgs?Q3DWh<*2tR3&)u9TN%K-:bL40,A6U(R\=]@V)s$SOs$gIub^C+Y/qmQZHZ_2d*q&a!f<R6_(]BQ9_#G*"@k/[,3<haPRe]ml*a51b.+3m)oimaC&"m=1%Vo?2f"i$TkIId.k4F[pdcDlo4Xi/%Q>;n7A<L;d?@jbn?=H`@V#HLm<BBN)7HhBn0<\@afn;Z[WIP$qX^)qB\f"6BUFN:2.UF/a)ZXE=/XS:RYZ!o!o<kSIho#rBfkK]TNkF[C[=]nn^0`>taX;;ci(Z0/pR#0:)c$O6Rihah3Z#n+B$g5j(3I1PDJOuDA+rfb$e-ZNY!G91A_d94i\GHFgNpW>n@)SF6Vp<AN1O%]'>0NK5`pB,X'?@kPOrPP['c,`0F`]l5^c\\,+7Ql<"?(!9f<+e_@ACk;QoKBV[-=rbQ9KH^CZA>`VY!OF(t1I3H2F:ugY5o,+(,<LIP;]l(Jj/p'%="1Y8:)kN?"KMDHpB!GUfMcN>n)XddSC^OqTmaDAH:1LY6!6I=-`tJB:s!DpXm]QJ/HY5\Q@KG$P`,p[(1!AakeTe/4]2W.2QGM;:527YM*CH+HsnYL!e64n]>@S]&@l`BtFYg,M.%?0?)gH7&@N9oiUPM$`]X3jal\(*;Q*mAa2BgFKr8!;!F(s$CBP;lI*q](ulRS$n,eh6pVd%NRXYU18rgmGlp-MN3Q&D;aUEk,`#F+4snNGqf2)0-G9];\1&N^lYdV-;C8([tpnOMrmm]RPkWd%1;UtEcZD'aJpj7kQdK+Q2UiZ08POuQd.6,0W8DNBGaH16UHADe?A'$m@i&aojBEpkQdK1Q2UhoCG1r'*Aq#E:N%>GYFiRZ4c9%3q<<"X?LFuAC)-"7k#G[uM-Q`p;EJZ"h;(4V4K7?!md?rpd4jsL9::+iG?<u5R"^g!+EeBsgd.WSFAf.s)J?'`1hsFn8u[oq,ke/AR$XKh2Kj6VM+l3:KV>1KF$L3FEg`/+LMbT($M=D*d2.IQLom5=]gO',11V)-%Ym%oVAr8k%.ukM^jN5T2T3V$km3PjR;UYZ)qojhJ2pU=*Es+k[Nm\=NiYtrZibtioi)r(4Zu'(:DJ\LPsl8\/:m!k?%HW#qO@Nczzzzzzzzzz!!!;nrrHe?D+=~>endstream
+endobj
+10 0 obj
+<< /BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font >>
+endobj
+11 0 obj
+<< /Annots [ 5 0 R 6 0 R 7 0 R ] /Contents 140 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] /XObject << /FormXob.12938940ef036783ae43d04dbfa3ae60 8 0 R >> >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+12 0 obj
+<< /BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font >>
+endobj
+13 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 11 0 R /XYZ 277.9078 281.6969 0 ] /Rect [ 334.6308 537.7736 377.2747 549.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+14 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 27 0 R /XYZ 62.69291 768.5236 0 ] /Rect [ 108.8329 465.7736 235.5429 477.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+15 0 obj
+<< /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font >>
+endobj
+16 0 obj
+<< /Annots [ 13 0 R 14 0 R ] /Contents 141 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+17 0 obj
+<< /Contents 142 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+18 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 16 0 R /XYZ 62.69291 211.0236 0 ] /Rect [ 142.7229 384.7736 259.9929 396.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+19 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 16 0 R /XYZ 62.69291 211.0236 0 ] /Rect [ 82.18163 217.5736 199.5091 229.5736 ] /Subtype /Link /Type /Annot >>
+endobj
+20 0 obj
+<< /Annots [ 18 0 R 19 0 R ] /Contents 143 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+21 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 80 0 R /XYZ 62.69291 768.0236 0 ] /Rect [ 146.4635 575.5736 165.8604 587.5736 ] /Subtype /Link /Type /Annot >>
+endobj
+22 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 80 0 R /XYZ 62.69291 267.4772 0 ] /Rect [ 494.7827 563.5736 530.6387 575.5736 ] /Subtype /Link /Type /Annot >>
+endobj
+23 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 27 0 R /XYZ 62.69291 293.8236 0 ] /Rect [ 374.5352 521.5736 415.7146 533.5736 ] /Subtype /Link /Type /Annot >>
+endobj
+24 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 27 0 R /XYZ 62.69291 293.8236 0 ] /Rect [ 359.0861 509.5736 400.3222 521.5736 ] /Subtype /Link /Type /Annot >>
+endobj
+25 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 27 0 R /XYZ 62.69291 293.8236 0 ] /Rect [ 452.5015 497.5736 494.2327 509.5736 ] /Subtype /Link /Type /Annot >>
+endobj
+26 0 obj
+<< /Annots [ 21 0 R 22 0 R 23 0 R 24 0 R 25 0 R ] /Contents 144 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+27 0 obj
+<< /Contents 145 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+28 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 55 0 R /XYZ 62.69291 364.9236 0 ] /Rect [ 158.3554 401.3736 185.741 413.3736 ] /Subtype /Link /Type /Annot >>
+endobj
+29 0 obj
+<< /Annots [ 28 0 R ] /Contents 146 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+30 0 obj
+<< /Contents 147 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+31 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 34 0 R /XYZ 62.69291 450.6236 0 ] /Rect [ 62.69291 741.7736 152.0372 753.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+32 0 obj
+<< /Annots [ 31 0 R ] /Contents 148 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+33 0 obj
+<< /BaseFont /Helvetica-BoldOblique /Encoding /WinAnsiEncoding /Name /F6 /Subtype /Type1 /Type /Font >>
+endobj
+34 0 obj
+<< /Contents 149 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+35 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 80 0 R /XYZ 62.69291 768.0236 0 ] /Rect [ 438.6533 132.1736 458.1057 144.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+36 0 obj
+<< /Annots [ 35 0 R ] /Contents 150 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+37 0 obj
+<< /Contents 151 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+38 0 obj
+<< /Contents 152 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+39 0 obj
+<< /Contents 153 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+40 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 62 0 R /XYZ 62.69291 290.0772 0 ] /Rect [ 316.1194 122.9736 367.0881 134.9736 ] /Subtype /Link /Type /Annot >>
+endobj
+41 0 obj
+<< /Annots [ 40 0 R ] /Contents 154 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+42 0 obj
+<< /Contents 155 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+43 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 60 0 R /XYZ 62.69291 591.0236 0 ] /Rect [ 85.69291 302.1736 532.5827 314.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+44 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 62 0 R /XYZ 62.69291 768.0236 0 ] /Rect [ 85.69291 284.1736 532.5827 296.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+45 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 62 0 R /XYZ 62.69291 290.0772 0 ] /Rect [ 85.69291 266.1736 532.5827 278.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+46 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 63 0 R /XYZ 62.69291 694.4772 0 ] /Rect [ 85.69291 248.1736 532.5827 260.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+47 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 63 0 R /XYZ 62.69291 451.9307 0 ] /Rect [ 85.69291 230.1736 532.5827 242.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+48 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 63 0 R /XYZ 62.69291 197.3843 0 ] /Rect [ 85.69291 212.1736 532.5827 224.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+49 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 66 0 R /XYZ 62.69291 318.2772 0 ] /Rect [ 85.69291 194.1736 532.5827 206.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+50 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 68 0 R /XYZ 62.69291 653.4772 0 ] /Rect [ 85.69291 176.1736 532.5827 188.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+51 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 68 0 R /XYZ 62.69291 343.9307 0 ] /Rect [ 85.69291 158.1736 532.5827 170.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+52 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 694.4772 0 ] /Rect [ 85.69291 140.1736 532.5827 152.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+53 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 204.5307 0 ] /Rect [ 85.69291 122.1736 532.5827 134.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+54 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 727.6772 0 ] /Rect [ 85.69291 104.1736 532.5827 116.1736 ] /Subtype /Link /Type /Annot >>
+endobj
+55 0 obj
+<< /Annots [ 43 0 R 44 0 R 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R
+ 53 0 R 54 0 R ] /Contents 156 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+56 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 74 0 R /XYZ 62.69291 715.6772 0 ] /Rect [ 85.69291 750.7736 532.5827 762.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+57 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 74 0 R /XYZ 62.69291 225.7307 0 ] /Rect [ 85.69291 732.7736 532.5827 744.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+58 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 80 0 R /XYZ 62.69291 768.0236 0 ] /Rect [ 85.69291 714.7736 532.5827 726.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+59 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 80 0 R /XYZ 62.69291 267.4772 0 ] /Rect [ 85.69291 696.7736 532.5827 708.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+60 0 obj
+<< /Annots [ 56 0 R 57 0 R 58 0 R 59 0 R ] /Contents 157 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+61 0 obj
+<< /A << /S /URI /Type /Action /URI (mailto:jane@example.com) >> /Border [ 0 0 0 ] /Rect [ 220.6129 102.8272 309.1229 114.8272 ] /Subtype /Link /Type /Annot >>
+endobj
+62 0 obj
+<< /Annots [ 61 0 R ] /Contents 158 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+63 0 obj
+<< /Contents 159 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+64 0 obj
+<< /A << /S /URI /Type /Action /URI (mailto:user@domain) >> /Border [ 0 0 0 ] /Rect [ 220.4912 582.7736 282.8812 594.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+65 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 63 0 R /XYZ 62.69291 197.3843 0 ] /Rect [ 487.4727 138.0272 520.9127 150.0272 ] /Subtype /Link /Type /Annot >>
+endobj
+66 0 obj
+<< /Annots [ 64 0 R 65 0 R ] /Contents 160 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+67 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 63 0 R /XYZ 62.69291 197.3843 0 ] /Rect [ 442.6147 492.2272 476.6807 504.2272 ] /Subtype /Link /Type /Annot >>
+endobj
+68 0 obj
+<< /Annots [ 67 0 R ] /Contents 161 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+69 0 obj
+<< /Contents 162 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+70 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 694.4772 0 ] /Rect [ 197.1929 753.7736 223.8629 765.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+71 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 69 0 R /XYZ 62.69291 694.4772 0 ] /Rect [ 401.1829 753.7736 427.8529 765.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+72 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 74 0 R /XYZ 62.69291 715.6772 0 ] /Rect [ 199.4129 107.4807 209.9729 119.4807 ] /Subtype /Link /Type /Annot >>
+endobj
+73 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 74 0 R /XYZ 62.69291 715.6772 0 ] /Rect [ 410.0829 107.4807 420.6429 119.4807 ] /Subtype /Link /Type /Annot >>
+endobj
+74 0 obj
+<< /Annots [ 70 0 R 71 0 R 72 0 R 73 0 R ] /Contents 163 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+75 0 obj
+<< /Contents 164 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+76 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 74 0 R /XYZ 62.69291 715.6772 0 ] /Rect [ 177.2584 637.7736 188.2523 649.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+77 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 727.6772 0 ] /Rect [ 200.3562 637.7736 242.47 649.7736 ] /Subtype /Link /Type /Annot >>
+endobj
+78 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 74 0 R /XYZ 62.69291 715.6772 0 ] /Rect [ 177.2584 138.2272 188.2523 150.2272 ] /Subtype /Link /Type /Annot >>
+endobj
+79 0 obj
+<< /Border [ 0 0 0 ] /Contents () /Dest [ 75 0 R /XYZ 62.69291 727.6772 0 ] /Rect [ 200.3562 138.2272 242.47 150.2272 ] /Subtype /Link /Type /Annot >>
+endobj
+80 0 obj
+<< /Annots [ 76 0 R 77 0 R 78 0 R 79 0 R ] /Contents 165 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0
+ /Trans << >> /Type /Page >>
+endobj
+81 0 obj
+<< /Contents 166 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 138 0 R /Resources << /Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ] >> /Rotate 0 /Trans << >>
+ /Type /Page >>
+endobj
+82 0 obj
+<< /Outlines 84 0 R /PageLabels 167 0 R /PageMode /UseNone /Pages 138 0 R /Type /Catalog >>
+endobj
+83 0 obj
+<< /Author () /CreationDate (D:20141102111551+05'00') /Creator (\(unspecified\)) /Keywords () /Producer (ReportLab PDF Library - www.reportlab.com) /Subject (\(unspecified\))
+ /Title () >>
+endobj
+84 0 obj
+<< /Count 73 /First 85 0 R /Last 107 0 R /Type /Outlines >>
+endobj
+85 0 obj
+<< /Count 3 /Dest [ 4 0 R /XYZ 62.69291 765.0236 0 ] /First 86 0 R /Last 88 0 R /Next 89 0 R /Parent 84 0 R
+ /Title (Introduction) >>
+endobj
+86 0 obj
+<< /Dest [ 11 0 R /XYZ 62.69291 681.0236 0 ] /Next 87 0 R /Parent 85 0 R /Title (Implementation Status) >>
+endobj
+87 0 obj
+<< /Dest [ 11 0 R /XYZ 62.69291 555.0236 0 ] /Next 88 0 R /Parent 85 0 R /Prev 86 0 R /Title (General Data Flow) >>
+endobj
+88 0 obj
+<< /Dest [ 16 0 R /XYZ 62.69291 597.0236 0 ] /Parent 85 0 R /Prev 87 0 R /Title (Example Assertion Transformation) >>
+endobj
+89 0 obj
+<< /Count 1 /Dest [ 26 0 R /XYZ 62.69291 715.8236 0 ] /First 90 0 R /Last 90 0 R /Next 91 0 R /Parent 84 0 R
+ /Prev 85 0 R /Title (Operation Model) >>
+endobj
+90 0 obj
+<< /Dest [ 26 0 R /XYZ 62.69291 454.8236 0 ] /Parent 89 0 R /Title (Pseudo Code Illustrating Operational Model) >>
+endobj
+91 0 obj
+<< /Count 7 /Dest [ 27 0 R /XYZ 62.69291 765.0236 0 ] /First 92 0 R /Last 98 0 R /Next 99 0 R /Parent 84 0 R
+ /Prev 89 0 R /Title (Structure Of Rule Definitions) >>
+endobj
+92 0 obj
+<< /Dest [ 27 0 R /XYZ 62.69291 290.8236 0 ] /Next 93 0 R /Parent 91 0 R /Title (Mapping) >>
+endobj
+93 0 obj
+<< /Dest [ 29 0 R /XYZ 62.69291 478.6236 0 ] /Next 94 0 R /Parent 91 0 R /Prev 92 0 R /Title (Syntax) >>
+endobj
+94 0 obj
+<< /Dest [ 30 0 R /XYZ 62.69291 485.8236 0 ] /Next 95 0 R /Parent 91 0 R /Prev 93 0 R /Title (Data Types) >>
+endobj
+95 0 obj
+<< /Dest [ 30 0 R /XYZ 62.69291 191.8236 0 ] /Next 96 0 R /Parent 91 0 R /Prev 94 0 R /Title (Rule Debugging and Documentation) >>
+endobj
+96 0 obj
+<< /Count 1 /Dest [ 32 0 R /XYZ 62.69291 257.8236 0 ] /First 97 0 R /Last 97 0 R /Next 98 0 R /Parent 91 0 R
+ /Prev 95 0 R /Title (Variables) >>
+endobj
+97 0 obj
+<< /Dest [ 34 0 R /XYZ 62.69291 528.6236 0 ] /Parent 96 0 R /Title (Escaping) >>
+endobj
+98 0 obj
+<< /Dest [ 34 0 R /XYZ 62.69291 447.6236 0 ] /Parent 91 0 R /Prev 96 0 R /Title (Reserved Variables) >>
+endobj
+99 0 obj
+<< /Count 6 /Dest [ 36 0 R /XYZ 62.69291 765.0236 0 ] /First 100 0 R /Last 105 0 R /Next 106 0 R /Parent 84 0 R
+ /Prev 91 0 R /Title (Examples) >>
+endobj
+100 0 obj
+<< /Dest [ 36 0 R /XYZ 62.69291 732.0236 0 ] /Next 101 0 R /Parent 99 0 R /Title (Split a fully qualified username into user and realm components) >>
+endobj
+101 0 obj
+<< /Dest [ 37 0 R /XYZ 62.69291 691.8236 0 ] /Next 102 0 R /Parent 99 0 R /Prev 100 0 R /Title (Build a set of roles based on group membership) >>
+endobj
+102 0 obj
+<< /Dest [ 38 0 R /XYZ 62.69291 193.4236 0 ] /Next 103 0 R /Parent 99 0 R /Prev 101 0 R /Title (White list certain users and grant them specific roles) >>
+endobj
+103 0 obj
+<< /Dest [ 41 0 R /XYZ 62.69291 765.0236 0 ] /Next 104 0 R /Parent 99 0 R /Prev 102 0 R /Title (Black list certain users) >>
+endobj
+104 0 obj
+<< /Dest [ 41 0 R /XYZ 62.69291 158.2236 0 ] /Next 105 0 R /Parent 99 0 R /Prev 103 0 R /Title (Format Strings and/or Concatenate Strings) >>
+endobj
+105 0 obj
+<< /Dest [ 42 0 R /XYZ 62.69291 225.0236 0 ] /Parent 99 0 R /Prev 104 0 R /Title (Make associative array lookups case insensitive) >>
+endobj
+106 0 obj
+<< /Dest [ 55 0 R /XYZ 62.69291 361.4236 0 ] /Next 107 0 R /Parent 84 0 R /Prev 99 0 R /Title (Verbs) >>
+endobj
+107 0 obj
+<< /Count 30 /Dest [ 60 0 R /XYZ 62.69291 621.0236 0 ] /First 108 0 R /Last 136 0 R /Parent 84 0 R /Prev 106 0 R
+ /Title (Verb Definitions) >>
+endobj
+108 0 obj
+<< /Count 1 /Dest [ 60 0 R /XYZ 62.69291 588.0236 0 ] /First 109 0 R /Last 109 0 R /Next 110 0 R /Parent 107 0 R
+ /Title (set) >>
+endobj
+109 0 obj
+<< /Dest [ 60 0 R /XYZ 62.69291 460.0236 0 ] /Parent 108 0 R /Title (Examples:) >>
+endobj
+110 0 obj
+<< /Count 1 /Dest [ 62 0 R /XYZ 62.69291 765.0236 0 ] /First 111 0 R /Last 111 0 R /Next 112 0 R /Parent 107 0 R
+ /Prev 108 0 R /Title (length) >>
+endobj
+111 0 obj
+<< /Dest [ 62 0 R /XYZ 62.69291 544.0236 0 ] /Parent 110 0 R /Title (Examples:) >>
+endobj
+112 0 obj
+<< /Count 1 /Dest [ 62 0 R /XYZ 62.69291 287.0772 0 ] /First 113 0 R /Last 113 0 R /Next 114 0 R /Parent 107 0 R
+ /Prev 110 0 R /Title (interpolate) >>
+endobj
+113 0 obj
+<< /Dest [ 62 0 R /XYZ 62.69291 147.0772 0 ] /Parent 112 0 R /Title (Examples:) >>
+endobj
+114 0 obj
+<< /Count 1 /Dest [ 63 0 R /XYZ 62.69291 691.4772 0 ] /First 115 0 R /Last 115 0 R /Next 116 0 R /Parent 107 0 R
+ /Prev 112 0 R /Title (append) >>
+endobj
+115 0 obj
+<< /Dest [ 63 0 R /XYZ 62.69291 563.4772 0 ] /Parent 114 0 R /Title (Examples:) >>
+endobj
+116 0 obj
+<< /Count 1 /Dest [ 63 0 R /XYZ 62.69291 448.9307 0 ] /First 117 0 R /Last 117 0 R /Next 118 0 R /Parent 107 0 R
+ /Prev 114 0 R /Title (unique) >>
+endobj
+117 0 obj
+<< /Dest [ 63 0 R /XYZ 62.69291 308.9307 0 ] /Parent 116 0 R /Title (Examples:) >>
+endobj
+118 0 obj
+<< /Count 1 /Dest [ 63 0 R /XYZ 62.69291 194.3843 0 ] /First 119 0 R /Last 119 0 R /Next 120 0 R /Parent 107 0 R
+ /Prev 116 0 R /Title (regexp) >>
+endobj
+119 0 obj
+<< /Dest [ 66 0 R /XYZ 62.69291 615.0236 0 ] /Parent 118 0 R /Title (Examples:) >>
+endobj
+120 0 obj
+<< /Count 1 /Dest [ 66 0 R /XYZ 62.69291 315.2772 0 ] /First 121 0 R /Last 121 0 R /Next 122 0 R /Parent 107 0 R
+ /Prev 118 0 R /Title (regexp_replace) >>
+endobj
+121 0 obj
+<< /Dest [ 68 0 R /XYZ 62.69291 765.0236 0 ] /Parent 120 0 R /Title (Examples:) >>
+endobj
+122 0 obj
+<< /Count 1 /Dest [ 68 0 R /XYZ 62.69291 650.4772 0 ] /First 123 0 R /Last 123 0 R /Next 124 0 R /Parent 107 0 R
+ /Prev 120 0 R /Title (split) >>
+endobj
+123 0 obj
+<< /Dest [ 68 0 R /XYZ 62.69291 467.4772 0 ] /Parent 122 0 R /Title (Examples:) >>
+endobj
+124 0 obj
+<< /Count 1 /Dest [ 68 0 R /XYZ 62.69291 340.9307 0 ] /First 125 0 R /Last 125 0 R /Next 126 0 R /Parent 107 0 R
+ /Prev 122 0 R /Title (join) >>
+endobj
+125 0 obj
+<< /Dest [ 68 0 R /XYZ 62.69291 169.9307 0 ] /Parent 124 0 R /Title (Examples:) >>
+endobj
+126 0 obj
+<< /Count 1 /Dest [ 69 0 R /XYZ 62.69291 691.4772 0 ] /First 127 0 R /Last 127 0 R /Next 128 0 R /Parent 107 0 R
+ /Prev 124 0 R /Title (lower) >>
+endobj
+127 0 obj
+<< /Dest [ 69 0 R /XYZ 62.69291 446.4772 0 ] /Parent 126 0 R /Title (Examples:) >>
+endobj
+128 0 obj
+<< /Dest [ 69 0 R /XYZ 62.69291 201.5307 0 ] /Next 129 0 R /Parent 107 0 R /Prev 126 0 R /Title (upper) >>
+endobj
+129 0 obj
+<< /Count 1 /Dest [ 74 0 R /XYZ 62.69291 712.6772 0 ] /First 130 0 R /Last 130 0 R /Next 131 0 R /Parent 107 0 R
+ /Prev 128 0 R /Title (in) >>
+endobj
+130 0 obj
+<< /Dest [ 74 0 R /XYZ 62.69291 479.6772 0 ] /Parent 129 0 R /Title (Examples:) >>
+endobj
+131 0 obj
+<< /Dest [ 74 0 R /XYZ 62.69291 222.7307 0 ] /Next 132 0 R /Parent 107 0 R /Prev 129 0 R /Title (not_in) >>
+endobj
+132 0 obj
+<< /Count 1 /Dest [ 75 0 R /XYZ 62.69291 724.6772 0 ] /First 133 0 R /Last 133 0 R /Next 134 0 R /Parent 107 0 R
+ /Prev 131 0 R /Title (compare) >>
+endobj
+133 0 obj
+<< /Dest [ 75 0 R /XYZ 62.69291 235.6772 0 ] /Parent 132 0 R /Title (Examples:) >>
+endobj
+134 0 obj
+<< /Count 1 /Dest [ 80 0 R /XYZ 62.69291 765.0236 0 ] /First 135 0 R /Last 135 0 R /Next 136 0 R /Parent 107 0 R
+ /Prev 132 0 R /Title (exit) >>
+endobj
+135 0 obj
+<< /Dest [ 80 0 R /XYZ 62.69291 391.0236 0 ] /Parent 134 0 R /Title (Examples:) >>
+endobj
+136 0 obj
+<< /Count 1 /Dest [ 80 0 R /XYZ 62.69291 264.4772 0 ] /First 137 0 R /Last 137 0 R /Parent 107 0 R /Prev 134 0 R
+ /Title (continue) >>
+endobj
+137 0 obj
+<< /Dest [ 81 0 R /XYZ 62.69291 621.0236 0 ] /Parent 136 0 R /Title (Examples:) >>
+endobj
+138 0 obj
+<< /Count 28 /Kids [ 4 0 R 11 0 R 16 0 R 17 0 R 20 0 R 26 0 R 27 0 R 29 0 R 30 0 R 32 0 R
+ 34 0 R 36 0 R 37 0 R 38 0 R 39 0 R 41 0 R 42 0 R 55 0 R 60 0 R 62 0 R
+ 63 0 R 66 0 R 68 0 R 69 0 R 74 0 R 75 0 R 80 0 R 81 0 R ] /Type /Pages >>
+endobj
+139 0 obj
+<< /Length 9118 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 744.0236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Introduction) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 666.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 62 Tm /F1 10 Tf 12 TL 3.09832 Tw (A need shared by many applications is the ability to authenticate a user and then bind a set of) Tj T* 0 Tw .363735 Tw (permissions to the user which indicate what actions the user is permitted to perform \(i.e. authorization\). A) Tj T* 0 Tw .317126 Tw (LocalSystem may have implemented it's own authentication and authorization and now wishes to utilize a) Tj T* 0 Tw 1.045366 Tw (federated Identity Provider \(IdP\). Typically the IdP provides an assertion with information describing the) Tj T* 0 Tw 1.041235 Tw (authenticated user. The goal is to transform the IdP assertion into a LocalSystem token. In it's simplest) Tj T* 0 Tw (terms this is a data transformation which might include:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 660.0236 cm
+Q
+q
+1 0 0 1 62.69291 660.0236 cm
+Q
+q
+1 0 0 1 62.69291 648.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (renaming of data items) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 642.0236 cm
+Q
+q
+1 0 0 1 62.69291 630.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (conversion to a different format) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 624.0236 cm
+Q
+q
+1 0 0 1 62.69291 612.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (deletion of data) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 606.0236 cm
+Q
+q
+1 0 0 1 62.69291 594.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (addition of data) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 588.0236 cm
+Q
+q
+1 0 0 1 62.69291 576.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (reorganization of data) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 576.0236 cm
+Q
+q
+1 0 0 1 62.69291 558.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (There are many ways such a transformation could be implemented:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 552.0236 cm
+Q
+q
+1 0 0 1 62.69291 552.0236 cm
+Q
+q
+1 0 0 1 62.69291 540.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Custom site specific code) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 534.0236 cm
+Q
+q
+1 0 0 1 62.69291 522.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Scripts written in a scripting language) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 516.0236 cm
+Q
+q
+1 0 0 1 62.69291 504.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (XSLT) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 498.0236 cm
+Q
+q
+1 0 0 1 62.69291 486.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Rule based transforms) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 486.0236 cm
+Q
+q
+1 0 0 1 62.69291 468.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (We also desire these goals for the transformation.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 462.0236 cm
+Q
+q
+1 0 0 1 62.69291 462.0236 cm
+Q
+q
+1 0 0 1 62.69291 450.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Site administrator configurable) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 444.0236 cm
+Q
+q
+1 0 0 1 62.69291 432.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Secure) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 426.0236 cm
+Q
+q
+1 0 0 1 62.69291 414.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Simple) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 408.0236 cm
+Q
+q
+1 0 0 1 62.69291 396.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Extensible) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 390.0236 cm
+Q
+q
+1 0 0 1 62.69291 378.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (5.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Efficient) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 378.0236 cm
+Q
+q
+1 0 0 1 62.69291 348.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.294987 Tw (Implementation choice 1, custom written code fails goals 1, 3 and 4, an admin cannot adapt it, it's not) Tj T* 0 Tw (simple, and it's likely to be difficult to extend.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 234.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 98 Tm /F1 10 Tf 12 TL 1.607318 Tw (Implementation choice 2, script based transformations have a lot of appeal. Because one has at their) Tj T* 0 Tw 2.25811 Tw (disposal the full power of an actual programming language there are virtually no limitations. If it's a) Tj T* 0 Tw 1.021235 Tw (popular scripting language an administrator is likely to already know the language and might be able to) Tj T* 0 Tw .343516 Tw (program a new transformation or at a minimum tweak an existing script. Forking out to a script interpreter) Tj T* 0 Tw 2.779983 Tw (is inefficient, but it's now possible to embed script interpreters in the existing application. However) Tj T* 0 Tw .01436 Tw (sandboxing the execution of a script such that it cannot perform malicious operations is difficult. One could) Tj T* 0 Tw 2.200651 Tw (run a separate script process to provide sandboxing but this introduces the vagaries of managing a) Tj T* 0 Tw .257126 Tw (subordinate process and inter-process communication. Therefore scripts either fail goals 1 or 5, secure or) Tj T* 0 Tw (efficient \(depending on whether the interpreter is embedded or not\).) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 204.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 2.236098 Tw (Implementation choice 3, XSLT fails goals 3 and 4, it is not simple, it may not have the necessary) Tj T* 0 Tw (features, and extending XSLT is difficult.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 138.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F1 10 Tf 12 TL .492126 Tw (Implementation choice 4, rules based transformations offers the best combination of features to meet the) Tj T* 0 Tw 1.12784 Tw (goals. Site administrators can understand rules and edit them. There are no sandboxing concerns, rule) Tj T* 0 Tw .633516 Tw (evaluation can be crafted to be secure. With careful design the rule syntax can easily be extended. Rule) Tj T* 0 Tw .775984 Tw (execution should be efficient because it's implemented in a native library loaded into the application and) Tj T* 0 Tw (does not depend on forking out to a separate process or using inter-process communication.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 96.02362 cm
+q
+BT 1 0 0 1 0 26 Tm .044431 Tw 12 TL /F1 10 Tf 0 0 0 rg (We describe a rule based system which offers much of the power and flexibility of a scripting language but ) Tj T* 0 Tw .69561 Tw (without it's downsides. The rules are written much like a scripting language where you can call functions ) Tj T* 0 Tw 1.681751 Tw (\(e.g. verbs\) and perform simple branching logic based on the result of a prior verb. Variables can be) Tj T* 0 Tw ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-1-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+140 0 obj
+<< /Length 5289 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 693.0236 cm
+q
+BT 1 0 0 1 0 62 Tm .682651 Tw 12 TL /F1 10 Tf 0 0 0 rg (assigned and referenced. As described in the ) Tj 0 0 .501961 rg (Variables ) Tj 0 0 0 rg (section a variable may be scalar, an associative) Tj T* 0 Tw .813735 Tw (array \(key/value\), or an indexed array \(ordered list\). A number of different data types are supported and) Tj T* 0 Tw .655777 Tw (are described in the ) Tj 0 0 .501961 rg (Data Types ) Tj 0 0 0 rg (section. Because the rules are written in JSON it should be easy for an) Tj T* 0 Tw .348651 Tw (administrator to understand and JSON provides the ability load site specific hardcoded data the rules can) Tj T* 0 Tw 1.552927 Tw (utilize. For example white lists, black lists, valid groups, invalid groups, etc. are all easy to express in) Tj T* 0 Tw (JSON.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 663.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Implementation Status) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 633.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 4.236647 Tw (The Mapping Rule Processor described in this document currently has implmentations in these) Tj T* 0 Tw (languages:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 627.0236 cm
+Q
+q
+1 0 0 1 62.69291 627.0236 cm
+Q
+q
+1 0 0 1 62.69291 615.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Java) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 609.0236 cm
+Q
+q
+1 0 0 1 62.69291 597.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Python) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 597.0236 cm
+Q
+q
+1 0 0 1 62.69291 567.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.52686 Tw (An application simply needs to load the implementation and invoke it's entry points. It is expected the) Tj T* 0 Tw (rules will reside in site specific configuration files.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 537.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (General Data Flow) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 495.0236 cm
+q
+BT 1 0 0 1 0 26 Tm .18686 Tw 12 TL /F1 10 Tf 0 0 .501961 rg (Figure 1. ) Tj 0 0 0 rg (illustrates the processing inside the application when it needs to authenticate a user and provide) Tj T* 0 Tw 4.125984 Tw (a LocalSystem token identifying the user, providing attributes bound to the user, and a set of) Tj T* 0 Tw (authorizations for the actions the user is permitted to perform \(e.g. roles\).) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 489.0236 cm
+Q
+q
+1 0 0 1 62.69291 264.6969 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 21 cm
+q
+457.8898 0 0 200.3268 0 0 cm
+/FormXob.12938940ef036783ae43d04dbfa3ae60 Do
+Q
+Q
+q
+1 0 0 1 6 3 cm
+q
+BT 1 0 0 1 0 2 Tm 209.2149 0 Td 12 TL /F3 10 Tf 0 0 0 rg (Figure 1.) Tj T* -209.2149 0 Td ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 264.6969 cm
+Q
+q
+1 0 0 1 62.69291 258.6969 cm
+Q
+q
+1 0 0 1 62.69291 231.6969 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 15 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 39.69937 0 Td (Step 1:) Tj T* -39.69937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 2.352533 Tw (A federated Identity Provider \(IdP\) is asked to authenticate a user and provide) Tj T* 0 Tw (additional information \(attributes\) concerning the user.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 192.6969 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 27 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 39.69937 0 Td (Step 2:) Tj T* -39.69937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 1.860036 Tw (Upon successful authentication the IdP provides an assertion for the user which) Tj T* 0 Tw 5.492039 Tw (also contains extra information \(attributes\) bound to the user \(e.g. group) Tj T* 0 Tw (membership, authorizations, etc.\)) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 99.69685 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 81 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 39.69937 0 Td (Step 3:) Tj T* -39.69937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 4.068366 Tw (The mapper is invoked to transform the external IdP assertion into a local) Tj T* 0 Tw 3.138933 Tw (representation. The transformation occurs according to the rules and mapping) Tj T* 0 Tw (templates loaded into the rule processor.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .292338 Tw (The Mapping Rule Processor is designed to accept a JSON object \(set of key/value) Tj T* 0 Tw .707171 Tw (pairs\) as input and emit a different JSON object as output. Thus the Mappgin Rule) Tj T* 0 Tw 1.381039 Tw (Processor effectively operates as a transformation engine on key/value pairs with) Tj T* 0 Tw (the ability to add or delete key/value pairs.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-2-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+141 0 obj
+<< /Length 7582 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 726.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 27 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 31.35937 0 Td (Step 3.1:) Tj T* -31.35937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 2.0186 Tw (The input assertion is rewritten as a JSON object in the format required by the) Tj T* 0 Tw .039199 Tw (Mapping Rule Processor. The JSON assertion is then passed into the Mapping Rule) Tj T* 0 Tw (Processor.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 651.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 63 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 31.35937 0 Td (Step 3.2:) Tj T* -31.35937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 62 Tm 1.105039 Tw 12 TL /F1 10 Tf 0 0 0 rg (The Mapping Rule Processor identified as ) Tj /F4 10 Tf 0 0 0 rg (IdPMapper ) Tj /F1 10 Tf 0 0 0 rg (evaluates the input JSON) Tj T* 0 Tw 2.00003 Tw (assertion in the context of the mapping rules defined for the site deployment. If) Tj T* 0 Tw .971569 Tw /F4 10 Tf 0 0 0 rg (IdPMapper ) Tj /F1 10 Tf 0 0 0 rg (is able to successfully transform the input it will return a JSON object) Tj T* 0 Tw .152885 Tw (which is called the ) Tj /F3 10 Tf (mapped ) Tj /F1 10 Tf (result. If the input JSON assertion is not compatible with) Tj T* 0 Tw 1.618492 Tw (the site specific rules loaded into the ) Tj /F4 10 Tf 0 0 0 rg (IdPMapper ) Tj /F1 10 Tf 0 0 0 rg (then NULL is returned by the) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg (IdPMapper) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 624.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 15 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 31.35937 0 Td (Step 3.3:) Tj T* -31.35937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 14 Tm 1.272039 Tw 12 TL /F1 10 Tf 0 0 0 rg (If the mapping was successful the ) Tj /F4 10 Tf 0 0 0 rg (IdPMapper ) Tj /F1 10 Tf 0 0 0 rg (returns the transformed assertion) Tj T* 0 Tw (as a JSON object.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 609.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 39.69937 0 Td (Step 4:) Tj T* -39.69937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapped JSON object is converted for use in the local system.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 579.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Example Assertion Transformation) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 465.0236 cm
+q
+BT 1 0 0 1 0 98 Tm .382209 Tw 12 TL /F1 10 Tf 0 0 0 rg (A federated IdP supplies metadata in a form unique to the IdP. This is called an assertion. That assertion) Tj T* 0 Tw .652126 Tw (must be transformed into a format and data understood by LocalSystem. More importantly that assertion) Tj T* 0 Tw .201984 Tw (needs to yield ) Tj /F3 10 Tf (authorization roles specific to LocalSystem) Tj /F1 10 Tf (. In ) Tj 0 0 .501961 rg (Figure 1. ) Tj 0 0 0 rg (Step 3.2 the ) Tj /F4 10 Tf 0 0 0 rg (IdPMapper ) Tj /F1 10 Tf 0 0 0 rg (provides) Tj T* 0 Tw 2.02936 Tw (the transformation from an external IdP assertion to a LocalSystem specific token. It does this via a) Tj T* 0 Tw 1.726412 Tw (Mapping Rule Processor which reads a site specific set of transformation rules. These mapping rules) Tj T* 0 Tw .50061 Tw (define how to transform the external IdP assertion into a LocalSystem token. The mapping rules also are) Tj T* 0 Tw 1.578735 Tw (responsible for validating the external IdP assertion to make sure it is consistent with the site specific) Tj T* 0 Tw 1.719318 Tw (requirements. The operation of the Mapping Rule Processor and the syntax of the mapping rules are) Tj T* 0 Tw (defined in ) Tj 0 0 .501961 rg (Structure Of Rule Definitions) Tj 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 423.0236 cm
+q
+BT 1 0 0 1 0 26 Tm .700574 Tw 12 TL /F1 10 Tf 0 0 0 rg (Below is an example mapping rule which might be loaded into the Mapping Rule Processor to support a) Tj T* 0 Tw 2.347674 Tw (fictional FOOBAR application. The IdP provides assertions using the ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER ) Tj /F1 10 Tf 0 0 0 rg (CGI style. It is) Tj T* 0 Tw (assumed there are two LocalSystem roles which may be assigned:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 407.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F5 10 Tf 12 TL (user) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 392.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (A role granting standard permissions for normal FOOBAR users.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 376.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F5 10 Tf 12 TL (admin) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 361.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (A special role granting full FOOBAR administrative permissions.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 331.0236 cm
+q
+BT 1 0 0 1 0 14 Tm .087633 Tw 12 TL /F1 10 Tf 0 0 0 rg (In this example assigning the ) Tj /F4 10 Tf 0 0 0 rg (user ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (admin ) Tj /F1 10 Tf 0 0 0 rg (roles will be based on group membership in the following) Tj T* 0 Tw (groups:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 315.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F5 10 Tf 12 TL (foobar_users) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 300.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Members of this group are normal FOOBAR users with restricted permissions.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 284.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F5 10 Tf 12 TL (foobar_admin) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 269.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Members of this group are FOOBAR administrators with permission to perform all operations.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 215.0236 cm
+q
+BT 1 0 0 1 0 38 Tm 4.288443 Tw 12 TL /F1 10 Tf 0 0 0 rg (Granting of the ) Tj /F4 10 Tf 0 0 0 rg (user ) Tj /F1 10 Tf 0 0 0 rg (and/or ) Tj /F4 10 Tf 0 0 0 rg (admin ) Tj /F1 10 Tf 0 0 0 rg (roles based on membership in the ) Tj /F4 10 Tf 0 0 0 rg (foobar_users ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw 1.387126 Tw /F4 10 Tf 0 0 0 rg (foobar_admin ) Tj /F1 10 Tf 0 0 0 rg (is illustrated in the follow mapping rule example which also extracts the user principal) Tj T* 0 Tw .275984 Tw (and domain information in the preferred format for the site \(e.g. usernames are lowercase without domain) Tj T* 0 Tw (suffixes and the domain is uppercase and supplied separately\).) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 197.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Mapping Rule Example 1.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 91.82362 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 96 re B*
+Q
+q
+BT 1 0 0 1 0 74 Tm 12 TL /F4 10 Tf 0 0 0 rg (1 [) Tj T* (2 {"mapping": {"ClientId": "$client_id",) Tj T* (3 "UserId": "$user_id",) Tj T* (4 "User": "$username",) Tj T* (5 "Domain": "$domain",) Tj T* (6 "roles": "$roles",) Tj T* (7 },) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-3-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+142 0 obj
+<< /Length 5287 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 307.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 516 456 re B*
+Q
+q
+BT 1 0 0 1 0 434 Tm 12 TL /F4 10 Tf 0 0 0 rg (8 "statement_blocks": [) Tj T* (9 [) Tj T* (10 ["set", "$groups", []],) Tj T* (11 ["set", "$roles", []]) Tj T* (12 ],) Tj T* (13 [) Tj T* (14 ["in", "REMOTE_USER", "$assertion"],) Tj T* (15 ["exit", "rule_fails", "if_not_success"],) Tj T* (16 ["regexp", "$assertion[REMOTE_USER]", "\(?) Tj (<) Tj (username) Tj (>) Tj (\\\\w+\)@\(?) Tj (<) Tj (domain) Tj (>) Tj (.+\)"],) Tj T* (17 ["exit", "rule_fails", "if_not_success"],) Tj T* (18 ["lower", "$username", "$regexp_map[username]"],) Tj T* (19 ["upper", "$domain", "$regexp_map[domain]"],) Tj T* (20 ],) Tj T* (21 [) Tj T* (22 ["in", "REMOTE_USER_GROUPS", "$assertion"],) Tj T* (23 ["exit", "rule_fails", "if_not_success"],) Tj T* (24 ["split", "$groups", "$assertion[REMOTE_USER_GROUPS]", ":"],) Tj T* (25 ],) Tj T* (26 [) Tj T* (27 ["in", "foobar_users", "$groups"],) Tj T* (28 ["continue", "if_not_success"],) Tj T* (29 ["append", "$roles", "user"],) Tj T* (30 ],) Tj T* (31 [) Tj T* (32 ["in", "foobar_admin", "$groups"],) Tj T* (33 ["continue", "if_not_success"],) Tj T* (34 ["append", "$roles", "admin"]) Tj T* (35 ],) Tj T* (36 [) Tj T* (37 ["unique", "$roles", "$roles"],) Tj T* (38 ["length", "$n_roles", "$roles"],) Tj T* (39 ["compare", "$n_roles", ") Tj (>) Tj (", 0],) Tj T* (40 ["exit", "rule_fails", "if_not_success"],) Tj T* (41 ],) Tj T* (42 ]) Tj T* (43 }) Tj T* (44 ]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 293.8236 cm
+Q
+q
+1 0 0 1 62.69291 230.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 51 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 40.80937 0 Td (Line 1:) Tj T* -40.80937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 50 Tm 1.466494 Tw 12 TL /F1 10 Tf 0 0 0 rg (Starts a list of rules. In this example only 1 rule is defined. Each rule is a JSON) Tj T* 0 Tw 2.652039 Tw (object containing a ) Tj /F4 10 Tf 0 0 0 rg (mapping ) Tj /F1 10 Tf 0 0 0 rg (and a required list of ) Tj /F4 10 Tf 0 0 0 rg (statement_blocks) Tj /F1 10 Tf 0 0 0 rg (. The) Tj T* 0 Tw .21815 Tw /F4 10 Tf 0 0 0 rg (mapping ) Tj /F1 10 Tf 0 0 0 rg (may either be specified inside a rule as it is here or may be referenced by) Tj T* 0 Tw .190023 Tw (name in a table of mappings \(this is easier to manage if you have a large number of) Tj T* 0 Tw (rules and small number of mappings\).) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 179.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 26.35937 0 Td (Lines 2-7:) Tj T* -26.35937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 38 Tm .409199 Tw 12 TL /F1 10 Tf 0 0 0 rg (Defines the JSON mapped result. Each key maps to LocalSystem token. The value) Tj T* 0 Tw 2.0586 Tw (is a rule variable whose value will be substituted if the rule succeeds. Thus for) Tj T* 0 Tw 1.521699 Tw (example the LocalSystem token value ) Tj /F4 10 Tf 0 0 0 rg (User ) Tj /F1 10 Tf 0 0 0 rg (will be assigned the value from the) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg ($username ) Tj /F1 10 Tf 0 0 0 rg (rule variable.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 164.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 40.80937 0 Td (Line 8:) Tj T* -40.80937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Begins the list of statement blocks. A statement must be contained inside a block.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 125.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 27 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 20.79937 0 Td (Lines 9-12:) Tj T* -20.79937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 26 Tm 2.080033 Tw 12 TL /F1 10 Tf 0 0 0 rg (The first block usually initializes variables that will be referenced later. Here we) Tj T* 0 Tw .854581 Tw (initialize ) Tj /F4 10 Tf 0 0 0 rg ($groups ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg ($roles ) Tj /F1 10 Tf 0 0 0 rg (to empty arrays. These arrays may be appended) Tj T* 0 Tw (to in later blocks and may be referenced in the final ) Tj /F4 10 Tf 0 0 0 rg (mapping ) Tj /F1 10 Tf 0 0 0 rg (output.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 98.82362 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 15 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 13-20:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 14 Tm .151699 Tw 12 TL /F1 10 Tf 0 0 0 rg (This block sets the user and domain information based on ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER ) Tj /F1 10 Tf 0 0 0 rg (and exits) Tj T* 0 Tw (the rule if ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER ) Tj /F1 10 Tf 0 0 0 rg (is not defined.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-4-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+143 0 obj
+<< /Length 8284 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 738.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 15 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 14-15:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 14 Tm .965028 Tw 12 TL /F1 10 Tf 0 0 0 rg (This test is critical, it assures ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER ) Tj /F1 10 Tf 0 0 0 rg (is defined in the assertion, if not the) Tj T* 0 Tw (rule is skipped because we depend on ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 687.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 16-17:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 38 Tm .629039 Tw 12 TL /F1 10 Tf 0 0 0 rg (Performs a regular expression match against ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER ) Tj /F1 10 Tf 0 0 0 rg (to split the username) Tj T* 0 Tw 2.770945 Tw (from the domain. The regular expression uses named groups, in this instance) Tj T* 0 Tw 3.041699 Tw /F4 10 Tf 0 0 0 rg (username ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (domain) Tj /F1 10 Tf 0 0 0 rg (. If the regular expression does not match the rule is) Tj T* 0 Tw (skipped.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 624.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 51 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 18-19:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 50 Tm .317533 Tw 12 TL /F1 10 Tf 0 0 0 rg (These lines reference the previous result of the regular expression match which are) Tj T* 0 Tw 1.167309 Tw (stored in the special variable ) Tj /F4 10 Tf 0 0 0 rg ($regexp_map) Tj /F1 10 Tf 0 0 0 rg (. The username is converted to lower) Tj T* 0 Tw 1.531569 Tw (case and stored in ) Tj /F4 10 Tf 0 0 0 rg ($username ) Tj /F1 10 Tf 0 0 0 rg (and the domain is converted to upper case and) Tj T* 0 Tw 4.828366 Tw (stored in ) Tj /F4 10 Tf 0 0 0 rg ($domain) Tj /F1 10 Tf 0 0 0 rg (. The choice of case is purely by convention and site) Tj T* 0 Tw (requirements.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 609.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 21-35:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (These 3 blocks assign roles based on group membership.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 546.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 51 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 21-25:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 50 Tm 2.764581 Tw 12 TL /F1 10 Tf 0 0 0 rg (Assures ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER_GROUPS ) Tj /F1 10 Tf 0 0 0 rg (is defined in the assertion; if not, the rule is) Tj T* 0 Tw 1.040039 Tw (skipped. ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER_GROUPS ) Tj /F1 10 Tf 0 0 0 rg (is colon separated list of group names. In order) Tj T* 0 Tw .149039 Tw (to operate on the individual group names appearing in ) Tj /F4 10 Tf 0 0 0 rg (REMOTE_USER_GROUPS ) Tj /F1 10 Tf 0 0 0 rg (line) Tj T* 0 Tw 1.525742 Tw (24 splits the string on the colon separator and stores the result in the ) Tj /F4 10 Tf 0 0 0 rg ($groups) Tj T* 0 Tw /F1 10 Tf 0 0 0 rg (array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 519.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 15 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 27-30:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 14 Tm 1.0536 Tw 12 TL /F1 10 Tf 0 0 0 rg (This block assigns the ) Tj /F4 10 Tf 0 0 0 rg (user ) Tj /F1 10 Tf 0 0 0 rg (role if the user is a member of the ) Tj /F4 10 Tf 0 0 0 rg (foobar_users) Tj T* 0 Tw /F1 10 Tf 0 0 0 rg (group.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 492.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 15 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 31-35:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 14 Tm .625028 Tw 12 TL /F1 10 Tf 0 0 0 rg (This block assigns the ) Tj /F4 10 Tf 0 0 0 rg (admin ) Tj /F1 10 Tf 0 0 0 rg (role if the user is a member of the ) Tj /F4 10 Tf 0 0 0 rg (foobar_admin) Tj T* 0 Tw /F1 10 Tf 0 0 0 rg (group.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 441.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 15.23937 0 Td (Lines 36-41:) Tj T* -15.23937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+BT 1 0 0 1 0 38 Tm .77336 Tw 12 TL /F1 10 Tf 0 0 0 rg (This block performs final clean up actions for the rule. First it assures there are no) Tj T* 0 Tw 1.995415 Tw (duplicates in the ) Tj /F4 10 Tf 0 0 0 rg ($roles ) Tj /F1 10 Tf 0 0 0 rg (array by calling the ) Tj /F4 10 Tf 0 0 0 rg (unique ) Tj /F1 10 Tf 0 0 0 rg (function. Then it gets a) Tj T* 0 Tw .778847 Tw (count of how many items are in the ) Tj /F4 10 Tf 0 0 0 rg ($roles ) Tj /F1 10 Tf 0 0 0 rg (array and tests to see if it's empty. If) Tj T* 0 Tw (there are no roles assigned the rule is skipped.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 402.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 27 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL 35.24937 0 Td (Line 43:) Tj T* -35.24937 0 Td ET
+Q
+Q
+q
+1 0 0 1 91.03937 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .549494 Tw (This is the end of the rule. If we reach the end of the rule it succeeds. When a rule) Tj T* 0 Tw 2.446699 Tw (succeeds the mapping associated with the rule is looked up. Any rule variable) Tj T* 0 Tw (appearing in the mapping is substituted with its value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 384.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Using the rules in ) Tj 0 0 .501961 rg (Mapping Rule Example 1. ) Tj 0 0 0 rg (and following example assertion in JSON format:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 366.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Assertion Example 1.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 248.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 108 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 86 Tm /F4 10 Tf 12 TL ({) Tj T* ( "REMOTE_USER": "TestUser@example.com",) Tj T* ( "REMOTE_AUTH_TYPE": "Negotiate",) Tj T* ( "REMOTE_USER_GROUPS": "foobar_users:foobar_admin",) Tj T* ( "REMOTE_USER_EMAIL": "test.user@example.com",) Tj T* ( "REMOTE_USER_FIRSTNAME": "Test",) Tj T* ( "REMOTE_USER_LASTNAME": "User") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 192.8236 cm
+q
+BT 1 0 0 1 0 38 Tm .488735 Tw 12 TL /F1 10 Tf 0 0 0 rg (Then the mapper will return the following mapped JSON document. This is the ) Tj /F4 10 Tf 0 0 0 rg (mapping ) Tj /F1 10 Tf 0 0 0 rg (defined on line) Tj T* 0 Tw .01436 Tw (2 of ) Tj 0 0 .501961 rg (Mapping Rule Example 1. ) Tj 0 0 0 rg (with the variables substituted after the rule successfully executed. Note any) Tj T* 0 Tw 1.152927 Tw (valid JSON data type can be returned, in this example the ) Tj /F4 10 Tf 0 0 0 rg (null ) Tj /F1 10 Tf 0 0 0 rg (value is returned for ) Tj /F4 10 Tf 0 0 0 rg (ClientId ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg (UserId) Tj /F1 10 Tf 0 0 0 rg (, normal strings for ) Tj /F4 10 Tf 0 0 0 rg (User ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (Domain ) Tj /F1 10 Tf 0 0 0 rg (and an array of strings for the ) Tj /F4 10 Tf 0 0 0 rg (roles ) Tj /F1 10 Tf 0 0 0 rg (value.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 174.8236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Mapped Result Example 1.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 93.62362 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F4 10 Tf 12 TL ({) Tj T* ( "ClientId": null,) Tj T* ( "UserId": null,) Tj T* ( "User": "testuser",) Tj T* ( "Domain": "EXAMPLE.COM",) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-5-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+144 0 obj
+<< /Length 4099 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 727.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F4 10 Tf 12 TL ( "roles": ["user", "admin"]) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 694.8236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Operation Model) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 616.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 62 Tm /F1 10 Tf 12 TL .846654 Tw (The assertions from an IdP are stored in an associative array. A sequence of rules are applied, the first) Tj T* 0 Tw 1.787485 Tw (rule which returns success is considered a match. During the execution of each rule values from the) Tj T* 0 Tw .406457 Tw (assertion can be tested and transformed with the results selectively stored in variables local to the rule. If) Tj T* 0 Tw .466235 Tw (the rule succeeds an associative array of mapped values is returned. The mapped values are taken from) Tj T* 0 Tw 2.23686 Tw (the local variables set during the rule execution. The definition of the rules and mapped results are) Tj T* 0 Tw (expressed in JSON notation.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 538.8236 cm
+q
+BT 1 0 0 1 0 62 Tm 2.359431 Tw 12 TL /F1 10 Tf 0 0 0 rg (A rule is somewhat akin to a function in a programming language. It starts execution with a set of) Tj T* 0 Tw 2.936647 Tw (predefined local variables. It executes statements which are grouped together in blocks. Execution) Tj T* 0 Tw 1.05686 Tw (continues until an ) Tj 0 0 .501961 rg (exit ) Tj 0 0 0 rg (statement returning a success/fail result is executed or until the last statement is) Tj T* 0 Tw 1.943984 Tw (reached which implies success. The remaining statements in a block may be skipped via a ) Tj 0 0 .501961 rg (continue) Tj T* 0 Tw 2.04881 Tw 0 0 0 rg (statement which tests a condition, this is equivalent to an "if" control flow of logic in a programming) Tj T* 0 Tw (language.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 484.8236 cm
+q
+BT 1 0 0 1 0 38 Tm .04936 Tw 12 TL /F1 10 Tf 0 0 0 rg (Rule execution continues until a rule returns success. Each rule has a ) Tj 0 0 .501961 rg (mapping ) Tj 0 0 0 rg (associative array bound to) Tj T* 0 Tw .106098 Tw (it which is a template for the transformed result. Upon success the ) Tj 0 0 .501961 rg (mapping ) Tj 0 0 0 rg (template for the rule is loaded) Tj T* 0 Tw .601163 Tw (and the local variables from the successful rule are used to populate the values in the ) Tj 0 0 .501961 rg (mapping ) Tj 0 0 0 rg (template) Tj T* 0 Tw (yielding the final mapped result.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 466.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (If no rules returns success authentication fails.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 436.8236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Pseudo Code Illustrating Operational Model) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 115.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 312 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 290 Tm /F4 10 Tf 12 TL (mapped = null) Tj T* (foreach rule in rules {) Tj T* ( result = null) Tj T* ( initialize rule.variables with pre-defined values) Tj T* T* ( foreach block in rule.statement_blocks {) Tj T* ( for statement in block.statements {) Tj T* ( if statement.verb is exit {) Tj T* ( result = exit.status) Tj T* ( break) Tj T* ( }) Tj T* ( elif statement.verb is continue {) Tj T* ( break) Tj T* ( }) Tj T* ( }) Tj T* ( if result {) Tj T* ( break) Tj T* ( }) Tj T* ( if result == null {) Tj T* ( result = success) Tj T* ( }) Tj T* (if result == success {) Tj T* ( mapped = rule.mapping\(rule.variables\)) Tj T* (}) Tj T* (return mapped) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-6-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+145 0 obj
+<< /Length 3697 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 744.0236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Structure Of Rule Definitions) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 702.0236 cm
+q
+BT 1 0 0 1 0 26 Tm .599431 Tw 12 TL /F1 10 Tf 0 0 0 rg (Rules are loaded by the rule processor via a JSON document called a rule definition. A definition has an) Tj T* 0 Tw .258876 Tw /F3 10 Tf (optional ) Tj /F1 10 Tf (set of mapping templates and a list of rules. Each rule has specifies a mapping template and has) Tj T* 0 Tw (a list of statement blocks. Each statement block has a list of statements.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 684.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (In pseudo-JSON \(JSON does not have comments, the ... ellipsis is a place holder\):) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 302.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 372 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 350 Tm /F4 10 Tf 12 TL ({) Tj T* ( "mappings": {) Tj T* ( "template1": "{...}",) Tj T* ( "template2": "{...}") Tj T* ( },) Tj T* ( "rules": [) Tj T* ( { # Rule 0. A rule has a mapping or a mapping name) Tj T* ( # and a list of statement blocks) Tj T* T* ( "mapping": {...},) Tj T* ( # -OR-) Tj T* ( "mapping_name": "template1",) Tj T* T* ( "statement_blocks": [) Tj T* ( [ # Block 0) Tj T* ( [statement 0]) Tj T* ( [statement 1]) Tj T* ( ],) Tj T* ( [ # Block 1) Tj T* ( [statement 0]) Tj T* ( [statement 1]) Tj T* ( ],) Tj T* T* ( ]) Tj T* ( },) Tj T* ( { # Rule 1 ...) Tj T* ( }) Tj T* ( ]) Tj T* T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 272.8236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Mapping) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 218.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .504104 Tw (A mapping template is used to produce the final associative array of name/value pairs. The template is a) Tj T* 0 Tw .788988 Tw (JSON Object. The value in a name/value pair can be a constant or a variable. If the template value is a) Tj T* 0 Tw 1.525542 Tw (variable the value of the variable is retrieved from the set of local variables bound to the rule thereby) Tj T* 0 Tw (replacing it in the final result.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 200.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (For example given this mapping template and rule variables in JSON:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 182.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (template:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 101.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F4 10 Tf 12 TL ({) Tj T* ( "organization": "BigCorp.com",) Tj T* ( "user: "$subject",) Tj T* ( "roles": "$roles") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-7-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+146 0 obj
+<< /Length 5083 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 753.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (local variables:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 683.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL ({) Tj T* ( "subject": "Sally",) Tj T* ( "roles": ["user", "admin"]) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 663.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The final mapped results would be:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 582.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 72 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F4 10 Tf 12 TL ({) Tj T* ( "organization": "BigCorp.com",) Tj T* ( "user: "Sally",) Tj T* ( "roles": ["user", "admin"]) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 550.6236 cm
+q
+BT 1 0 0 1 0 14 Tm .307633 Tw 12 TL /F1 10 Tf 0 0 0 rg (Each rule must bind a mapping template to the rule. The mapping template may either be defined directly) Tj T* 0 Tw (in the rule via the ) Tj /F4 10 Tf 0 0 0 rg (mapping ) Tj /F1 10 Tf 0 0 0 rg (key or referenced by name via the ) Tj /F4 10 Tf 0 0 0 rg (mapping_name ) Tj /F1 10 Tf 0 0 0 rg (key.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 508.6236 cm
+q
+BT 1 0 0 1 0 26 Tm .185542 Tw 12 TL /F1 10 Tf 0 0 0 rg (If the ) Tj /F4 10 Tf 0 0 0 rg (mapping_name ) Tj /F1 10 Tf 0 0 0 rg (is specified the mapping is looked up in a table of mapping templates bound to the) Tj T* 0 Tw 1.299985 Tw (Rule Processor. Using the name of a mapping template is useful when many rules generate the exact) Tj T* 0 Tw (same template values.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 490.6236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If both ) Tj /F4 10 Tf 0 0 0 rg (mapping ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (mapping_name ) Tj /F1 10 Tf 0 0 0 rg (are defined the locally bound ) Tj /F4 10 Tf 0 0 0 rg (mapping ) Tj /F1 10 Tf 0 0 0 rg (takes precedence.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 460.6236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Syntax) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 430.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .977882 Tw (The logic for a rule consists of a sequence of statements grouped in blocks. A statement is similar to a) Tj T* 0 Tw (function call in a programming language.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 376.6236 cm
+q
+BT 1 0 0 1 0 38 Tm 1.012488 Tw 12 TL /F1 10 Tf 0 0 0 rg (A statement is a list of values the first of which is a verb which defines the operation the statement will) Tj T* 0 Tw .15561 Tw (perform. Think of the ) Tj 0 0 .501961 rg (verbs ) Tj 0 0 0 rg (as function names or operators. Following the verb are parameters which may) Tj T* 0 Tw .628876 Tw (be constants or variables. If the statement assigns a value to a variable left hand side of the assignment) Tj T* 0 Tw (\(lhs\) is always the first parameter following the verb in the list of statement values.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 358.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (For example this statement in JSON:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 325.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["split", "$groups", "$assertion[Groups]", ":"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 293.4236 cm
+q
+BT 1 0 0 1 0 14 Tm .287209 Tw 12 TL /F1 10 Tf 0 0 0 rg (will assign an array to the variable ) Tj /F4 10 Tf 0 0 0 rg ($groups) Tj /F1 10 Tf 0 0 0 rg (. It looks up the string named ) Tj /F4 10 Tf 0 0 0 rg (Groups ) Tj /F1 10 Tf 0 0 0 rg (in the assertion which) Tj T* 0 Tw (is a colon \(:\) separated list of group names splitting that string on the colon character.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 251.4236 cm
+q
+BT 1 0 0 1 0 26 Tm .598876 Tw 12 TL /F1 10 Tf 0 0 0 rg (Statements ) Tj /F2 10 Tf (must ) Tj /F1 10 Tf (be grouped together in blocks. Therefore a rule is a sequence of blocks and block is a) Tj T* 0 Tw .864692 Tw (sequence of statements. The purpose of blocks is allow for crude flow of control logic. For example this) Tj T* 0 Tw (JSON rule has 4 blocks.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 98.22362 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 144 re B*
+Q
+q
+BT 1 0 0 1 0 122 Tm 12 TL /F4 10 Tf 0 0 0 rg ([) Tj T* ( [) Tj T* ( ["set", $user, ""],) Tj T* ( ["set", $roles, []]) Tj T* ( ],) Tj T* ( [) Tj T* ( ["in", "UserName", "$assertion"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["set", "$user", "$assertion[UserName"],) Tj T* ( ],) Tj T* ( [) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-8-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+147 0 obj
+<< /Length 8967 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 619.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 144 re B*
+Q
+q
+BT 1 0 0 1 0 122 Tm 12 TL /F4 10 Tf 0 0 0 rg ( ["in", "subject", "$assertion"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["set", "$user", "$assertion[subject]"],) Tj T* ( ],) Tj T* ( [) Tj T* ( ["length", "$temp", "$user"],) Tj T* ( ["compare", "$temp", ") Tj (>) Tj (", 0],) Tj T* ( ["exit", "rule_fails", "if_not_success"]) Tj T* ( ["append" "$roles", "unprivileged"]) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 575.8236 cm
+q
+BT 1 0 0 1 0 26 Tm 1.695542 Tw 12 TL /F1 10 Tf 0 0 0 rg (The rule will succeed if either ) Tj /F4 10 Tf 0 0 0 rg (UserName ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (subject ) Tj /F1 10 Tf 0 0 0 rg (is defined in the assertion and if so the local) Tj T* 0 Tw .11832 Tw (variable ) Tj /F4 10 Tf 0 0 0 rg ($user ) Tj /F1 10 Tf 0 0 0 rg (will be set to the value found in the assertion and the "unprivileged" role will be appended) Tj T* 0 Tw (to the roles array.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 497.8236 cm
+q
+BT 1 0 0 1 0 62 Tm 3.211235 Tw 12 TL /F1 10 Tf 0 0 0 rg (The first block performs initialization. The second block tests to see if the assertion has the key) Tj T* 0 Tw .59186 Tw /F4 10 Tf 0 0 0 rg (UserName ) Tj /F1 10 Tf 0 0 0 rg (if not execution continues at the next block otherwise the value of UserName in the assertion) Tj T* 0 Tw .62528 Tw (is copied into the variable ) Tj /F4 10 Tf 0 0 0 rg ($user) Tj /F1 10 Tf 0 0 0 rg (. The third block performs a similar operation looking for a ) Tj /F4 10 Tf 0 0 0 rg (subject ) Tj /F1 10 Tf 0 0 0 rg (in) Tj T* 0 Tw .907988 Tw (the assertion. The fourth block checks to see if the ) Tj /F4 10 Tf 0 0 0 rg ($user ) Tj /F1 10 Tf 0 0 0 rg (variable is empty, if it is empty the rule fails) Tj T* 0 Tw 1.347765 Tw (because it didn't find either a ) Tj /F4 10 Tf 0 0 0 rg (UserName ) Tj /F1 10 Tf 0 0 0 rg (nor a ) Tj /F4 10 Tf 0 0 0 rg (subject ) Tj /F1 10 Tf 0 0 0 rg (in the assertion. If ) Tj /F4 10 Tf 0 0 0 rg ($user ) Tj /F1 10 Tf 0 0 0 rg (is not empty the) Tj T* 0 Tw ("unprivileged" role is appended and the rule succeeds.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 467.8236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Data Types) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 389.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 62 Tm /F1 10 Tf 12 TL .304198 Tw (There are 7 supported types which equate to the types available in JSON. At the time of this writing there) Tj T* 0 Tw .569985 Tw (are 2 implementations of this Mapping specification, one in Python and one in Java. This table illustrates) Tj T* 0 Tw 1.090651 Tw (how each data type is represented. The first two columns are definitions from an abstract specification.) Tj T* 0 Tw 4.106412 Tw (The JSON column enumerates the data type JSON supports. The Mapping column lists the 7) Tj T* 0 Tw .214983 Tw (enumeration names used by the Mapping implemenation in each language. The following columns list the) Tj T* 0 Tw (concrete data type used in that language.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 383.8236 cm
+Q
+q
+1 0 0 1 62.69291 203.8236 cm
+1 1 1 rg
+n 0 180 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 162 469.8898 -18 re f*
+1 1 1 rg
+n 0 144 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 126 469.8898 -18 re f*
+1 1 1 rg
+n 0 108 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 90 469.8898 -18 re f*
+1 1 1 rg
+n 0 72 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 54 469.8898 -18 re f*
+1 1 1 rg
+n 0 36 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 18 469.8898 -18 re f*
+.960784 .960784 .862745 rg
+n 0 180 469.8898 -18 re f*
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 165 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 68.7623 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 21.04615 0 Td (JSON) Tj T* -21.04615 0 Td ET
+Q
+Q
+q
+1 0 0 1 86.7623 165 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 76.10433 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 18.87717 0 Td (Mapping) Tj T* -18.87717 0 Td ET
+Q
+Q
+q
+1 0 0 1 174.8666 165 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 134.8406 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 51.85528 0 Td (Python) Tj T* -51.85528 0 Td ET
+Q
+Q
+q
+1 0 0 1 321.7072 165 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 142.1826 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 60.53129 0 Td (Java) Tj T* -60.53129 0 Td ET
+Q
+Q
+0 0 0 rg
+q
+1 0 0 1 6 147 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (object) Tj T* ET
+Q
+Q
+q
+1 0 0 1 86.7623 147 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (MAP) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 147 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (dict) Tj T* ET
+Q
+Q
+q
+1 0 0 1 321.7072 147 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Map) Tj (<) Tj (String, Object) Tj (>) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 129 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 86.7623 129 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (ARRAY) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 129 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (list) Tj T* ET
+Q
+Q
+q
+1 0 0 1 321.7072 129 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (List) Tj (<) Tj (Object) Tj (>) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 111 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 86.7623 111 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (STRING) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 111 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (unicode \(Python 2\)) Tj T* ET
+Q
+Q
+q
+1 0 0 1 321.7072 111 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (String) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (str \(Python 3\)) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (number) Tj T* ET
+Q
+Q
+q
+1 0 0 1 86.7623 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (INTEGER) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (int) Tj T* ET
+Q
+Q
+q
+1 0 0 1 321.7072 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Long) Tj T* ET
+Q
+Q
+q
+1 0 0 1 86.7623 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (REAL) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (float) Tj T* ET
+Q
+Q
+q
+1 0 0 1 321.7072 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Double) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (true) Tj T* ET
+Q
+Q
+q
+1 0 0 1 86.7623 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (BOOLEAN) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (bool) Tj T* ET
+Q
+Q
+q
+1 0 0 1 321.7072 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Boolean) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (false) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (null) Tj T* ET
+Q
+Q
+q
+1 0 0 1 86.7623 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (NULL) Tj T* ET
+Q
+Q
+q
+1 0 0 1 174.8666 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (None) Tj T* ET
+Q
+Q
+q
+1 0 0 1 321.7072 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (null) Tj T* ET
+Q
+Q
+q
+1 J
+1 j
+0 0 0 RG
+.25 w
+n 0 162 m 469.8898 162 l S
+n 0 144 m 469.8898 144 l S
+n 0 126 m 469.8898 126 l S
+n 168.8666 108 m 315.7072 108 l S
+n 0 90 m 469.8898 90 l S
+n 80.7623 72 m 469.8898 72 l S
+n 0 54 m 469.8898 54 l S
+n 0 36 m 80.7623 36 l S
+n 0 18 m 469.8898 18 l S
+n 80.7623 0 m 80.7623 180 l S
+n 168.8666 0 m 168.8666 180 l S
+n 315.7072 0 m 315.7072 180 l S
+n 0 180 m 469.8898 180 l S
+n 0 0 m 469.8898 0 l S
+n 0 0 m 0 180 l S
+n 469.8898 0 m 469.8898 180 l S
+Q
+Q
+q
+1 0 0 1 62.69291 203.8236 cm
+Q
+q
+1 0 0 1 62.69291 173.8236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Rule Debugging and Documentation) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 107.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F1 10 Tf 12 TL .061654 Tw (If the rule processor reports an error or if you're debugging your rules by enabling DEBUG log tracing then) Tj T* 0 Tw 1.278876 Tw (you must be able to correlate the reported statement to where it appears in your rule JSON source. A) Tj T* 0 Tw 2.16936 Tw (message will always identify a statement by the rule number, block number within that rule and the) Tj T* 0 Tw .417126 Tw (statement number within that block. However once your rules become moderately complex it will become) Tj T* 0 Tw (increasingly difficult to identify a statement by counting rules, blocks and statements.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 234.8349 0 Td (-9-) Tj T* -234.8349 0 Td ET
+Q
+Q
+
+endstream
+endobj
+148 0 obj
+<< /Length 5236 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 729.0236 cm
+q
+BT 1 0 0 1 0 26 Tm 1.766303 Tw 12 TL /F1 10 Tf 0 0 0 rg (A better approach is to tag rules and blocks with a name or other identifying string. You can set the) Tj T* 0 Tw 2.094269 Tw 0 0 .501961 rg (Reserved Variables) Tj 0 0 0 rg ( ) Tj /F4 10 Tf 0 0 0 rg (rule_name ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (block_name ) Tj /F1 10 Tf 0 0 0 rg (to a string of your choice. These strings will be) Tj T* 0 Tw (reported in all messages along with the rule, block and statement numbers.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 675.0236 cm
+q
+BT 1 0 0 1 0 38 Tm .720651 Tw 12 TL /F1 10 Tf 0 0 0 rg (JSON does not permit comments, as such you cannot include explanatory comments next to your rules,) Tj T* 0 Tw 1.895697 Tw (blocks and statements in the JSON source. The ) Tj /F4 10 Tf 0 0 0 rg (rule_name ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (block_name ) Tj /F1 10 Tf 0 0 0 rg (can serve a similar) Tj T* 0 Tw .55436 Tw (purpose. By putting assignments to these variables as the first statement in a block you'll both document) Tj T* 0 Tw (your rules and be able to identify specific statements in log messages.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 645.0236 cm
+q
+BT 1 0 0 1 0 14 Tm 2.807126 Tw 12 TL /F1 10 Tf 0 0 0 rg (During rule execution the ) Tj /F4 10 Tf 0 0 0 rg (rule_name ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg (block_name ) Tj /F1 10 Tf 0 0 0 rg (are initialized to the empty string at the) Tj T* 0 Tw (beginning of each rule and block respectively.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 615.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .19832 Tw (The above example is augmented to include this information. The rule name is set in the first statement in) Tj T* 0 Tw (the first block.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 269.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 528 336 re B*
+Q
+q
+BT 1 0 0 1 0 314 Tm 12 TL /F4 10 Tf 0 0 0 rg ([) Tj T* ( [) Tj T* ( ["set", "$rule_name", "Must have UserName or subject"],) Tj T* ( ["set", "block_name", "Initialization"],) Tj T* ( ["set", $user, ""],) Tj T* ( ["set", $roles, []]) Tj T* ( ],) Tj T* ( [) Tj T* ( ["set", "block_name", "Test for UserName, set $user"],) Tj T* ( ["in", "UserName", "$assertion"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["set", "$user", "$assertion[UserName"],) Tj T* ( ],) Tj T* ( [) Tj T* ( ["set", "block_name", "Test for subject, set $user"],) Tj T* ( ["in", "subject", "$assertion"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["set", "$user", "$assertion[subject]"],) Tj T* ( ],) Tj T* ( [) Tj T* ( ["set", "block_name", "If not $user fail, else append unprivileged to roles"],) Tj T* ( ["length", "$temp", "$user"],) Tj T* ( ["compare", "$temp", ") Tj (>) Tj (", 0],) Tj T* ( ["exit", "rule_fails", "if_not_success"]) Tj T* ( ["append" "$roles", "unprivileged"]) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 239.8236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Variables) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 185.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F1 10 Tf 12 TL .137765 Tw (Variables always begin with a dollar sign \($\) and are followed by an identifier which is any alpha character) Tj T* 0 Tw 3.269982 Tw (followed by zero or more alphanumeric or underscore characters. The variable may optionally be) Tj T* 0 Tw 1.757984 Tw (delimited with braces \({}\) to separate the variable from surrounding text. Three types of variables are) Tj T* 0 Tw (supported:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 179.8236 cm
+Q
+q
+1 0 0 1 62.69291 179.8236 cm
+Q
+q
+1 0 0 1 62.69291 167.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (scalar) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 161.8236 cm
+Q
+q
+1 0 0 1 62.69291 149.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (array \(indexed by zero based integer\)) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 143.8236 cm
+Q
+q
+1 0 0 1 62.69291 131.8236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (associative array \(indexed by string\)) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 131.8236 cm
+Q
+q
+1 0 0 1 62.69291 101.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .113516 Tw (Both arrays and associative arrays use square brackets \([]\) to specify a member of the array. Examples of) Tj T* 0 Tw (variable usage:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-10-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+149 0 obj
+<< /Length 6068 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 679.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 84 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 62 Tm /F4 10 Tf 12 TL ($name) Tj T* (${name}) Tj T* ($groups[0]) Tj T* (${groups[0]}) Tj T* ($properties[key]) Tj T* (${properties[key]}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 623.8236 cm
+q
+BT 1 0 0 1 0 38 Tm .001163 Tw 12 TL /F1 10 Tf 0 0 0 rg (An array or an associative array may be referenced by it's base name \(omitting the indexing brackets\). For) Tj T* 0 Tw 5.84748 Tw (example the associative array array named "properties" is referenced using it's base name) Tj T* 0 Tw .301318 Tw /F4 10 Tf 0 0 0 rg ($properties ) Tj /F1 10 Tf 0 0 0 rg (but if you want to access a member of the "properties" associative array named "duration") Tj T* 0 Tw (you would do this ) Tj /F4 10 Tf 0 0 0 rg ($properties[duration]) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 593.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.059986 Tw (This is not a general purpose language with full expression syntax. Only one level of variable lookup is) Tj T* 0 Tw (supported. Therefore compound references like this) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 560.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL ($properties[$groups[2]]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 540.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (will not work.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 513.6236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Escaping) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 459.6236 cm
+q
+BT 1 0 0 1 0 38 Tm .461894 Tw 12 TL /F1 10 Tf 0 0 0 rg (If you need to include a dollar sign in a string \(where it is immediately followed by either an identifier or a) Tj T* 0 Tw .196654 Tw (brace and identifier\) and do not want to have it be interpreted as representing a variable you must escape) Tj T* 0 Tw 2.522651 Tw (the dollar sign with a backslash, for example "$amount" is interpreted as the variable ) Tj /F4 10 Tf 0 0 0 rg (amount ) Tj /F1 10 Tf 0 0 0 rg (but) Tj T* 0 Tw ("\\$amount" is interpreted as the string "$amount" .) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 429.6236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Reserved Variables) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 411.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (A rule has the following reserved variables:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 395.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (assertion) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 380.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The current assertion values from the federated IdP. It is a dictionary of key/value pairs.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 364.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (regexp_array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 325.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 26 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .276651 Tw (The regular expression groups from the last successful regexp match indexed by number. Group 0 is) Tj T* 0 Tw .690697 Tw (the entire match. Groups 1..n are the corresponding parenthesized group counting from the left. For) Tj T* 0 Tw (example regexp_array[1] is the first group.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 309.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (regexp_map) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 294.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The regular expression groups from the last successful regexp match indexed by group name.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 278.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (rule_number) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 263.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The zero based index of the currently executing rule.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 247.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (rule_name) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 232.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The name of the currently executing rule. If the rule name has not been set it will be the empty string.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 216.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (block_number) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 201.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The zero based index of the currently executing block within the currently executing rule.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 185.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (block_name) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 158.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 14 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.094198 Tw (The name of the currently executing block. If the block name has not been set it will be the empty) Tj T* 0 Tw (string.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 142.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (statement_number) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 127.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The zero based index of the currently executing statement within the currently executing block.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-11-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+150 0 obj
+<< /Length 6055 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 744.0236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Examples) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 714.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Split a fully qualified username into user and realm components) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 648.0236 cm
+q
+BT 1 0 0 1 0 50 Tm 2.38311 Tw 12 TL /F1 10 Tf 0 0 0 rg (It's common for some IdP's to return a fully qualified username \(e.g. principal or subject\). The fully) Tj T* 0 Tw 2.834983 Tw (qualified username is the concatenation of the user name, separator and realm name. A common) Tj T* 0 Tw .239318 Tw (separator is the @ character. In this example lets say the fully qualified username is ) Tj /F4 10 Tf 0 0 0 rg (bob@example.com) Tj T* 0 Tw .731751 Tw /F1 10 Tf 0 0 0 rg (and you want to return the user and realm as independent values in your mapped result. The username) Tj T* 0 Tw (appears in the assertion as the value ) Tj /F4 10 Tf 0 0 0 rg (Principal) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 618.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .569398 Tw (Our strategy will be to use a regular expression identify the user and realm components and then assign) Tj T* 0 Tw (them to local variables which will then populate the mapped result.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 600.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapping in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 530.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL ({) Tj T* ( "user": "$username",) Tj T* ( "realm": "$domain") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 510.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The assertion in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 453.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "Principal": "bob@example.com") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 433.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Our rule is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 292.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 492 132 re B*
+Q
+q
+BT 1 0 0 1 0 110 Tm 12 TL /F4 10 Tf 0 0 0 rg ([) Tj T* ( [) Tj T* ( ["in", "Principal", "assertion"],) Tj T* ( ["exit", "rule_fails", "if_not_success"],) Tj T* ( ["regexp", "$assertion[Principal]", \(?P) Tj (<) Tj (username) Tj (>) Tj (\\\\w+\)@\(?P) Tj (<) Tj (domain) Tj (>) Tj (.+\)"],) Tj T* ( ["set", "$username", "$regexp_map[username]"],) Tj T* ( ["set", "$domain", "$regexp_map[domain]"],) Tj T* ( ["exit, "rule_succeeds", "always"]) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 272.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Rule explanation:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 254.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 0:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 248.4236 cm
+Q
+q
+1 0 0 1 62.69291 248.4236 cm
+Q
+q
+1 0 0 1 62.69291 236.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if the assertion contains a Principal value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 230.4236 cm
+Q
+q
+1 0 0 1 62.69291 218.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Abort the rule if the assertion does not contain a Principal value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 212.4236 cm
+Q
+q
+1 0 0 1 62.69291 188.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 9 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.867126 Tw (Apply a regular expression the the Principal value. Use named groupings for the username and) Tj T* 0 Tw (domain components for clarity.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 182.4236 cm
+Q
+q
+1 0 0 1 62.69291 170.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Assign the regexp group username to the $username local variable.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 164.4236 cm
+Q
+q
+1 0 0 1 62.69291 152.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (5.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Assign the regexp group domain to the $domain local variable.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 146.4236 cm
+Q
+q
+1 0 0 1 62.69291 122.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 9 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (6.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+BT 1 0 0 1 0 14 Tm 1.112339 Tw 12 TL /F1 10 Tf 0 0 0 rg (Exit the rule, apply the mapping, return the mapped values. Note, an explicit ) Tj 0 0 .501961 rg (exit ) Tj 0 0 0 rg (is not required if) Tj T* 0 Tw (there are no further statements in the rule, as is the case here.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 122.4236 cm
+Q
+q
+1 0 0 1 62.69291 104.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapped result in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-12-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+151 0 obj
+<< /Length 3622 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 703.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL ({) Tj T* ( "user": "bob",) Tj T* ( "realm": "example.com") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 673.8236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Build a set of roles based on group membership) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 607.8236 cm
+q
+BT 1 0 0 1 0 50 Tm .028409 Tw 12 TL /F1 10 Tf 0 0 0 rg (Often one wants to grant roles to a user based on their membership in certain groups. In this example let's) Tj T* 0 Tw .518221 Tw (say the assertion contains a ) Tj /F4 10 Tf 0 0 0 rg (Groups ) Tj /F1 10 Tf 0 0 0 rg (value which is a colon separated list of group names. Our strategy) Tj T* 0 Tw .064274 Tw (is to split the ) Tj /F4 10 Tf 0 0 0 rg (Groups ) Tj /F1 10 Tf 0 0 0 rg (assertion value into an array of group names. Then we'll test if a specific group is in) Tj T* 0 Tw .555898 Tw (the groups array, if it is we'll add a role. Finally if no roles have been mapped we fail. Users in the group) Tj T* 0 Tw ("student" will get the role "unprivileged" and users in the group "helpdesk" will get the role "admin".) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 589.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapping in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 532.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "roles": "$roles",) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 512.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The assertion in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 455.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "Groups": "student:helpdesk") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 435.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Our rule is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 114.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 312 re B*
+Q
+q
+BT 1 0 0 1 0 290 Tm 12 TL /F4 10 Tf 0 0 0 rg ([) Tj T* ( [) Tj T* ( ["in", "Groups", "assertion"],) Tj T* ( ["exit", "rule_fails", "if_not_success"],) Tj T* ( ["set", "$roles", []],) Tj T* ( ["split", "$groups", "$assertion[Groups]", ":"],) Tj T* ( ],) Tj T* ( [) Tj T* ( ["in", "student", "$groups"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["append", "$roles", "unprivileged"]) Tj T* ( ],) Tj T* ( [) Tj T* ( ["in", "helpdesk", "$groups"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["append", "$roles", "admin"]) Tj T* ( ],) Tj T* ( [) Tj T* ( ["unique", "$roles", "$roles"],) Tj T* ( ["length", "$temp", "roles"],) Tj T* ( ["compare", $temp", ") Tj (>) Tj (", 0],) Tj T* ( ["exit", "rule_fails", "if_not_success"]) Tj T* ( ]) Tj T* T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 94.22362 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Rule explanation:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-13-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+152 0 obj
+<< /Length 8175 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 753.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 0) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 747.0236 cm
+Q
+q
+1 0 0 1 62.69291 747.0236 cm
+Q
+q
+1 0 0 1 62.69291 735.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if the assertion contains a Groups value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 729.0236 cm
+Q
+q
+1 0 0 1 62.69291 717.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Abort the rule if the assertion does not contain a Groups value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 711.0236 cm
+Q
+q
+1 0 0 1 62.69291 699.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Initialize the $roles variable to an empty array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 693.0236 cm
+Q
+q
+1 0 0 1 62.69291 681.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Split the colon separated list of group names into an array of individual group names) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 681.0236 cm
+Q
+q
+1 0 0 1 62.69291 663.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 1) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 657.0236 cm
+Q
+q
+1 0 0 1 62.69291 657.0236 cm
+Q
+q
+1 0 0 1 62.69291 645.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if "student" is in the $groups array) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 639.0236 cm
+Q
+q
+1 0 0 1 62.69291 627.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Exit the block if it's not.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 621.0236 cm
+Q
+q
+1 0 0 1 62.69291 609.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Append "unprivileged" to the $roles array) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 609.0236 cm
+Q
+q
+1 0 0 1 62.69291 591.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 2) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 585.0236 cm
+Q
+q
+1 0 0 1 62.69291 585.0236 cm
+Q
+q
+1 0 0 1 62.69291 573.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if "helpdesk" is in the $groups array) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 567.0236 cm
+Q
+q
+1 0 0 1 62.69291 555.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Exit the block if it's not.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 549.0236 cm
+Q
+q
+1 0 0 1 62.69291 537.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Append "admin" to the $roles array) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 537.0236 cm
+Q
+q
+1 0 0 1 62.69291 519.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 3) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 513.0236 cm
+Q
+q
+1 0 0 1 62.69291 513.0236 cm
+Q
+q
+1 0 0 1 62.69291 489.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 9 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .91528 Tw (Strip any duplicate roles that might have been appended to the $roles array to assure each role is) Tj T* 0 Tw (unique.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 483.0236 cm
+Q
+q
+1 0 0 1 62.69291 471.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Count how many members are in the $roles array, assign the length to the $temp variable.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 465.0236 cm
+Q
+q
+1 0 0 1 62.69291 453.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test to see if the $roles array had any members.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 447.0236 cm
+Q
+q
+1 0 0 1 62.69291 435.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Fail if no roles had been assigned.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 435.0236 cm
+Q
+q
+1 0 0 1 62.69291 417.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapped result in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 359.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "roles": ["unprivileged", "admin"]) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 315.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .258735 Tw (However, suppose whatever is receiving your mapped results is not expecting an array of roles. Instead it) Tj T* 0 Tw .136654 Tw (expects a comma separated list in a string. To accomplish this add the following statement as the last one) Tj T* 0 Tw (in the final block:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 282.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["join", "$roles", "$roles", ","]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 262.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Then the mapped result will be:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 205.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "roles": "unprivileged,admin"]) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 175.4236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (White list certain users and grant them specific roles) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 133.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 1.326412 Tw (Suppose you have certain users you always want to unconditionally accept and authorize with specific) Tj T* 0 Tw 1.323735 Tw (roles. For example if the user is "head_of_IT" then assign her the "user" and "admin" roles. Otherwise) Tj T* 0 Tw (keep processing. The list of white listed users is hard-coded into the rule.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 115.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapping in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-14-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+153 0 obj
+<< /Length 5659 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 703.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL ({) Tj T* ( "user": $user,) Tj T* ( "roles": "$roles",) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 683.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The assertion in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 626.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "UserName": "head_of_IT") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 606.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Our rule in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 417.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 480 180 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 158 Tm /F4 10 Tf 12 TL ([) Tj T* ( [) Tj T* ( ["in", "UserName", "assertion"],) Tj T* ( ["exit", "rule_fails", "if_not_success"],) Tj T* ( ["in", "$assertion[UserName]", ["head_of_IT", "head_of_Engineering"]],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["set", "$user", "$assertion[UserName"]) Tj T* ( ["set", "$roles", ["user", "admin"]],) Tj T* ( ["exit", "rule_succeeds", "always"]) Tj T* ( ],) Tj T* ( [) Tj T* ( ...) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 397.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Rule explanation:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 379.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 0) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 373.4236 cm
+Q
+q
+1 0 0 1 62.69291 373.4236 cm
+Q
+q
+1 0 0 1 62.69291 361.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if the assertion contains a UserName value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 355.4236 cm
+Q
+q
+1 0 0 1 62.69291 343.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Abort the rule if the assertion does not contain a UserName value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 337.4236 cm
+Q
+q
+1 0 0 1 62.69291 325.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if the user is in the hardcoded list of white listed users.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 319.4236 cm
+Q
+q
+1 0 0 1 62.69291 307.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (If the user isn't in the white listed array then exit the block and continue execution at the next block.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 301.4236 cm
+Q
+q
+1 0 0 1 62.69291 289.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (5.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Set the $user local variable to $assertion[UserName]) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 283.4236 cm
+Q
+q
+1 0 0 1 62.69291 271.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (6.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Set the $roles local variable to the hardcoded array containing "user" and "admin") Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 265.4236 cm
+Q
+q
+1 0 0 1 62.69291 253.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (7.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (We're done, unconditionally exit and return the mapped result.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 253.4236 cm
+Q
+q
+1 0 0 1 62.69291 235.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 1) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 229.4236 cm
+Q
+q
+1 0 0 1 62.69291 229.4236 cm
+Q
+q
+1 0 0 1 62.69291 217.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Further processing) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 217.4236 cm
+Q
+q
+1 0 0 1 62.69291 199.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapped result in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 130.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL ({) Tj T* ( "user": "head_of_IT",) Tj T* ( "roles": ["users", "admin"]) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-15-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+154 0 obj
+<< /Length 5457 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 747.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Black list certain users) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 705.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .56881 Tw (Suppose you have certain users you always want to unconditionally deny access to by placing them in a) Tj T* 0 Tw 1.411654 Tw (black list. In this example the user "BlackHat" will try to gain access. The black list includes the users) Tj T* 0 Tw ("BlackHat" and "Spook".) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 687.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapping in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 617.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL ({) Tj T* ( "user": $user,) Tj T* ( "roles": "$roles",) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 597.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The assertion in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 540.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "UserName": "BlackHat") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 520.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Our rule in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 367.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 144 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 122 Tm /F4 10 Tf 12 TL ([) Tj T* ( [) Tj T* ( ["in", "UserName", "assertion"],) Tj T* ( ["exit", "rule_fails", "if_not_success"],) Tj T* ( ["in", "$assertion[UserName]", ["BlackHat", "Spook"]],) Tj T* ( ["exit", "rule_fails", "if_success"]) Tj T* ( ],) Tj T* ( [) Tj T* ( ...) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 347.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Rule explanation:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 329.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 0) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 323.4236 cm
+Q
+q
+1 0 0 1 62.69291 323.4236 cm
+Q
+q
+1 0 0 1 62.69291 311.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if the assertion contains a UserName value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 305.4236 cm
+Q
+q
+1 0 0 1 62.69291 293.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Abort the rule if the assertion does not contain a UserName value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 287.4236 cm
+Q
+q
+1 0 0 1 62.69291 275.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if the user is in the hard-coded list of black listed users.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 269.4236 cm
+Q
+q
+1 0 0 1 62.69291 257.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (If the test succeeds then immediately abort and return failure.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 257.4236 cm
+Q
+q
+1 0 0 1 62.69291 239.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 1) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 233.4236 cm
+Q
+q
+1 0 0 1 62.69291 233.4236 cm
+Q
+q
+1 0 0 1 62.69291 221.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Further processing) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 221.4236 cm
+Q
+q
+1 0 0 1 62.69291 203.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapped result in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 170.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (Null) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 140.2236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Format Strings and/or Concatenate Strings) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 98.22362 cm
+q
+BT 1 0 0 1 0 26 Tm 1.498651 Tw 12 TL /F1 10 Tf 0 0 0 rg (You can replace variables in a format string using the ) Tj 0 0 .501961 rg (interpolate ) Tj 0 0 0 rg (verb. String concatenation is trivially) Tj T* 0 Tw 1.745868 Tw (placing two variables adjacent to one another in a format string. Suppose you want to form an email) Tj T* 0 Tw (address from the username and domain in an assertion.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-16-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+155 0 obj
+<< /Length 4434 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 753.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapping in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 695.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "email": $email,) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 675.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The assertion in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 606.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL ({) Tj T* ( "UserName": "Bob",) Tj T* ( "Domain": "example.com") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 586.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Our rule in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 505.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 474 72 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F4 10 Tf 12 TL ([) Tj T* ( [) Tj T* ( ["interpolate", "$email", "$assertion[UserName]@$assertion[Domain]"],) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 485.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Rule explanation:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 467.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 0) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 461.4236 cm
+Q
+q
+1 0 0 1 62.69291 461.4236 cm
+Q
+q
+1 0 0 1 62.69291 437.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 9 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 8.205976 Tw (Replace the variable $assertion[UserName] with it's value and replace the variable) Tj T* 0 Tw ($assertion[Domain] with it's value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 437.4236 cm
+Q
+q
+1 0 0 1 62.69291 419.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapped result in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 362.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "email": "Bob@example.com",) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 318.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL .667984 Tw (Note, sometimes it's necessary to utilize braces to separate variables from surrounding text by using the) Tj T* 0 Tw .39811 Tw (brace notation. This can also make the format string more readable. Using braces to delimit variables the) Tj T* 0 Tw (above would be:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 237.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 498 72 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 50 Tm /F4 10 Tf 12 TL ([) Tj T* ( [) Tj T* ( ["interpolate", "$email", "${assertion[UserName]}@${assertion[Domain]}"],) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 207.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (Make associative array lookups case insensitive) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 165.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F1 10 Tf 12 TL 2.917126 Tw (Many systems treat field names as case insensitive. By default associative array indexing is case) Tj T* 0 Tw .627356 Tw (sensitive. The solution is to lower case all the keys in an associative array and then only use lower case) Tj T* 0 Tw (indices. Suppose you want the assertion associative array to be case insensitive.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 147.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapping in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 89.82362 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "user": $user,) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-17-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+156 0 obj
+<< /Length 7739 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 753.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The assertion in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 695.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "UserName": "Bob") Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 675.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Our rule in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 558.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 108 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 86 Tm /F4 10 Tf 12 TL ([) Tj T* ( [) Tj T* ( ["lower", "$assertion", "$assertion"],) Tj T* ( ["in", "username", "assertion"],) Tj T* ( ["exit", "rule_fails", "if_not_success"],) Tj T* ( ["set", "$user", "$assertion[username"]) Tj T* ( ]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 538.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Rule explanation:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 520.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Block 0) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 514.6236 cm
+Q
+q
+1 0 0 1 62.69291 514.6236 cm
+Q
+q
+1 0 0 1 62.69291 502.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (1.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Lower case all the keys in the assertion associative array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 496.6236 cm
+Q
+q
+1 0 0 1 62.69291 484.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (2.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test if the assertion contains a username value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 478.6236 cm
+Q
+q
+1 0 0 1 62.69291 466.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (3.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Abort the rule if the assertion does not contain a username value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 460.6236 cm
+Q
+q
+1 0 0 1 62.69291 448.6236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66 0 Td (4.) Tj T* -5.66 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Assign the username value in the assertion to $user) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 448.6236 cm
+Q
+q
+1 0 0 1 62.69291 430.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The mapped result in JSON is:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 373.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 48 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 26 Tm /F4 10 Tf 12 TL ({) Tj T* ( "user": "Bob",) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 340.4236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Verbs) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 322.4236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The following verbs are supported:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 316.4236 cm
+Q
+q
+1 0 0 1 62.69291 316.4236 cm
+Q
+q
+1 0 0 1 62.69291 304.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (set) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 298.4236 cm
+Q
+q
+1 0 0 1 62.69291 286.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (length) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 280.4236 cm
+Q
+q
+1 0 0 1 62.69291 268.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (interpolate) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 262.4236 cm
+Q
+q
+1 0 0 1 62.69291 250.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (append) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 244.4236 cm
+Q
+q
+1 0 0 1 62.69291 232.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (unique) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 226.4236 cm
+Q
+q
+1 0 0 1 62.69291 214.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (regexp) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 208.4236 cm
+Q
+q
+1 0 0 1 62.69291 196.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (regexp_replace) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 190.4236 cm
+Q
+q
+1 0 0 1 62.69291 178.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (split) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 172.4236 cm
+Q
+q
+1 0 0 1 62.69291 160.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (join) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 154.4236 cm
+Q
+q
+1 0 0 1 62.69291 142.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (lower) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 136.4236 cm
+Q
+q
+1 0 0 1 62.69291 124.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (upper) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 118.4236 cm
+Q
+q
+1 0 0 1 62.69291 106.4236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (compare) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 100.4236 cm
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-18-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+157 0 obj
+<< /Length 6506 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 753.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (in) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 747.0236 cm
+Q
+q
+1 0 0 1 62.69291 735.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (not_in) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 729.0236 cm
+Q
+q
+1 0 0 1 62.69291 717.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (exit) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 711.0236 cm
+Q
+q
+1 0 0 1 62.69291 699.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 -3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 10.5 0 Td (\177) Tj T* -10.5 0 Td ET
+Q
+Q
+q
+1 0 0 1 23 -3 cm
+q
+0 0 .501961 rg
+0 0 .501961 RG
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (continue) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 699.0236 cm
+Q
+q
+1 0 0 1 62.69291 633.0236 cm
+q
+BT 1 0 0 1 0 50 Tm .753876 Tw 12 TL /F1 10 Tf 0 0 0 rg (Some verbs have a side effects. A verb may set a boolean success/fail result which may then be tested) Tj T* 0 Tw .428988 Tw (with a subsequent verb. For example the ) Tj /F4 10 Tf 0 0 0 rg (fail ) Tj /F1 10 Tf 0 0 0 rg (verb can be used to indicate the rule fails if a prior result) Tj T* 0 Tw .029318 Tw (is either ) Tj /F4 10 Tf 0 0 0 rg (success ) Tj /F1 10 Tf 0 0 0 rg (or ) Tj /F4 10 Tf 0 0 0 rg (not_success) Tj /F1 10 Tf 0 0 0 rg (. The ) Tj /F4 10 Tf 0 0 0 rg (regexp ) Tj /F1 10 Tf 0 0 0 rg (verb which performs a regular expression search on a) Tj T* 0 Tw .726412 Tw (string stores the regular expression sub-matches as a side effect in the variables ) Tj /F4 10 Tf 0 0 0 rg ($regexp_array ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg ($regexp_map) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 600.0236 cm
+q
+BT 1 0 0 1 0 3.5 Tm 21 TL /F2 17.5 Tf 0 0 0 rg (Verb Definitions) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 570.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (set) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 552.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (set) Tj ( ) Tj ($variable) Tj ( ) Tj (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 536.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 521.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The variable being assigned \(i.e. lhs\)) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 505.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 490.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The value to assign to the variable \(i.e. rhs\). The value may be another variable or a constant.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 472.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 0 rg (set ) Tj /F1 10 Tf (assigns a value to a variable, in other words it's an assignment statement.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 445.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 427.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Initialize a variable to an empty array.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 393.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["set", "$groups", []]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 373.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Initialize a variable to an empty associative array.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 340.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["set", "$groups", {}]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 320.6236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Assign a string.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 287.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["set", "$version", "1.2.3"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 267.4236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Copy the ) Tj /F4 10 Tf 0 0 0 rg (UserName ) Tj /F1 10 Tf 0 0 0 rg (value from the assertion to a temporary variable.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 234.2236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["set", "$temp", "$assertion[UserName]"],) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 214.2236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Get the 2nd item in an array \(array indexing is zero based\)) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 181.0236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["set", "$group", "$groups[1]"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 161.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Set the associative array entry "IdP" to "kdc.example.com".) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 127.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["set", "$metadata[IdP]", "kdc.example.com""]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 91.47717 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-19-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+158 0 obj
+<< /Length 6125 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 747.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (length) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 729.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (length) Tj ( ) Tj ($variable) Tj ( ) Tj (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 713.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 698.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The variable which receives the length value) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 682.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 667.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The value whose length is to be determined. May be one of array, associative array, or string.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 649.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 0 rg (length ) Tj /F1 10 Tf (computes the number of items in the value. How this is done depends upon the type of value:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 633.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 618.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The length is the number of items in the array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 602.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (associative array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 587.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The length is the number of key/value pairs in the associative array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 571.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 556.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The length is the number of ) Tj /F3 10 Tf (characters ) Tj /F1 10 Tf (\(not octets\) in the string.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 529.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 499.0236 cm
+q
+BT 1 0 0 1 0 14 Tm 2.338651 Tw 12 TL /F1 10 Tf 0 0 0 rg (Count how many items are in the ) Tj /F4 10 Tf 0 0 0 rg ($groups ) Tj /F1 10 Tf 0 0 0 rg (array and assign that value to the ) Tj /F4 10 Tf 0 0 0 rg ($groups_length) Tj T* 0 Tw /F1 10 Tf 0 0 0 rg (variable.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 465.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["length", "$groups_length", "$groups"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 433.8236 cm
+q
+BT 1 0 0 1 0 14 Tm .752485 Tw 12 TL /F1 10 Tf 0 0 0 rg (Count how many key/value pairs are in the ) Tj /F4 10 Tf 0 0 0 rg ($assertion ) Tj /F1 10 Tf 0 0 0 rg (associative array and assign that value to the) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg ($num_assertion_values ) Tj /F1 10 Tf 0 0 0 rg (variable.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 400.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["length", "$num_assertion_values", "$assertion"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 368.6236 cm
+q
+BT 1 0 0 1 0 14 Tm 7.268443 Tw 12 TL /F1 10 Tf 0 0 0 rg (Count how many characters are in the assertion's UserName and assign the value to) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg ($username_length) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 335.4236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["length", "$user_name_length", "$assertion[UserName]"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 299.0772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 269.0772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (interpolate) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 251.0772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (interpolate) Tj ( ) Tj ($variable) Tj ( ) Tj (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 235.0772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 220.0772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (This variable is assigned the result of the interpolation.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 204.0772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 189.0772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (A string containing references to variables which will be replaced in the string.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 159.0772 cm
+q
+BT 1 0 0 1 0 14 Tm 1.30881 Tw 12 TL /F2 10 Tf 0 0 0 rg (interpolate ) Tj /F1 10 Tf (replaces each occurrence of a variable in a string with it's value. The result is assigned to) Tj T* 0 Tw ($variable.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 132.0772 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 102.0772 cm
+q
+BT 1 0 0 1 0 14 Tm 1.557633 Tw 12 TL /F1 10 Tf 0 0 0 rg (Form an email address given the username and domain. If the username is "jane" and the domain is) Tj T* 0 Tw ("example.com" then $email will be ") Tj 0 0 .501961 rg (jane@example.com) Tj 0 0 0 rg (") Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-20-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+159 0 obj
+<< /Length 5390 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 739.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["interpolate", "$email", "${username}@${domain}"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 703.4772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 673.4772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (append) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 655.4772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (append) Tj ( ) Tj ($variable) Tj ( ) Tj (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 639.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 624.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (This variable ) Tj /F2 10 Tf (must ) Tj /F1 10 Tf (be an array. It is modified in place by appending ) Tj /F4 10 Tf 0 0 0 rg (value ) Tj /F1 10 Tf 0 0 0 rg (to the end of the array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 608.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 593.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The value to append to the end of the array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 575.4772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 0 rg (append ) Tj /F1 10 Tf (adds a value to end of an array.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 548.4772 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 530.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Append the role "qa_test" to the roles list.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 497.2772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["append", "$roles", "qa_test"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 460.9307 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 430.9307 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (unique) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 412.9307 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (unique) Tj ( ) Tj ($variable) Tj ( ) Tj (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 396.9307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 381.9307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (This variable is assigned the unique values in the ) Tj /F4 10 Tf 0 0 0 rg (value ) Tj /F1 10 Tf 0 0 0 rg (array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 365.9307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 350.9307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (An array of values. ) Tj /F2 10 Tf (must ) Tj /F1 10 Tf (be an array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 320.9307 cm
+q
+BT 1 0 0 1 0 14 Tm 1.099986 Tw 12 TL /F2 10 Tf 0 0 0 rg (unique ) Tj /F1 10 Tf (builds an array of unique values in ) Tj /F4 10 Tf 0 0 0 rg (value ) Tj /F1 10 Tf 0 0 0 rg (by stripping out duplicates and assigns the array of) Tj T* 0 Tw (unique values to ) Tj /F4 10 Tf 0 0 0 rg ($variable) Tj /F1 10 Tf 0 0 0 rg (. The order of items in the ) Tj /F4 10 Tf 0 0 0 rg (value ) Tj /F1 10 Tf 0 0 0 rg (array are preserved.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 293.9307 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 275.9307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL ($one_of_a_kind will be assigned ["a", "b"]) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 242.7307 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["unique", "$one_of_a_kind", ["a", "b", "a"]]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 206.3843 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 176.3843 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (regexp) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 158.3843 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (regexp) Tj ( ) Tj (string) Tj ( ) Tj (pattern) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 142.3843 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 127.3843 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The string the regular expression pattern is applied to.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 111.3843 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (pattern) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 96.38425 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The regular expression pattern.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-21-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+160 0 obj
+<< /Length 6206 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 741.0236 cm
+q
+BT 1 0 0 1 0 14 Tm 1.098443 Tw 12 TL /F2 10 Tf 0 0 0 rg (regexp ) Tj /F1 10 Tf (performs a regular expression match against ) Tj /F4 10 Tf 0 0 0 rg (string) Tj /F1 10 Tf 0 0 0 rg (. The regular expression pattern syntax is) Tj T* 0 Tw (defined by the regular expression implementation of the language this API is written in.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 699.0236 cm
+q
+BT 1 0 0 1 0 26 Tm 2.001412 Tw 12 TL /F1 10 Tf 0 0 0 rg (Pattern groups are a convenient way to select sub-matches. Pattern groups may accessed by either) Tj T* 0 Tw .952485 Tw (group number or group name. After a successful regular expression match the groups are stored in the) Tj T* 0 Tw (special variables ) Tj /F4 10 Tf 0 0 0 rg ($regexp_array ) Tj /F1 10 Tf 0 0 0 rg (and ) Tj /F4 10 Tf 0 0 0 rg ($regexp_map) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 657.0236 cm
+q
+BT 1 0 0 1 0 26 Tm .150651 Tw 12 TL /F4 10 Tf 0 0 0 rg ($regexp_array ) Tj /F1 10 Tf 0 0 0 rg (is used to access the groups by numerical index. Groups are numbered by counting the) Tj T* 0 Tw 2.123318 Tw (left parenthesis group delimiter starting at 1. Group 0 is the entire match. ) Tj /F4 10 Tf 0 0 0 rg ($regexp_array ) Tj /F1 10 Tf 0 0 0 rg (is valid) Tj T* 0 Tw (irregardless of whether you used named groups or not.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 627.0236 cm
+q
+BT 1 0 0 1 0 14 Tm 1.219985 Tw 12 TL /F4 10 Tf 0 0 0 rg ($regexp_map ) Tj /F1 10 Tf 0 0 0 rg (is used to access the groups by name. ) Tj /F4 10 Tf 0 0 0 rg ($regexp_map ) Tj /F1 10 Tf 0 0 0 rg (is only valid if you used named) Tj T* 0 Tw (groups in the pattern.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 600.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 534.0236 cm
+q
+BT 1 0 0 1 0 50 Tm .59832 Tw 12 TL /F1 10 Tf 0 0 0 rg (Many user names are of the form ") Tj 0 0 .501961 rg (user@domain) Tj 0 0 0 rg (", to split the username from the domain and to be able) Tj T* 0 Tw 2.444985 Tw (to work with those values independently use a regular expression and then assign the results to a) Tj T* 0 Tw .340574 Tw (variable. In this example there are two regular expression groups, the first group is the username and the) Tj T* 0 Tw 1.974104 Tw (second group is the domain. In the first example we use named groups and then access the match) Tj T* 0 Tw (information in the special variable ) Tj /F4 10 Tf 0 0 0 rg ($regexp_map ) Tj /F1 10 Tf 0 0 0 rg (via the name of the group.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 464.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+BT 1 0 0 1 0 38 Tm 12 TL /F4 10 Tf 0 0 0 rg (["regexp", "$assertion[UserName]", "\(?P) Tj (<) Tj (username) Tj (>) Tj (\\\\w+\)@\(?P) Tj (<) Tj (domain) Tj (>) Tj (.+\)"],) Tj T* (["continue", "if_not_success"],) Tj T* (["set", "$username", "$regexp_map[username]"],) Tj T* (["set", "$domain", "$regexp_map[domain]"],) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 432.8236 cm
+q
+BT 1 0 0 1 0 14 Tm .429985 Tw 12 TL /F1 10 Tf 0 0 0 rg (This is exactly equivalent but uses numbered groups instead of named groups. In this instance the group) Tj T* 0 Tw (matches are stored in the special variable ) Tj /F4 10 Tf 0 0 0 rg ($regexp_array ) Tj /F1 10 Tf 0 0 0 rg (and accessed by numerical index.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 363.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 60 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 38 Tm /F4 10 Tf 12 TL (["regexp", "$assertion[UserName]", "\(\\\\w+\)@\(.+\)"],) Tj T* (["continue", "if_not_success"],) Tj T* (["set", "$username", "$regexp_array[1]"],) Tj T* (["set", "$domain", "$regexp_array[2]"],) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 327.2772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 297.2772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (regexp_replace) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 279.2772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (regexp_replace) Tj ( ) Tj ($variable) Tj ( ) Tj (string) Tj ( ) Tj (pattern) Tj ( ) Tj (replacement) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 263.2772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 248.2772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The variable which receives result of the replacement.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 232.2772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 217.2772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The string to perform the replacement on.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 201.2772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (pattern) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 186.2772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The regular expression pattern.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 170.2772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (replacement) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 155.2772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The replacement specification.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 125.2772 cm
+q
+BT 1 0 0 1 0 14 Tm .08998 Tw 12 TL /F2 10 Tf 0 0 0 rg (regexp_replace ) Tj /F1 10 Tf (replaces each occurrence of ) Tj /F4 10 Tf 0 0 0 rg (pattern ) Tj /F1 10 Tf 0 0 0 rg (in ) Tj /F4 10 Tf 0 0 0 rg ($string ) Tj /F1 10 Tf 0 0 0 rg (with ) Tj /F4 10 Tf 0 0 0 rg (replacement) Tj /F1 10 Tf 0 0 0 rg (. See ) Tj 0 0 .501961 rg (regexp ) Tj 0 0 0 rg (for) Tj T* 0 Tw (details of using regular expressions.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-22-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+161 0 obj
+<< /Length 5909 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 750.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 732.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Convert hyphens in a name to underscores.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 698.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["regexp_replace", "$name", "$name", "-", "_"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 662.4772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 632.4772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (split) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 614.4772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (split) Tj ( ) Tj ($variable) Tj ( ) Tj (string) Tj ( ) Tj (pattern) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 598.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 583.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (This variable is assigned an array containing the split items.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 567.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 552.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The string to split into separate items.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 536.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (pattern) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 521.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The regular expression pattern used to split the string.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 479.4772 cm
+q
+BT 1 0 0 1 0 26 Tm 1.24686 Tw 12 TL /F2 10 Tf 0 0 0 rg (split ) Tj /F1 10 Tf (splits ) Tj /F4 10 Tf 0 0 0 rg (string ) Tj /F1 10 Tf 0 0 0 rg (into separate pieces and assigns the result to ) Tj /F4 10 Tf 0 0 0 rg ($variable ) Tj /F1 10 Tf 0 0 0 rg (as an array of pieces.) Tj T* 0 Tw .715984 Tw (The split occurs wherever the regular expression ) Tj /F4 10 Tf 0 0 0 rg (pattern ) Tj /F1 10 Tf 0 0 0 rg (occurs in ) Tj /F4 10 Tf 0 0 0 rg (string) Tj /F1 10 Tf 0 0 0 rg (. See ) Tj 0 0 .501961 rg (regexp ) Tj 0 0 0 rg (for details of) Tj T* 0 Tw (using regular expressions.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 452.4772 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 422.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .074431 Tw (Split a list of groups separated by a colon \(:\) into an array of individual group names. If $assertion[Groups]) Tj T* 0 Tw (contained the string "user:admin" then $group_list will set to ["user", "admin"].) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 389.2772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["split", "$group_list", "$assertion[Groups]", ":"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 352.9307 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 322.9307 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (join) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 304.9307 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (join) Tj ( ) Tj ($variable) Tj ( ) Tj (array) Tj ( ) Tj (join_string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 288.9307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 273.9307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (This variable is assigned the string result of the join operation.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 257.9307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 242.9307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (An array of string items to be joined together with ) Tj /F4 10 Tf 0 0 0 rg ($join_string) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 226.9307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (join_string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 211.9307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The string inserted between each element in ) Tj /F4 10 Tf 0 0 0 rg (array) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 181.9307 cm
+q
+BT 1 0 0 1 0 14 Tm .074987 Tw 12 TL /F2 10 Tf 0 0 0 rg (join ) Tj /F1 10 Tf (accepts an array of strings and produces a single string where each element in the array is separated) Tj T* 0 Tw (by ) Tj /F4 10 Tf 0 0 0 rg (join_string) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 154.9307 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 112.9307 cm
+q
+BT 1 0 0 1 0 26 Tm .817488 Tw 12 TL /F1 10 Tf 0 0 0 rg (Convert a list of group names into a single string where each group name is separated by a colon \(:\). If) Tj T* 0 Tw 1.533059 Tw (the array ) Tj /F4 10 Tf 0 0 0 rg ($group_list ) Tj /F1 10 Tf 0 0 0 rg (is ["user", "admin"] and the ) Tj /F4 10 Tf 0 0 0 rg (join_string ) Tj /F1 10 Tf 0 0 0 rg (is ":" then the ) Tj /F4 10 Tf 0 0 0 rg ($group_string) Tj T* 0 Tw /F1 10 Tf 0 0 0 rg (variable will be set to "user:admin".) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-23-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+162 0 obj
+<< /Length 6038 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 739.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["join", "$group_string", "$groups", ":"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 703.4772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 673.4772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (lower) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 655.4772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (lower) Tj ( ) Tj ($variable) Tj ( ) Tj (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 639.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 624.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (This variable is assigned the result of the lower operation.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 608.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 593.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The value to lower case, may be either a string, array, or associative array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 575.4772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 0 rg (lower ) Tj /F1 10 Tf (lower cases the input value. The input value may be one of the following types:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 559.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 544.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The string is lower cased.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 528.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 501.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 14 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.242619 Tw (Each member of the array must be a string, the result is an array with the items replaced by their) Tj T* 0 Tw (lower case value.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 485.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (associative array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 458.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 14 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 14 Tm 2.587485 Tw 12 TL /F1 10 Tf 0 0 0 rg (Each key in the associative array is lower cased. The values associated with the key are ) Tj /F2 10 Tf (not) Tj T* 0 Tw /F1 10 Tf (modified.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 431.4772 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 413.4772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Lookup ) Tj /F4 10 Tf 0 0 0 rg (UserName ) Tj /F1 10 Tf 0 0 0 rg (in the assertion and set the variable ) Tj /F4 10 Tf 0 0 0 rg ($username ) Tj /F1 10 Tf 0 0 0 rg (to it's lower case value.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 380.2772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["lower", "$username", "$assertion[UserName]"],) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 348.2772 cm
+q
+BT 1 0 0 1 0 14 Tm .416457 Tw 12 TL /F1 10 Tf 0 0 0 rg (Set each member of the ) Tj /F4 10 Tf 0 0 0 rg ($groups ) Tj /F1 10 Tf 0 0 0 rg (array to it's lower case value. If ) Tj /F4 10 Tf 0 0 0 rg ($groups ) Tj /F1 10 Tf 0 0 0 rg (was ["User", "Admin"] then) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg ($groups ) Tj /F1 10 Tf 0 0 0 rg (will become ["user", "admin"].) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 315.0772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["lower", "$groups", "$groups"],) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 283.0772 cm
+q
+BT 1 0 0 1 0 14 Tm .065868 Tw 12 TL /F1 10 Tf 0 0 0 rg (To enable case insensitive lookup's in an associative array lower case each key in the associative array. If) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg ($assertion ) Tj /F1 10 Tf 0 0 0 rg (was {"UserName": "JoeUser"} then ) Tj /F4 10 Tf 0 0 0 rg ($assertion ) Tj /F1 10 Tf 0 0 0 rg (will become {"username": "JoeUser"}) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 249.8772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 24 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F4 10 Tf 12 TL (["lower", "$assertion", $assertion"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 213.5307 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 183.5307 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (upper) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 165.5307 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (upper) Tj ( ) Tj ($variable) Tj ( ) Tj (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 149.5307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL ($variable) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 134.5307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (This variable is assigned the result of the upper operation.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 118.5307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (value) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 103.5307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The value to upper case, may be either a string, array, or associative array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-24-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+163 0 obj
+<< /Length 6022 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 753.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 0 rg (upper ) Tj /F1 10 Tf (is exactly analogous to ) Tj 0 0 .501961 rg (lower ) Tj 0 0 0 rg (except the values are upper cased, see ) Tj 0 0 .501961 rg (lower ) Tj 0 0 0 rg (for details.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 724.6772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 694.6772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (in) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 676.6772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (in) Tj ( ) Tj (member) Tj ( ) Tj (collection) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 660.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (member) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 645.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The value whose membership is being tested.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 629.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (collection) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 614.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (A collection of members. May be string, array or associative array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 584.6772 cm
+q
+BT 1 0 0 1 0 14 Tm 1.200542 Tw 12 TL /F2 10 Tf 0 0 0 rg (in ) Tj /F1 10 Tf (tests to see if ) Tj /F4 10 Tf 0 0 0 rg (member ) Tj /F1 10 Tf 0 0 0 rg (is a member of ) Tj /F4 10 Tf 0 0 0 rg (collection) Tj /F1 10 Tf 0 0 0 rg (. The membership test depends on the type of) Tj T* 0 Tw (collection, the following are supported:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 568.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 553.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If any item in the array is equal to ) Tj /F4 10 Tf 0 0 0 rg (member ) Tj /F1 10 Tf 0 0 0 rg (then the result is success.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 537.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (associative array) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 522.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If the associative array contains a key equal to ) Tj /F4 10 Tf 0 0 0 rg (member ) Tj /F1 10 Tf 0 0 0 rg (then the result is success.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 506.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (string) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 491.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If the string contains a sub-string equal to ) Tj /F4 10 Tf 0 0 0 rg (member ) Tj /F1 10 Tf 0 0 0 rg (then the result is success.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 464.6772 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 446.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test to see if the assertion contains a UserName value.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 401.4772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F4 10 Tf 12 TL (["in", "UserName", "$assertion"]) Tj T* (["continue", "if_not_success"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 381.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Test to see if a group is one of "user" or "admin".) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 336.2772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F4 10 Tf 12 TL (["in", "$group", ["user", "admin"]]) Tj T* (["continue", "if_not_success"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 316.2772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Test to see if the sub-string "BigCorp" is in the assertion's ) Tj /F4 10 Tf 0 0 0 rg (Provider ) Tj /F1 10 Tf 0 0 0 rg (value.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 271.0772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F4 10 Tf 12 TL (["in", "BigCorp", "$assertion[Provider]"]) Tj T* (["continue", "if_not_success"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 234.7307 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 204.7307 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (not_in) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 186.7307 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (in) Tj ( ) Tj (member) Tj ( ) Tj (collection) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 170.7307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (member) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 155.7307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The value whose membership is being tested.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 139.7307 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (collection) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 124.7307 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (A collection of members. May be string, array or associative array.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 106.7307 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F2 10 Tf 0 0 0 rg (not_in ) Tj /F1 10 Tf (is exactly analogous to ) Tj 0 0 .501961 rg (in ) Tj 0 0 0 rg (except the sense of the test is reversed. See ) Tj 0 0 .501961 rg (in ) Tj 0 0 0 rg (for details.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-25-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+164 0 obj
+<< /Length 11031 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 736.6772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 706.6772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (compare) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 688.6772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (compare) Tj ( ) Tj (left) Tj ( ) Tj (operator) Tj ( ) Tj (right) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 672.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (left) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 657.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The left hand value of the binary operator.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 641.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (operator) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 626.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The binary operator used for comparing left to right.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 610.6772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (right) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 595.6772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The right hand value of the binary operator.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 565.6772 cm
+q
+BT 1 0 0 1 0 14 Tm 2.41061 Tw 12 TL /F2 10 Tf 0 0 0 rg (compare ) Tj /F1 10 Tf (compares the left value to the right value according the operator and sets success if the) Tj T* 0 Tw (comparison evaluates to True. The following relational operators are supported.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 559.6772 cm
+Q
+q
+1 0 0 1 62.69291 433.6772 cm
+1 1 1 rg
+n 0 126 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 108 469.8898 -18 re f*
+1 1 1 rg
+n 0 90 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 72 469.8898 -18 re f*
+1 1 1 rg
+n 0 54 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 36 469.8898 -18 re f*
+1 1 1 rg
+n 0 18 469.8898 -18 re f*
+.960784 .960784 .862745 rg
+n 0 126 469.8898 -18 re f*
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 130.3908 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 45.46542 0 Td (Operator) Tj T* -45.46542 0 Td ET
+Q
+Q
+q
+1 0 0 1 148.3908 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 315.4989 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 132.7445 0 Td (Description) Tj T* -132.7445 0 Td ET
+Q
+Q
+0 0 0 rg
+q
+1 0 0 1 6 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (==) Tj T* ET
+Q
+Q
+q
+1 0 0 1 148.3908 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (equal) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (!=) Tj T* ET
+Q
+Q
+q
+1 0 0 1 148.3908 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (not equal) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (<) Tj T* ET
+Q
+Q
+q
+1 0 0 1 148.3908 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (less than) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 39 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (<) Tj (=) Tj T* ET
+Q
+Q
+q
+1 0 0 1 148.3908 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (less than or equal) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (>) Tj T* ET
+Q
+Q
+q
+1 0 0 1 148.3908 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (greater than) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 3 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (>) Tj (=) Tj T* ET
+Q
+Q
+q
+1 0 0 1 148.3908 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (greater than or equal) Tj T* ET
+Q
+Q
+q
+1 J
+1 j
+0 0 0 RG
+.25 w
+n 0 108 m 469.8898 108 l S
+n 0 90 m 469.8898 90 l S
+n 0 72 m 469.8898 72 l S
+n 0 54 m 469.8898 54 l S
+n 0 36 m 469.8898 36 l S
+n 0 18 m 469.8898 18 l S
+n 142.3908 0 m 142.3908 126 l S
+n 0 126 m 469.8898 126 l S
+n 0 0 m 469.8898 0 l S
+n 0 0 m 0 126 l S
+n 469.8898 0 m 469.8898 126 l S
+Q
+Q
+q
+1 0 0 1 62.69291 433.6772 cm
+Q
+q
+1 0 0 1 62.69291 379.6772 cm
+q
+BT 1 0 0 1 0 38 Tm .320542 Tw 12 TL /F1 10 Tf 0 0 0 rg (The left and right hand sides of the comparison operator ) Tj /F3 10 Tf (must ) Tj /F1 10 Tf (be the same type, no type conversions are) Tj T* 0 Tw 2.43784 Tw (performed. Not all combinations of operator and type are supported. The table below illustrates the) Tj T* 0 Tw 1.126651 Tw (supported combinations. Essentially you can test for equality or inequality on any type. But only strings) Tj T* 0 Tw (and numbers support the magnitude relational operators.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 373.6772 cm
+Q
+q
+1 0 0 1 62.69291 247.6772 cm
+1 1 1 rg
+n 0 126 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 108 469.8898 -18 re f*
+1 1 1 rg
+n 0 90 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 72 469.8898 -18 re f*
+1 1 1 rg
+n 0 54 469.8898 -18 re f*
+.878431 .878431 .878431 rg
+n 0 36 469.8898 -18 re f*
+1 1 1 rg
+n 0 18 469.8898 -18 re f*
+.960784 .960784 .862745 rg
+n 0 126 469.8898 -18 re f*
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+q
+1 0 0 1 6 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 67.64233 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 14.09117 0 Td (Operator) Tj T* -14.09117 0 Td ET
+Q
+Q
+q
+1 0 0 1 85.64233 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 51.71387 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 6.966933 0 Td (STRING) Tj T* -6.966933 0 Td ET
+Q
+Q
+q
+1 0 0 1 149.3562 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 59.6781 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 7.61405 0 Td (INTEGER) Tj T* -7.61405 0 Td ET
+Q
+Q
+q
+1 0 0 1 221.0343 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 35.7854 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 4.8327 0 Td (REAL) Tj T* -4.8327 0 Td ET
+Q
+Q
+q
+1 0 0 1 268.8197 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 59.6781 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.66405 0 Td (BOOLEAN) Tj T* -5.66405 0 Td ET
+Q
+Q
+q
+1 0 0 1 340.4978 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 27.82117 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 3.075583 0 Td (MAP) Tj T* -3.075583 0 Td ET
+Q
+Q
+q
+1 0 0 1 380.319 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 35.7854 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 7.3327 0 Td (LIST) Tj T* -7.3327 0 Td ET
+Q
+Q
+q
+1 0 0 1 428.1044 111 cm
+q
+.960784 .960784 .862745 rg
+n 0 0 35.7854 12 re f*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 5.1127 0 Td (NULL) Tj T* -5.1127 0 Td ET
+Q
+Q
+0 0 0 rg
+q
+1 0 0 1 6 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (==) Tj T* ET
+Q
+Q
+q
+1 0 0 1 85.64233 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 149.3562 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 221.0343 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 268.8197 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 340.4978 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 380.319 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 428.1044 93 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (!=) Tj T* ET
+Q
+Q
+q
+1 0 0 1 85.64233 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 149.3562 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 221.0343 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 268.8197 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 340.4978 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 380.319 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 428.1044 75 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (<) Tj T* ET
+Q
+Q
+q
+1 0 0 1 85.64233 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 149.3562 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 221.0343 57 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 39 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (<) Tj (=) Tj T* ET
+Q
+Q
+q
+1 0 0 1 85.64233 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 149.3562 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 221.0343 39 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (>) Tj T* ET
+Q
+Q
+q
+1 0 0 1 85.64233 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 149.3562 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 221.0343 21 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 6 3 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (>) Tj (=) Tj T* ET
+Q
+Q
+q
+1 0 0 1 85.64233 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 149.3562 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 0 0 1 221.0343 3 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (X) Tj T* ET
+Q
+Q
+q
+1 J
+1 j
+0 0 0 RG
+.25 w
+n 0 108 m 469.8898 108 l S
+n 0 90 m 469.8898 90 l S
+n 0 72 m 469.8898 72 l S
+n 0 54 m 469.8898 54 l S
+n 0 36 m 469.8898 36 l S
+n 0 18 m 469.8898 18 l S
+n 79.64233 0 m 79.64233 126 l S
+n 143.3562 0 m 143.3562 126 l S
+n 215.0343 0 m 215.0343 126 l S
+n 262.8197 0 m 262.8197 126 l S
+n 334.4978 0 m 334.4978 126 l S
+n 374.319 0 m 374.319 126 l S
+n 422.1044 0 m 422.1044 126 l S
+n 0 126 m 469.8898 126 l S
+n 0 0 m 469.8898 0 l S
+n 0 0 m 0 126 l S
+n 469.8898 0 m 469.8898 126 l S
+Q
+Q
+q
+1 0 0 1 62.69291 247.6772 cm
+Q
+q
+1 0 0 1 62.69291 220.6772 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 202.6772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Test to see if the ) Tj /F4 10 Tf 0 0 0 rg ($groups ) Tj /F1 10 Tf 0 0 0 rg (array has at least 2 members) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 157.4772 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+BT 1 0 0 1 0 14 Tm 12 TL /F4 10 Tf 0 0 0 rg (["length", "$group_length", "$groups"],) Tj T* (["compare", "$group_length", ") Tj (>) Tj (=", 2]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 121.1307 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-26-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+165 0 obj
+<< /Length 6843 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 747.0236 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (exit) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 729.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (exit) Tj ( ) Tj (status) Tj ( ) Tj (criteria) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 713.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (status) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 698.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The result for the rule.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 682.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (criteria) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 667.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The criteria upon which will cause the rule will be immediately exited with a failed status.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 625.0236 cm
+q
+BT 1 0 0 1 0 26 Tm 1.094431 Tw 12 TL /F2 10 Tf 0 0 0 rg (exit ) Tj /F1 10 Tf (causes the rule being executed to immediately exit and a rule result if the specified criteria is met.) Tj T* 0 Tw .433876 Tw (Statement verbs such as ) Tj 0 0 .501961 rg (in ) Tj 0 0 0 rg (or ) Tj 0 0 .501961 rg (compare ) Tj 0 0 0 rg (set the result status which may be tested with the ) Tj /F4 10 Tf 0 0 0 rg (success ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg (not_success ) Tj /F1 10 Tf 0 0 0 rg (criteria.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 607.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The exit ) Tj /F4 10 Tf 0 0 0 rg (status ) Tj /F1 10 Tf 0 0 0 rg (may be one of:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 591.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (rule_fails) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 576.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The rule has failed and no mapping will occur.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 560.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (rule_succeeds) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 545.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The rule succeeded and the mapping will be applied.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 527.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The ) Tj /F4 10 Tf 0 0 0 rg (criteria ) Tj /F1 10 Tf 0 0 0 rg (may be one of:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 511.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (if_success) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 496.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If current result status is success then exit with ) Tj /F4 10 Tf 0 0 0 rg (status) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 480.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (if_not_success) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 465.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (If current result status is not success then exit with ) Tj /F4 10 Tf 0 0 0 rg (status) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 449.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (always) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 434.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (Unconditionally exit with ) Tj /F4 10 Tf 0 0 0 rg (status) Tj /F1 10 Tf 0 0 0 rg (.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 418.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (never) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 403.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Effectively a no-op. Useful for debugging.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 376.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 358.0236 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The rule requires ) Tj /F4 10 Tf 0 0 0 rg (UserName ) Tj /F1 10 Tf 0 0 0 rg (to be in the assertion.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 312.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 36 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F4 10 Tf 12 TL (["in", "UserName", "$assertion"]) Tj T* (["exit", "rule_fails", "if_not_success"]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 276.4772 cm
+n 0 14.17323 m 469.8898 14.17323 l S
+Q
+q
+1 0 0 1 62.69291 246.4772 cm
+q
+BT 1 0 0 1 0 3 Tm 18 TL /F2 15 Tf 0 0 0 rg (continue) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 228.4772 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F4 10 Tf 0 0 0 rg (continue) Tj ( ) Tj (criteria) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 212.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (criteria) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 197.4772 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+BT 1 0 0 1 0 2 Tm 12 TL /F1 10 Tf 0 0 0 rg (The criteria which causes the remainder of the ) Tj /F3 10 Tf (block ) Tj /F1 10 Tf (to be skipped.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 155.4772 cm
+q
+BT 1 0 0 1 0 26 Tm .277356 Tw 12 TL /F2 10 Tf 0 0 0 rg (continue ) Tj /F1 10 Tf (is used to control execution for statement blocks. It mirrors in a crude way the ) Tj /F3 10 Tf 0 0 0 rg (if ) Tj /F1 10 Tf 0 0 0 rg (expression in a) Tj T* 0 Tw .112485 Tw (procedural language. ) Tj /F4 10 Tf 0 0 0 rg (continue ) Tj /F1 10 Tf 0 0 0 rg (does ) Tj /F3 10 Tf (not ) Tj /F1 10 Tf (affect the success or failure of a rule, rather it controls whether) Tj T* 0 Tw (subsequent statements in a block are executed or not. Control continues at the next statement block.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 125.4772 cm
+q
+BT 1 0 0 1 0 14 Tm .433876 Tw 12 TL /F1 10 Tf 0 0 0 rg (Statement verbs such as ) Tj 0 0 .501961 rg (in ) Tj 0 0 0 rg (or ) Tj 0 0 .501961 rg (compare ) Tj 0 0 0 rg (set the result status which may be tested with the ) Tj /F4 10 Tf 0 0 0 rg (success ) Tj /F1 10 Tf 0 0 0 rg (and) Tj T* 0 Tw /F4 10 Tf 0 0 0 rg (not_success ) Tj /F1 10 Tf 0 0 0 rg (criteria.) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 107.4772 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The criteria may be one of:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 91.47717 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (if_success) Tj T* ET
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-27-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+166 0 obj
+<< /Length 3107 >>
+stream
+1 0 0 1 0 0 cm BT /F1 12 Tf 14.4 TL ET
+q
+1 0 0 1 62.69291 738.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 14 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL 1.22936 Tw (If current result status is success then exit the statement block and continue execution at the next) Tj T* 0 Tw (statement block.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 722.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (if_not_success) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 695.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 14 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 14 Tm /F1 10 Tf 12 TL .175868 Tw (If current result status is not success then exit the statement block and continue execution at the next) Tj T* 0 Tw (statement block.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 679.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (always) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 664.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Immediately exit the statement block and continue execution at the next statement block.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 648.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F2 10 Tf 12 TL (never) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 633.0236 cm
+0 0 0 rg
+BT /F1 10 Tf 12 TL ET
+BT 1 0 0 1 0 2 Tm T* ET
+q
+1 0 0 1 20 0 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (Effectively a no-op. Useful for debugging. Execution continues at the next statement.) Tj T* ET
+Q
+Q
+q
+Q
+Q
+q
+1 0 0 1 62.69291 606.0236 cm
+q
+BT 1 0 0 1 0 2.5 Tm 15 TL /F6 12.5 Tf 0 0 0 rg (Examples:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 588.0236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (The following pseudo code:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 482.8236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 96 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 74 Tm /F4 10 Tf 12 TL (roles = [];) Tj T* (if \("Groups" in assertion\) {) Tj T* ( groups = assertion["Groups"].split\(":"\);) Tj T* ( if \("qa_test" in groups\) {) Tj T* ( roles.append\("tester"\);) Tj T* ( }) Tj T* (}) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 62.69291 462.8236 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL (could be implemented this way:) Tj T* ET
+Q
+Q
+q
+1 0 0 1 62.69291 333.6236 cm
+q
+q
+1 0 0 1 0 0 cm
+q
+1 0 0 1 6.6 6.6 cm
+q
+.662745 .662745 .662745 RG
+.5 w
+.960784 .960784 .862745 rg
+n -6 -6 468.6898 120 re B*
+Q
+q
+0 0 0 rg
+BT 1 0 0 1 0 98 Tm /F4 10 Tf 12 TL ([) Tj T* ( ["set", "$roles", []],) Tj T* ( ["in", "Groups", "$assertion"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["split" "$groups", $assertion[Groups]", ":"],) Tj T* ( ["in", "qa_test", "$groups"],) Tj T* ( ["continue", "if_not_success"],) Tj T* ( ["append", "$roles", "tester"]) Tj T* (]) Tj T* ET
+Q
+Q
+Q
+Q
+Q
+q
+1 0 0 1 56.69291 56.69291 cm
+q
+0 0 0 rg
+BT 1 0 0 1 0 2 Tm /F1 10 Tf 12 TL 232.0549 0 Td (-28-) Tj T* -232.0549 0 Td ET
+Q
+Q
+
+endstream
+endobj
+167 0 obj
+<< /Nums [ 0 168 0 R 1 169 0 R 2 170 0 R 3 171 0 R 4 172 0 R
+ 5 173 0 R 6 174 0 R 7 175 0 R 8 176 0 R 9 177 0 R
+ 10 178 0 R 11 179 0 R 12 180 0 R 13 181 0 R 14 182 0 R
+ 15 183 0 R 16 184 0 R 17 185 0 R 18 186 0 R 19 187 0 R
+ 20 188 0 R 21 189 0 R 22 190 0 R 23 191 0 R 24 192 0 R
+ 25 193 0 R 26 194 0 R 27 195 0 R ] >>
+endobj
+168 0 obj
+<< /S /D /St 1 >>
+endobj
+169 0 obj
+<< /S /D /St 2 >>
+endobj
+170 0 obj
+<< /S /D /St 3 >>
+endobj
+171 0 obj
+<< /S /D /St 4 >>
+endobj
+172 0 obj
+<< /S /D /St 5 >>
+endobj
+173 0 obj
+<< /S /D /St 6 >>
+endobj
+174 0 obj
+<< /S /D /St 7 >>
+endobj
+175 0 obj
+<< /S /D /St 8 >>
+endobj
+176 0 obj
+<< /S /D /St 9 >>
+endobj
+177 0 obj
+<< /S /D /St 10 >>
+endobj
+178 0 obj
+<< /S /D /St 11 >>
+endobj
+179 0 obj
+<< /S /D /St 12 >>
+endobj
+180 0 obj
+<< /S /D /St 13 >>
+endobj
+181 0 obj
+<< /S /D /St 14 >>
+endobj
+182 0 obj
+<< /S /D /St 15 >>
+endobj
+183 0 obj
+<< /S /D /St 16 >>
+endobj
+184 0 obj
+<< /S /D /St 17 >>
+endobj
+185 0 obj
+<< /S /D /St 18 >>
+endobj
+186 0 obj
+<< /S /D /St 19 >>
+endobj
+187 0 obj
+<< /S /D /St 20 >>
+endobj
+188 0 obj
+<< /S /D /St 21 >>
+endobj
+189 0 obj
+<< /S /D /St 22 >>
+endobj
+190 0 obj
+<< /S /D /St 23 >>
+endobj
+191 0 obj
+<< /S /D /St 24 >>
+endobj
+192 0 obj
+<< /S /D /St 25 >>
+endobj
+193 0 obj
+<< /S /D /St 26 >>
+endobj
+194 0 obj
+<< /S /D /St 27 >>
+endobj
+195 0 obj
+<< /S /D /St 28 >>
+endobj
+xref
+0 196
+0000000000 65535 f
+0000000075 00000 n
+0000000163 00000 n
+0000000273 00000 n
+0000000388 00000 n
+0000000599 00000 n
+0000000770 00000 n
+0000000940 00000 n
+0000001111 00000 n
+0000026970 00000 n
+0000037046 00000 n
+0000037165 00000 n
+0000037470 00000 n
+0000037579 00000 n
+0000037751 00000 n
+0000037923 00000 n
+0000038037 00000 n
+0000038275 00000 n
+0000038487 00000 n
+0000038659 00000 n
+0000038831 00000 n
+0000039069 00000 n
+0000039241 00000 n
+0000039413 00000 n
+0000039585 00000 n
+0000039757 00000 n
+0000039929 00000 n
+0000040188 00000 n
+0000040400 00000 n
+0000040571 00000 n
+0000040802 00000 n
+0000041014 00000 n
+0000041186 00000 n
+0000041417 00000 n
+0000041540 00000 n
+0000041752 00000 n
+0000041924 00000 n
+0000042155 00000 n
+0000042367 00000 n
+0000042579 00000 n
+0000042791 00000 n
+0000042963 00000 n
+0000043194 00000 n
+0000043406 00000 n
+0000043578 00000 n
+0000043750 00000 n
+0000043922 00000 n
+0000044094 00000 n
+0000044266 00000 n
+0000044438 00000 n
+0000044610 00000 n
+0000044782 00000 n
+0000044954 00000 n
+0000045126 00000 n
+0000045298 00000 n
+0000045470 00000 n
+0000045782 00000 n
+0000045954 00000 n
+0000046126 00000 n
+0000046298 00000 n
+0000046470 00000 n
+0000046722 00000 n
+0000046901 00000 n
+0000047132 00000 n
+0000047344 00000 n
+0000047518 00000 n
+0000047690 00000 n
+0000047928 00000 n
+0000048100 00000 n
+0000048331 00000 n
+0000048543 00000 n
+0000048715 00000 n
+0000048887 00000 n
+0000049059 00000 n
+0000049231 00000 n
+0000049483 00000 n
+0000049695 00000 n
+0000049867 00000 n
+0000050037 00000 n
+0000050209 00000 n
+0000050379 00000 n
+0000050631 00000 n
+0000050843 00000 n
+0000050954 00000 n
+0000051165 00000 n
+0000051244 00000 n
+0000051400 00000 n
+0000051526 00000 n
+0000051661 00000 n
+0000051798 00000 n
+0000051971 00000 n
+0000052105 00000 n
+0000052292 00000 n
+0000052404 00000 n
+0000052528 00000 n
+0000052656 00000 n
+0000052806 00000 n
+0000052973 00000 n
+0000053073 00000 n
+0000053196 00000 n
+0000053365 00000 n
+0000053535 00000 n
+0000053702 00000 n
+0000053877 00000 n
+0000054022 00000 n
+0000054184 00000 n
+0000054338 00000 n
+0000054463 00000 n
+0000054629 00000 n
+0000054782 00000 n
+0000054885 00000 n
+0000055055 00000 n
+0000055158 00000 n
+0000055333 00000 n
+0000055436 00000 n
+0000055606 00000 n
+0000055709 00000 n
+0000055879 00000 n
+0000055982 00000 n
+0000056152 00000 n
+0000056255 00000 n
+0000056433 00000 n
+0000056536 00000 n
+0000056705 00000 n
+0000056808 00000 n
+0000056976 00000 n
+0000057079 00000 n
+0000057248 00000 n
+0000057351 00000 n
+0000057478 00000 n
+0000057644 00000 n
+0000057747 00000 n
+0000057875 00000 n
+0000058046 00000 n
+0000058149 00000 n
+0000058317 00000 n
+0000058420 00000 n
+0000058578 00000 n
+0000058681 00000 n
+0000058943 00000 n
+0000068119 00000 n
+0000073466 00000 n
+0000081106 00000 n
+0000086451 00000 n
+0000094793 00000 n
+0000098950 00000 n
+0000102705 00000 n
+0000107846 00000 n
+0000116871 00000 n
+0000122165 00000 n
+0000128291 00000 n
+0000134404 00000 n
+0000138084 00000 n
+0000146317 00000 n
+0000152034 00000 n
+0000157549 00000 n
+0000162041 00000 n
+0000169838 00000 n
+0000176402 00000 n
+0000182585 00000 n
+0000188033 00000 n
+0000194297 00000 n
+0000200264 00000 n
+0000206360 00000 n
+0000212440 00000 n
+0000223530 00000 n
+0000230431 00000 n
+0000233596 00000 n
+0000233950 00000 n
+0000233988 00000 n
+0000234026 00000 n
+0000234064 00000 n
+0000234102 00000 n
+0000234140 00000 n
+0000234178 00000 n
+0000234216 00000 n
+0000234254 00000 n
+0000234292 00000 n
+0000234331 00000 n
+0000234370 00000 n
+0000234409 00000 n
+0000234448 00000 n
+0000234487 00000 n
+0000234526 00000 n
+0000234565 00000 n
+0000234604 00000 n
+0000234643 00000 n
+0000234682 00000 n
+0000234721 00000 n
+0000234760 00000 n
+0000234799 00000 n
+0000234838 00000 n
+0000234877 00000 n
+0000234916 00000 n
+0000234955 00000 n
+0000234994 00000 n
+trailer
+<< /ID
+ % ReportLab generated PDF document -- digest (http://www.reportlab.com)
+ [(\232\310\351\341{\201\026\211\227\020\263\243\343>\213\037) (\232\310\351\341{\201\026\211\227\020\263\243\343>\213\037)]
+ /Info 83 0 R /Root 82 0 R /Size 196 >>
+startxref
+235033
+%%EOF
diff --git a/doc/mapping.rst b/doc/mapping.rst
index 3363550..2f76177 100644
--- a/doc/mapping.rst
+++ b/doc/mapping.rst
@@ -1,3 +1,347 @@
+Introduction
+============
+
+A need shared by many applications is the ability to authenticate a
+user and then bind a set of permissions to the user which indicate
+what actions the user is permitted to perform
+(i.e. authorization). A LocalSystem may have implemented it's own
+authentication and authorization and now wishes to utilize a federated
+Identity Provider (IdP). Typically the IdP provides an assertion with
+information describing the authenticated user. The goal is to
+transform the IdP assertion into a LocalSystem token. In it's simplest
+terms this is a data transformation which might include:
+
+* renaming of data items
+* conversion to a different format
+* deletion of data
+* addition of data
+* reorganization of data
+
+There are many ways such a transformation could be implemented:
+
+1. Custom site specific code
+2. Scripts written in a scripting language
+3. XSLT
+4. Rule based transforms
+
+We also desire these goals for the transformation.
+
+1. Site administrator configurable
+2. Secure
+3. Simple
+4. Extensible
+5. Efficient
+
+Implementation choice 1, custom written code fails goals 1, 3 and 4, an
+admin cannot adapt it, it's not simple, and it's likely to be
+difficult to extend.
+
+Implementation choice 2, script based transformations have a lot of
+appeal. Because one has at their disposal the full power of an actual
+programming language there are virtually no limitations. If it's a
+popular scripting language an administrator is likely to already know
+the language and might be able to program a new transformation or at a
+minimum tweak an existing script. Forking out to a script interpreter
+is inefficient, but it's now possible to embed script interpreters in
+the existing application. However sandboxing the execution of a
+script such that it cannot perform malicious operations is
+difficult. One could run a separate script process to provide
+sandboxing but this introduces the vagaries of managing a subordinate
+process and inter-process communication. Therefore scripts either fail
+goals 1 or 5, secure or efficient (depending on whether the
+interpreter is embedded or not).
+
+Implementation choice 3, XSLT fails goals 3 and 4, it is not simple,
+it may not have the necessary features, and extending XSLT is
+difficult.
+
+Implementation choice 4, rules based transformations offers the best
+combination of features to meet the goals. Site administrators can
+understand rules and edit them. There are no sandboxing concerns, rule
+evaluation can be crafted to be secure. With careful design the rule
+syntax can easily be extended. Rule execution should be efficient
+because it's implemented in a native library loaded into the
+application and does not depend on forking out to a separate process
+or using inter-process communication.
+
+We describe a rule based system which offers much of the power and
+flexibility of a scripting language but without it's downsides. The
+rules are written much like a scripting language where you can call
+functions (e.g. verbs) and perform simple branching logic based on the
+result of a prior verb. Variables can be assigned and referenced. As
+described in the `Variables`_ section a variable may be scalar, an
+associative array (key/value), or an indexed array (ordered list). A
+number of different data types are supported and are described in the
+`Data Types`_ section. Because the rules are written in JSON it
+should be easy for an administrator to understand and JSON provides
+the ability load site specific hardcoded data the rules can
+utilize. For example white lists, black lists, valid groups, invalid
+groups, etc. are all easy to express in JSON.
+
+Implementation Status
+---------------------
+
+The Mapping Rule Processor described in this document currently has
+implmentations in these languages:
+
+* Java
+* Python
+
+An application simply needs to load the implementation and invoke it's
+entry points. It is expected the rules will reside in site specific
+configuration files.
+
+General Data Flow
+-----------------
+
+`Figure 1.`_ illustrates the processing inside the application when it
+needs to authenticate a user and provide a LocalSystem token
+identifying the user, providing attributes bound to the user, and a
+set of authorizations for the actions the user is permitted to perform
+(e.g. roles).
+
+
+.. figure:: figure-01.png
+ :align: center
+
+ _`Figure 1.`
+
+:Step 1:
+ A federated Identity Provider (IdP) is asked to authenticate a user
+ and provide additional information (attributes) concerning the user.
+
+:Step 2:
+ Upon successful authentication the IdP provides an assertion for the
+ user which also contains extra information (attributes) bound to
+ the user (e.g. group membership, authorizations, etc.)
+
+:Step 3:
+ The mapper is invoked to transform the external IdP assertion into a
+ local representation. The transformation occurs according to the
+ rules and mapping templates loaded into the rule processor.
+
+ The Mapping Rule Processor is designed to accept a JSON object (set
+ of key/value pairs) as input and emit a different JSON object as
+ output. Thus the Mappgin Rule Processor effectively operates as a
+ transformation engine on key/value pairs with the ability to add or
+ delete key/value pairs.
+
+:Step 3.1:
+ The input assertion is rewritten as a JSON object in the format
+ required by the Mapping Rule Processor. The JSON assertion is then
+ passed into the Mapping Rule Processor.
+
+:Step 3.2:
+ The Mapping Rule Processor identified as ``IdPMapper`` evaluates
+ the input JSON assertion in the context of the mapping rules defined
+ for the site deployment. If ``IdPMapper`` is able to successfully
+ transform the input it will return a JSON object which is called the
+ *mapped* result. If the input JSON assertion is not compatible with
+ the site specific rules loaded into the ``IdPMapper`` then NULL is
+ returned by the ``IdPMapper``.
+
+:Step 3.3:
+ If the mapping was successful the ``IdPMapper`` returns the
+ transformed assertion as a JSON object.
+
+:Step 4:
+ The mapped JSON object is converted for use in the local system.
+
+Example Assertion Transformation
+--------------------------------
+
+A federated IdP supplies metadata in a form unique to the IdP. This is
+called an assertion. That assertion must be transformed into a format
+and data understood by LocalSystem. More importantly that assertion
+needs to yield *authorization roles specific to LocalSystem*. In
+`Figure 1.`_ Step 3.2 the ``IdPMapper`` provides the transformation
+from an external IdP assertion to a LocalSystem specific token. It
+does this via a Mapping Rule Processor which reads a site specific set
+of transformation rules. These mapping rules define how to transform
+the external IdP assertion into a LocalSystem token. The mapping rules
+also are responsible for validating the external IdP assertion to make
+sure it is consistent with the site specific requirements. The
+operation of the Mapping Rule Processor and the syntax of the mapping
+rules are defined in `Structure Of Rule Definitions`_.
+
+Below is an example mapping rule which might be loaded into the
+Mapping Rule Processor to support a fictional FOOBAR application. The
+IdP provides assertions using the ``REMOTE_USER`` CGI style. It is
+assumed there are two LocalSystem roles which may be assigned:
+
+``user``
+ A role granting standard permissions for normal FOOBAR users.
+
+``admin``
+ A special role granting full FOOBAR administrative permissions.
+
+In this example assigning the ``user`` and ``admin`` roles
+will be based on group membership in the following groups:
+
+``foobar_users``
+ Members of this group are normal FOOBAR users with restricted permissions.
+
+``foobar_admin``
+ Members of this group are FOOBAR administrators with permission to
+ perform all operations.
+
+Granting of the ``user`` and/or ``admin`` roles based on
+membership in the ``foobar_users`` and ``foobar_admin`` is illustrated in
+the follow mapping rule example which also extracts the user principal
+and domain information in the preferred format for the site
+(e.g. usernames are lowercase without domain suffixes and the domain
+is uppercase and supplied separately).
+
+_`Mapping Rule Example 1.`
+
+::
+
+ 1 [
+ 2 {"mapping": {"ClientId": "$client_id",
+ 3 "UserId": "$user_id",
+ 4 "User": "$username",
+ 5 "Domain": "$domain",
+ 6 "roles": "$roles",
+ 7 },
+ 8 "statement_blocks": [
+ 9 [
+ 10 ["set", "$groups", []],
+ 11 ["set", "$roles", []]
+ 12 ],
+ 13 [
+ 14 ["in", "REMOTE_USER", "$assertion"],
+ 15 ["exit", "rule_fails", "if_not_success"],
+ 16 ["regexp", "$assertion[REMOTE_USER]", "(?<username>\\w+)@(?<domain>.+)"],
+ 17 ["exit", "rule_fails", "if_not_success"],
+ 18 ["lower", "$username", "$regexp_map[username]"],
+ 19 ["upper", "$domain", "$regexp_map[domain]"],
+ 20 ],
+ 21 [
+ 22 ["in", "REMOTE_USER_GROUPS", "$assertion"],
+ 23 ["exit", "rule_fails", "if_not_success"],
+ 24 ["split", "$groups", "$assertion[REMOTE_USER_GROUPS]", ":"],
+ 25 ],
+ 26 [
+ 27 ["in", "foobar_users", "$groups"],
+ 28 ["continue", "if_not_success"],
+ 29 ["append", "$roles", "user"],
+ 30 ],
+ 31 [
+ 32 ["in", "foobar_admin", "$groups"],
+ 33 ["continue", "if_not_success"],
+ 34 ["append", "$roles", "admin"]
+ 35 ],
+ 36 [
+ 37 ["unique", "$roles", "$roles"],
+ 38 ["length", "$n_roles", "$roles"],
+ 39 ["compare", "$n_roles", ">", 0],
+ 40 ["exit", "rule_fails", "if_not_success"],
+ 41 ],
+ 42 ]
+ 43 }
+ 44 ]
+
+:Line 1:
+ Starts a list of rules. In this example only 1 rule is defined. Each
+ rule is a JSON object containing a ``mapping`` and a required list
+ of ``statement_blocks``. The ``mapping`` may either be specified
+ inside a rule as it is here or may be referenced by name in a table
+ of mappings (this is easier to manage if you have a large number of
+ rules and small number of mappings).
+:Lines 2-7:
+ Defines the JSON mapped result. Each key maps to LocalSystem token.
+ The value is a rule variable whose value will be substituted
+ if the rule succeeds. Thus for example the LocalSystem token value
+ ``User`` will be assigned the value from the ``$username`` rule
+ variable.
+:Line 8:
+ Begins the list of statement blocks. A statement must be contained
+ inside a block.
+:Lines 9-12:
+ The first block usually initializes variables that will be
+ referenced later. Here we initialize ``$groups`` and ``$roles`` to
+ empty arrays. These arrays may be appended to in later blocks and
+ may be referenced in the final ``mapping`` output.
+:Lines 13-20:
+ This block sets the user and domain information based on
+ ``REMOTE_USER`` and exits the rule if ``REMOTE_USER`` is not defined.
+:Lines 14-15:
+ This test is critical, it assures ``REMOTE_USER`` is defined in the
+ assertion, if not the rule is skipped because we depend on
+ ``REMOTE_USER``.
+:Lines 16-17:
+ Performs a regular expression match against ``REMOTE_USER`` to split
+ the username from the domain. The regular expression uses named
+ groups, in this instance ``username`` and ``domain``. If the regular
+ expression does not match the rule is skipped.
+:Lines 18-19:
+ These lines reference the previous result of the regular expression
+ match which are stored in the special variable ``$regexp_map``. The
+ username is converted to lower case and stored in ``$username`` and
+ the domain is converted to upper case and stored in ``$domain``. The
+ choice of case is purely by convention and site requirements.
+:Lines 21-35:
+ These 3 blocks assign roles based on group membership.
+:Lines 21-25:
+ Assures ``REMOTE_USER_GROUPS`` is defined in the assertion; if not, the
+ rule is skipped. ``REMOTE_USER_GROUPS`` is colon separated list of group
+ names. In order to operate on the individual group names appearing
+ in ``REMOTE_USER_GROUPS`` line 24 splits the string on the colon
+ separator and stores the result in the ``$groups`` array.
+:Lines 27-30:
+ This block assigns the ``user`` role if the user is a member of the
+ ``foobar_users`` group.
+:Lines 31-35:
+ This block assigns the ``admin`` role if the user is a
+ member of the ``foobar_admin`` group.
+:Lines 36-41:
+ This block performs final clean up actions for the rule. First it
+ assures there are no duplicates in the ``$roles`` array by calling
+ the ``unique`` function. Then it gets a count of how many items are
+ in the ``$roles`` array and tests to see if it's empty. If there are
+ no roles assigned the rule is skipped.
+:Line 43:
+ This is the end of the rule. If we reach the end of the rule it
+ succeeds. When a rule succeeds the mapping associated with the rule
+ is looked up. Any rule variable appearing in the mapping is
+ substituted with its value.
+
+Using the rules in `Mapping Rule Example 1.`_ and following example assertion
+in JSON format:
+
+_`Assertion Example 1.`
+
+::
+
+ {
+ "REMOTE_USER": "TestUser@example.com",
+ "REMOTE_AUTH_TYPE": "Negotiate",
+ "REMOTE_USER_GROUPS": "foobar_users:foobar_admin",
+ "REMOTE_USER_EMAIL": "test.user@example.com",
+ "REMOTE_USER_FIRSTNAME": "Test",
+ "REMOTE_USER_LASTNAME": "User"
+ }
+
+Then the mapper will return the following mapped JSON document. This
+is the ``mapping`` defined on line 2 of `Mapping Rule Example 1.`_ with the
+variables substituted after the rule successfully executed. Note any
+valid JSON data type can be returned, in this example the ``null``
+value is returned for ``ClientId`` and ``UserId``, normal strings for
+``User`` and ``Domain`` and an array of strings for the ``roles`` value.
+
+_`Mapped Result Example 1.`
+
+::
+
+ {
+ "ClientId": null,
+ "UserId": null,
+ "User": "testuser",
+ "Domain": "EXAMPLE.COM",
+ "roles": ["user", "admin"]
+ }
+
+
Operation Model
===============