/* Ċ Ġ* ĠCopyright Ġ 2 0 1 4 - 2 0 1 9 ĠJetBrains Ġs . r . o Ġand Ġcontributors . ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense . Ċ Ġ*/ Ċ Ċ package Ġio . ktor . client . features . auth . providers Ċ Ċ import Ġio . ktor . client . features . auth .* Ċ import Ġio . ktor . client . request .* Ċ import Ġio . ktor . http .* Ċ import Ġio . ktor . http . auth .* Ċ import Ġio . ktor . util .* Ċ import Ġkotlinx . atomic fu .* Ċ import Ġio . ktor . utils . io . char sets .* Ċ import Ġio . ktor . utils . io . core .* Ċ Ċ /** Ċ Ġ* ĠInstall Ġclient Ġ[ Digest Auth Provider ]. Ċ Ġ*/ Ċ fun ĠAuth . digest ( block : ĠDigest Auth Config . () Ġ-> ĠUnit ) Ġ{ ĊĠĠĠ Ġval Ġconfig Ġ= ĠDigest Auth Config (). apply ( block ) ĊĠĠĠ Ġwith ( config ) Ġ{ ĊĠĠĠĠĠĠĠ Ġproviders Ġ+= ĠDigest Auth Provider ( username , Ġpassword , Ġrealm , Ġalgorithm Name ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* Ġ[ Digest Auth Provider ] Ġconfiguration . Ċ Ġ*/ Ċ @ Suppress (" K Doc Missing Documentation ") Ċ class ĠDigest Auth Config Ġ{ ĊĠĠĠ Ġvar Ġusername : ĠString Ġ= Ġ"" ĊĠĠĠ Ġvar Ġpassword : ĠString Ġ= Ġ"" ĊĠĠĠ Ġvar Ġrealm : ĠString ? Ġ= Ġnull ĊĠĠĠ Ġvar Ġalgorithm Name : ĠString Ġ= Ġ" MD 5 " Ċ } Ċ Ċ /** Ċ Ġ* ĠClient Ġdigest Ġ[ Auth Provider ]. Ċ Ġ*/ Ċ @ Suppress (" K Doc Missing Documentation ") Ċ class ĠDigest Auth Provider ( ĊĠĠĠ Ġval Ġusername : ĠString , ĊĠĠĠ Ġval Ġpassword : ĠString , ĊĠĠĠ Ġval Ġrealm : ĠString ?, ĊĠĠĠ Ġval Ġalgorithm Name : ĠString Ġ= Ġ" MD 5 " Ċ ) Ġ: ĠAuth Provider Ġ{ ĊĠĠĠ Ġoverride Ġval Ġsend Without Request : ĠBoolean Ġ= Ġfalse ĊĊĠĠĠ Ġprivate Ġval Ġserver Nonce Ġ= Ġatomic < String ? >( null ) ĊĠĠĠ Ġprivate Ġval Ġq op Ġ= Ġatomic < String ? >( null ) ĊĠĠĠ Ġprivate Ġval Ġopaque Ġ= Ġatomic < String ? >( null ) ĊĠĠĠ Ġprivate Ġval Ġclient Nonce Ġ= Ġgenerate Nonce () ĊĊĠĠĠ Ġprivate Ġval Ġrequest Counter Ġ= Ġatomic ( 0 ) ĊĊĠĠĠ Ġoverride Ġfun Ġis Applicable ( auth : ĠHttp Auth Header ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( auth Ġ! is ĠHttp Auth Header . Parameterized Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġauth . parameter (" realm ") Ġ!= Ġrealm Ġ|| ĊĠĠĠĠĠĠĠĠĠĠĠ Ġauth . auth Scheme Ġ!= ĠAuth Scheme . Digest ĊĠĠĠĠĠĠĠ Ġ) Ġreturn Ġfalse ĊĊĠĠĠĠĠĠĠ Ġval Ġnew Nonce Ġ= Ġauth . parameter (" nonce ") Ġ?: Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġval Ġnew Q op Ġ= Ġauth . parameter (" q op ") ĊĠĠĠĠĠĠĠ Ġval Ġnew Opaque Ġ= Ġauth . parameter (" opaque ") ĊĊĠĠĠĠĠĠĠ Ġserver Nonce . value Ġ= Ġnew Nonce ĊĠĠĠĠĠĠĠ Ġq op . value Ġ= Ġnew Q op ĊĠĠĠĠĠĠĠ Ġopaque . value Ġ= Ġnew Opaque ĊĊĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġsuspend Ġfun Ġadd Request Headers ( request : ĠHttpRequest Builder ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnonce Count Ġ= Ġrequest Counter . increment AndGet () ĊĠĠĠĠĠĠĠ Ġval ĠmethodName Ġ= Ġrequest . method . value . toUpperCase () ĊĠĠĠĠĠĠĠ Ġval Ġurl Ġ= ĠURL Builder (). take From ( request . url ). build () ĊĊĠĠĠĠĠĠĠ Ġval Ġnonce Ġ= Ġserver Nonce . value !! ĊĠĠĠĠĠĠĠ Ġval Ġserver Opaque Ġ= Ġopaque . value ĊĠĠĠĠĠĠĠ Ġval Ġactual Q op Ġ= Ġq op . value ĊĊĠĠĠĠĠĠĠ Ġval Ġcredential Ġ= Ġmake Digest ("$ username :$ realm :$ password ") ĊĊĠĠĠĠĠĠĠ Ġval Ġstart Ġ= Ġhex ( credential ) ĊĠĠĠĠĠĠĠ Ġval Ġend Ġ= Ġhex ( make Digest ("$ methodName :${ url . encoded Path } ")) ĊĠĠĠĠĠĠĠ Ġval Ġtoken Sequence Ġ= Ġif Ġ( actual Q op Ġ== Ġnull ) ĠlistOf ( start , Ġnonce , Ġend ) Ġelse ĠlistOf ( start , Ġnonce , Ġnonce Count , Ġclient Nonce ) ĊĠĠĠĠĠĠĠ Ġval Ġtoken Ġ= Ġmake Digest ( token Sequence . join ToString (" :" )) ĊĊĠĠĠĠĠĠĠ Ġval Ġauth Ġ= ĠHttp Auth Header . Parameterized ( Auth Scheme . Digest , Ġlinked Map Of < String , ĠString >(). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrealm ?. let Ġ{ Ġthis [" realm "] Ġ= Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġserver Opaque ?. let Ġ{ Ġthis [" opaque "] Ġ= Ġit Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis [" username "] Ġ= Ġusername ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis [" nonce "] Ġ= Ġnonce ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis [" c nonce "] Ġ= Ġclient Nonce ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis [" response "] Ġ= Ġhex ( token ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthis [" uri "] Ġ= Ġurl . encoded Path ĊĠĠĠĠĠĠĠ Ġ}) ĊĊĠĠĠĠĠĠĠ Ġrequest . headers Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġappend ( HttpHeaders . Authorization , Ġauth . render ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġsuspend Ġfun Ġmake Digest ( data : ĠString ): ĠByteArray Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdigest Ġ= ĠDigest ( algorithm Name ) ĊĠĠĠĠĠĠĠ Ġreturn Ġdigest . build ( data . toByteArray ( Charsets . UTF _ 8 )) ĊĠĠĠ Ġ} Ċ } Ċ