DIRECTORY Basics USING [LongNumber], CrRPC USING [Call, CreateClientHandle, DestroyClientHandle, Error, GetBYTE, GetCARDINAL, GetCHAR, GetFWORD, GetHAlign, GetHWORD, GetINTEGER, GetErrorProc, GetResultsProc, Handle, PutArgsProc, PutCARD, PutCARDINAL, PutCHAR, PutFWORD, PutHAlign, SetHops, SetTimeout], DESFace USING [Block, CorrectParity, EncryptBlock, Key, nullKey], Endian USING [BYTE, FWORD, HWORD], IO USING [UnsafeBlock], RefText USING [AppendChar, ObtainScratch, ReleaseScratch], Rope USING [Concat, FromRefText, InlineFetch, Length, ROPE, SkipTo, Substr], XNS USING [Address, broadcastNet, broadcastHost, Socket, unknownAddress], XNSAddressParsing USING [AddressFromRope, RopeFromSocket], XNSWKS USING [authenticationInfo, clearinghouse]; CrRPCTest: CEDAR PROGRAM IMPORTS CrRPC, DESFace, RefText, Rope, XNSAddressParsing ~ { CARD: TYPE ~ LONG CARDINAL; BYTE: TYPE ~ Endian.BYTE; FWORD: TYPE ~ Endian.FWORD; HWORD: TYPE ~ Endian.HWORD; ROPE: TYPE ~ Rope.ROPE; Handle: TYPE ~ CrRPC.Handle; GetXNSAddress: PROC [h: Handle] RETURNS [XNS.Address] ~ { xNet: FWORD; xHost: MACHINE DEPENDENT RECORD [a, b, c: HWORD]; xSocket: HWORD; xNet _ CrRPC.GetFWORD[h]; xHost.a _ CrRPC.GetHWORD[h]; xHost.b _ CrRPC.GetHWORD[h]; xHost.c _ CrRPC.GetHWORD[h]; xSocket _ CrRPC.GetHWORD[h]; TRUSTED { RETURN [ [net~LOOPHOLE[xNet], host~LOOPHOLE[xHost], socket~LOOPHOLE[xSocket]] ] }; }; PutRope: PROC [h: Handle, rope: ROPE] ~ { len: CARDINAL ~ Rope.Length[rope]; CrRPC.PutCARDINAL[h, len]; FOR i: CARDINAL IN [0..len) DO CrRPC.PutCHAR[h, Rope.InlineFetch[rope, i]]; ENDLOOP; CrRPC.PutHAlign[h]; }; MarshalledRopeHWords: PROC [rope: ROPE] RETURNS [hWords: CARDINAL] ~ { RETURN [ (Rope.Length[rope] + 3) / 2 ] }; GetRope: PROC [h: Handle] RETURNS [rope: ROPE] ~ { text: REF TEXT; len: CARDINAL; len _ CrRPC.GetCARDINAL[h]; text _ RefText.ObtainScratch[len]; FOR i: INT IN [0 .. len) DO text _ RefText.AppendChar[to~text, from~CrRPC.GetCHAR[h]] ENDLOOP; CrRPC.GetHAlign[h]; rope _ Rope.FromRefText[text]; RefText.ReleaseScratch[text]; }; SkipRope: PROC [h: Handle] ~ { len: CARDINAL ~ CrRPC.GetCARDINAL[h]; THROUGH [0 .. len) DO [] _ CrRPC.GetCHAR[h]; ENDLOOP; CrRPC.GetHAlign[h]; }; CHName: TYPE ~ RECORD [ org: ROPE, dom: ROPE, name: ROPE ]; defaultDom: ROPE _ "PARC"; defaultOrg: ROPE _ "Xerox"; SetDefaultDomain: PROC [default: ROPE] ~ { defaultDom _ default }; SetDefaultOrg: PROC [default: ROPE] ~ { defaultOrg _ default }; CHNameFromRope: PROC [rope: ROPE] RETURNS [result: CHName] ~ { pos: INT _ 0; len: INT ~ Rope.Length[rope]; GetField: PROC RETURNS [field: ROPE _ NIL] ~ { startPos: INT _ pos; IF startPos >= len THEN RETURN; pos _ Rope.SkipTo[s~rope, pos~startPos, skip~":"]; IF pos = startPos THEN RETURN; field _ Rope.Substr[base~rope, start~startPos, len~pos-startPos]; pos _ pos + 1; }; result.name _ GetField[]; result.dom _ GetField[]; result.org _ GetField[]; IF result.name = NIL THEN ERROR; -- FIX THIS LATER IF result.dom = NIL THEN result.dom _ defaultDom; IF result.org = NIL THEN result.org _ defaultOrg; }; PutCHName: PROC [h: Handle, chName: CHName] ~ { PutRope[h, chName.org]; PutRope[h, chName.dom]; PutRope[h, chName.name]; }; GetCHName: PROC [h: Handle] RETURNS [chName: CHName] ~ { chName.org _ GetRope[h]; chName.dom _ GetRope[h]; chName.name _ GetRope[h]; }; SkipCHName: PROC [h: Handle] ~ { [] _ SkipRope[h]; [] _ SkipRope[h]; [] _ SkipRope[h] }; GetCHError: CrRPC.GetErrorProc ~ { errArg: CARDINAL _ CrRPC.GetCARDINAL[h]; ERROR; }; SimpleCredentials: TYPE ~ CHName; simpleCredentialsType: CARDINAL ~ 0; PutSimpleCredentials: PROC [h: Handle, credentials: SimpleCredentials] ~ { CrRPC.PutCARDINAL[h, simpleCredentialsType]; CrRPC.PutCARDINAL[h, MarshalledRopeHWords[credentials.org] + MarshalledRopeHWords[credentials.dom] + MarshalledRopeHWords[credentials.name]]; PutRope[h, credentials.org]; PutRope[h, credentials.dom]; PutRope[h, credentials.name]; }; SimpleVerifier: TYPE ~ CARDINAL; PutSimpleVerifier: PROC [h: Handle, verifier: SimpleVerifier] ~ { CrRPC.PutCARDINAL[h, 1]; CrRPC.PutCARDINAL[h, verifier]; }; HashPassword: PROC [password: ROPE] RETURNS [hashVal: CARDINAL _ 0] ~ { c: CHAR; acc: Basics.LongNumber; FOR i: INT IN [0 .. Rope.Length[password]) DO c _ Rope.InlineFetch[password, i]; SELECT c FROM IN ['A .. 'Z] => c _ 'a + (c - 'A); ENDCASE; acc.hi _ hashVal; acc.lo _ ORD[c]; hashVal _ acc.lc MOD 65357; ENDLOOP; }; BlockFromPassword: PROC [password: ROPE, index, len: INT, to: LONG POINTER TO DESFace.Block] ~ { c: CHAR; blockIndex: INT _ 0; WHILE blockIndex < len DO c _ Rope.InlineFetch[password, index]; SELECT c FROM IN ['A .. 'Z] => c _ 'a + (c - 'A); ENDCASE; TRUSTED { to[blockIndex] _ ORD[c] }; index _ index + 1; blockIndex _ blockIndex + 1; ENDLOOP; WHILE blockIndex < 4 DO TRUSTED { to[blockIndex] _ 0 }; blockIndex _ blockIndex + 1; ENDLOOP; }; DBBlockFromPassword: PROC [password: ROPE, index, len: INT] RETURNS [block: PACKED ARRAY[0..8) OF BYTE] ~ { TRUSTED { BlockFromPassword[password, index, len, LOOPHOLE[LONG[@block]]] }; RETURN; }; StrongKeyFromPassword: PROC [password: ROPE] RETURNS [strongKey: PACKED ARRAY[0..8) OF BYTE] ~ { index: INT; passwordLen: INT ~ Rope.Length[password]; ki: DESFace.Key _ DESFace.nullKey; bi: DESFace.Block; biPlus1: DESFace.Block; newbi: DESFace.Block; FOR index _ 0, index + 4 WHILE index < passwordLen DO len: INT ~ MIN[4, passwordLen-index]; TRUSTED { BlockFromPassword[password, index, len, @bi]; DESFace.CorrectParity[@ki]; DESFace.EncryptBlock[key~ki, from~@bi, to~@biPlus1]; DESFace.EncryptBlock[key~ki, from~@biPlus1, to~@newbi]; ki _ LOOPHOLE[biPlus1] }; ENDLOOP; TRUSTED { DESFace.CorrectParity[@ki] }; RETURN [ LOOPHOLE[ki] ]; }; TestDES: PROC [k0, k1, k2, k3: CARDINAL, d0, d1, d2, d3: CARDINAL] RETURNS [c0, c1, c2, c3: CARDINAL] ~ { k: DESFace.Block; d: DESFace.Block; c: DESFace.Block; k[0] _ k0; k[1] _ k1; k[2] _ k2; k[3] _ k3; d[0] _ d0; d[1] _ d1; d[2] _ d2; d[3] _ d3; TRUSTED { DESFace.EncryptBlock[key~LOOPHOLE[k], from~@d, to~@c] }; RETURN [ c[0], c[1], c[2], c[3] ] }; AddressList: TYPE ~ LIST OF XNS.Address; AddToAddressList: PROC [new: XNS.Address, list: AddressList] RETURNS [AddressList] ~ { FOR temp: AddressList _ list, temp.rest WHILE temp # NIL DO IF temp.first = new THEN RETURN [list]; ENDLOOP; RETURN [ CONS[new, list] ]; }; FindAuthServer: PROC [h: Handle] RETURNS [answer: XNS.Address _ XNS.unknownAddress] ~ { PutArgs: CrRPC.PutArgsProc ~ { NULL }; GetResults: CrRPC.GetResultsProc ~ { n: CARDINAL _ CrRPC.GetCARDINAL[h]; IF (n > 0) AND (answer = XNS.unknownAddress) THEN answer _ GetXNSAddress[h]; }; CrRPC.Call[ h~h, remotePgm~14, remotePgmVersion~2, remoteProc~0, putArgs~PutArgs, getResults~GetResults ! CrRPC.Error => CONTINUE]; }; FindAuthServers: PROC [h: Handle, oldList: AddressList] RETURNS [newList: AddressList] ~ { PutArgs: CrRPC.PutArgsProc ~ { NULL }; GetResults: CrRPC.GetResultsProc ~ { n: CARDINAL _ CrRPC.GetCARDINAL[h]; IF n > 0 THEN newList _ AddToAddressList[GetXNSAddress[h], newList]; }; newList _ oldList; CrRPC.Call[ h~h, remotePgm~14, remotePgmVersion~2, remoteProc~0, putArgs~PutArgs, getResults~GetResults ! CrRPC.Error => CONTINUE]; }; FindCHServer: PROC [h: Handle] RETURNS [answer: XNS.Address _ XNS.unknownAddress] ~ { PutArgs: CrRPC.PutArgsProc ~ { NULL }; GetResults: CrRPC.GetResultsProc ~ { n: CARDINAL _ CrRPC.GetCARDINAL[h]; IF (n > 0) AND (answer = XNS.unknownAddress) THEN answer _ GetXNSAddress[h]; }; CrRPC.Call[ h~h, remotePgm~2, remotePgmVersion~2, remoteProc~0, putArgs~PutArgs, getResults~GetResults ! CrRPC.Error => CONTINUE]; }; FindCHServers: PROC [h: Handle, oldList: AddressList] RETURNS [newList: AddressList] ~ { PutArgs: CrRPC.PutArgsProc ~ { NULL }; GetResults: CrRPC.GetResultsProc ~ { n: CARDINAL _ CrRPC.GetCARDINAL[h]; IF n > 0 THEN newList _ AddToAddressList[GetXNSAddress[h], newList]; }; newList _ oldList; CrRPC.Call[ h~h, remotePgm~2, remotePgmVersion~2, remoteProc~0, putArgs~PutArgs, getResults~GetResults ! CrRPC.Error => CONTINUE]; }; CheckSimpleCredentials: PROC [ h: Handle, credentials: SimpleCredentials, verifier: SimpleVerifier] RETURNS [ok: BOOL] ~ { PutArgs: CrRPC.PutArgsProc ~ { PutSimpleCredentials[h, credentials]; PutSimpleVerifier[h, verifier] }; GetResults: CrRPC.GetResultsProc ~ { ok _ (CrRPC.GetCARDINAL[h] # 0) }; CrRPC.Call[ h~h, remotePgm~14, remotePgmVersion~2, remoteProc~2, putArgs~PutArgs, getResults~GetResults ]; }; GetStrongCredentials: PROC [ h: Handle, iCHName, rCHName: CHName, nonce: CARD] RETURNS [answer: INTEGER _ -1] ~ { PutArgs: CrRPC.PutArgsProc ~ { PutCHName[h, iCHName]; PutCHName[h, rCHName]; CrRPC.PutCARD[h, nonce] }; GetResults: CrRPC.GetResultsProc ~ { answer _ CrRPC.GetINTEGER[h] }; CrRPC.Call[ h~h, remotePgm~14, remotePgmVersion~2, remoteProc~1, putArgs~PutArgs, getResults~GetResults ]; }; CHPropID: TYPE ~ LONG CARDINAL; GetCHPropID: PROC [h: Handle] RETURNS [CHPropID] ~ { RETURN [ LOOPHOLE[CrRPC.GetFWORD[h]] ] }; PutCHPropID: PROC [h: Handle, propID: CHPropID] ~ { CrRPC.PutCARD[h, LOOPHOLE[propID]] }; ListProperties: PROC [ h: Handle, pattern: CHName, credentials: SimpleCredentials, verifier: SimpleVerifier] RETURNS [properties: LIST OF CHPropID] ~ { PutArgs: CrRPC.PutArgsProc ~ { PutCHName[h, pattern]; PutSimpleCredentials[h, credentials]; PutSimpleVerifier[h, verifier] }; GetResults: CrRPC.GetResultsProc ~ { nProps: CARDINAL; SkipCHName[h]; nProps _ CrRPC.GetCARDINAL[h]; properties _ NIL; THROUGH [0 .. nProps) DO properties _ CONS[GetCHPropID[h], properties]; ENDLOOP; }; CrRPC.Call[ h~h, remotePgm~2, remotePgmVersion~2, remoteProc~15, putArgs~PutArgs, getResults~GetResults, getError~GetCHError ]; }; GetCHItemProc: TYPE ~ PROC [h: Handle, nBytesReceived: INT] RETURNS [nBytesRead: INT]; RetrieveItemInner: PROC [ h: Handle, pattern: CHName, propID: CHPropID, credentials: SimpleCredentials, verifier: SimpleVerifier, getCHItem: GetCHItemProc] RETURNS [nBytesReceived, nBytesRead: INT] ~ { PutArgs: CrRPC.PutArgsProc ~ { PutCHName[h, pattern]; PutCHPropID[h, propID]; PutSimpleCredentials[h, credentials]; PutSimpleVerifier[h, verifier] }; GetResults: CrRPC.GetResultsProc ~ { SkipCHName[h]; nBytesReceived _ CrRPC.GetCARDINAL[h] * 2; nBytesRead _ getCHItem[h, nBytesReceived]; THROUGH [nBytesRead .. nBytesReceived) DO [] _ CrRPC.GetBYTE[h]; ENDLOOP; }; CrRPC.Call[ h~h, remotePgm~2, remotePgmVersion~2, remoteProc~16, putArgs~PutArgs, getResults~GetResults, getError~GetCHError ]; }; RetrieveAddress: PROC [ h: Handle, pattern: CHName, credentials: SimpleCredentials, verifier: SimpleVerifier] RETURNS [address: XNS.Address _ XNS.unknownAddress] ~ { GetAddress: GetCHItemProc ~ { numAddresses: INT; IF nBytesReceived < 2 THEN RETURN[0]; numAddresses _ CrRPC.GetCARDINAL[h]; IF (numAddresses < 1) OR (nBytesReceived # (2 + (numAddresses * SIZE[XNS.Address] * 2))) THEN -- RETURN[2] -- ERROR; address _ GetXNSAddress[h]; THROUGH [1..numAddresses) DO [] _ GetXNSAddress[h] ENDLOOP; RETURN[nBytesReceived]; }; [] _ RetrieveItemInner[h~h, pattern~pattern, propID~4 -- nsAddress -- , credentials~credentials, verifier~verifier, getCHItem~GetAddress]; }; FindServer: PROC [socket: XNS.Socket, proc: PROC [Handle] RETURNS [XNS.Address]] RETURNS [answer: XNS.Address _ XNS.unknownAddress] ~ { h: Handle; h _ CrRPC.CreateClientHandle[ class~$EXCHANGE, remote~[net~XNS.broadcastNet, host~XNS.broadcastHost, socket~socket], timeoutMsec~200]; BEGIN FOR hops: CARDINAL IN [0..3] DO h _ CrRPC.SetHops[h~h, low~hops, high~hops]; h _ CrRPC.SetTimeout[h, 200 + 300 * hops]; THROUGH [0..4) DO IF (answer _ proc[h]) # XNS.unknownAddress THEN GOTO Found; ENDLOOP; ENDLOOP; EXITS Found => NULL; END; CrRPC.DestroyClientHandle[h]; }; FindServers: PROC [ socket: XNS.Socket, proc: PROC [Handle, AddressList] RETURNS [AddressList] ] RETURNS [answer: AddressList _ NIL] ~ { h: Handle; h _ CrRPC.CreateClientHandle[ class~$EXCHANGE, remote~[net~XNS.broadcastNet, host~XNS.broadcastHost, socket~socket], timeoutMsec~200]; FOR hops: CARDINAL IN [0..2] DO h _ CrRPC.SetHops[h~h, low~hops, high~hops]; h _ CrRPC.SetTimeout[h, 200 + 300 * hops]; THROUGH [0..4) DO answer _ proc[h, answer]; ENDLOOP; ENDLOOP; CrRPC.DestroyClientHandle[h]; }; DBAuthFind: PROC RETURNS [XNS.Address] ~ { RETURN [FindServer[socket~XNSWKS.authenticationInfo, proc~FindAuthServer]] }; DBAuthFindAll: PROC RETURNS [AddressList] ~ { RETURN [FindServers[socket~XNSWKS.authenticationInfo, proc~FindAuthServers]] }; DBCHFind: PROC RETURNS [XNS.Address] ~ { RETURN [FindServer[socket~XNSWKS.clearinghouse, proc~FindCHServer]] }; DBCHFindAll: PROC RETURNS [AddressList] ~ { RETURN [FindServers[socket~XNSWKS.clearinghouse, proc~FindCHServers]] }; DBCheckSimpleCredentials: PROC [destRope: ROPE, name: ROPE, password: ROPE] RETURNS [ok: BOOL] ~ { h: Handle; h _ CrRPC.CreateClientHandle[ class~$SPP, remote~XNSAddressParsing.AddressFromRope[destRope], timeoutMsec~20000]; ok _ CheckSimpleCredentials[ h, CHNameFromRope[name], HashPassword[password]]; CrRPC.DestroyClientHandle[h]; }; DBListProperties: PROC [destRope: ROPE, pattern: ROPE, name: ROPE, password: ROPE] RETURNS [properties: LIST OF CHPropID] ~ { h: Handle; h _ CrRPC.CreateClientHandle[ class~$SPP, remote~XNSAddressParsing.AddressFromRope[destRope], timeoutMsec~20000]; properties _ ListProperties[ h, CHNameFromRope[pattern], CHNameFromRope[name], HashPassword[password]]; CrRPC.DestroyClientHandle[h]; }; DBRetrieveAddress: PROC [destRope: ROPE, pattern: ROPE, name: ROPE, password: ROPE] RETURNS [address: XNS.Address] ~ { h: Handle; h _ CrRPC.CreateClientHandle[ class~$SPP, remote~XNSAddressParsing.AddressFromRope[destRope], timeoutMsec~20000]; address _ RetrieveAddress[ h, CHNameFromRope[pattern], CHNameFromRope[name], HashPassword[password]]; CrRPC.DestroyClientHandle[h]; }; DBERetrieveAddress: PROC [destRope: ROPE, pattern: ROPE, name: ROPE, password: ROPE] RETURNS [address: XNS.Address] ~ { h: Handle; h _ CrRPC.CreateClientHandle[ class~$EXCHANGE, remote~XNSAddressParsing.AddressFromRope[destRope], timeoutMsec~1500]; address _ RetrieveAddress[ h, CHNameFromRope[pattern], CHNameFromRope[name], HashPassword[password]]; CrRPC.DestroyClientHandle[h]; }; DoIt: PROC [destRope, initiator, recipient: ROPE] RETURNS [answer: INTEGER] ~ { h: Handle; h _ CrRPC.CreateClientHandle[ class~$SPP, remote~XNSAddressParsing.AddressFromRope[destRope], timeoutMsec~20000]; answer _ GetStrongCredentials[ h, CHNameFromRope[initiator], CHNameFromRope[recipient], 17]; CrRPC.DestroyClientHandle[h]; }; }. @CrRPCTest.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Demers, October 16, 1986 3:43:05 pm PDT TODO: [h: Handle, errNum: CARDINAL] DESFace.EncryptBlock[key~ki, from~@bi, to~LOOPHOLE[LONG[@ki]]] }; The following are STRANGE because of a BUG in the way CH V 2 marshalls/unmarshalls its PropIDs: Κ˜™Icodešœ Οmœ1™Kšœžœ˜ Kšœžœ˜š Ÿœžœžœ žœžœ˜.Kšœ žœ˜Kšžœžœžœ˜K˜2Kšžœžœžœ˜K˜AK˜K˜—K˜K˜K˜Kš žœžœžœžœΟc˜2Kšžœžœžœ˜1Kšžœžœžœ˜1K˜K˜—šŸ œžœ ˜/KšœJ˜JK˜K˜—šŸ œžœ žœ˜8K˜K˜K˜K˜K˜—šŸ œžœ˜ K˜7K˜—šŸ œ˜K™K˜Kšœžœ˜(Kšžœ˜K˜K˜—Kšœžœ ˜!Kšœžœ˜$šŸœžœ0˜JKšœ,˜,Kšœ˜KšœY˜YK˜K˜—Kšœžœžœ˜ šŸœžœ*˜AKšœ˜Kšœ˜K˜K˜—š Ÿ œžœ žœžœ žœ ˜GKšœžœ˜K˜šžœžœžœž˜-J˜"šžœž˜ Jšžœ!˜#Jšžœ˜—Jšœžœ˜#Jšœ˜Kšžœ˜—K˜K˜—šŸœžœ žœžœžœžœžœ˜`Kšœžœ˜Jšœ žœ˜šžœž˜Jšœ&˜&šžœž˜ Jšžœ!˜#Jšžœ˜—Jšžœžœ˜$J˜J˜Jšžœ˜—šžœž˜Jšžœ˜J˜Jšžœ˜—K˜K˜—šŸœžœ žœžœžœ žœžœžœžœ˜kKšžœ+žœžœ ˜LKšžœ˜K˜K˜—šŸœžœ žœžœ ž œžœžœ˜`Kšœžœ˜ Kšœ žœ˜)K˜"K˜K˜K˜šžœžœž˜5Kšœžœžœ˜%šžœ˜ Kšœ-˜-Kšœ˜Kšœ*žœžœ ™AKšœ4˜4Kšœ7˜7Kšœžœ ˜—Kšžœ˜—Kšžœ ˜'Kšžœžœ˜K˜K˜—š Ÿœžœžœžœžœžœ˜iK˜K˜K˜K˜+K˜+Kšžœžœ˜BKšžœ˜$K˜—Kš œ žœžœžœžœ ˜(šŸœžœžœžœ˜Všžœ%žœžœž˜;Kšžœžœžœ˜'Kšžœ˜—Kšžœžœ˜K˜K˜—š Ÿœžœ žœ žœ žœ˜SKšœ˜KšŸœžœ˜&šŸ œ˜$Kšœžœ˜#šžœ žœ žœ˜,Kšžœ˜—K˜—šœ ˜ K˜4K˜&Kšœžœ˜—K˜K˜—šŸœžœ#žœ˜VKšœ˜KšŸœžœ˜&šŸ œ˜$Kšœžœ˜#Kšžœžœ7˜DK˜—K˜šœ ˜ K˜4K˜&Kšœžœ˜—K˜K˜—š Ÿ œžœ žœ žœ žœ˜QKšœ˜KšŸœžœ˜&šŸ œ˜$Kšœžœ˜#šžœ žœ žœ˜,Kšžœ˜—K˜—šœ ˜ K˜3K˜&Kšœžœ˜—K˜K˜—šŸ œžœ#žœ˜TKšœ˜KšŸœžœ˜&šŸ œ˜$Kšœžœ˜#Kšžœžœ7˜DK˜—K˜šœ ˜ K˜3K˜&Kšœžœ˜—K˜K˜—šŸœžœHžœžœ˜vKšœ˜šŸœ˜Jšœ%˜%Kšœ!˜!—šŸ œ˜$Kšœ"˜"—šœ ˜ K˜4K˜&Kšœ˜—K˜K˜—š Ÿœžœ/žœžœ žœ˜mKšœ˜šŸœ˜K˜K˜Kšœ˜—šŸ œ˜$Kšœ˜—šœ ˜ K˜4K˜&Kšœ˜—K˜K˜—Kšœ žœžœžœ˜K˜™_šŸ œžœ žœ˜4Kšžœžœ˜)K˜—šŸ œžœ"˜3Kšœžœ ˜%K˜——š ŸœžœYžœžœžœ ˜“K˜šŸœ˜Kšœ˜K˜%K˜!—šŸ œ˜$Kšœžœ˜K˜Kšœ˜Kšœ žœ˜šžœž˜Kšœ žœ˜.Kšžœ˜—K˜—šœ ˜ K˜4K˜;Kšœ˜—K˜K˜—Kš œžœžœžœžœžœ˜VšŸœžœ…žœžœ˜ΙšŸœ˜Kšœ˜K˜K˜%K˜!—šŸ œ˜$K˜Kšœ*˜*Kšœ*˜*šžœ ž˜)Kšœ˜Kšžœ˜—K˜—šœ ˜ K˜4K˜;Kšœ˜—K˜K˜—š ŸœžœYžœ žœ žœ˜₯šŸ œ˜Kšœžœ˜Kšžœžœžœ˜%Kšœ$˜$šžœžœ(žœžœ˜XKšžœ œžœ˜—Kšœ˜Kšžœžœžœ˜;Kšžœ˜Kšœ˜—Kšœ6 œE˜ŠK˜K˜—šŸ œžœ žœžœ žœžœ žœ žœ žœ˜‡K˜ šœ˜Kšœ˜Kšœ žœžœ˜EK˜—šž˜šžœžœžœž˜Kšœ,˜,Kšœ*˜*šžœž˜šžœžœ˜*Kšžœžœ˜—Kšžœ˜—Kšžœ˜—šž˜Kšœ žœ˜—Kšžœ˜—Kšœ˜K˜K˜—š Ÿ œžœ žœžœžœ˜^Kšœžœžœ˜)K˜ šœ˜Kšœ˜Kšœ žœžœ˜EK˜—šžœžœžœž˜Kšœ,˜,Kšœ*˜*šžœž˜Kšœ˜Kšžœ˜—Kšžœ˜—Kšœ˜K˜K˜—šŸ œžœžœžœ ˜*Kšžœžœ-˜MK˜—šŸ œžœžœ˜-Kšžœžœ.˜OK˜—šŸœžœžœžœ ˜(Kšžœžœ&˜FK˜—šŸ œžœžœ˜+Kšžœžœ'˜HK˜—šŸœžœ žœžœ žœžœžœ˜^Kšœ˜K˜ šœ˜Kšœ ˜ Kšœ3˜3Kšœ˜—šœ˜K˜1—Kšœ˜K˜K˜—šŸœžœ žœ žœžœ žœžœžœžœ ˜yKšœ˜K˜ šœ˜Kšœ ˜ Kšœ3˜3Kšœ˜—šœ˜KšœJ˜J—Kšœ˜K˜K˜—šŸœžœ žœ žœžœ žœžœ žœ ˜rKšœ˜K˜ šœ˜Kšœ ˜ Kšœ3˜3Kšœ˜—šœ˜KšœJ˜J—Kšœ˜K˜K˜—šŸœžœ žœ žœžœ žœžœ žœ ˜sKšœ˜K˜ šœ˜Kšœ˜Kšœ3˜3Kšœ˜—šœ˜KšœJ˜J—Kšœ˜K˜K˜—š Ÿœžœ"žœžœ žœ˜OK˜ šœ˜Kšœ ˜ Kšœ3˜3Kšœ˜—šœ˜Kšœ=˜=—Kšœ˜K˜—K˜——…—8\J³