From e05abd7c243a5b1ced472200c81e37600977d37a Mon Sep 17 00:00:00 2001 From: Mygod Date: Thu, 14 Apr 2016 18:51:36 -0500 Subject: [PATCH] Support one-time authentication in ss urls for sharing (#644) This commit implements the new ss protocol proposed here: https://github.com/shadowsocks/shadowsocks-org/issues/16 --- .../github/shadowsocks/database/Profile.scala | 4 +-- .../com/github/shadowsocks/utils/Parser.scala | 30 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main/scala/com/github/shadowsocks/database/Profile.scala b/src/main/scala/com/github/shadowsocks/database/Profile.scala index 2472f059..ede0c720 100644 --- a/src/main/scala/com/github/shadowsocks/database/Profile.scala +++ b/src/main/scala/com/github/shadowsocks/database/Profile.scala @@ -99,6 +99,6 @@ class Profile { @DatabaseField var userOrder: Long = _ - override def toString = "ss://" + Base64.encodeToString("%s:%s@%s:%d".formatLocal(Locale.ENGLISH, - method, password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP) + override def toString = "ss://" + Base64.encodeToString("%s%s:%s@%s:%d".formatLocal(Locale.ENGLISH, + method, if (auth) "-auth" else "", password, host, remotePort).getBytes, Base64.NO_PADDING | Base64.NO_WRAP) } diff --git a/src/main/scala/com/github/shadowsocks/utils/Parser.scala b/src/main/scala/com/github/shadowsocks/utils/Parser.scala index f1a38ccd..32b5802b 100644 --- a/src/main/scala/com/github/shadowsocks/utils/Parser.scala +++ b/src/main/scala/com/github/shadowsocks/utils/Parser.scala @@ -45,22 +45,22 @@ import com.github.shadowsocks.database.Profile object Parser { val TAG = "ShadowParser" private val pattern = "(?i)ss://([A-Za-z0-9+-/=_]+)".r + private val decodedPattern = "(?i)^((.+?)(-auth)??:(.*)@(.+?):(\\d+?))$".r - def findAll(data: CharSequence) = pattern.findAllMatchIn(data).map(m => try { - val content = new String(Base64.decode(m.group(1), Base64.NO_PADDING), "UTF-8") - val methodIdx = content.indexOf(':') - val passwordIdx = content.lastIndexOf('@') - val hostIdx = content.lastIndexOf(':') - val host = content.substring(passwordIdx + 1, hostIdx) - - val profile = new Profile - profile.name = host - profile.host = host - profile.remotePort = content.substring(hostIdx + 1).toInt - profile.method = content.substring(0, methodIdx).toLowerCase - profile.password = content.substring(methodIdx + 1, passwordIdx) - profile - } catch { + def findAll(data: CharSequence) = pattern.findAllMatchIn(data).map(m => try + decodedPattern.findFirstMatchIn(new String(Base64.decode(m.group(1), Base64.NO_PADDING), "UTF-8")) match { + case Some(ss) => + val profile = new Profile + profile.method = ss.group(2).toLowerCase + if (ss.group(3) != null) profile.auth = true + profile.password = ss.group(4) + profile.name = ss.group(5) + profile.host = profile.name + profile.remotePort = ss.group(6).toInt + profile + case _ => null + } + catch { case ex: Exception => Log.e(TAG, "parser error: " + m.source, ex)// Ignore null