;;;; (web uri) --- URI manipulation tools
;;;;
;;;; Copyright (C) 1997,2001,2002,2010,2011,2012,2013,2014,2019 Free Software Foundation, Inc.
;;;;
;;;; This library is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU Lesser General Public
;;;; License as published by the Free Software Foundation; either
;;;; version 3 of the License, or (at your option) any later version.
;;;;
;;;; This library is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;;;; Lesser General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU Lesser General Public
;;;; License along with this library; if not, write to the Free Software
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
;;;;

;;; Commentary:

;; A data type for Universal Resource Identifiers, as defined in RFC
;; 3986.

;;; Code:

(define-module (web uri)
  #:use-module (srfi srfi-9)
  #:use-module (ice-9 regex)
  #:use-module (ice-9 rdelim)
  #:use-module (ice-9 control)
  #:use-module (rnrs bytevectors)
  #:use-module (ice-9 binary-ports)
  #:export (uri?
            uri-scheme uri-userinfo uri-host uri-port
            uri-path uri-query uri-fragment

            build-uri
            build-uri-reference
            declare-default-port!
            string->uri string->uri-reference
            uri->string
            uri-decode uri-encode
            split-and-decode-uri-path
            encode-and-join-uri-path

            uri-reference? relative-ref?
            build-uri-reference build-relative-ref
            string->uri-reference string->relative-ref))

(define-record-type <uri>
  (make-uri scheme userinfo host port path query fragment)
  uri-reference?
  (scheme uri-scheme)
  (userinfo uri-userinfo)
  (host uri-host)
  (port uri-port)
  (path uri-path)
  (query uri-query)
  (fragment uri-fragment))

;;;
;;; Predicates.
;;;
;;; These are quick, and assume rigid validation at construction time.

;;; RFC 3986, #3.
;;;
;;;   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
;;;
;;;   hier-part   = "//" authority path-abempty
;;;               / path-absolute
;;;               / path-rootless
;;;               / path-empty

(define (uri? obj)
  (and (uri-reference? obj)
       (if (include-deprecated-features)
           (begin
             (unless (uri-scheme obj)
               (issue-deprecation-warning
                "Use uri-reference? instead of uri?; in the future, uri?
will require that the object not be a relative-ref."))
             #t)
           (uri-scheme obj))
       #t))

;;; RFC 3986, #4.2.
;;;
;;;   relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
;;;
;;;   relative-part = "//" authority path-abempty
;;;                 / path-absolute
;;;                 / path-noscheme
;;;                 / path-empty

(define (relative-ref? obj)
  (and (uri-reference? obj)
       (not (uri-scheme obj))))

