-(defun elpher-url-from-string (url-string)
- "Create a URL object corresponding to the given URL-STRING."
- (let ((url (url-generic-parse-url url-string)))
- (if (and (url-type url)
- (url-host url))
- (setf (url-filename url) (url-unhex-string (url-filename url)))
- (error "Malformed URL" url))))
-
-(defun elpher-url-to-url-string (url)
- "Get string representation of URL."
- (url-encode-url (url-recreate url)))
-
-(defun elpher-url-gopher-p (url)
- "Return non-nil if URL object specifies a gopher address."
- (let ((protocol (url-type url)))
- (if (or (string-equal protocol "gopher")
- (string-equal protocol "gophers")))))
-
-(defun elpher-gopher-url-selector-type (url)
- "Retrieve selector type from URL object."
- (let ((filename (url-filename url)))
- (if (> (length filename) 0)
- (string-to-char filename)
- ?1)))
-
-(defun elpher-gopher-url-selector (url)
- "Retrieve selector from URL object."
- (let ((filename (url-filename url)))
- (if (> (length filename) 0)
- (substring filename 1)
- "")))
-
-(defun elpher-url-host (url)
- "Retrieve host from URL object."
- (url-host url))
-
-(defun elpher-url-port (url)
- "Retrieve port from URL object."
- (url-port url))
-
-(defun elpher-url-use-tls-p (url)
- "Return non-nil if URL is marked as needing TLS."
- (string-equal (url-type address) "gophers"))
-
-(defun elpher-url-special-p (url)
- "Return non-nil if URL object is special (e.g. start page, bookmarks page)."
- (symbolp url))
+;; An elpher "address" object is either a url object or a symbol.
+;; Symbol addresses are "special", corresponding to pages generated
+;; dynamically for and by elpher. All others represent pages which
+;; rely on content retrieved over the network.
+
+(defun elpher-address-from-url (url-string)
+ "Create a ADDRESS object corresponding to the given URL-STRING."
+ (let ((data (match-data))) ; Prevent parsing clobbering match data
+ (unwind-protect
+ (let ((url (url-generic-parse-url url-string)))
+ (setf (url-fullness url) t)
+ (unless (url-host url)
+ (setf (url-host url) (url-filename url))
+ (setf (url-filename url) ""))
+ (unless (url-type url)
+ (setf (url-type url) "gopher"))
+ (if (and (url-type url)
+ (url-host url))
+ (let ((is-gopher (or (equal "gopher" (url-type url))
+ (equal "gophers" (url-type url)))))
+ (setf (url-filename url)
+ (url-unhex-string (url-filename url)))
+ (when (or (equal (url-filename url) "")
+ (equal (url-filename url) "/"))
+ (if is-gopher
+ (setf (url-filename url) "/1")))
+ (unless (> (url-port url) 0)
+ (if is-gopher
+ (setf (url-port url) 70)))
+ url)
+ (error "Malformed URL" url)))
+ (set-match-data data))))
+
+(defun elpher-make-gopher-address (type selector host port &optional tls)
+ "Create an ADDRESS object corresponding to the given gopher directory record
+attributes: TYPE, SELECTOR, HOST and PORT."
+ (if (and (equal type ?h)
+ (string-prefix-p "URL:" selector))
+ (elpher-address-from-url (elt (split-string selector "URL:") 1))
+ (elpher-address-from-url
+ (concat "gopher" (if tls "s" "")
+ "://" host
+ ":" (number-to-string port)
+ "/" (string type)
+ selector))))
+
+(defun elpher-make-special-address (type)
+ "Create an ADDRESS object corresponding to the given special page symbol TYPE."
+ type)
+
+(defun elpher-address-to-url (address)
+ "Get string representation of ADDRESS, or nil if ADDRESS is special."
+ (if (not (elpher-address-special-p address))
+ (url-encode-url (url-recreate-url address))
+ nil))
+
+(defun elpher-address-type (address)
+ "Retrieve selector type from ADDRESS object."
+ (if (symbolp address)
+ (list 'special address)
+ (let ((protocol (url-type address)))
+ (cond ((or (equal protocol "gopher")
+ (equal protocol "gophers"))
+ (list 'gopher (string-to-char (substring (url-filename address) 1))))
+ ((equal protocol "gemini")
+ 'gemini)
+ (t 'other-url)))))
+
+(defun elpher-address-protocol (address)
+ (if (symbolp address)
+ nil
+ (url-type address)))
+
+(defun elpher-address-filename (address)
+ (if (symbolp address)
+ nil
+ (url-filename address)))
+
+(defun elpher-address-host (address)
+ "Retrieve host from ADDRESS object."
+ (url-host address))
+
+(defun elpher-address-port (address)
+ "Retrieve port from ADDRESS object."
+ (url-port address))
+
+(defun elpher-address-special-p (address)
+ "Return non-nil if ADDRESS object is special (e.g. start page, bookmarks page)."
+ (symbolp address))
+
+(defun elpher-address-gopher-p (address)
+ "Return non-nill if ADDRESS object is a gopher address."
+ (memq (elpher-address-protocol address) '("gopher gophers")))
+
+(defun elpher-gopher-address-selector (address)
+ "Retrieve gopher selector from ADDRESS object."
+ (substring (url-filename address) 2))