Add/Change: Use .well-known server URI when available

Fixes #2.  Thanks to Daniel Pérez (@0xSteeW) for reporting.
This commit is contained in:
Adam Porter 2021-07-17 08:16:31 -05:00
parent faab3c7316
commit e5c25307b2
3 changed files with 33 additions and 8 deletions

View file

@ -60,12 +60,13 @@
"FIXME: Docstring."
;; FIXME: Use transaction-id or add it in calling functions.
(declare (indent defun))
(pcase-let* (((cl-struct ement-server hostname port) server)
(pcase-let* (((cl-struct ement-server uri-prefix port) server)
((cl-struct url type host) (url-generic-parse-url uri-prefix))
(path (concat "/_matrix/client/r0/" endpoint))
(query (url-build-query-string params))
(filename (concat path "?" query))
(url (url-recreate-url
(url-parse-make-urlobj "https" nil nil hostname port filename nil data t)))
(url-parse-make-urlobj type nil nil host port filename nil data t)))
(headers (ement-alist "Content-Type" content-type
"Authorization" (concat "Bearer " token))))
;; Omit `then' from debugging because if it's a partially applied

View file

@ -44,7 +44,7 @@
id sender content origin-server-ts type unsigned)
(cl-defstruct ement-server
hostname port)
name port uri-prefix)
(cl-defstruct ement-session
user server token transaction-id rooms next-batch

View file

@ -43,6 +43,7 @@
;; Built in.
(require 'cl-lib)
(require 'dns)
(require 'files)
(require 'map)
@ -124,14 +125,15 @@ session and log in again."
'password (read-passwd "Password: ")))))
(list username password token transaction-id)))
(unless (string-match (rx bos "@" (1+ (not (any ":"))) ; Username (actually unused)
":" (group (optional (1+ (not (any blank)))))) ; Hostname
":" (group (optional (1+ (not (any blank)))))) ; Server name
user-id)
(user-error "Invalid user ID format: use @USERNAME:HOSTNAME"))
(let* (;; FIXME: Lookup hostname from user ID with DNS.
(hostname (match-string 1 user-id))
(user-error "Invalid user ID format: use @USERNAME:SERVER"))
(let* ((server-name (match-string 1 user-id))
;; TODO: Also return port, and actually use that port elsewhere.
(uri-prefix (ement--hostname-uri server-name))
(user (make-ement-user :id user-id))
;; FIXME: Dynamic port.
(server (make-ement-server :hostname hostname :port 443))
(server (make-ement-server :name server-name :port 443 :uri-prefix uri-prefix))
;; FIXME: Be smarter about transaction ID to prevent conflicts.
(transaction-id (or transaction-id (random 100000)))
(session (make-ement-session :user user :server server :token token :transaction-id transaction-id)))
@ -205,6 +207,28 @@ call `pop-to-buffer'."
;;;; Functions
(defun ement--hostname-uri (hostname)
"Return the \".well-known\" URI for server HOSTNAME.
If no URI is found, prompt the user for the hostname."
;; SPEC: <https://matrix.org/docs/spec/client_server/r0.6.1#id178> ("4.1 Well-known URI")
(cl-labels ((fail-prompt
() (let ((input (read-string "Auto-discovery of server's well-known URI failed. Input server hostname, or leave blank to use server name: ")))
(pcase input
("" hostname)
(_ input))))
(parse (string)
(if-let ((object (ignore-errors (json-read-from-string string))))
;; Return extracted value.
(map-nested-elt object '(m.homeserver base_url))
;; Parsing error: FAIL_PROMPT.
(fail-prompt))))
(let ((response (plz-get-sync (concat "https://" hostname "/.well-known/matrix/client")
:as 'response)))
(pcase (plz-response-status response)
(404 (fail-prompt))
(200 (parse (plz-response-body response)))
(_ (fail-prompt))))))
(defun ement--room-buffer-name (room)
"Return name for ROOM's buffer."
(concat ement-room-buffer-name-prefix