64
65
(decode-coding-string string elmo-nntp-group-coding-system)
69
(defvar elmo-nntp-debug nil
70
"Non-nil forces NNTP folder as debug mode.
71
Debug information is inserted in the buffer \"*NNTP DEBUG*\"")
74
(defsubst elmo-nntp-debug (message &rest args)
76
(let ((biff (string-match "BIFF-" (buffer-name)))
78
(with-current-buffer (get-buffer-create (concat "*NNTP DEBUG*"
80
(goto-char (point-max))
82
(insert (apply 'format message args) "\n")))))
67
84
;;; ELMO NNTP folder
69
86
(luna-define-class elmo-nntp-folder (elmo-net-folder)
79
96
(append elmo-nntp-stream-type-alist
80
97
elmo-network-stream-type-alist))
81
98
elmo-network-stream-type-alist))
83
100
(setq name (luna-call-next-method))
84
101
(setq parse (elmo-parse-token name ":"))
85
102
(elmo-nntp-folder-set-group-internal folder
86
103
(elmo-nntp-encode-group-string
105
(setq explicit-user (eq ?: (string-to-char (cdr parse))))
88
106
(setq parse (elmo-parse-prefixed-element ?: (cdr parse)))
89
107
(elmo-net-folder-set-user-internal folder
90
108
(if (eq (length (car parse)) 0)
91
elmo-nntp-default-user
109
(unless explicit-user
110
elmo-nntp-default-user)
93
112
(unless (elmo-net-folder-server-internal folder)
94
113
(elmo-net-folder-set-server-internal folder
287
307
(elmo-nntp-send-command session
288
308
(format "authinfo user %s"
289
309
(elmo-network-session-user-internal
291
313
(or (elmo-nntp-read-response session)
292
314
(signal 'elmo-authenticate-error '(authinfo)))
293
315
(elmo-nntp-send-command
295
317
(format "authinfo pass %s"
296
(elmo-get-passwd (elmo-network-session-password-key session))))
318
(elmo-get-passwd (elmo-network-session-password-key session)))
297
321
(or (elmo-nntp-read-response session)
298
322
(signal 'elmo-authenticate-error '(authinfo))))))
302
326
(run-hooks 'elmo-nntp-opened-hook))
304
328
(defun elmo-nntp-process-filter (process output)
306
(set-buffer (process-buffer process))
307
(goto-char (point-max))
329
(when (buffer-live-p (process-buffer process))
330
(with-current-buffer (process-buffer process)
331
(goto-char (point-max))
333
(elmo-nntp-debug "RECEIVED: %s\n" output))))
310
335
(defun elmo-nntp-send-mode-reader (session)
311
336
(elmo-nntp-send-command session "mode reader")
312
337
(if (null (elmo-nntp-read-response session t))
313
338
(message "Mode reader failed")))
315
(defun elmo-nntp-send-command (session command &optional noerase)
340
(defun elmo-nntp-send-command (session command &optional noerase no-log)
316
341
(with-current-buffer (elmo-network-session-buffer session)
319
344
(goto-char (point-min)))
320
345
(setq elmo-nntp-read-point (point))
346
(elmo-nntp-debug "SEND: %s\n" (if no-log "<NO LOGGING>" command))
321
347
(process-send-string (elmo-network-session-process-internal
322
348
session) command)
323
349
(process-send-string (elmo-network-session-process-internal
441
468
(defsubst elmo-nntp-catchup-msgdb (msgdb max-number)
442
(let (msgdb-max number-alist)
443
(setq number-alist (elmo-msgdb-get-number-alist msgdb))
444
(setq msgdb-max (car (nth (max (- (length number-alist) 1) 0)
446
(if (or (not msgdb-max)
447
(and msgdb-max max-number
448
(< msgdb-max max-number)))
449
(elmo-msgdb-set-number-alist
451
(nconc number-alist (list (cons max-number nil)))))))
469
(let ((numbers (elmo-msgdb-list-messages msgdb))
471
(setq msgdb-max (if numbers (apply #'max numbers) 0))
474
(< msgdb-max max-number))
475
(let ((i (1+ msgdb-max))
477
(while (<= i max-number)
478
(setq killed (cons i killed))
480
(nreverse killed)))))
453
482
(luna-define-method elmo-folder-list-subfolders ((folder elmo-nntp-folder)
454
483
&optional one-level)
522
551
(format "^\\(%s[^. ]+\\)\\([. ]\\).*\n"
524
(elmo-nntp-folder-group-internal folder)
526
(elmo-nntp-folder-group-internal
552
(if (and (elmo-nntp-folder-group-internal folder)
554
(elmo-nntp-folder-group-internal
528
556
(concat (elmo-nntp-folder-group-internal
531
560
(while (looking-at regexp)
532
561
(setq top-ng (elmo-match-buffer 1))
533
562
(if (string= (elmo-match-buffer 2) " ")
557
586
(when (> len elmo-display-progress-threshold)
558
587
(elmo-display-progress
559
588
'elmo-nntp-list-folders "Parsing active..." 100))))
560
(unless (string= (elmo-net-folder-server-internal folder)
561
elmo-nntp-default-server)
590
(setq username (elmo-net-folder-user-internal folder))
592
elmo-nntp-default-user
593
(string= username elmo-nntp-default-user))
596
(when (or username ; XXX: ad-hoc fix against username includes "@"
597
(not (string= (elmo-net-folder-server-internal folder)
598
elmo-nntp-default-server)))
562
599
(setq append-serv (concat "@" (elmo-net-folder-server-internal
564
601
(unless (eq (elmo-net-folder-port-internal folder) elmo-nntp-default-port)
575
612
(mapcar '(lambda (fld)
577
614
(list (concat "-" (elmo-nntp-decode-group-string (car fld))
578
(and (elmo-net-folder-user-internal folder)
581
(elmo-net-folder-user-internal folder)))
583
620
(concat append-serv))))
584
621
(concat "-" (elmo-nntp-decode-group-string fld)
585
(and (elmo-net-folder-user-internal folder)
586
(concat ":" (elmo-net-folder-user-internal
623
(concat ":" username))
589
625
(concat append-serv)))))
592
628
(defun elmo-nntp-make-msglist (beg-str end-str)
594
(let ((beg-num (string-to-int beg-str))
595
(end-num (string-to-int end-str))
599
(while (<= i end-num)
600
(insert (format "%s " i))
603
(goto-char (point-min))
604
(read (current-buffer)))))
629
(elmo-make-number-list (string-to-int beg-str) (string-to-int end-str)))
606
631
(luna-define-method elmo-folder-list-messages-plugged ((folder
607
632
elmo-nntp-folder)
705
(defun elmo-nntp-create-msgdb-from-overview-string (str
730
(defun elmo-nntp-create-msgdb-from-overview-string (folder
711
733
&optional numlist)
712
(let (ov-list gmark message-id seen
713
ov-entity overview number-alist mark-alist num
714
extras extra ext field field-index)
734
(let ((new-msgdb (elmo-make-msgdb))
735
ov-list message-id entity
737
extras extra ext field field-index flags)
715
738
(setq ov-list (elmo-nntp-parse-overview-string str))
717
740
(setq ov-entity (car ov-list))
730
753
(setq ext (downcase (car extras)))
731
754
(when (setq field-index (cdr (assoc ext elmo-nntp-overview-index)))
732
(when (> (length ov-entity) field-index)
755
(when (> (length ov-entity) field-index)
733
756
(setq field (aref ov-entity field-index))
734
757
(when (eq field-index 8) ;; xref
735
758
(setq field (elmo-msgdb-remove-field-string field)))
736
(setq extra (cons (cons ext field) extra))))
759
(setq extra (cons (cons ext field) extra))))
737
760
(setq extras (cdr extras)))
739
(elmo-msgdb-append-element
741
(cons (aref ov-entity 4)
743
(elmo-msgdb-get-last-message-id
746
(elmo-mime-string (elmo-delete-char
752
(elmo-mime-string (or (aref ov-entity 1)
754
(aref ov-entity 3) ;date
758
(aref ov-entity 6)) ; size
759
extra ; extra-field-list
762
(elmo-msgdb-number-add number-alist num
764
(setq message-id (aref ov-entity 4))
765
(setq seen (member message-id seen-list))
766
(if (setq gmark (or (elmo-msgdb-global-mark-get message-id)
767
(if (elmo-file-cache-status
768
(elmo-file-cache-get message-id))
773
(if elmo-nntp-use-cache
777
(elmo-msgdb-mark-append mark-alist
761
(setq entity (elmo-msgdb-make-message-entity
762
(elmo-msgdb-message-entity-handler new-msgdb)
763
:message-id (aref ov-entity 4)
765
:references (elmo-msgdb-get-last-message-id
767
:from (elmo-mime-string (elmo-delete-char
772
:subject (elmo-mime-string (or (aref ov-entity 1)
774
:date (aref ov-entity 3)
775
:size (string-to-int (aref ov-entity 6))
777
(setq message-id (elmo-message-entity-field entity 'message-id)
778
flags (elmo-flag-table-get flag-table message-id))
779
(elmo-global-flags-set flags folder num message-id)
780
(elmo-msgdb-append-entity new-msgdb entity flags))
779
781
(setq ov-list (cdr ov-list)))
780
(list overview number-alist mark-alist)))
782
784
(luna-define-method elmo-folder-msgdb-create ((folder elmo-nntp-folder)
783
numbers new-mark already-mark
784
seen-mark important-mark
786
(elmo-nntp-folder-msgdb-create folder numbers new-mark already-mark
787
seen-mark important-mark
786
(elmo-nntp-folder-msgdb-create folder numbers flag-table))
790
(defun elmo-nntp-folder-msgdb-create (folder numbers new-mark already-mark
791
seen-mark important-mark
788
(defun elmo-nntp-folder-msgdb-create (folder numbers flag-table)
793
789
(let ((filter numbers)
794
790
(session (elmo-nntp-get-session folder))
791
(new-msgdb (elmo-make-msgdb))
795
792
beg-num end-num cur length
796
ret-val ov-str use-xover dir)
793
new-msgdb ov-str use-xover dir)
797
794
(elmo-nntp-select-group session (elmo-nntp-folder-group-internal
799
796
(when (setq use-xover (elmo-nntp-xover-p session))
842
834
(elmo-display-progress
843
835
'elmo-nntp-msgdb-create "Getting overview..." 100)))
844
836
(if (not use-xover)
845
(setq ret-val (elmo-nntp-msgdb-create-by-header
847
new-mark already-mark seen-mark seen-list))
837
(setq new-msgdb (elmo-nntp-msgdb-create-by-header
838
session numbers flag-table))
848
839
(with-current-buffer (elmo-network-session-buffer session)
853
(elmo-nntp-create-msgdb-from-overview-string
843
(elmo-nntp-create-msgdb-from-overview-string
861
848
(elmo-folder-set-killed-list-internal
864
851
(elmo-folder-killed-list-internal folder)
865
852
(car (elmo-list-diff
868
(elmo-msgdb-get-number-alist
854
(elmo-msgdb-list-messages new-msgdb)))))
870
855
;; If there are canceled messages, overviews are not obtained
871
856
;; to max-number(inn 2.3?).
872
857
(when (and (elmo-nntp-max-number-precedes-list-active-p)
880
865
(elmo-nntp-set-list-active session nil)
881
866
(error "NNTP list command failed")))
882
(elmo-nntp-catchup-msgdb
884
(nth 1 (read (concat "(" (elmo-nntp-read-contents
867
(let ((killed (elmo-nntp-catchup-msgdb
869
(nth 1 (read (concat "(" (elmo-nntp-read-contents
872
(elmo-folder-kill-messages folder killed))))
888
875
(luna-define-method elmo-folder-update-number ((folder elmo-nntp-folder))
889
(if (elmo-nntp-max-number-precedes-list-active-p)
890
(let ((session (elmo-nntp-get-session folder))
891
(number-alist (elmo-msgdb-get-number-alist
892
(elmo-folder-msgdb folder))))
893
(if (elmo-nntp-list-active-p session)
894
(let (msgdb-max max-number)
895
;; If there are canceled messages, overviews are not obtained
896
;; to max-number(inn 2.3?).
897
(elmo-nntp-select-group session
898
(elmo-nntp-folder-group-internal folder))
899
(elmo-nntp-send-command session
900
(format "list active %s"
901
(elmo-nntp-folder-group-internal
903
(if (null (elmo-nntp-read-response session))
904
(error "NNTP list command failed"))
906
(nth 1 (read (concat "(" (elmo-nntp-read-contents
909
(car (nth (max (- (length number-alist) 1) 0)
911
(if (or (and number-alist (not msgdb-max))
912
(and msgdb-max max-number
913
(< msgdb-max max-number)))
914
(elmo-msgdb-set-number-alist
915
(elmo-folder-msgdb folder)
917
(list (cons max-number nil))))))))))
876
(when (elmo-nntp-max-number-precedes-list-active-p)
877
(let ((session (elmo-nntp-get-session folder)))
878
(when (elmo-nntp-list-active-p session)
879
(let ((numbers (elmo-folder-list-messages folder nil 'in-msgdb))
880
msgdb-max max-number)
881
;; If there are canceled messages, overviews are not obtained
882
;; to max-number(inn 2.3?).
883
(elmo-nntp-select-group session
884
(elmo-nntp-folder-group-internal folder))
885
(elmo-nntp-send-command session
886
(format "list active %s"
887
(elmo-nntp-folder-group-internal
889
(if (null (elmo-nntp-read-response session))
890
(error "NNTP list command failed"))
892
(nth 1 (read (concat "(" (elmo-nntp-read-contents
894
(setq msgdb-max (if numbers (apply #'max numbers) 0))
897
(< msgdb-max max-number))
898
(let ((i (1+ msgdb-max))
900
(while (<= i max-number)
901
(setq killed (cons i killed))
903
(elmo-folder-kill-messages folder (nreverse killed)))))))))
919
(defun elmo-nntp-msgdb-create-by-header (session numbers
920
new-mark already-mark
905
(defun elmo-nntp-msgdb-create-by-header (session numbers flag-table)
922
906
(with-temp-buffer
923
907
(elmo-nntp-retrieve-headers session (current-buffer) numbers)
924
908
(elmo-nntp-msgdb-create-message
925
(length numbers) new-mark already-mark seen-mark seen-list)))
909
(length numbers) flag-table)))
927
911
(defun elmo-nntp-parse-xhdr-response (string)
977
961
(with-current-buffer (elmo-network-session-buffer session)
978
962
(std11-field-body "Newsgroups")))))
980
(luna-define-method elmo-message-fetch-with-cache-process :around
981
((folder elmo-nntp-folder) number strategy &optional section unread)
964
(luna-define-method elmo-message-fetch :around
965
((folder elmo-nntp-folder) number strategy &optional unread section)
982
966
(when (luna-call-next-method)
983
967
(elmo-nntp-setup-crosspost-buffer folder number)
1078
1062
(luna-define-method elmo-folder-delete-messages ((folder elmo-nntp-folder)
1080
(elmo-nntp-folder-delete-messages folder numbers))
1082
(defun elmo-nntp-folder-delete-messages (folder numbers)
1083
(let ((killed-list (elmo-folder-killed-list-internal folder)))
1084
(dolist (number numbers)
1086
(elmo-msgdb-set-as-killed killed-list number)))
1087
(elmo-folder-set-killed-list-internal folder killed-list))
1064
(elmo-folder-kill-messages folder numbers)
1090
1067
(luna-define-method elmo-folder-exists-p-plugged ((folder elmo-nntp-folder))
1091
1068
(let ((session (elmo-nntp-get-session folder)))
1092
(elmo-nntp-send-command
1095
(elmo-nntp-folder-group-internal folder)))
1069
(elmo-nntp-send-command
1072
(elmo-nntp-folder-group-internal folder)))
1096
1073
(elmo-nntp-read-response session)))
1098
1075
(defun elmo-nntp-retrieve-field (spec field from-msgs)
1393
1370
(elmo-display-progress
1394
1371
'elmo-nntp-retrieve-headers "Getting headers..." 100))
1395
1372
(message "Getting headers...done")
1396
;; Remove all "\r"'s.
1397
(goto-char (point-min))
1398
(while (search-forward "\r\n" nil t)
1399
(replace-match "\n"))
1373
;; Replace all CRLF with LF.
1374
(elmo-delete-cr-buffer)
1400
1375
(copy-to-buffer outbuf (point-min) (point-max)))))
1402
1377
;; end of from Gnus
1404
(defun elmo-nntp-msgdb-create-message (len new-mark
1405
already-mark seen-mark seen-list)
1379
(defun elmo-nntp-msgdb-create-message (len flag-table)
1406
1380
(save-excursion
1407
(let (beg overview number-alist mark-alist
1408
entity i num gmark seen message-id)
1409
(elmo-set-buffer-multibyte nil)
1381
(let ((new-msgdb (elmo-make-msgdb))
1382
beg entity i num message-id)
1383
(set-buffer-multibyte nil)
1410
1384
(goto-char (point-min))
1412
1386
(message "Creating msgdb...")
1423
1397
(save-restriction
1424
1398
(narrow-to-region beg (point))
1426
(elmo-msgdb-create-overview-from-buffer num))
1400
(elmo-msgdb-create-message-entity-from-buffer
1401
(elmo-msgdb-message-entity-handler new-msgdb) num))
1429
(elmo-msgdb-append-element
1432
(elmo-msgdb-number-add
1434
(elmo-msgdb-overview-entity-get-number entity)
1436
(setq message-id (car entity))
1437
(setq seen (member message-id seen-list))
1439
(or (elmo-msgdb-global-mark-get message-id)
1440
(if (elmo-file-cache-status
1441
(elmo-file-cache-get message-id))
1446
(if elmo-nntp-use-cache
1450
(elmo-msgdb-mark-append
1404
(elmo-message-entity-field entity 'message-id))
1405
(elmo-msgdb-append-entity
1408
(elmo-flag-table-get flag-table message-id))))))
1454
1409
(when (> len elmo-display-progress-threshold)
1455
1410
(setq i (1+ i))
1456
1411
(if (or (zerop (% i 20)) (= i len))
1483
1438
;; temp-crosses slot is a list of cons cell:
1484
1439
;; (NUMBER . (MESSAGE-ID (LIST-OF-NEWSGROUPS) 'ng))
1485
1440
;; 1.2. In elmo-folder-close, `temp-crosses' slot is cleared,
1486
;; 1.3. In elmo-folder-mark-as-read, move crosspost entry
1441
;; 1.3. In elmo-folder-flag-as-read, move crosspost entry
1487
1442
;; from `temp-crosses' slot to `elmo-crosspost-message-alist'.
1489
1444
;; 2. process crosspost alist.
1542
1497
(delq elem (elmo-nntp-folder-temp-crosses-internal folder)))))))
1544
(luna-define-method elmo-folder-mark-as-read ((folder elmo-nntp-folder)
1546
(elmo-nntp-folder-update-crosspost-message-alist folder numbers)
1549
(luna-define-method elmo-folder-process-crosspost ((folder elmo-nntp-folder)
1552
(elmo-nntp-folder-process-crosspost folder number-alist))
1554
(defun elmo-nntp-folder-process-crosspost (folder number-alist)
1499
(luna-define-method elmo-folder-set-flag :before ((folder elmo-nntp-folder)
1503
(when (eq flag 'read)
1504
(elmo-nntp-folder-update-crosspost-message-alist folder numbers)))
1506
(luna-define-method elmo-folder-unset-flag :before ((folder elmo-nntp-folder)
1510
(when (eq flag 'unread)
1511
(elmo-nntp-folder-update-crosspost-message-alist folder numbers)))
1513
(defsubst elmo-nntp-folder-process-crosspost (folder)
1555
1514
;; 2.1. At elmo-folder-process-crosspost, setup `reads' slot from
1556
1515
;; `elmo-crosspost-message-alist'.
1557
1516
;; 2.2. remove crosspost entry for current newsgroup from
1558
1517
;; `elmo-crosspost-message-alist'.
1559
1518
(let (cross-deletes reads entity ngs)
1560
1519
(dolist (cross elmo-crosspost-message-alist)
1562
(when (setq entity (rassoc (nth 0 cross) number-alist))
1563
(setq reads (cons (car entity) reads)))
1564
(when (setq entity (elmo-msgdb-overview-get-entity
1566
(elmo-folder-msgdb folder)))
1567
(setq reads (cons (elmo-msgdb-overview-entity-get-number entity)
1520
(when (setq entity (elmo-message-entity folder (nth 0 cross)))
1521
(setq reads (cons (elmo-message-entity-number entity) reads)))
1570
1523
(if (setq ngs (delete (elmo-nntp-folder-group-internal folder)
1571
1524
(nth 1 cross)))
1578
1531
elmo-crosspost-message-alist)))
1579
1532
(elmo-nntp-folder-set-reads-internal folder reads)))
1581
(luna-define-method elmo-folder-list-unreads-internal
1582
((folder elmo-nntp-folder) unread-marks mark-alist)
1534
(luna-define-method elmo-folder-process-crosspost ((folder elmo-nntp-folder))
1535
(elmo-nntp-folder-process-crosspost folder))
1537
(luna-define-method elmo-folder-list-flagged :around ((folder elmo-nntp-folder)
1538
flag &optional in-msgdb)
1583
1539
;; 2.3. elmo-folder-list-unreads return unread message list according to
1584
1540
;; `reads' slot.
1585
(let ((mark-alist (or mark-alist (elmo-msgdb-get-mark-alist
1586
(elmo-folder-msgdb folder)))))
1587
(elmo-living-messages (delq nil
1590
(if (member (nth 1 x) unread-marks)
1593
(elmo-nntp-folder-reads-internal folder))))
1541
(let ((msgs (luna-call-next-method)))
1546
(elmo-living-messages msgs (elmo-nntp-folder-reads-internal folder)))
1547
;; Should consider read, digest and any flag?
1595
1551
(require 'product)
1596
1552
(product-provide (provide 'elmo-nntp) (require 'elmo-version))