From 1bf429571f756b88fb7ab2ec85552e39ecebfdaa Mon Sep 17 00:00:00 2001 From: Jaidyn Ann <10477760+JadedCtrl@users.noreply.github.com> Date: Mon, 12 Feb 2024 22:10:43 -0600 Subject: [PATCH] =?UTF-8?q?Signal=20exception=20if=20input=20isn=E2=80=99t?= =?UTF-8?q?=20vCard?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … with a somewhat naïve check. Also, also count horizontal-tab characters as starters of folded lines (as per spec). --- vcarded.scm | 50 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/vcarded.scm b/vcarded.scm index 2b41b58..d1abfb4 100644 --- a/vcarded.scm +++ b/vcarded.scm @@ -21,6 +21,7 @@ (chicken base) (chicken condition) (chicken io) + (chicken irregex) (srfi 1) (srfi 4) (srfi 13) @@ -223,24 +224,53 @@ (parse-vcard-value property value-elements)))) - ;; Reader thunk. Read/parse an entire vcard into a “vcard alist.” - (define (read-vcard) - (let [(element (read-vcard-element))] + ;; Reader thunk. Read/parse an entire vCard into a “vCard alist.” + ;; Ignore the IGNORED parameter. + (define (read-vcard . ignored) + (let* [(first-element? (optional ignored #t)) + (element (read-vcard-element first-element?))] (if (not (eof-object? (peek-char))) - (append (list element) (read-vcard)) + (append (list element) (read-vcard #f)) (list element)))) - ;; Read a single unfolded line into a vcard “element” list. - (define (read-vcard-element) - (parse-vcard-line (read-folded-line))) + ;; Read a single unfolded line into a vCard “element” list. + ;; The optional FIRST-ELEMENT? argument simply makes sure the next line is a + ;; BEGIN:VCARD element (as the first element in any valid vCard file should + ;; be. It is used internally by READ-VCARD. + (define (read-vcard-element . first-element?) + (let* [(first-element? (optional first-element? #f)) + (line (read-folded-line (if first-element? 100 #f)))] + (cond + ;; Ignore blank lines, they’re not doing anyone any harm! + [(or (string-null? line) + (irregex-search "^[[:whitespace:]]+$" line)) + (read-vcard-element first-element?)] + ;; If we’ve previously established this is a vCard stream we’re dealing + ;; with, just go ahead and parse. If we haven’t established that, make + ;; sure it’s a BEGIN:VCARD line first. + [(or (not first-element?) + (and first-element? + (string-contains line "BEGIN") + (string-contains line "VCARD"))) + (parse-vcard-line (read-folded-line))] + ;; If we’re still making sure the file is vCard, and the first non-blank + ;; line *isn’t* a BEGIN:VCARD line, then the file probably isn’t a vCard. + [#t + (signal + (condition '(exn location vcarded message + "Not a valid vCard file.") + '(file) + '(vcard)))]))) + ;; Reader-thunk. Read a “logical” folded-line, where a line beginning with a ;; space is a continuation of the previous line — like with vcards. - (define (read-folded-line) - (let [(line (read-line))] - (if (eq? (peek-char) #\space) + (define (read-folded-line #!optional limit) + (let [(line (read-line (current-input-port) limit))] + (if (or (eq? (peek-char) #\space) + (eq? (peek-char) #\tab)) (string-concatenate (list line (string-drop (read-folded-line) 1)))