* Parses the SSH connection address. This behaves like OpenSSH and for the * sake of parity (and simplicity) also emulates some of its quirks. * * The SSH source[1] is relatively simple. First, we try to parse the string as * a fully-qualified URI. The URL module helps with that. If that works a
(str: string)
| 226 | * 3. https://github.com/openssh/openssh-portable/blob/master///misc.c#L875-L877 |
| 227 | */ |
| 228 | function parseConnectionString(str: string): { hostname: string; port?: string; username?: string } { |
| 229 | let url: URL | undefined; |
| 230 | try { |
| 231 | url = new URL(str); |
| 232 | } catch { |
| 233 | // ignored |
| 234 | } |
| 235 | |
| 236 | // It may seem a little odd, but the handling within OpenSSH is to fall |
| 237 | // back to the splitting method (rather than erroring) if the wrong protocol |
| 238 | // is provided. Do the same here for parity's sake. |
| 239 | // https://github.com/openssh/openssh-portable/blob/e3b6c966b79c3ea5d51b923c3bbdc41e13b96ea0/misc.c#L854-L855 |
| 240 | if (url && url.protocol === 'ssh:') { |
| 241 | return url; |
| 242 | } |
| 243 | |
| 244 | // Manual splitting algorithm, augmented with the ability to remove the password: |
| 245 | // https://github.com/openssh/openssh-portable/blob/e3b6c966b79c3ea5d51b923c3bbdc41e13b96ea0/ssh.c#L1016-L1030 |
| 246 | const hostDelimiter: number = str.lastIndexOf('@'); |
| 247 | if (hostDelimiter === -1) { |
| 248 | return { hostname: str }; |
| 249 | } |
| 250 | |
| 251 | const hostname: string = str.slice(hostDelimiter + 1); |
| 252 | let username: string = str.slice(0, hostDelimiter); |
| 253 | |
| 254 | const passwordDelimiter: number = username.indexOf(':'); |
| 255 | if (passwordDelimiter !== -1) { |
| 256 | username = username.slice(0, passwordDelimiter); |
| 257 | } |
| 258 | |
| 259 | return { hostname, username }; |
| 260 | } |
no outgoing calls
no test coverage detected