The substrings of a `:txt' record can be at most 255 bytes long. If the
argument is a single string that's too long then split it into pieces;
prefer to split at semicolons, or spaces.
If the argument is a list of strings, then respect their split.
Theoretically, the split positions are semantically transparent, but
it's possible that some programs are sensitive to the boundaries.
(defpackage #:zone
(:use #:common-lisp
(defpackage #:zone
(:use #:common-lisp
- #:mdw.base #:mdw.str #:collect #:safely
+ #:mdw.base #:mdw.str #:anaphora #:collect #:safely
#:net #:services)
(:import-from #:net #:round-down #:round-up))
#:net #:services)
(:import-from #:net #:round-down #:round-up))
(rec-name (zr-data zr))
5)
(rec-name (zr-data zr))
5)
+(defun split-txt-data (data)
+ (collecting ()
+ (let ((i 0) (n (length data)))
+ (loop
+ (let ((end (+ i 255)))
+ (when (<= n end) (return))
+ (let ((split (acond ((position #\; data :from-end t
+ :start i :end end)
+ (+ it 1))
+ ((position #\space data :from-end t
+ :start i :end end)
+ (+ it 1))
+ (t end))))
+ (loop
+ (when (or (>= split end)
+ (char/= (char data split) #\space))
+ (return))
+ (incf split))
+ (collect (subseq data i split))
+ (setf i split))))
+ (collect (subseq data i)))))
+
(defzoneparse :txt (name data rec)
":txt (TEXT*)"
(defzoneparse :txt (name data rec)
":txt (TEXT*)"
- (rec :data (listify data)))
+ (rec :data (cond ((stringp data) (split-txt-data data))
+ (t
+ (dolist (piece data)
+ (unless (<= (length piece) 255)
+ (error "`:txt' record piece `~A' too long" piece)))
+ data))))
(defmethod zone-record-rrdata ((type (eql :txt)) zr)
(mapc #'rec-string (zr-data zr))
(defmethod zone-record-rrdata ((type (eql :txt)) zr)
(mapc #'rec-string (zr-data zr))