Importing Liece 1.4.3.
[elisp/liece.git] / lisp / liece-filter.el
1 ;;; liece-filter.el --- Process filters for IRC process.
2 ;; Copyright (C) 1998-2000 Daiki Ueno
3
4 ;; Author: Daiki Ueno <ueno@unixuser.org>
5 ;; Created: 1998-09-28
6 ;; Revised: 1998-11-25
7 ;; Keywords: IRC, liece
8
9 ;; This file is part of Liece.
10
11 ;; This program is free software; you can redistribute it and/or modify
12 ;; it under the terms of the GNU General Public License as published by
13 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; any later version.
15
16 ;; This program is distributed in the hope that it will be useful,
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 ;; GNU General Public License for more details.
20
21 ;; You should have received a copy of the GNU General Public License
22 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
23 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 ;; Boston, MA 02111-1307, USA.
25
26
27 ;;; Commentary:
28 ;; 
29
30 ;;; Code:
31
32 (require 'liece-inlines)
33 (require 'liece-misc)
34 (require 'liece-intl)
35 (require 'liece-handler)
36
37 (defvar liece-current-function nil)
38
39 (defun* liece-handle-message (prefix message line)
40   (let ((hook (intern (concat "liece-" message "-hook")))
41         (after-hook (intern (concat "liece-after-" message "-hook")))
42         (number (car (read-from-string message)))
43         func)
44     (if (condition-case nil
45             (run-hook-with-args-until-success hook prefix line)
46           (error nil))
47         (return-from liece-handle-message))
48     
49     (cond
50      ((numberp number)
51       (let* ((base (/ number 100))
52              (backend (format "liece-%d00" base)))
53         (or (eval `(featurep ',(intern backend)))
54             (load backend t))
55         (setq func (liece-handler-find-function message '(prefix line)
56                                         (format "%d00" base)))
57         (if func
58             (funcall func prefix line)
59           (funcall (symbol-function (intern
60                                      (format "liece-handle-%d00-messages"
61                                              base)))
62                    message prefix line))))
63      (t
64       (setq func (liece-handler-find-function
65                   message '(prefix line) "generic"))
66       (if func
67           (funcall func prefix line))))
68
69     (ignore-errors (run-hook-with-args after-hook prefix line))))
70
71 (defun liece-parse-user-at-host ()
72   (let ((cookie
73          (and (stringp liece-user-at-host)
74               (> (length liece-user-at-host) 2)
75               (string-to-char liece-user-at-host))))
76     (cond
77      ((null cookie)
78       (setq liece-user-at-host-type 'invalid))
79      ((or (eq cookie ?^) (eq cookie ?=))
80       (setq liece-user-at-host (substring liece-user-at-host 1)
81             liece-user-at-host-type 'fake))
82      ((or (eq cookie ?~) (eq cookie ?-))
83       (setq liece-user-at-host (substring liece-user-at-host 1)
84             liece-user-at-host-type 'not-verified))
85      ((eq cookie ?+)
86       (setq liece-user-at-host (substring liece-user-at-host 1)
87             liece-user-at-host-type 'ok))
88      (t (setq liece-user-at-host-type 'ok)))))
89
90 (defun liece-parse-line (line)
91   (let (prefix message)
92     (when (or (string-match "^\\(:[^! ]*\\)!\\([^ ]*\\) +\\([^ ]+\\) +:?"
93                             line)
94               (string-match "^\\(:[^ ]*\\)?\\(\\) *\\([^ ]+\\) +:?"
95                             line)
96               (string-match "^\\(:[^! \t]*\\)!\\([^ \t]*\\) +\\([^ \t]+\\) +:?"
97                             line)
98               (string-match "^\\(:[^ ]*\\)?\\(\\) *\\([^ \t]+\\) +:?"
99                             line))
100       (setq prefix (if (match-beginning 1)
101                        (substring (match-string 1 line) 1))
102             liece-user-at-host (match-string 2 line)
103             message (downcase (match-string 3 line))
104             line (liece-coding-decode-charset-string
105                   (substring line (match-end 0))))
106       
107       (liece-parse-user-at-host)
108       (setq liece-current-function (list prefix message))
109       (liece-handle-message prefix message line)
110       (setq liece-current-function '("" "")))))
111
112 (defun liece-filter (process output)
113   "Filter function for IRC server process."
114   (with-current-buffer (process-buffer process)
115     (goto-char (point-max))
116     (insert (liece-convert-received-input output))
117     (goto-char (point-min))
118     (while (progn (end-of-line) (and (not (eobp)) (eq (char-after) ?\n)))
119       (if (eq (char-after (1- (point))) ?\r) ; cut off preceding LF
120           (delete-region (1- (point)) (point)))
121       (liece-parse-line (buffer-substring (point-min) (point)))
122       (delete-region (point-min) (progn (beginning-of-line 2) (point))))))
123
124 (defun liece-sentinel (proc status)
125   "Sentinel function for Liece process."
126   (cond
127    ((or (not liece-server-process) (liece-server-opened)))
128    ((not (or liece-reconnect-automagic liece-reconnect-with-password))
129     (if (process-id proc)
130         (liece-sentinel-error proc status)
131       (liece-message (_ "Connection closed. (%s)")
132                       (substring status 0 (1- (length status)))))
133     (liece-clear-system))
134    (liece-reconnect-with-password
135     (liece))
136    (t
137     (condition-case nil
138         (progn
139           (set-process-filter liece-server-process nil)
140           (set-process-sentinel liece-server-process nil))
141       (wrong-type-argument nil))
142     (setq liece-server-process nil)
143     (liece))))
144
145 (defun liece-sentinel-error (proc status)
146   (if (not (string-match "^exited abnormally with code \\([0-9]+\\)" status))
147       (liece-message (_ "Connection closed. (%s)")
148                       (substring status 0 (1- (length status))))
149     (let ((status (string-to-int (match-string 1 status))))
150       (cond
151        ((= 99 status) ;; unsupported command
152         (liece-message (_ "Please use a newer \"%s\".") liece-dcc-program))
153        ((= 98 status) ;; bad argment number
154         (liece-message (_ "Please use a newer \"%s\".") liece-dcc-program))
155        ((= 97 status)
156         (liece-message (_ "Cannot connect to IRC server.")))
157        (t
158         (liece-message (_ "Server connection closed.")))))))
159
160 (provide 'liece-filter)
161
162 ;;; liece-filter.el ends here