Merge branch 'upstream' into store-groups

# By Magnus Henoch (18) and others
# Via Magnus Henoch
* upstream: (31 commits)
  Ensure that jabber-bookmarks is loaded in jabber-jid-bookmarkname
  Fix :get function for jabber-roster-default-group-name
  If all accounts are already connected in jabber-connect-all, say so
  Make nick coloring work in Emacs24
  Don't display "added to roster" messages for initial roster population
  Don't add extra newline when using STARTTLS
  Fix reporting of STARTTLS negotiation errors
  Fix error handling for old-style SSL/TLS connections
  Support native GnuTLS for STARTTLS
  s/screen/tmux/ in jabber-tmux.el
  Mention tmux alerts in the documentation
  Add tmux alerts
  Fix build with automake > 1.11.4
  Avoid groupchat buffer on RET in roster if we're not 100% sure it's a groupchat (bug 3483380)
  Version 0.8.91
  * jabberd.el (jabberd-handle): Update for new namespace handling.
  Use namespace prefixes declared on stream root element
  jabber-core: Fix header parsing
  Fix :get function for jabber-roster-default-group-name
  Use xml-parse-region to parse stream header
  ...

Conflicts:
	jabber-roster.el
	jabber.texi
This commit is contained in:
Evgenii Terechkov 2012-09-29 22:46:50 +08:00
commit a7823c0e8b
22 changed files with 410 additions and 178 deletions

View File

@ -7,6 +7,7 @@ Evgenii Terechkov
Contributors: Contributors:
Anthony Chaumas-Pellet Anthony Chaumas-Pellet
Jérémy Compostella
Mathias Dahl Mathias Dahl
Mario Domenech Goulart Mario Domenech Goulart
Nolan Eakins Nolan Eakins
@ -24,5 +25,6 @@ Xavier Maillard
Vitaly Mayatskikh Vitaly Mayatskikh
Alexander Solovyov Alexander Solovyov
Demyan Rogozhin Demyan Rogozhin
Michael Cardell Widerkrantz
arch-tag: 15700144-3BD9-11D9-871C-000A95C2FCD0 arch-tag: 15700144-3BD9-11D9-871C-000A95C2FCD0

View File

@ -22,7 +22,7 @@ jabber-time.el jabber-truncate.el jabber-util.el \
jabber-vcard-avatars.el jabber-vcard.el jabber-version.el \ jabber-vcard-avatars.el jabber-vcard.el jabber-version.el \
jabber-watch.el jabber-widget.el jabber-wmii.el jabber-xmessage.el \ jabber-watch.el jabber-widget.el jabber-wmii.el jabber-xmessage.el \
jabber-muc-nick-coloring.el \ jabber-muc-nick-coloring.el \
jabber-xml.el jabber.el srv.el jabber-xml.el jabber.el srv.el jabber-tmux.el
compat_lisp_sources = compat_lisp_sources =
if USE_OUR_SHA1 if USE_OUR_SHA1
@ -74,6 +74,7 @@ elpa: dist
mv emacs-jabber-$(PACKAGE_VERSION) jabber-$(PACKAGE_VERSION) mv emacs-jabber-$(PACKAGE_VERSION) jabber-$(PACKAGE_VERSION)
cd jabber-$(PACKAGE_VERSION) ; install-info jabber.info dir cd jabber-$(PACKAGE_VERSION) ; install-info jabber.info dir
sed "s/@""PACKAGE_VERSION@""/$(PACKAGE_VERSION)/" < $(srcdir)/jabber-pkg.el.in > jabber-$(PACKAGE_VERSION)/jabber-pkg.el sed "s/@""PACKAGE_VERSION@""/$(PACKAGE_VERSION)/" < $(srcdir)/jabber-pkg.el.in > jabber-$(PACKAGE_VERSION)/jabber-pkg.el
mv jabber-$(PACKAGE_VERSION)/compat/*.el jabber-$(PACKAGE_VERSION)/
$(AMTAR) chf jabber-$(PACKAGE_VERSION).tar jabber-$(PACKAGE_VERSION) $(AMTAR) chf jabber-$(PACKAGE_VERSION).tar jabber-$(PACKAGE_VERSION)
rm -rf jabber-$(PACKAGE_VERSION) rm -rf jabber-$(PACKAGE_VERSION)
@echo "Created jabber-$(PACKAGE_VERSION).tar" @echo "Created jabber-$(PACKAGE_VERSION).tar"

5
NEWS
View File

@ -24,6 +24,11 @@ MUC participants list format is now customizable: see
jabber-muc-print-names-format in manual. Also, participants sorted by jabber-muc-print-names-format in manual. Also, participants sorted by
role. role.
** Treat XML namespace prefixes correctly
A change in the Google Talk server has brought to light the fact that
jabber.el didn't handle XML namespace prefixes correctly. This should
be fixed by the new jabber-xml-resolve-namespace-prefixes function.
* New features in jabber.el 0.8 * New features in jabber.el 0.8
** Support for multiple accounts ** Support for multiple accounts
Configuration variables have changed. See section "Account settings" Configuration variables have changed. See section "Account settings"

View File

@ -167,6 +167,7 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;###autoload
(eval-and-compile (eval-and-compile
(defun hexrgb-canonicalize-defined-colors (list) (defun hexrgb-canonicalize-defined-colors (list)
"Copy of LIST with color names canonicalized. "Copy of LIST with color names canonicalized.

View File

@ -1,6 +1,6 @@
AC_INIT([jabber.el], [0.8.0], [emacs-jabber-general@lists.sourceforge.net], [emacs-jabber]) AC_INIT([jabber.el], [0.8.91], [emacs-jabber-general@lists.sourceforge.net], [emacs-jabber])
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([-Wall -Werror foreign dist-bzip2 dist-lzma dist-zip 1.9]) AM_INIT_AUTOMAKE([-Wall -Werror foreign dist-bzip2 dist-xz dist-zip 1.9])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AM_PATH_LISPDIR AM_PATH_LISPDIR

View File

@ -55,7 +55,8 @@ window or at `fill-column', whichever is shorter."
(make-local-variable 'scroll-conservatively) (make-local-variable 'scroll-conservatively)
(make-local-variable 'jabber-point-insert) (make-local-variable 'jabber-point-insert)
(make-local-variable 'jabber-chat-ewoc) (make-local-variable 'jabber-chat-ewoc)
(make-local-variable 'buffer-undo-list)
(setq jabber-buffer-connection jc (setq jabber-buffer-connection jc
scroll-conservatively 5 scroll-conservatively 5
buffer-undo-list t) ;dont keep undo list for chatbuffer buffer-undo-list t) ;dont keep undo list for chatbuffer

View File

@ -27,6 +27,9 @@
(eval-when-compile (require 'cl)) (eval-when-compile (require 'cl))
;; Emacs 24 can be linked with GnuTLS
(ignore-errors (require 'gnutls))
;; Try two different TLS/SSL libraries, but don't fail if none available. ;; Try two different TLS/SSL libraries, but don't fail if none available.
(or (ignore-errors (require 'tls)) (or (ignore-errors (require 'tls))
(ignore-errors (require 'ssl))) (ignore-errors (require 'ssl)))
@ -45,11 +48,13 @@
(defun jabber-have-starttls () (defun jabber-have-starttls ()
"Return true if we can use STARTTLS." "Return true if we can use STARTTLS."
(and (featurep 'starttls) (or (and (fboundp 'gnutls-available-p)
(or (and (bound-and-true-p starttls-gnutls-program) (gnutls-available-p))
(executable-find starttls-gnutls-program)) (and (featurep 'starttls)
(and (bound-and-true-p starttls-program) (or (and (bound-and-true-p starttls-gnutls-program)
(executable-find starttls-program))))) (executable-find starttls-gnutls-program))
(and (bound-and-true-p starttls-program)
(executable-find starttls-program))))))
(defconst jabber-default-connection-type (defconst jabber-default-connection-type
(cond (cond
@ -72,9 +77,19 @@ nil means prefer gnutls but fall back to openssl.
(const :tag "Use openssl" openssl)) (const :tag "Use openssl" openssl))
:group 'jabber-conn) :group 'jabber-conn)
(defcustom jabber-invalid-certificate-servers ()
"Jabber servers for which we accept invalid TLS certificates.
This is a list of server names, each matching the hostname part
of your JID.
This option has effect only when using native GnuTLS in Emacs 24
or later."
:type '(repeat string)
:group 'jabber-conn)
(defvar jabber-connect-methods (defvar jabber-connect-methods
'((network jabber-network-connect jabber-network-send) '((network jabber-network-connect jabber-network-send)
(starttls jabber-starttls-connect jabber-ssl-send) (starttls jabber-starttls-connect jabber-network-send)
(ssl jabber-ssl-connect jabber-ssl-send) (ssl jabber-ssl-connect jabber-ssl-send)
(virtual jabber-virtual-connect jabber-virtual-send)) (virtual jabber-virtual-connect jabber-virtual-send))
"Alist of connection methods and functions. "Alist of connection methods and functions.
@ -166,14 +181,19 @@ connection fails."
(error "Neither TLS nor SSL connect functions available"))))) (error "Neither TLS nor SSL connect functions available")))))
(let ((process-buffer (generate-new-buffer jabber-process-buffer)) (let ((process-buffer (generate-new-buffer jabber-process-buffer))
connection) connection)
(unwind-protect (setq network-server (or network-server server))
(setq port (or port 5223))
(condition-case e
(setq connection (funcall connect-function (setq connection (funcall connect-function
"jabber" "jabber"
process-buffer process-buffer
(or network-server server) network-server
(or port 5223))) port))
(unless (or connection jabber-debug-keep-process-buffers) (error
(kill-buffer process-buffer))) (message "Couldn't connect to %s:%d: %s" network-server port
(error-message-string e))))
(unless (or connection jabber-debug-keep-process-buffers)
(kill-buffer process-buffer))
(if connection (if connection
(fsm-send fsm (list :connected connection)) (fsm-send fsm (list :connected connection))
(fsm-send fsm :connection-failed))))) (fsm-send fsm :connection-failed)))))
@ -191,9 +211,19 @@ connection succeeds. Send a message :connection-failed if
connection fails." connection fails."
(let ((coding-system-for-read 'utf-8) (let ((coding-system-for-read 'utf-8)
(coding-system-for-write 'utf-8) (coding-system-for-write 'utf-8)
(targets (jabber-srv-targets server network-server port))) (targets (jabber-srv-targets server network-server port))
(unless (fboundp 'starttls-open-stream) (connect-function
(error "starttls.el not available")) (cond
((and (fboundp 'gnutls-available-p)
(gnutls-available-p))
(lambda (buffer host port)
(open-network-stream "jabber" buffer host port)))
((fboundp 'starttls-open-stream)
(lambda (buffer host port)
(starttls-open-stream "jabber" buffer host port)))
(t
(error "Neither native GnuTLS nor starttls.el available")))))
(catch 'connected (catch 'connected
(dolist (target targets) (dolist (target targets)
(condition-case e (condition-case e
@ -201,11 +231,10 @@ connection fails."
connection) connection)
(unwind-protect (unwind-protect
(setq connection (setq connection
(starttls-open-stream (funcall connect-function
"jabber" process-buffer
process-buffer (car target)
(car target) (cdr target)))
(cdr target)))
(unless (or connection jabber-debug-keep-process-buffers) (unless (or connection jabber-debug-keep-process-buffers)
(kill-buffer process-buffer))) (kill-buffer process-buffer)))
(when connection (when connection
@ -223,12 +252,31 @@ connection fails."
(defun jabber-starttls-process-input (fsm xml-data) (defun jabber-starttls-process-input (fsm xml-data)
"Process result of starttls request. "Process result of starttls request.
Return non-nil on success, nil on failure." On failure, signal error."
(cond (cond
((eq (car xml-data) 'proceed) ((eq (car xml-data) 'proceed)
(starttls-negotiate (plist-get (fsm-get-state-data fsm) :connection))) (let* ((state-data (fsm-get-state-data fsm))
(connection (plist-get state-data :connection)))
;; Did we use open-network-stream or starttls-open-stream? We
;; can tell by process-type.
(case (process-type connection)
(network
(let* ((hostname (plist-get state-data :server))
(verifyp (not (member hostname jabber-invalid-certificate-servers))))
;; gnutls-negotiate might signal an error, which is caught
;; by our caller
(gnutls-negotiate
:process connection
;; This is the hostname that the certificate should be valid for:
:hostname hostname
:verify-hostname-error verifyp
:verify-error verifyp)))
(real
(or
(starttls-negotiate connection)
(error "Negotiation failure"))))))
((eq (car xml-data) 'failure) ((eq (car xml-data) 'failure)
nil))) (error "Command rejected by server"))))
(defvar *jabber-virtual-server-function* nil (defvar *jabber-virtual-server-function* nil
"Function to use for sending stanzas on a virtual connection. "Function to use for sending stanzas on a virtual connection.

View File

@ -64,6 +64,10 @@
(defvar jabber-choked-timer nil) (defvar jabber-choked-timer nil)
(defvar jabber-namespace-prefixes nil
"XML namespace prefixes used for the current connection.")
(make-variable-buffer-local 'jabber-namespace-prefixes)
(defgroup jabber-core nil "customize core functionality" (defgroup jabber-core nil "customize core functionality"
:group 'jabber) :group 'jabber)
@ -182,7 +186,10 @@ With many prefix arguments, one less is passed to `jabber-connect'."
(jabber-jid-server jid) (jabber-jid-server jid)
(jabber-jid-resource jid) (jabber-jid-resource jid)
nil password network-server nil password network-server
port connection-type)))))))) port connection-type)
(setq connected-one t))))
(unless connected-one
(message "All configured Jabber accounts are already connected"))))))
;;;###autoload (autoload 'jabber-connect "jabber" "Connect to the Jabber server and start a Jabber XML stream.\nWith prefix argument, register a new account.\nWith double prefix argument, specify more connection details." t) ;;;###autoload (autoload 'jabber-connect "jabber" "Connect to the Jabber server and start a Jabber XML stream.\nWith prefix argument, register a new account.\nWith double prefix argument, specify more connection details." t)
(defun jabber-connect (username server resource &optional (defun jabber-connect (username server resource &optional
@ -440,7 +447,7 @@ With double prefix argument, specify more connection details."
(let ((stanza (cadr event))) (let ((stanza (cadr event)))
(cond (cond
;; At this stage, we only expect a stream:features stanza. ;; At this stage, we only expect a stream:features stanza.
((not (eq (jabber-xml-node-name stanza) 'stream:features)) ((not (eq (jabber-xml-node-name stanza) 'features))
(list nil (plist-put state-data (list nil (plist-put state-data
:disconnection-reason :disconnection-reason
(format "Unexpected stanza %s" stanza)))) (format "Unexpected stanza %s" stanza))))
@ -479,11 +486,16 @@ With double prefix argument, specify more connection details."
(jabber-fsm-handle-sentinel state-data event)) (jabber-fsm-handle-sentinel state-data event))
(:stanza (:stanza
(if (jabber-starttls-process-input fsm (cadr event)) (condition-case e
;; Connection is encrypted. Send a stream tag again. (progn
(list :connected (plist-put state-data :encrypted t)) (jabber-starttls-process-input fsm (cadr event))
(message "STARTTLS negotiation failed") ;; Connection is encrypted. Send a stream tag again.
(list nil state-data))) (list :connected (plist-put state-data :encrypted t)))
(error
(let* ((msg (concat "STARTTLS negotiation failed: "
(error-message-string e)))
(new-state-data (plist-put state-data :disconnection-reason msg)))
(list nil new-state-data)))))
(:do-disconnect (:do-disconnect
(jabber-send-string fsm "</stream:stream>") (jabber-send-string fsm "</stream:stream>")
@ -632,7 +644,7 @@ With double prefix argument, specify more connection details."
(:stanza (:stanza
(let ((stanza (cadr event))) (let ((stanza (cadr event)))
(cond (cond
((eq (jabber-xml-node-name stanza) 'stream:features) ((eq (jabber-xml-node-name stanza) 'features)
(if (and (jabber-xml-get-children stanza 'bind) (if (and (jabber-xml-get-children stanza 'bind)
(jabber-xml-get-children stanza 'session)) (jabber-xml-get-children stanza 'session))
(labels (labels
@ -854,30 +866,24 @@ DATA is any sexp."
(return (fsm-send fsm :stream-end))) (return (fsm-send fsm :stream-end)))
;; Stream header? ;; Stream header?
(when (looking-at "<stream:stream[^>]*>") (when (looking-at "<stream:stream[^>]*\\(>\\)")
(let ((stream-header (match-string 0)) ;; Let's pretend that the stream header is a closed tag,
(ending-at (match-end 0)) ;; and parse it as such.
session-id stream-version) (replace-match "/>" t t nil 1)
;; These regexps extract attribute values from the stream (let* ((ending-at (point))
;; header, taking into account that the quotes may be either (stream-header (car (xml-parse-region (point-min) ending-at)))
;; single or double quotes. (session-id (jabber-xml-get-attribute stream-header 'id))
(setq session-id (stream-version (jabber-xml-get-attribute stream-header 'version)))
(and (or (string-match "id='\\([^']+\\)'" stream-header)
(string-match "id=\"\\([^\"]+\\)\"" stream-header))
(jabber-unescape-xml (match-string 1 stream-header))))
(setq stream-version
(and (or
(string-match "version='\\([0-9.]+\\)'" stream-header)
(string-match "version=\"\\([0-9.]+\\)\"" stream-header))
(match-string 1 stream-header)))
(jabber-log-xml fsm "receive" stream-header)
;; If the server is XMPP compliant, i.e. there is a version attribute
;; and it's >= 1.0, there will be a stream:features tag shortly,
;; so just wait for that.
;; Need to keep any namespace attributes on the stream
;; header, as they can affect any stanza in the
;; stream...
(setq jabber-namespace-prefixes
(jabber-xml-merge-namespace-declarations
(jabber-xml-node-attributes stream-header)
nil))
(jabber-log-xml fsm "receive" stream-header)
(fsm-send fsm (list :stream-start session-id stream-version)) (fsm-send fsm (list :stream-start session-id stream-version))
(delete-region (point-min) ending-at))) (delete-region (point-min) ending-at)))
;; Normal tag ;; Normal tag
@ -911,7 +917,9 @@ DATA is any sexp."
(sit-for 2))) (sit-for 2)))
(delete-region (point-min) (point)) (delete-region (point-min) (point))
(fsm-send fsm (list :stanza (car xml-data))) (fsm-send fsm (list :stanza
(jabber-xml-resolve-namespace-prefixes
(car xml-data) nil jabber-namespace-prefixes)))
;; XXX: move this logic elsewhere ;; XXX: move this logic elsewhere
;; We explicitly don't catch errors in jabber-process-input, ;; We explicitly don't catch errors in jabber-process-input,
;; to facilitate debugging. ;; to facilitate debugging.

View File

@ -105,7 +105,7 @@ for all accounts regardless of the argument."
(current-time-string) (current-time-string)
(plist-get (fsm-get-state-data jc) :server))) (plist-get (fsm-get-state-data jc) :server)))
(setq jabber-keepalive-pending (remq jc jabber-keepalive-pending)) (setq jabber-keepalive-pending (remq jc jabber-keepalive-pending))
(when (null jabber-keepalive-pending) (when (and (null jabber-keepalive-pending) (timerp jabber-keepalive-timeout-timer))
(jabber-cancel-timer jabber-keepalive-timeout-timer) (jabber-cancel-timer jabber-keepalive-timeout-timer)
(setq jabber-keepalive-timeout-timer nil))) (setq jabber-keepalive-timeout-timer nil)))

View File

@ -91,7 +91,8 @@
':string (encode-coding-string body 'utf-8) ':string (encode-coding-string body 'utf-8)
'(:array) '(:array)
'(:array :signature "{sv}") '(:array :signature "{sv}")
':int32 jabber-libnotify-timeout)))))) ':int32 jabber-libnotify-timeout)))
(error nil))))
(define-jabber-alert libnotify "Show a message through the libnotify interface" (define-jabber-alert libnotify "Show a message through the libnotify interface"
'jabber-libnotify-message) 'jabber-libnotify-message)

View File

@ -30,6 +30,10 @@
[jabber-menu-connect] [jabber-menu-connect]
'("Connect" . jabber-connect-all)) '("Connect" . jabber-connect-all))
(define-key map
[jabber-menu-nextmsg]
'("Next unread message" . jabber-activity-switch-to))
(define-key map (define-key map
[jabber-menu-disconnect] [jabber-menu-disconnect]
'("Disconnect" . jabber-disconnect)) '("Disconnect" . jabber-disconnect))

View File

@ -1,6 +1,6 @@
;;; jabber-muc-nick-coloring.el --- Add nick coloring abilyty to emacs-jabber ;;; jabber-muc-nick-coloring.el --- Add nick coloring abilyty to emacs-jabber
;; Copyright 2009, 2010 Terechkov Evgenii - evg@altlinux.org ;; Copyright 2009, 2010, 2012 Terechkov Evgenii - evg@altlinux.org
;; This program is free software; you can redistribute it and/or modify ;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by ;; it under the terms of the GNU General Public License as published by
@ -56,7 +56,7 @@
(defun jabber-muc-nick-gen-color (nick) (defun jabber-muc-nick-gen-color (nick)
"Return good enough color from available pool" "Return good enough color from available pool"
(let ((hue (/ (mod (string-to-number (md5 nick) 16) 360) 360.0))) (let ((hue (/ (mod (string-to-number (substring (md5 nick) 0 6) 16) 360) 360.0)))
(hexrgb-hsv-to-hex hue jabber-muc-nick-saturation jabber-muc-nick-value))) (hexrgb-hsv-to-hex hue jabber-muc-nick-saturation jabber-muc-nick-value)))
(defun jabber-muc-nick-get-color (nick) (defun jabber-muc-nick-get-color (nick)

View File

@ -500,13 +500,17 @@ groupchat buffer."
) )
;; Maybe another error occurred. Report it to user ;; Maybe another error occurred. Report it to user
(condition (condition
(message "Couldn't query groupchat: %s" (jabber-parse-error result)))) (message "Couldn't query groupchat: %s" (jabber-parse-error result)))
;; Bad stanza? Without NS, for example
((and (eq identities 'error) (not condition))
(message "Bad error stanza received")))
;; Continue only if it is really chat room. If there was an ;; Continue only if it is really chat room. If there was an
;; error, give the chat room the benefit of the doubt. (Needed ;; error, give the chat room the benefit of the doubt. (Needed
;; for ejabberd's mod_irc, for example) ;; for ejabberd's mod_irc, for example)
(when (or condition (when (or condition
(find "conference" identities (find "conference" (if (sequencep identities) identities nil)
:key (lambda (i) (aref i 1)) :key (lambda (i) (aref i 1))
:test #'string=)) :test #'string=))
(let ((password (let ((password

View File

@ -76,7 +76,8 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(if roster-item (if roster-item
(push roster-item changed-items) (push roster-item changed-items)
;; If not found, create a new roster item. ;; If not found, create a new roster item.
(message "%s added to roster" jid) (unless (eq closure-data 'initial)
(message "%s added to roster" jid))
(setq roster-item jid) (setq roster-item jid)
(push roster-item new-items)) (push roster-item new-items))
@ -323,8 +324,9 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(buffer-local-value 'jabber-buffer-connection buffer))) (buffer-local-value 'jabber-buffer-connection buffer)))
(subelements (cdr (assq jc subelements-map)))) (subelements (cdr (assq jc subelements-map))))
(when jc (when jc
(jabber-send-sexp-if-connected jc `(presence ((to . ,(car gc))) (jabber-send-sexp-if-connected
,@subelements)))))) jc `(presence ((to . ,(concat (car gc) "/" (cdr gc))))
,@subelements))))))
(jabber-display-roster)) (jabber-display-roster))

View File

@ -25,6 +25,7 @@
(require 'jabber-alert) (require 'jabber-alert)
(require 'jabber-keymap) (require 'jabber-keymap)
(require 'format-spec) (require 'format-spec)
(require 'cl) ;for `find'
(require 'jabber-private) (require 'jabber-private)
(defgroup jabber-roster nil "roster display options" (defgroup jabber-roster nil "roster display options"
@ -156,12 +157,13 @@ Trailing newlines are always removed, regardless of this variable."
:group 'jabber-roster :group 'jabber-roster
:type 'string :type 'string
:get '(lambda (var) :get '(lambda (var)
(if (stringp var) (let ((val (symbol-value var)))
(set-text-properties 0 (length var) nil var) (when (stringp val)
var)) (set-text-properties 0 (length val) nil val))
val))
:set '(lambda (var val) :set '(lambda (var val)
(if (stringp val) (when (stringp val)
(set-text-properties 0 (length val) nil val)) (set-text-properties 0 (length val) nil val))
(custom-set-default var val)) (custom-set-default var val))
) )
@ -254,11 +256,27 @@ chat-with-jid-at-point is no group at point"
'jabber-jid))) 'jabber-jid)))
(if (and group-at-point account-at-point) (if (and group-at-point account-at-point)
(jabber-roster-roll-group account-at-point group-at-point) (jabber-roster-roll-group account-at-point group-at-point)
(jabber-chat-with-jid-at-point) ;; Is this a normal contact, or a groupchat? Let's ask it.
(ignore-errors (jabber-muc-join (jabber-disco-get-info
account-at-point account-at-point (jabber-jid-user jid-at-point) nil
jid-at-point #'jabber-roster-ret-action-at-point-1
(jabber-muc-read-my-nickname account-at-point jid-at-point t) t))))) jid-at-point))))
(defun jabber-roster-ret-action-at-point-1 (jc jid result)
;; If we get an error, assume it's a normal contact.
(if (eq (car result) 'error)
(jabber-chat-with jc jid)
;; Otherwise, let's check whether it has a groupchat identity.
(let ((identities (car result)))
(if (find "conference" (if (sequencep identities) identities nil)
:key (lambda (i) (aref i 1))
:test #'string=)
;; Yes! Let's join it.
(jabber-muc-join jc jid
(jabber-muc-read-my-nickname jc jid t)
t)
;; No. Let's open a normal chat buffer.
(jabber-chat-with jc jid)))))
(defun jabber-roster-mouse-2-action-at-point (e) (defun jabber-roster-mouse-2-action-at-point (e)
"Action for mouse-2. Before try to roll up/down group. Eval "Action for mouse-2. Before try to roll up/down group. Eval

View File

@ -187,7 +187,9 @@ determined from the incoming packet passed in XML-DATA."
(id (jabber-xml-get-attribute xml-data 'id))) (id (jabber-xml-get-attribute xml-data 'id)))
(jabber-send-iq jc to "result" (jabber-send-iq jc to "result"
`(time ((xmlns . "jabber:iq:last") `(time ((xmlns . "jabber:iq:last")
(seconds . ,(int-to-string (jabber-autoaway-get-idle-time))))) ;; XEP-0012 specifies that this is an integer.
(seconds . ,(number-to-string
(floor (jabber-autoaway-get-idle-time))))))
nil nil nil nil nil nil nil nil
id))) id)))

32
jabber-tmux.el Normal file
View File

@ -0,0 +1,32 @@
;; jabber-tmux.el - emacs-jabber interface to tmux
;; Copyright (C) 2012 - Michael Cardell Widerkrantz <mc@hack.org>
;; This file is a part of jabber.el.
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
(eval-when-compile (require 'jabber-alert))
(defun jabber-tmux-message (msg)
"Show MSG in tmux"
(call-process "tmux" nil nil nil "display-message" msg))
; Automatically defines jabber-{message,muc,presence,info}-tmux
; functions.
(define-jabber-alert tmux "Show a message through the tmux terminal multiplexer"
'jabber-tmux-message)
(provide 'jabber-tmux)

View File

@ -187,6 +187,7 @@ Return nil if none found."
(defun jabber-jid-bookmarkname (string) (defun jabber-jid-bookmarkname (string)
"Return the conference name from boomarks or displayname from roster, or JID if none set" "Return the conference name from boomarks or displayname from roster, or JID if none set"
(require 'jabber-bookmarks)
(or (loop for conference in (first (loop for value being the hash-values of jabber-bookmarks (or (loop for conference in (first (loop for value being the hash-values of jabber-bookmarks
collect value)) collect value))
do (let ((ls (cadr conference))) do (let ((ls (cadr conference)))

View File

@ -21,6 +21,8 @@
(require 'xml) (require 'xml)
(require 'jabber-util) (require 'jabber-util)
(eval-when-compile
(require 'cl))
(defun jabber-escape-xml (str) (defun jabber-escape-xml (str)
"escape strings for xml" "escape strings for xml"
@ -221,6 +223,55 @@ any string character data of this node"
,@body)) ,@body))
(put 'jabber-xml-let-attributes 'lisp-indent-function 2) (put 'jabber-xml-let-attributes 'lisp-indent-function 2)
(defun jabber-xml-resolve-namespace-prefixes (xml-data &optional default-ns prefixes)
(let ((node-name (jabber-xml-node-name xml-data))
(attrs (jabber-xml-node-attributes xml-data)))
(setq prefixes (jabber-xml-merge-namespace-declarations attrs prefixes))
;; If there is an xmlns attribute, it is the new default
;; namespace.
(let ((xmlns (jabber-xml-get-xmlns xml-data)))
(when xmlns
(setq default-ns xmlns)))
;; Now, if the node name has a prefix, replace it and add an
;; "xmlns" attribute. Slightly ugly, but avoids the need to
;; change all the rest of jabber.el at once.
(let ((node-name-string (symbol-name node-name)))
(when (string-match "\\(.*\\):\\(.*\\)" node-name-string)
(let* ((prefix (match-string 1 node-name-string))
(unprefixed (match-string 2 node-name-string))
(ns (assoc prefix prefixes)))
(if (null ns)
;; This is not supposed to happen...
(message "jabber-xml-resolve-namespace-prefixes: Unknown prefix in %s" node-name-string)
(setf (car xml-data) (intern unprefixed))
(setf (cadr xml-data) (cons (cons 'xmlns (cdr ns)) (delq 'xmlns attrs)))))))
;; And iterate through all child elements.
(mapc (lambda (x)
(when (listp x)
(jabber-xml-resolve-namespace-prefixes x default-ns prefixes)))
(jabber-xml-node-children xml-data))
xml-data))
(defun jabber-xml-merge-namespace-declarations (attrs prefixes)
;; First find any xmlns:foo attributes..
(dolist (attr attrs)
(let ((attr-name (symbol-name (car attr))))
(when (string-match "xmlns:" attr-name)
(let ((prefix (substring attr-name (match-end 0)))
(ns-uri (cdr attr)))
;; A slightly complicated dance to never change the
;; original value of prefixes (since the caller depends on
;; it), but also to avoid excessive copying (which remove
;; always does). Might need to profile and tweak this for
;; performance.
(setq prefixes
(cons (cons prefix ns-uri)
(if (assoc prefix prefixes)
(remove (assoc prefix prefixes) prefixes)
prefixes)))))))
prefixes)
(provide 'jabber-xml) (provide 'jabber-xml)
;;; arch-tag: ca206e65-7026-4ee8-9af2-ff6a9c5af98a ;;; arch-tag: ca206e65-7026-4ee8-9af2-ff6a9c5af98a

View File

@ -148,6 +148,7 @@ configure a Google Talk account like this:
;; External notifiers ;; External notifiers
(require 'jabber-screen) (require 'jabber-screen)
(require 'jabber-tmux)
(require 'jabber-ratpoison) (require 'jabber-ratpoison)
(require 'jabber-sawfish) (require 'jabber-sawfish)
(require 'jabber-festival) (require 'jabber-festival)

View File

@ -42,26 +42,26 @@ this permission notice are preserved on all copies.
@end ifnottex @end ifnottex
@menu @menu
* Introduction:: * Introduction::
* Basic operation:: * Basic operation::
* Groupchat:: * Groupchat::
* Composing messages:: * Composing messages::
* File transfer:: * File transfer::
* Services:: * Services::
* Personal information:: * Personal information::
* Avatars:: * Avatars::
* Time queries:: * Time queries::
* Useful features:: * Useful features::
* Message history:: * Message history::
* Typing notifications:: * Typing notifications::
* Roster import and export:: * Roster import and export::
* XMPP URIs:: * XMPP URIs::
* Customization:: * Customization::
* Hacking and extending:: * Hacking and extending::
* Protocol support:: * Protocol support::
* Concept index:: * Concept index::
* Function index:: * Function index::
* Variable index:: * Variable index::
@end menu @end menu
@ -84,11 +84,11 @@ jabber.el does not yet support PGP encryption, sending and receiving
roster items, and various other things. roster items, and various other things.
@menu @menu
* Contact:: * Contacts::
@end menu @end menu
@node Contact, , Introduction, Introduction @node Contacts, , , Introduction
@section Contact @section Contacts
@itemize @bullet @itemize @bullet
@item @item
@ -131,16 +131,16 @@ start with @kbd{C-x C-j}, and you can get a list of them by typing
@kbd{C-x C-j C-h}. @kbd{C-x C-j C-h}.
@menu @menu
* Do you have a Jabber account?:: * Do you have a Jabber account?::
* Registering an account:: * Registering an account::
* Connecting:: * Connecting::
* Chatting:: * Chatting::
* Presence:: * Presence::
* Presence subscription:: * Presence subscription::
* Roster buffer:: * Roster buffer::
@end menu @end menu
@node Do you have a Jabber account?, Registering an account, Basic operation, Basic operation @node Do you have a Jabber account?, Registering an account, , Basic operation
@section Do you have a Jabber account? @section Do you have a Jabber account?
Jabber has become rather popular as an instant messaging technology. Jabber has become rather popular as an instant messaging technology.
@ -293,11 +293,11 @@ presence that is sent, change the variables
With jabber.el, you can set your presence remotely. @xref{Ad-Hoc Commands}. With jabber.el, you can set your presence remotely. @xref{Ad-Hoc Commands}.
@menu @menu
* Resources and priority:: * Resources and priority::
* Directed presence:: * Directed presence::
@end menu @end menu
@node Resources and priority, Directed presence, Presence, Presence @node Resources and priority, Directed presence, , Presence
@subsection Resources and priority @subsection Resources and priority
@cindex Resource @cindex Resource
@ -440,13 +440,13 @@ shown here.
@findex jabber-muc-join @findex jabber-muc-join
@cindex Joining a groupchat @cindex Joining a groupchat
@cindex Changing nickname @cindex Changing nickname
@cindex Nickname, changing @cindex Nickname, changing
To join a groupchat, type @kbd{M-x jabber-muc-join}. You will To join a groupchat, type @kbd{M-x jabber-muc-join}. You will
be prompted for the groupchat to join, and your nickname in the be prompted for the groupchat to join, and your nickname in the
groupchat. This nickname doesn't need to have any correlation to your groupchat. This nickname doesn't need to have any correlation to your
JID; in fact, groupchats are usually (but not always) configured such JID; in fact, groupchats are usually (but not always) configured such
that only moderators can see your JID. You can change your nickname that only moderators can see your JID. You can change your nickname
with @kbd{M-x jabber-muc-nick}. @xref{Configuration}, for setting default with @kbd{M-x jabber-muc-nick}. @xref{Configuration}, for setting default
nicknames. nicknames.
@cindex Query groupchat @cindex Query groupchat
@ -503,13 +503,13 @@ jabber-muc-names}. This gives a list of nicknames,
@menu @menu
* Configuration:: * Configuration::
* Invitations:: * Invitations::
* Private messages:: * Private messages::
* MUC Administration:: * MUC Administration::
@end menu @end menu
@node Configuration, Invitations, Groupchat, Groupchat @node Configuration, Invitations, , Groupchat
@section Configuration @section Configuration
@vindex jabber-muc-default-nicknames @vindex jabber-muc-default-nicknames
@ -686,11 +686,11 @@ client. The Google Talk client uses a different file transfer protocol
which, at the time of this release, has not been published. which, at the time of this release, has not been published.
@menu @menu
* Receiving files:: * Receiving files::
* Sending files:: * Sending files::
@end menu @end menu
@node Receiving files, Sending files, File transfer, File transfer @node Receiving files, Sending files, , File transfer
@section Receiving files @section Receiving files
Receiving files requires no configuration. When someone wants to send a Receiving files requires no configuration. When someone wants to send a
@ -779,14 +779,14 @@ You can change the buffer name template by customizing
the variable @code{jabber-browse-buffer-format}. the variable @code{jabber-browse-buffer-format}.
@menu @menu
* Commands:: * Commands::
* Your home server:: * Your home server::
* Transports:: * Transports::
* User directories:: * User directories::
* MUC services:: * MUC services::
@end menu @end menu
@node Commands, Your home server, Services, Services @node Commands, Your home server, , Services
@section Commands @section Commands
A small number of commands is used for almost all interaction with A small number of commands is used for almost all interaction with
@ -798,14 +798,14 @@ opened by typing @kbd{C-c C-s}. Service discovery is under the Info
menu instead, which is available under @kbd{C-c C-i}. menu instead, which is available under @kbd{C-c C-i}.
@menu @menu
* Registration:: * Registration::
* Search:: * Search::
* Ad-Hoc Commands:: * Ad-Hoc Commands::
* Service discovery:: * Service discovery::
* Browsing:: * Browsing::
@end menu @end menu
@node Registration, Search, Commands, Commands @node Registration, Search, , Commands
@subsection Registration @subsection Registration
@cindex Registration @cindex Registration
@ -832,10 +832,6 @@ jabber-get-search}. This gives you a single-stage form to fill in.
After you press the ``Submit'' button at the bottom, the search results After you press the ``Submit'' button at the bottom, the search results
will be displayed in the same buffer. will be displayed in the same buffer.
@menu
* Ad-Hoc Commands::
@end menu
@node Ad-Hoc Commands, Service discovery, Search, Commands @node Ad-Hoc Commands, Service discovery, Search, Commands
@subsection Ad-Hoc Commands @subsection Ad-Hoc Commands
@ -1104,17 +1100,18 @@ jabber.el includes a number of features meant to improve the user
interface and do other useful things. interface and do other useful things.
@menu @menu
* Autoaway:: * Autoaway::
* Modeline status:: * Modeline status::
* Keepalive:: * Keepalive::
* Reconnecting:: * Reconnecting::
* Tracking activity:: * Tracking activity::
* Watch buddies:: * Watch buddies::
* Spell checking:: * Spell checking::
* Gmail notifications::
* Saving groups roll state:: * Saving groups roll state::
@end menu @end menu
@node Autoaway, Modeline status, Useful features, Useful features @node Autoaway, Modeline status, , Useful features
@section Autoaway @section Autoaway
@cindex autoaway @cindex autoaway
@ -1273,7 +1270,7 @@ minibuffer).
jabber.el supports automatic reconnection to Jabber server(s) upon lost jabber.el supports automatic reconnection to Jabber server(s) upon lost
connection. By default it is off. To turn on, customize connection. By default it is off. To turn on, customize
the @code{jabber-auto-reconnect} variable. the @code{jabber-auto-reconnect} variable.
This is of limited use if you have to type your password every time This is of limited use if you have to type your password every time
jabber.el reconnects. There are two ways to save your password: you can jabber.el reconnects. There are two ways to save your password: you can
@ -1346,7 +1343,7 @@ online. jabber.el will remember this for the rest of your Emacs
session (it's not saved to disk, though), but if you want to get rid session (it's not saved to disk, though), but if you want to get rid
of it, type @kbd{M-x jabber-watch-remove}. of it, type @kbd{M-x jabber-watch-remove}.
@node Spell checking, Saving groups roll state, Watch buddies, Useful features @node Spell checking, Gmail notifications, Watch buddies, Useful features
@section Spell checking @section Spell checking
@cindex flyspell @cindex flyspell
@ -1360,7 +1357,53 @@ what you receive or what you have already sent. You may want to add
For more information about Emacs spell checking, @pxref{Spelling, , For more information about Emacs spell checking, @pxref{Spelling, ,
Checking and Correcting Spelling, emacs, GNU Emacs Manual}. Checking and Correcting Spelling, emacs, GNU Emacs Manual}.
@node Saving groups roll state, , Spell Checking, Useful features @node Gmail notifications, Saving groups roll state, Spell checking, Useful features
@section Gmail notifications
@cindex Gmail notifications
If you are connected to a Google Talk account, you can receive
notifications when a new Gmail message arrives. Gmail notifications
are enabled by adding the following line to your @file{.emacs}:
@example
(add-hook 'jabber-post-connect-hooks 'jabber-gmail-subscribe)
@end example
Default behavior is to display a message that mentions the number of
received gmails. You can customize this behavior by providing your
own @code{jabber-gmail-dothreads} function.
Example:
@example
(eval-after-load "jabber-gmail"
'(defun jabber-gmail-dothreads (threads)
"Process <mail-thread-info/> elements.
THREADS is a list of XML sexps corresponding to <mail-thread-info/>
elements.
See http://code.google.com/apis/talk/jep_extensions/gmail.html#response"
(osd "gmail: %d" (length threads))))
;;; It's usually a good idea to have a shortcut for querying GTalk server.
(global-set-key (kbd "<f9> g") 'jabber-gmail-query)
;;; The definition of `osd' function used by `jabber-gmail-dothreads'.
;;; `osd_cat' is shipped with the X OSD library
;;; [http://www.ignavus.net/software.html].
(if (and (display-graphic-p) (file-executable-p "/usr/bin/osd_cat"))
(defun osd (fmt &rest args)
"Display message on X screen."
(let ((opts "-p bottom -A center -l 1 \
-f '-adobe-helvetica-bold-r-*-*-24-*-*-*-*-*-iso10646-1'")
(msg (apply 'format (concat fmt "\n") args)))
(start-process "osd" nil shell-file-name shell-command-switch
(format "echo %s | osd_cat %s"
(shell-quote-argument msg) opts))))
(defalias 'osd 'message))
@end example
@node Saving groups roll state, , Gmail notifications, Useful features
@section Saving groups roll state @section Saving groups roll state
@cindex Saving groups roll state @cindex Saving groups roll state
@ -1377,6 +1420,7 @@ saving (by default, all groups rolled down). Also note that at now,
@code{jabber-pre-disconnect-hook} run only with @code{jabber-pre-disconnect-hook} run only with
@code{jabber-disconnect} (not with @code{jabber-disconnect-one}). @code{jabber-disconnect} (not with @code{jabber-disconnect-one}).
@node Message history, Typing notifications, Useful features, Top @node Message history, Typing notifications, Useful features, Top
@chapter Message history @chapter Message history
@ -1651,16 +1695,16 @@ this is Emacs. To open a customization buffer for jabber.el, type
@kbd{M-x jabber-customize}. @kbd{M-x jabber-customize}.
@menu @menu
* Account settings:: * Account settings::
* Menu:: * Menu::
* Customizing the roster buffer:: * Customizing the roster buffer::
* Customizing the chat buffer:: * Customizing the chat buffer::
* Customizing alerts:: * Customizing alerts::
* Hooks:: * Hooks::
* Debug options:: * Debug options::
@end menu @end menu
@node Account settings, Menu, Customization, Customization @node Account settings, Menu, , Customization
@section Account settings @section Account settings
@cindex Username @cindex Username
@ -1715,6 +1759,8 @@ you also need to set
``network server'' to @kbd{talk.google.com} and ``connection type'' to ``network server'' to @kbd{talk.google.com} and ``connection type'' to
``legacy SSL''. ``legacy SSL''.
See also @ref{Gmail notifications}.
@subsection Upgrade note @subsection Upgrade note
Previous versions of jabber.el had the variables @code{jabber-username}, Previous versions of jabber.el had the variables @code{jabber-username},
@ -1939,7 +1985,7 @@ same arguments as the corresponding hooks, except for that last
argument. argument.
Alert hook contributions are very welcome. You can send them to the Alert hook contributions are very welcome. You can send them to the
mailing list, or to the Sourceforge patch tracker. mailing list, or to the Sourceforge patch tracker. @xref{Contacts}.
Alert hooks are meant for optional UI things, that are subject to Alert hooks are meant for optional UI things, that are subject to
varying user tastes, and that can be toggled by simply adding or varying user tastes, and that can be toggled by simply adding or
@ -1951,14 +1997,14 @@ e.g. @code{jabber-message-hooks} vs @code{jabber-alert-message-hooks},
etc. etc.
@menu @menu
* Standard alerts:: * Standard alerts::
* Presence alerts:: * Presence alerts::
* Message alerts:: * Message alerts::
* MUC alerts:: * MUC alerts::
* Info alerts:: * Info alerts::
@end menu @end menu
@node Standard alerts, Presence alerts, Customizing alerts, Customizing alerts @node Standard alerts, Presence alerts, , Customizing alerts
@subsection Standard alerts @subsection Standard alerts
@cindex Alerts @cindex Alerts
@ -2000,6 +2046,10 @@ The @code{screen} alerts send a message through the Screen terminal
manager@footnote{See @uref{http://www.gnu.org/software/screen/}.}. They do no manager@footnote{See @uref{http://www.gnu.org/software/screen/}.}. They do no
harm if called when you don't use Screen. harm if called when you don't use Screen.
@cindex Tmux terminal manager
The @code{tmux} alerts send a message through the tmux terminal
manager@footnote{See @uref{http://tmux.sourceforge.net/}.}.
@cindex Ratpoison window manager @cindex Ratpoison window manager
@cindex Window manager, Ratpoison @cindex Window manager, Ratpoison
The @code{ratpoison} alerts send a message through the Ratpoison The @code{ratpoison} alerts send a message through the Ratpoison
@ -2276,17 +2326,17 @@ yourself and trying to figure it out, but as a guide on where to
look. Knowledge of Jabber protocols is assumed. look. Knowledge of Jabber protocols is assumed.
@menu @menu
* Connection object:: * Connection object::
* XML representation:: * XML representation::
* JID symbols:: * JID symbols::
* Listening for new requests:: * Listening for new requests::
* Sending new requests:: * Sending new requests::
* Extending service discovery:: * Extending service discovery::
* Chat printers:: * Chat printers::
* Stanza chains:: * Stanza chains::
@end menu @end menu
@node Connection object, XML representation, Hacking and extending, Hacking and extending @node Connection object, XML representation, , Hacking and extending
@section Connection object @section Connection object
@cindex connection object @cindex connection object
@cindex account object @cindex account object
@ -2518,11 +2568,11 @@ information.
@menu @menu
* Providing info:: * Providing info::
* Requesting info:: * Requesting info::
@end menu @end menu
@node Providing info, Requesting info, Extending service discovery, Extending service discovery @node Providing info, Requesting info, , Extending service discovery
@subsection Providing info @subsection Providing info
Your new IQ request handlers will likely want to advertise their Your new IQ request handlers will likely want to advertise their
@ -2703,7 +2753,7 @@ jabber.el.
* XEP-0245:: The /me Command * XEP-0245:: The /me Command
@end menu @end menu
@node RFC 3920, RFC 3921, Protocol support, Protocol support @node RFC 3920, RFC 3921, , Protocol support
@section RFC 3920 (XMPP-CORE) @section RFC 3920 (XMPP-CORE)
Most of RFC 3920 is supported, with the following exceptions. Most of RFC 3920 is supported, with the following exceptions.

View File

@ -73,8 +73,8 @@ arguments, the client FSM and the stanza.")
;; If so, send <stream:features>. ;; If so, send <stream:features>.
(when (string-match "version=[\"']" stanza) (when (string-match "version=[\"']" stanza)
(jabberd-send fsm (jabberd-send fsm
'(stream:features '(features
() ((xmlns . "http://etherx.jabber.org/streams"))
;; Interesting implementation details ;; Interesting implementation details
;; of jabber.el permit us to send all ;; of jabber.el permit us to send all
;; features at once, without caring about ;; features at once, without caring about