Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -142,13 +142,18 @@ public object AuthChallengeParser {
@Suppress("ReturnCount")
private fun parseAuthParamOrToken68(cursor: Cursor): Pair<String, String>? {
val saved = cursor.position

fun rewindAsToken68(): Pair<String, String>? {
cursor.position = saved
val token68 = cursor.readToken68() ?: return null
return "token68" to token68
}

val name = cursor.readToken() ?: return null
cursor.skipOws()
if (!cursor.hasMore() || cursor.peek() != '=') {
// No `=` after the token — it's a token68.
cursor.position = saved
val token68 = cursor.readToken68() ?: return null
return "token68" to token68
return rewindAsToken68()
}
cursor.advance() // consume the first `=`

Expand All @@ -159,19 +164,15 @@ public object AuthChallengeParser {
// entire `cmVhbA==` is recovered. Without this branch a doubly-padded
// base64 token would be silently dropped.
if (cursor.hasMore() && cursor.peek() == '=') {
cursor.position = saved
val token68 = cursor.readToken68() ?: return null
return "token68" to token68
return rewindAsToken68()
}
cursor.skipOws()

// We've already consumed the `=`; check whether what follows is a value.
if (!cursor.hasMore() || cursor.peek() == ',') {
// looked like `key=` with nothing after — try to treat the whole
// thing as token68 (rewind and read it as such).
cursor.position = saved
val token68 = cursor.readToken68() ?: return null
return "token68" to token68
return rewindAsToken68()
}
val value = cursor.readTokenOrQuotedString() ?: return null
return name.lowercase(Locale.US) to value
Expand Down Expand Up @@ -274,25 +275,18 @@ public object AuthChallengeParser {
while (position < len) {
when (src[position]) {
',' -> return
'"' -> {
// skip the quoted string — but if it's unterminated, just
// jump to EOF.
position++
while (position < len && src[position] != '"') {
if (src[position] == '\\' && position + 1 < len) position++
position++
}
if (position < len) position++ // closing quote
}
// Reuse the escape-aware reader; on an unterminated string it
// consumes through to EOF, exactly where recovery wants to land.
'"' -> readQuotedString()
else -> position++
}
}
}
}

private val TOKEN_PUNCTUATION: Set<Char> = "!#$%&'*+-.^_`|~".toSet()
private const val TOKEN_PUNCTUATION = "!#$%&'*+-.^_`|~"

private val TOKEN68_PUNCTUATION: Set<Char> = "-._~+/".toSet()
private const val TOKEN68_PUNCTUATION = "-._~+/"

/** RFC 7230 token char: ALPHA / DIGIT / one of the punctuation set. */
private fun isTokenChar(c: Char): Boolean =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,10 +374,7 @@ public class DigestChallengeHandler
/** True if [qop] is absent (legacy) or contains the `auth` token (case-insensitive). */
private fun qopSupportsAuth(qop: String?): Boolean {
if (qop == null) return true
for (token in qop.split(',')) {
if (token.trim().equals("auth", ignoreCase = true)) return true
}
return false
return qop.split(',').any { it.trim().equals("auth", ignoreCase = true) }
}

/** Lower-case hex of a byte array — minimal allocation, no intermediate strings. */
Expand Down
Loading