source: tags/pre_mode_tracking/utility.lisp

Last change on this file was 76, checked in by Erik Huelsmann, 19 years ago

Make default behaviours obey rpl_isupport parameters advertized by the server.

  • variable.lisp (*default-isupport-values*): New.
  • utility.lisp (irc-string-downcase): New. Method to do case mapping required to canonicalize entity (channel, nick) identity names. (parse-isupport-multivalue-argument): New. Parse isupport string used in multi-value argument-values as used for CHANLIMIT, CHANMODES, IDCHAN and others.
  • protocol.lisp (connection:server-capabilities): New. This slot stores the assoc list of parameter keys and their values. (case-map-name): New. Returns the case-mapping used for a connection. (re-apply-case-mapping): New. Make sure all nicks and channels have been mapped using the same function. Also assures all hashes are based on the same mapping function. (add-default-hooks): Add irc-rpl_isupport-message to the default hooks list. (normalize-channel-name): Add connection parameter; use case-mapping active for the given connection. (make-channel): Add a connection to be passed in order to be able to do name-normalization. (make-user): Add connection parameter in order to be able to do name-normalization. (canonicalize-nickname): Use server-advertized nickname prefixes to determine how to canonicalize. (normalize-nickname): Use connections case-mapping to do normalization. (find-or-make-user): Pass connection in call to make-user. (find-channel, find-user, change-nickname): Update callers of normalize-nickname, normalize-channel-name and canonicalize-nickname
  • command.lisp (connect): Change instance creation order; creating a user requires a connection now.
  • event.lisp (default-hook [irc-rpl_isupport-message]): New. Implement default hook message for rpl_isupport message. Make sure that default values do get set. (default-hook [irc-rpl_list-message,

irc-join-message]): Update caller of make-channel.

(default-hook [irc-rpl_namreply-message]): Update caller of
canonicalize-nickname.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.8 KB
Line 
1;;;; $Id: utility.lisp 76 2005-01-20 23:59:19Z ehuelsmann $
2;;;; $Source$
3
4;;;; See the LICENSE file for licensing information.
5
6(in-package :irc)
7
8(defun get-day-name (day-number)
9  "Given a number, such as 1, return the appropriate day name,
10abbrevated, such as \"Tue\".  Index 0 is Monday."
11  (case day-number
12    (0 "Mon")
13    (1 "Tue")
14    (2 "Wed")
15    (3 "Thu")
16    (4 "Fri")
17    (5 "Sat")
18    (6 "Sun")
19    (otherwise
20     (error "Unknown day ~A." day-number))))
21
22(defun get-month-name (month-number)
23  "Index 1 is January."
24  (case month-number
25    (1 "Jan")
26    (2 "Feb")
27    (3 "Mar")
28    (4 "Apr")
29    (5 "May")
30    (6 "Jun")
31    (7 "Jul")
32    (8 "Aug")
33    (9 "Sep")
34    (10 "Oct")
35    (11 "Nov")
36    (12 "Dec")
37    (otherwise
38     (error "Unknown month ~A." month-number))))
39
40(defun make-time-message (second minute hour date month year day)
41  "Returns a string composed of the input parameters so that it
42represents a time message as by the IRC protocol."
43  (format nil "~A ~A ~2D ~2,'0D:~2,'0D:~2,'0D ~D"
44          (get-day-name day)
45          (get-month-name month)
46          date
47          hour
48          minute
49          second
50          year))
51
52(defun make-irc-message (command &key (arguments nil)
53                                 (trailing-argument nil))
54  "Return a valid IRC message, as a string, composed of the input
55parameters."
56  (let ((*print-circle* nil))
57    (format nil "~A~{ ~A~}~A~A~A~A" command arguments
58            (if trailing-argument
59                " :"
60              "")
61            (or trailing-argument "")
62            #\Return
63            #\Linefeed)))
64
65(defun make-ctcp-message (string)
66  "Return a valid IRC CTCP message, as a string, composed by
67`string'."
68  (format nil "~A~A~A" +soh+ string +soh+))
69
70(defun tokenize-string (string &key
71                               (delimiters '(#\Space #\Return #\Linefeed #\Newline)))
72  "Split string into a list, splitting on `delimiters' and removing any
73empty subsequences."
74  (split-sequence:split-sequence-if #'(lambda (character)
75                                        (member character delimiters))
76                                    string :remove-empty-subseqs t))
77
78(defun list-of-strings-to-integers (list)
79  "Take a list of strings and return a new list of integers (from
80parse-integer) on each of the string elements."
81  (let ((new-list nil))
82    (dolist (element (reverse list))
83      (push (parse-integer element) new-list))
84    new-list))
85
86(defun host-byte-order (string)
87  "Convert a string, such as 192.168.1.1, to host-byte-order, such as
883232235777."
89  (let ((list (list-of-strings-to-integers (split-sequence:split-sequence #\. string))))
90    (+ (* (first list) 256 256 256) (* (second list) 256 256)
91       (* (third list) 256) (fourth list))))
92
93(defun hbo-to-dotted-quad (integer)
94  "Host-byte-order integer to dotted-quad string conversion utility."
95  (let ((first (ldb (byte 8 24) integer))
96        (second (ldb (byte 8 16) integer))
97        (third (ldb (byte 8 8) integer))
98        (fourth (ldb (byte 8 0) integer)))
99    (format nil "~A.~A.~A.~A" first second third fourth)))
100
101(defun hbo-to-vector-quad (integer)
102  "Host-byte-order integer to dotted-quad string conversion utility."
103  (let ((first (ldb (byte 8 24) integer))
104        (second (ldb (byte 8 16) integer))
105        (third (ldb (byte 8 8) integer))
106        (fourth (ldb (byte 8 0) integer)))
107    (vector first second third fourth)))
108
109(defun cut-between (string start-char end-chars &key (start 0) (cut-extra t))
110  "If `start-char' is not nil, cut string between `start-char' and any
111of the `end-chars', from `start'.  If `start-char' is nil, cut from
112`start' until any of the `end-chars'.
113
114If `cut-extra' is t, we will cut from start + 1 instead of just
115`start'.
116
117When there is no string matching the input parameters `start' and nil
118will be returned, otherwise `end-position' and the string are
119returned."
120  (let ((end-position (position-if #'(lambda (char)
121                                       (member char end-chars))
122                                   string :start (1+ start)))
123        (cut-from (if cut-extra
124                      (1+ start)
125                      start)))
126    (if (and end-position start-char)
127        (if (eql (char string start) start-char)
128            (values end-position
129                    (subseq string cut-from end-position))
130            (values start nil))
131        (if end-position
132            (values end-position
133                    (subseq string cut-from end-position))
134            (values start nil)))))
135
136(defun cut-before (string substring end-chars &key (start 0) (cut-extra t))
137  "Cut `string' before `substring' or any of the `end-chars', from `start'.
138
139If `cut-extra' is t, we will cut from start + 1 instead of just
140`start'.
141
142When there is no string matching the input parameters `start' and nil
143will be returned, otherwise `end-position' and the string are
144returned."
145  (let ((end-position (search substring string :start2 start)))
146    (if end-position
147        (values (+ end-position (1- (length substring)))
148                (subseq string (if (and cut-extra
149                                        (< start end-position))
150                                   (1+ start) start) end-position))
151      (let ((end-position (position-if #'(lambda (x)
152                                           (member x end-chars))
153                                       string :start (1+ start)))
154            (cut-from (if cut-extra (1+ start) start)))
155        (if end-position
156            (values end-position
157                    (subseq string cut-from end-position))
158          (values start nil))))))
159
160(defgeneric irc-string-downcase (map-name string &key start end))
161
162(defmethod irc-string-downcase (map-name
163                                string &key (start 0) end)
164  (declare (ignore map-name))
165  (let* ((new-string (substitute #\[ #\{ string :start start :end end))
166         (new-string (substitute #\] #\} new-string :start start :end end))
167         (new-string (substitute #\\ #\| new-string :start start :end end))
168         (new-string (substitute #\~ #\^ new-string :start start :end end)))
169    (string-downcase new-string :start start :end end)))
170
171(defmethod irc-string-downcase ((map-name (eql :ascii))
172                                string &key (start 0) end)
173  (declare (ignore map-name))
174  (string-downcase string :start start :end end))
175
176(defun parse-isupport-prefix-argument (prefix)
177  (declare (type string prefix))
178  (let ((closing-paren-pos (position #\) prefix)))
179    (when (and (eq (elt prefix 0) #\( )
180               closing-paren-pos)
181      (let ((prefixes (subseq prefix (1+ closing-paren-pos)))
182            (modes (subseq prefix 1 closing-paren-pos)))
183        (when (= (length prefixes)
184                 (length modes))
185          (values prefixes modes))))))
186
187(defun parse-isupport-multivalue-argument (argument)
188  (declare (type string argument))
189  (mapcar #'(lambda (x)
190              (split-sequence:split-sequence #\: x))
191          (split-sequence:split-sequence #\, argument)))
Note: See TracBrowser for help on using the repository browser.