aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Olson2008-10-08 04:05:10 +0000
committerMichael Olson2008-10-08 04:05:10 +0000
commit1c86baa408007e4ab3774ebdb53e620eacb7a4c1 (patch)
tree0b0e18c0481d7de26ff1f09614c25ef2a24ddd9b
parentf2602864b661c32888029f38921fb19f65bf337e (diff)
downloademacs-1c86baa408007e4ab3774ebdb53e620eacb7a4c1.tar.gz
emacs-1c86baa408007e4ab3774ebdb53e620eacb7a4c1.zip
ERC: DCC fixes.
-rw-r--r--lisp/erc/ChangeLog34
-rw-r--r--lisp/erc/erc-dcc.el151
2 files changed, 142 insertions, 43 deletions
diff --git a/lisp/erc/ChangeLog b/lisp/erc/ChangeLog
index 5d93364dc4a..3d1ac3baab0 100644
--- a/lisp/erc/ChangeLog
+++ b/lisp/erc/ChangeLog
@@ -1,3 +1,37 @@
12008-10-03 Michael Olson <mwolson@gnu.org>
2
3 * erc-dcc.el (english): Increase size heading by two places.
4 (erc-dcc-byte-count): Move higher.
5 (erc-dcc-do-LIST-command): Use erc-dcc-byte-count to get accurate
6 count. Coerce byte total to floating point before performing
7 computation, otherwise division will truncate to 0.
8 (erc-dcc-append-contents): Update erc-dcc-byte-count.
9 (erc-dcc-get-filter): Don't update erc-dcc-byte-count, because
10 that will give incorrect size totals. Instead, figure out how
11 much we have by summing byte count and current buffer size.
12 (erc-dcc-get-sentinel): Don't update erc-dcc-byte-count.
13
142008-10-01 Michael Olson <mwolson@gnu.org>
15
16 * erc-dcc.el (erc-pack-int): Make sure returned string is within 4
17 bytes. Always return a 4-byte string, so that we conform to the
18 CTCP spec.
19 (erc-most-positive-int-bytes): New constant representing the
20 number of bytes that most-positive-fixnum can be stored in.
21 (erc-most-positive-int-msb): New constant representing the
22 contents of the most significant byte of most-positive-fixnum.
23 (erc-unpack-int): Make sure that the integer we get back can be
24 represented in Emacs.
25 (erc-dcc-do-CLOSE-command): Update docstring. Don't use the line
26 variable. Try to disambiguate between type and nick when only one
27 is provided. Validate both type and nick arguments. Allow
28 matching by just nick.
29 (erc-dcc-append-contents): Set inhibit-read-only to t. Prevent
30 auto-compression from triggering when we write the contents to a
31 file.
32 (erc-dcc-get-file): Prevent auto-compression from triggering when
33 we truncate a file.
34
12008-07-27 Dan Nicolaescu <dann@ics.uci.edu> 352008-07-27 Dan Nicolaescu <dann@ics.uci.edu>
2 36
3 * erc.el: Remove code for Carbon. 37 * erc.el: Remove code for Carbon.
diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el
index 2877107bb96..e6329c10cbb 100644
--- a/lisp/erc/erc-dcc.el
+++ b/lisp/erc/erc-dcc.el
@@ -79,6 +79,11 @@ IRC users."
79 :group 'erc-dcc 79 :group 'erc-dcc
80 :type 'boolean) 80 :type 'boolean)
81 81
82(defconst erc-dcc-connection-types
83 '("CHAT" "GET" "SEND")
84 "List of valid DCC connection types.
85All values of the list must be uppercase strings.")
86
82(defvar erc-dcc-list nil 87(defvar erc-dcc-list nil
83 "List of DCC connections. Looks like: 88 "List of DCC connections. Looks like:
84 ((:nick \"nick!user@host\" :type GET :peer proc :parent proc :size size :file file) 89 ((:nick \"nick!user@host\" :type GET :peer proc :parent proc :size size :file file)
@@ -145,9 +150,9 @@ IRC users."
145 (dcc-get-file-too-long 150 (dcc-get-file-too-long
146 . "DCC: %f: File longer than sender claimed; aborting transfer") 151 . "DCC: %f: File longer than sender claimed; aborting transfer")
147 (dcc-get-notfound . "DCC: %n hasn't offered %f for DCC transfer") 152 (dcc-get-notfound . "DCC: %n hasn't offered %f for DCC transfer")
148 (dcc-list-head . "DCC: From Type Active Size Filename") 153 (dcc-list-head . "DCC: From Type Active Size Filename")
149 (dcc-list-line . "DCC: -------- ---- ------ ------------ --------") 154 (dcc-list-line . "DCC: -------- ---- ------ -------------- --------")
150 (dcc-list-item . "DCC: %-8n %-4t %-6a %-12s %f") 155 (dcc-list-item . "DCC: %-8n %-4t %-6a %-14s %f")
151 (dcc-list-end . "DCC: End of list.") 156 (dcc-list-end . "DCC: End of list.")
152 (dcc-malformed . "DCC: error: %n (%u@%h) sent malformed request: %q") 157 (dcc-malformed . "DCC: error: %n (%u@%h) sent malformed request: %q")
153 (dcc-privileged-port 158 (dcc-privileged-port
@@ -200,25 +205,55 @@ compared with `erc-nick-equal-p' which is IRC case-insensitive."
200 result)) 205 result))
201 206
202(defun erc-pack-int (value) 207(defun erc-pack-int (value)
203 "Convert an integer into a packed string." 208 "Convert an integer into a packed string in network byte order,
204 (let* ((len (ceiling (/ value 256.0))) 209which is big-endian."
205 (str (make-string len ?a)) 210 ;; make sure value is not negative
206 (i (1- len))) 211 (when (< value 0)
207 (while (>= i 0) 212 (error "ERC-DCC (erc-pack-int): packet size is negative"))
213 ;; make sure size is not larger than 4 bytes
214 (let ((len (if (= value 0) 0
215 (ceiling (/ (ceiling (/ (log value) (log 2))) 8.0)))))
216 (when (> len 4)
217 (error "ERC-DCC (erc-pack-int): packet too large")))
218 ;; pack
219 (let ((str (make-string 4 0))
220 (i 3))
221 (while (and (>= i 0) (> value 0))
208 (aset str i (% value 256)) 222 (aset str i (% value 256))
209 (setq value (/ value 256)) 223 (setq value (/ value 256))
210 (setq i (1- i))) 224 (setq i (1- i)))
211 str)) 225 str))
212 226
227(defconst erc-most-positive-int-bytes
228 (ceiling (/ (ceiling (/ (log most-positive-fixnum) (log 2))) 8.0))
229 "Maximum number of bytes for a fixnum.")
230
231(defconst erc-most-positive-int-msb
232 (lsh most-positive-fixnum (- 0 (* 8 (1- erc-most-positive-int-bytes))))
233 "Content of the most significant byte of most-positive-fixnum.")
234
213(defun erc-unpack-int (str) 235(defun erc-unpack-int (str)
214 "Unpack a packed string into an integer." 236 "Unpack a packed string into an integer."
215 (let ((len (length str)) 237 (let ((len (length str)))
216 (num 0) 238 ;; strip leading 0-bytes
217 (count 0)) 239 (let ((start 0))
218 (while (< count len) 240 (while (and (> len start) (eq (aref str start) 0))
219 (setq num (+ num (lsh (aref str (- len count 1)) (* 8 count)))) 241 (setq start (1+ start)))
220 (setq count (1+ count))) 242 (when (> start 0)
221 num)) 243 (setq str (substring str start))
244 (setq len (- len start))))
245 ;; make sure size is not larger than Emacs can handle
246 (when (or (> len (min 4 erc-most-positive-int-bytes))
247 (and (eq len erc-most-positive-int-bytes)
248 (> (aref str 0) erc-most-positive-int-msb)))
249 (error "ERC-DCC (erc-unpack-int): packet to send is too large"))
250 ;; unpack
251 (let ((num 0)
252 (count 0))
253 (while (< count len)
254 (setq num (+ num (lsh (aref str (- len count 1)) (* 8 count))))
255 (setq count (1+ count)))
256 num)))
222 257
223(defconst erc-dcc-ipv4-regexp 258(defconst erc-dcc-ipv4-regexp
224 (concat "^" 259 (concat "^"
@@ -447,19 +482,32 @@ where FOO is one of CLOSE, GET, SEND, LIST, CHAT, etc."
447 t)))) 482 t))))
448 483
449(defun erc-dcc-do-CLOSE-command (proc &optional type nick) 484(defun erc-dcc-do-CLOSE-command (proc &optional type nick)
450 "/dcc close type nick 485 "Close a connection. Usage: /dcc close type nick.
451type and nick are optional." 486At least one of TYPE and NICK must be provided."
452 ;; FIXME, should also work if only nick is specified 487 ;; disambiguate type and nick if only one is provided
453 (when (string-match (concat "^\\s-*\\(\\S-+\\)? *\\(" 488 (when (and type (null nick)
454 erc-valid-nick-regexp "\\)?\\s-*$") line) 489 (not (member (upcase type) erc-dcc-connection-types)))
455 (let ((type (when (match-string 1 line) 490 (setq nick type)
456 (intern (upcase (match-string 1 line))))) 491 (setq type nil))
457 (nick (match-string 2 line)) 492 ;; validate nick argument
458 (ret t)) 493 (unless (and nick (string-match (concat "\\`" erc-valid-nick-regexp "\\'")
494 nick))
495 (setq nick nil))
496 ;; validate type argument
497 (if (and type (member (upcase type) erc-dcc-connection-types))
498 (setq type (intern (upcase type)))
499 (setq type nil))
500 (when (or nick type)
501 (let ((ret t))
459 (while ret 502 (while ret
460 (if nick 503 (cond ((and nick type)
461 (setq ret (erc-dcc-member :type type :nick nick)) 504 (setq ret (erc-dcc-member :type type :nick nick)))
462 (setq ret (erc-dcc-member :type type))) 505 (nick
506 (setq ret (erc-dcc-member :nick nick)))
507 (type
508 (setq ret (erc-dcc-member :type type)))
509 (t
510 (setq ret nil)))
463 (when ret 511 (when ret
464 ;; found a match - delete process if it exists. 512 ;; found a match - delete process if it exists.
465 (and (processp (plist-get ret :peer)) 513 (and (processp (plist-get ret :peer))
@@ -470,7 +518,7 @@ type and nick are optional."
470 'dcc-closed 518 'dcc-closed
471 ?T (plist-get ret :type) 519 ?T (plist-get ret :type)
472 ?n (erc-extract-nick (plist-get ret :nick)))))) 520 ?n (erc-extract-nick (plist-get ret :nick))))))
473 t)) 521 t))
474 522
475(defun erc-dcc-do-GET-command (proc nick &rest file) 523(defun erc-dcc-do-GET-command (proc nick &rest file)
476 "Do a DCC GET command. NICK is the person who is sending the file. 524 "Do a DCC GET command. NICK is the person who is sending the file.
@@ -503,6 +551,9 @@ PROC is the server process."
503 nil '(notice error) 'active 551 nil '(notice error) 'active
504 'dcc-get-notfound ?n nick ?f filename)))) 552 'dcc-get-notfound ?n nick ?f filename))))
505 553
554(defvar erc-dcc-byte-count nil)
555(make-variable-buffer-local 'erc-dcc-byte-count)
556
506(defun erc-dcc-do-LIST-command (proc) 557(defun erc-dcc-do-LIST-command (proc)
507 "This is the handler for the /dcc list command. 558 "This is the handler for the /dcc list command.
508It lists the current state of `erc-dcc-list' in an easy to read manner." 559It lists the current state of `erc-dcc-list' in an easy to read manner."
@@ -538,12 +589,18 @@ It lists the current state of `erc-dcc-list' in an easy to read manner."
538 (plist-member elt :file) 589 (plist-member elt :file)
539 (buffer-live-p (get-buffer (plist-get elt :file))) 590 (buffer-live-p (get-buffer (plist-get elt :file)))
540 (plist-member elt :size)) 591 (plist-member elt :size))
541 (concat " (" (number-to-string 592 (let ((byte-count (with-current-buffer
593 (get-buffer (plist-get elt :file))
594 (+ (buffer-size) 0.0
595 erc-dcc-byte-count))))
596 (concat " ("
597 (if (= byte-count 0)
598 "0"
599 (number-to-string
600 (truncate
542 (* 100 601 (* 100
543 (/ (buffer-size 602 (/ byte-count (plist-get elt :size))))))
544 (get-buffer (plist-get elt :file))) 603 "%)"))))
545 (plist-get elt :size))))
546 "%)")))
547 ?f (or (and (plist-member elt :file) (plist-get elt :file)) ""))) 604 ?f (or (and (plist-member elt :file) (plist-get elt :file)) "")))
548 (erc-display-message 605 (erc-display-message
549 nil 'notice 'active 606 nil 'notice 'active
@@ -853,8 +910,6 @@ other client."
853 :group 'erc-dcc 910 :group 'erc-dcc
854 :type 'integer) 911 :type 'integer)
855 912
856(defvar erc-dcc-byte-count nil)
857(make-variable-buffer-local 'erc-dcc-byte-count)
858(defvar erc-dcc-file-name nil) 913(defvar erc-dcc-file-name nil)
859(make-variable-buffer-local 'erc-dcc-file-name) 914(make-variable-buffer-local 'erc-dcc-file-name)
860 915
@@ -880,7 +935,11 @@ filter and a process sentinel, and making the connection."
880 (setq erc-dcc-file-name file) 935 (setq erc-dcc-file-name file)
881 936
882 ;; Truncate the given file to size 0 before appending to it. 937 ;; Truncate the given file to size 0 before appending to it.
883 (write-region (point) (point) erc-dcc-file-name nil 'nomessage) 938 (let ((inhibit-file-name-handlers
939 (append '(jka-compr-handler image-file-handler)
940 inhibit-file-name-handlers))
941 (inhibit-file-name-operation 'write-region))
942 (write-region (point) (point) erc-dcc-file-name nil 'nomessage))
884 943
885 (setq erc-server-process parent-proc 944 (setq erc-server-process parent-proc
886 erc-dcc-entry-data entry) 945 erc-dcc-entry-data entry)
@@ -904,8 +963,14 @@ filter and a process sentinel, and making the connection."
904 "Append the contents of BUFFER to FILE. 963 "Append the contents of BUFFER to FILE.
905The contents of the BUFFER will then be erased." 964The contents of the BUFFER will then be erased."
906 (with-current-buffer buffer 965 (with-current-buffer buffer
907 (let ((coding-system-for-write 'binary)) 966 (let ((coding-system-for-write 'binary)
967 (inhibit-read-only t)
968 (inhibit-file-name-handlers
969 (append '(jka-compr-handler image-file-handler)
970 inhibit-file-name-handlers))
971 (inhibit-file-name-operation 'write-region))
908 (write-region (point-min) (point-max) erc-dcc-file-name t 'nomessage) 972 (write-region (point-min) (point-max) erc-dcc-file-name t 'nomessage)
973 (setq erc-dcc-byte-count (+ (buffer-size) erc-dcc-byte-count))
909 (erase-buffer)))) 974 (erase-buffer))))
910 975
911(defun erc-dcc-get-filter (proc str) 976(defun erc-dcc-get-filter (proc str)
@@ -915,23 +980,24 @@ buffer, and sends back the replies after each block of data per the DCC
915protocol spec. Well not really. We write back a reply after each read, 980protocol spec. Well not really. We write back a reply after each read,
916rather than every 1024 byte block, but nobody seems to care." 981rather than every 1024 byte block, but nobody seems to care."
917 (with-current-buffer (process-buffer proc) 982 (with-current-buffer (process-buffer proc)
918 (let ((inhibit-read-only t)) 983 (let ((inhibit-read-only t)
984 received-bytes)
919 (goto-char (point-max)) 985 (goto-char (point-max))
920 (insert (string-make-unibyte str)) 986 (insert (string-make-unibyte str))
921 987
922 (setq erc-dcc-byte-count (+ (length str) erc-dcc-byte-count))
923 (when (> (point-max) erc-dcc-receive-cache) 988 (when (> (point-max) erc-dcc-receive-cache)
924 (erc-dcc-append-contents (current-buffer) erc-dcc-file-name)) 989 (erc-dcc-append-contents (current-buffer) erc-dcc-file-name))
990 (setq received-bytes (+ (buffer-size) erc-dcc-byte-count))
925 991
926 (and erc-dcc-verbose 992 (and erc-dcc-verbose
927 (erc-display-message 993 (erc-display-message
928 nil 'notice erc-server-process 994 nil 'notice erc-server-process
929 'dcc-get-bytes-received 995 'dcc-get-bytes-received
930 ?f (file-name-nondirectory buffer-file-name) 996 ?f (file-name-nondirectory buffer-file-name)
931 ?b (number-to-string erc-dcc-byte-count))) 997 ?b (number-to-string received-bytes)))
932 (cond 998 (cond
933 ((and (> (plist-get erc-dcc-entry-data :size) 0) 999 ((and (> (plist-get erc-dcc-entry-data :size) 0)
934 (> erc-dcc-byte-count (plist-get erc-dcc-entry-data :size))) 1000 (> received-bytes (plist-get erc-dcc-entry-data :size)))
935 (erc-display-message 1001 (erc-display-message
936 nil '(error notice) 'active 1002 nil '(error notice) 'active
937 'dcc-get-file-too-long 1003 'dcc-get-file-too-long
@@ -939,7 +1005,7 @@ rather than every 1024 byte block, but nobody seems to care."
939 (delete-process proc)) 1005 (delete-process proc))
940 (t 1006 (t
941 (process-send-string 1007 (process-send-string
942 proc (erc-pack-int erc-dcc-byte-count))))))) 1008 proc (erc-pack-int received-bytes)))))))
943 1009
944 1010
945(defun erc-dcc-get-sentinel (proc event) 1011(defun erc-dcc-get-sentinel (proc event)
@@ -951,7 +1017,6 @@ transfer is complete."
951 (delete-process proc) 1017 (delete-process proc)
952 (setq erc-dcc-list (delete erc-dcc-entry-data erc-dcc-list)) 1018 (setq erc-dcc-list (delete erc-dcc-entry-data erc-dcc-list))
953 (unless (= (point-min) (point-max)) 1019 (unless (= (point-min) (point-max))
954 (setq erc-dcc-byte-count (+ (buffer-size) erc-dcc-byte-count))
955 (erc-dcc-append-contents (current-buffer) erc-dcc-file-name)) 1020 (erc-dcc-append-contents (current-buffer) erc-dcc-file-name))
956 (erc-display-message 1021 (erc-display-message
957 nil 'notice erc-server-process 1022 nil 'notice erc-server-process