summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatteo F. Vescovi <mfv@debian.org>2016-11-06 14:36:11 +0100
committerMatteo F. Vescovi <mfv@debian.org>2016-11-06 14:36:11 +0100
commit8e7ca604077584e6c2b1e079844306a9f4ce321b (patch)
treea6e26996de2930e6cafd5195e843aefa954e7eda
parent484a3c53538e94f8d8c6a432b3c3174d98deb92f (diff)
Import Upstream version 0.7.1
-rw-r--r--AUTHORS3
-rw-r--r--NEWS40
-rw-r--r--README40
-rw-r--r--filetransfer.txt55
-rw-r--r--fsm.el275
-rw-r--r--hex-util.el75
-rw-r--r--html/Account-settings.html69
-rw-r--r--html/Ad_002dHoc-Commands.html77
-rw-r--r--html/Autoaway.html72
-rw-r--r--html/Automation.html56
-rw-r--r--html/Avatars.html61
-rw-r--r--html/Basic-operation.html61
-rw-r--r--html/Chat-printers.html67
-rw-r--r--html/Chatting.html66
-rw-r--r--html/Composing-messages.html55
-rw-r--r--html/Concept-index.html153
-rw-r--r--html/Connecting.html81
-rw-r--r--html/Connection-settings.html74
-rw-r--r--html/Contact.html50
-rw-r--r--html/Customization.html60
-rw-r--r--html/Customizing-alerts.html96
-rw-r--r--html/Customizing-the-chat-buffer.html96
-rw-r--r--html/Customizing-the-roster-buffer.html89
-rw-r--r--html/Debug-options.html51
-rw-r--r--html/Extending-service-discovery.html71
-rw-r--r--html/File-transfer.html69
-rw-r--r--html/Function-index.html104
-rw-r--r--html/Groupchat.html91
-rw-r--r--html/Hacking-and-extending.html59
-rw-r--r--html/Hooks.html68
-rw-r--r--html/Info-alerts.html53
-rw-r--r--html/Introduction.html63
-rw-r--r--html/Invitations.html57
-rw-r--r--html/Keepalive.html64
-rw-r--r--html/Listening-for-new-requests.html67
-rw-r--r--html/MUC-Administration.html91
-rw-r--r--html/MUC-alerts.html68
-rw-r--r--html/Message-alerts.html79
-rw-r--r--html/Message-events.html71
-rw-r--r--html/Message-history.html83
-rw-r--r--html/Miscellaneous-settings.html52
-rw-r--r--html/Modeline-status.html58
-rw-r--r--html/Personal-information.html60
-rw-r--r--html/Presence-alerts.html69
-rw-r--r--html/Presence-subscription.html63
-rw-r--r--html/Presence.html91
-rw-r--r--html/Private-messages.html57
-rw-r--r--html/Protocol-support.html77
-rw-r--r--html/RFC-3920.html60
-rw-r--r--html/RFC-3921.html58
-rw-r--r--html/Receiving-files.html67
-rw-r--r--html/Registering.html78
-rw-r--r--html/Roster-buffer.html77
-rw-r--r--html/Roster-import-and-export.html62
-rw-r--r--html/Roster-structure.html81
-rw-r--r--html/Searching.html59
-rw-r--r--html/Sending-files.html82
-rw-r--r--html/Sending-new-requests.html86
-rw-r--r--html/Service-discovery-and-browsing.html68
-rw-r--r--html/Services.html63
-rw-r--r--html/Spell-checking.html51
-rw-r--r--html/Standard-alerts.html101
-rw-r--r--html/Stanza-chains.html52
-rw-r--r--html/Time-queries.html56
-rw-r--r--html/Tracking-activity.html77
-rw-r--r--html/Useful-features.html56
-rw-r--r--html/Variable-index.html132
-rw-r--r--html/Watch-buddies.html57
-rw-r--r--html/XEP_002d0004.html61
-rw-r--r--html/XEP_002d0012.html48
-rw-r--r--html/XEP_002d0020.html47
-rw-r--r--html/XEP_002d0022.html50
-rw-r--r--html/XEP_002d0030.html48
-rw-r--r--html/XEP_002d0045.html51
-rw-r--r--html/XEP_002d0049.html48
-rw-r--r--html/XEP_002d0050.html49
-rw-r--r--html/XEP_002d0054.html49
-rw-r--r--html/XEP_002d0055.html50
-rw-r--r--html/XEP_002d0065.html54
-rw-r--r--html/XEP_002d0066.html50
-rw-r--r--html/XEP_002d0068.html48
-rw-r--r--html/XEP_002d0077.html54
-rw-r--r--html/XEP_002d0078.html49
-rw-r--r--html/XEP_002d0082.html48
-rw-r--r--html/XEP_002d0086.html48
-rw-r--r--html/XEP_002d0090.html48
-rw-r--r--html/XEP_002d0091.html48
-rw-r--r--html/XEP_002d0092.html49
-rw-r--r--html/XEP_002d0095.html49
-rw-r--r--html/XEP_002d0096.html51
-rw-r--r--html/XEP_002d0146.html47
-rw-r--r--html/XEP_002d0153.html46
-rw-r--r--html/XML-representation.html71
-rw-r--r--html/XMPP-URIs.html84
-rw-r--r--html/index.html201
-rw-r--r--jabber-activity.el13
-rw-r--r--jabber-ahc-presence.el22
-rw-r--r--jabber-alert.el55
-rw-r--r--jabber-autoaway.el182
-rw-r--r--jabber-avatar.el205
-rw-r--r--jabber-browse.el2
-rw-r--r--jabber-chat.el362
-rw-r--r--jabber-chatbuffer.el70
-rw-r--r--jabber-compose.el80
-rw-r--r--jabber-conn.el110
-rw-r--r--jabber-core.el30
-rw-r--r--jabber-disco.el16
-rw-r--r--jabber-events.el65
-rw-r--r--jabber-ft-client.el35
-rw-r--r--jabber-ft-common.el44
-rw-r--r--jabber-ft-server.el16
-rw-r--r--jabber-history.el12
-rw-r--r--jabber-iq.el30
-rw-r--r--jabber-keymap.el1
-rw-r--r--jabber-logon.el8
-rw-r--r--jabber-muc.el514
-rw-r--r--jabber-newdisco.el164
-rw-r--r--jabber-presence.el106
-rw-r--r--jabber-private.el55
-rw-r--r--jabber-register.el8
-rw-r--r--jabber-roster.el50
-rw-r--r--jabber-sasl.el9
-rw-r--r--jabber-si-client.el14
-rw-r--r--jabber-si-common.el61
-rw-r--r--jabber-si-server.el20
-rw-r--r--jabber-socks5.el739
-rw-r--r--jabber-time.el133
-rw-r--r--jabber-util.el140
-rw-r--r--jabber-vcard-avatars.el116
-rw-r--r--jabber-vcard.el108
-rw-r--r--jabber-version.el6
-rw-r--r--jabber-watch.el8
-rw-r--r--jabber-widget.el41
-rw-r--r--jabber-xml.el20
-rw-r--r--jabber.el22
-rw-r--r--jabber.info2539
-rw-r--r--jabber.texi740
-rw-r--r--sha1.el443
-rw-r--r--srv.el95
-rwxr-xr-xxmppuri.sh7
140 files changed, 12449 insertions, 1543 deletions
diff --git a/AUTHORS b/AUTHORS
index 79bdf54..210fd03 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -7,9 +7,10 @@ Mathias Dahl
Mario Domenech Goulart
Nolan Eakins
François Fleuret
+David Hansen
Justin Kirby
Carl Henrik Lunde
Andrey Slusar
-
+Milan Zamazal
arch-tag: 15700144-3BD9-11D9-871C-000A95C2FCD0
diff --git a/NEWS b/NEWS
index 41bddf7..cc26e34 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,45 @@
-*- mode: outline -*-
+* New features in jabber.el 0.7.1
+
+** STARTTLS
+
+** SRV records
+Requires No Gnus.
+
+** Message composition buffer
+Try jabber-compose.
+
+** XMPP URIs are handled
+See manual for setup.
+
+** Autoaway
+
+** MUC features
+*** Don't display alerts for your own messages
+See jabber-muc-alert-self.
+*** Presence changes are sent to MUC rooms too
+*** Check room features before joining
+
+** Avatars
+Viewing and publishing JEP-0153 avatars (vCard-based) is now
+supported.
+
+** File transfer
+
+** Sound files per contact for alerts
+
+** Per-user history files changed
+For some time after 0.7 these file names erroneously contained double
+quotes. If you have used the CVS version you'll need to rename your
+history files manually.
+
+** New function: jabber-send-directed-presence
+
+** Entity time supported (XEP-0090)
+
+** Last activity supported (XEP-0012)
+
* New features in jabber.el 0.7
** SSL connections possible
diff --git a/README b/README
index 5ef9faf..698bd58 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-This is jabber.el 0.7, a Jabber client for Emacs. If you don't know
+This is jabber.el 0.7.1, a Jabber client for Emacs. If you don't know
what Jabber is, see http://www.jabber.org .
Home page: http://emacs-jabber.sourceforge.net
@@ -6,6 +6,7 @@ Project page: http://sourceforge.net/projects/emacs-jabber
Wiki page: http://www.emacswiki.org/cgi-bin/wiki/JabberEl
Mailing list: http://lists.sourceforge.net/lists/listinfo/emacs-jabber-general
and: http://dir.gmane.org/gmane.emacs.jabber.general
+MUC room: jabber.el@conference.jabber.se
GNU Emacs
=========
@@ -13,8 +14,7 @@ GNU Emacs
jabber.el depends on GNU Emacs 21, in particular xml.el, and some
files from Gnus 5.10. If you don't have Gnus 5.10 (M-x gnus-version
will tell), you can download sha1.el and hex-util.el from Gnus CVS
-at http://quimby.gnus.org/cgi-bin/cvsweb.cgi/gnus/lisp/ . For your
-convenience, these files are included in the tarball.
+at http://quimby.gnus.org/cgi-bin/cvsweb.cgi/gnus/lisp/ .
XEmacs
======
@@ -28,25 +28,28 @@ SASL
====
jabber.el will use the SASL library of FLIM (Faithful Library about
Internet Message; it is also included in newer versions of Gnus) if
-it's present. If not, it will fall back to JEP-0077 authentication.
+it's present. If not, it will fall back to XEP-0077 authentication.
TLS/SSL
=======
-To get an encrypted connection, you need either tls.el (from Gnus) or
-ssl.el. These are interfaces to GnuTLS and OpenSSL, respectively; use
-the appropriate one. Recent versions of tls.el support both programs,
-though. The version of ssl.el distributed with Gnus is outdated; use
-the one from W3 CVS instead:
+To get an encrypted connection, the most convenient option is to
+install starttls.el from Gnus (currently only present in the
+development version). This requires GnuTLS to be installed, but
+requires no configuration at all.
+
+You can also use either tls.el (from Gnus) or ssl.el. These are
+interfaces to GnuTLS and OpenSSL, respectively; use the appropriate
+one. Recent versions of tls.el support both programs, though. The
+version of ssl.el distributed with Gnus is outdated; use the one from
+W3 CVS instead:
http://cvs.savannah.gnu.org/viewcvs/w3/lisp/ssl.el?root=w3
-To actually use encryption, customize the variables
-jabber-connection-type and jabber-connection-ssl-program.
+To actually use encryption with one of these libraries, customize the
+variables jabber-connection-type and jabber-connection-ssl-program.
Note that only the connection from you to the server is encrypted;
there is no guarantee of other connections being encrypted.
-StartTLS is not supported in this version of jabber.el.
-
Installation
============
To install, put all .el files somewhere in your load-path (or have
@@ -99,6 +102,11 @@ nil.
File transfer
=============
-This release of jabber.el contains experimental support for file
-transfer. It is not enabled by default. See the file
-filetransfer.txt for details.
+This release of jabber.el contains support for file transfer. You may
+need to configure some variables to make it work; see the manual for
+details.
+
+XMPP URIs
+=========
+It is possible to make various web browsers pass links starting with
+"xmpp:" to jabber.el. See the manual, section "XMPP URIs".
diff --git a/filetransfer.txt b/filetransfer.txt
deleted file mode 100644
index 756f7e3..0000000
--- a/filetransfer.txt
+++ /dev/null
@@ -1,55 +0,0 @@
--*- outline -*-
-* File transfer
-
-This release of jabber.el contains some support for file transfer.
-Both sending and receiving files are supported. Since this feature
-needs more testing, it is not enabled by default. To enable it, add
-
-(require 'jabber-ft-server)
-(require 'jabber-ft-client)
-(require 'jabber-socks5)
-
-to your .emacs file. Please share your experiences - does it work for
-you? Can you suggest any improvements?
-
-** Sending files
-
-Sending files over Jabber normally requires the ability to listen on a
-network port. As of Emacs 21.3 and XEmacs 21.4, elisp programs can't
-do this, so you have to specify a JEP-0065 proxy. The variable
-jabber-socks5-proxies is a list of proxies to use. "proxy.jabber.org"
-and "proxy65.jabber.ccc.de" are the only proxies I know of.
-
-After you have specified one or more proxies, jabber.el needs to know
-their network addresses. Type M-x jabber-socks5-query-all-proxies,
-and watch the progress in the echo area. Note that you have to be
-connected when you do this, and that you have to do this every
-session.
-
-To send a file, type M-x jabber-ft-send. You will be asked for which
-file to send, and whom to send it to. You have to specify a complete
-JID with resource, such as user@domain/resource - only user@domain
-will not work. To see the resources of your contacts, set
-jabber-show-resources to t and type M-x jabber-display-roster.
-
-While the file is being sent, your Emacs will be locked up and you
-can't do anything else. Hopefully, this will be fixed some time.
-
-** Receiving files
-
-When someone tries to send a file to you, you will get a message
-either in the echo area or in a dialog box, asking you to confirm.
-You will also be asked for where to save the file.
-
-Receiving a file should not cause any interruption to your work. If
-it does, please tell.
-
-** Protocol details
-
-See JEPs 95, 96 and 65.
-
-SOCKS5 (JEP-0065) is the only stream method currently supported by
-jabber.el, in conflict with JEP-0096, which requires that In-Band
-Bytestreams be supported as well.
-
-Range requests are not supported, neither in sending nor in receiving.
diff --git a/fsm.el b/fsm.el
new file mode 100644
index 0000000..23182b4
--- /dev/null
+++ b/fsm.el
@@ -0,0 +1,275 @@
+;;; fsm.el --- state machine library
+
+;; Copyright (C) 2006 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+;; Version: 0.1
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; fsm.el is an exercise in metaprogramming inspired by gen_fsm of
+;; Erlang/OTP. It aims to make asynchronous programming in Emacs Lisp
+;; easy and fun. By "asynchronous" I mean that long-lasting tasks
+;; don't interfer with normal editing.
+
+;; Some people say that it would be nice if Emacs Lisp had threads
+;; and/or continuations. They are probably right, but there are few
+;; things that can't be made to run in the background using facilities
+;; already available: timers, filters and sentinels. As the code can
+;; become a bit messy when using such means, with callbacks everywhere
+;; and such things, it can be useful to structure the program as a
+;; state machine.
+
+;; In this model, a state machine passes between different "states",
+;; which are actually only different event handler functions. The
+;; state machine receives "events" (from timers, filters, user
+;; requests, etc) and reacts to them, possibly entering another state,
+;; possibly returning a value.
+
+;; The essential macros/functions are:
+;;
+;; define-state-machine - create start-FOO function
+;; define-state - event handler for each state (required)
+;; define-enter-state - called when entering a state (optional)
+;; fsm-send - send an event to a state machine
+;; fsm-call - send an event and wait for reply
+
+;; fsm.el is similar to but different from Distel:
+;; <URL:http://fresh.homeunix.net/~luke/distel/>
+;; Emacs' tq library is a similar idea.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+(defvar fsm-debug "*fsm-debug*"
+ "Name of buffer for fsm debug messages.
+If nil, don't output debug messages.")
+
+(defun fsm-debug-output (format &rest args)
+ "Append debug output to buffer named by `fsm-debug'.
+FORMAT and ARGS are passed to `format'."
+ (when fsm-debug
+ (with-current-buffer (get-buffer-create fsm-debug)
+ (save-excursion
+ (goto-char (point-max))
+ (insert (current-time-string) ": " (apply 'format format args) "\n")))))
+
+(defmacro* define-state-machine (name &key start sleep)
+ "Define a state machine class called NAME.
+A function called start-NAME is created, which uses the argument
+list and body specified in the :start argument. BODY should
+return a list of the form (STATE STATE-DATA [TIMEOUT]), where
+STATE is the initial state (defined by `define-state'),
+STATE-DATA is any object, and TIMEOUT is the number of seconds
+before a :timeout event will be sent to the state machine. BODY
+may refer to the instance being created through the dynamically
+bound variable `fsm'.
+
+SLEEP-FUNCTION, if provided, takes one argument, the number of
+seconds to sleep while allowing events concerning this state
+machine to happen. There is probably no reason to change the
+default, which is accept-process-output with rearranged
+arguments.
+
+\(fn NAME :start ((ARG ...) DOCSTRING BODY) [:sleep SLEEP-FUNCTION])"
+ (let ((start-name (intern (concat "start-" (symbol-name name)))))
+ (destructuring-bind (arglist docstring &body body) start
+ (unless (stringp docstring)
+ (error "Docstring is not a string"))
+ `(progn
+ (defun ,start-name ,arglist
+ ,docstring
+ (fsm-debug-output "Starting %s" ',name)
+ (let ((fsm (list :fsm ',name)))
+ (destructuring-bind (state state-data &optional timeout)
+ (progn ,@body)
+ (nconc fsm (list :state nil :state-data nil
+ :sleep ,(or sleep (lambda (secs) (accept-process-output nil secs)))
+ :deferred nil))
+ (fsm-update fsm state state-data timeout)
+ fsm)))))))
+
+(defmacro* define-state (fsm state-name arglist &body body)
+ "Define a state called STATE-NAME in the state machine FSM.
+ARGLIST and BODY make a function that gets called when the state
+machine receives an event in this state. The arguments are:
+
+FSM the state machine instance (treat it as opaque)
+STATE-DATA An object
+EVENT The occurred event, an object.
+CALLBACK A function of one argument that expects the response
+ to this event, if any (often `ignore' is used)
+
+If the event should return a response, the state machine should
+arrange to call CALLBACK at some point in the future (not necessarily
+in this handler).
+
+The function should return a list of the form (NEW-STATE
+NEW-STATE-DATA TIMEOUT):
+
+NEW-STATE The next state, a symbol
+NEW-STATE-DATA An object
+TIMEOUT A number: send timeout event after this many seconds
+ nil: cancel existing timer
+ :keep: let existing timer continue
+
+Alternatively, the function may return the keyword :defer, in
+which case the event will be resent when the state machine enters
+another state."
+ (let ((fn-name (intern (concat "fsm-" (symbol-name fsm) "-" (symbol-name state-name)))))
+ `(defun ,fn-name ,arglist
+ ,@body)))
+
+(defmacro* define-enter-state (fsm state-name arglist &body body)
+ "Define a function to call when FSM enters the state STATE-NAME.
+ARGLIST and BODY make a function that gets called when the state
+machine enters this state. The arguments are:
+
+FSM the state machine instance (treat it as opaque)
+STATE-DATA An object
+
+The function should return a list of the form (NEW-STATE-DATA
+TIMEOUT):
+
+NEW-STATE-DATA An object
+TIMEOUT A number: send timeout event after this many seconds
+ nil: cancel existing timer
+ :keep: let existing timer continue"
+ (let ((fn-name (intern (concat "fsm-" (symbol-name fsm) "-enter-" (symbol-name state-name)))))
+ `(defun ,fn-name ,arglist
+ ,@body)))
+
+(defun fsm-start-timer (fsm secs)
+ "Send a timeout event to FSM after SECS seconds.
+The timer is canceled if another event occurs before, unless the
+event handler explicitly asks to keep the timer."
+ (fsm-stop-timer fsm)
+ (setf (cddr fsm)
+ (plist-put
+ (cddr fsm)
+ :timeout (run-with-timer secs
+ nil
+ #'fsm-send-sync fsm
+ :timeout))))
+
+(defun fsm-stop-timer (fsm)
+ "Stop the timeout timer of FSM."
+ (let ((timer (plist-get (cddr fsm) :timeout)))
+ (when (timerp timer)
+ (cancel-timer timer)
+ (setf (cddr fsm) (plist-put (cddr fsm) :timeout nil)))))
+
+(defun fsm-maybe-change-timer (fsm timeout)
+ "Change the timer of FSM according to TIMEOUT."
+ (cond
+ ((numberp timeout)
+ (fsm-start-timer fsm timeout))
+ ((null timeout)
+ (fsm-stop-timer fsm))
+ ;; :keep needs no timer change
+ ))
+
+(defun fsm-send (fsm event &optional callback)
+ "Send EVENT to FSM asynchronously.
+If the state machine generates a response, eventually call
+CALLBACK with the response as only argument."
+ (run-with-timer 0.1 nil #'fsm-send-sync fsm event callback))
+
+(defun fsm-update (fsm new-state new-state-data timeout)
+ (let ((old-state (plist-get (cddr fsm) :state)))
+ (plist-put (cddr fsm) :state new-state)
+ (plist-put (cddr fsm) :state-data new-state-data)
+ (fsm-maybe-change-timer fsm timeout)
+
+ ;; On state change, call enter function and send deferred events
+ ;; again.
+ (unless (eq old-state new-state)
+ (fsm-debug-output "%s enters %s" (cadr fsm) new-state)
+ (let ((enter-fn (intern (concat "fsm-" (symbol-name (cadr fsm)) "-enter-" (symbol-name new-state)))))
+ (when (functionp enter-fn)
+ (destructuring-bind (newer-state-data newer-timeout)
+ (funcall enter-fn fsm new-state-data)
+ (plist-put (cddr fsm) :state-data newer-state-data)
+ (fsm-maybe-change-timer fsm newer-timeout))))
+
+ (let ((deferred (nreverse (plist-get (cddr fsm) :deferred))))
+ (setf (cddr fsm)
+ (plist-put (cddr fsm) :deferred nil))
+ (dolist (event deferred)
+ (apply 'fsm-send-sync fsm event))))))
+
+(defun fsm-send-sync (fsm event &optional callback)
+ "Send EVENT to FSM synchronously.
+If the state machine generates a response, eventually call
+CALLBACK with the response as only argument."
+ (save-match-data
+ (let* ((fsm-name (second fsm))
+ (state (plist-get (cddr fsm) :state))
+ (state-data (plist-get (cddr fsm) :state-data))
+ (state-fn (intern (concat "fsm-" (symbol-name fsm-name)
+ "-" (symbol-name state)))))
+ ;; If the event is a list, output only the car, to avoid an
+ ;; overflowing debug buffer.
+ (fsm-debug-output "Sent %S to %s in state %s" (or (car-safe event) event) fsm-name state)
+ (let ((result (condition-case e
+ (funcall state-fn fsm state-data event (or callback 'ignore))
+ (error (cons :error-signaled e)))))
+ ;; Special case for deferring an event until next state change.
+ (cond
+ ((eq result :defer)
+ (let ((deferred (plist-get (cddr fsm) :deferred)))
+ (plist-put (cddr fsm) :deferred (cons (list event callback) deferred))))
+ ((null result)
+ (fsm-debug-output "Warning: event %S ignored in state %s" event state))
+ ((eq (car-safe result) :error-signaled)
+ (fsm-debug-output "Error: %s" (error-message-string (cdr result))))
+ (t
+ (destructuring-bind (new-state new-state-data &optional timeout) result
+ (fsm-update fsm new-state new-state-data timeout))))))))
+
+(defun fsm-call (fsm event)
+ "Send EVENT to FSM synchronously, and wait for a reply.
+Return the reply.
+`with-timeout' might be useful."
+ (lexical-let (reply)
+ (fsm-send-sync fsm event (lambda (r) (setq reply (list r))))
+ (while (null reply)
+ (fsm-sleep fsm 1))
+ (car reply)))
+
+(defun fsm-make-filter (fsm)
+ "Return a filter function that sends events to FSM.
+Events sent are of the form (:filter PROCESS STRING)."
+ (lexical-let ((fsm fsm))
+ (lambda (process string)
+ (fsm-send-sync fsm (list :filter process string)))))
+
+(defun fsm-make-sentinel (fsm)
+ "Return a sentinel function that sends events to FSM.
+Events sent are of the form (:sentinel PROCESS STRING)."
+ (lexical-let ((fsm fsm))
+ (lambda (process string)
+ (fsm-send-sync fsm (list :sentinel process string)))))
+
+(defun fsm-sleep (fsm secs)
+ "Sleep up to SECS seconds in a way that lets FSM receive events."
+ (funcall (plist-get (cddr fsm) :sleep) secs))
+
+(provide 'fsm)
+;;; fsm.el ends here
diff --git a/hex-util.el b/hex-util.el
deleted file mode 100644
index 1cc67c2..0000000
--- a/hex-util.el
+++ /dev/null
@@ -1,75 +0,0 @@
-;;; hex-util.el --- Functions to encode/decode hexadecimal string.
-
-;; Copyright (C) 1999, 2001, 2002, 2003, 2004,
-;; 2005 Free Software Foundation, Inc.
-
-;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
-;; Keywords: data
-
-;; This file is part of FLIM (Faithful Library about Internet Message).
-
-;; 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, 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; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;;; Code:
-
-(eval-when-compile
- (defmacro hex-char-to-num (chr)
- (` (let ((chr (, chr)))
- (cond
- ((and (<= ?a chr)(<= chr ?f)) (+ (- chr ?a) 10))
- ((and (<= ?A chr)(<= chr ?F)) (+ (- chr ?A) 10))
- ((and (<= ?0 chr)(<= chr ?9)) (- chr ?0))
- (t (error "Invalid hexadecimal digit `%c'" chr))))))
- (defmacro num-to-hex-char (num)
- (` (aref "0123456789abcdef" (, num)))))
-
-(defun decode-hex-string (string)
- "Decode hexadecimal STRING to octet string."
- (let* ((len (length string))
- (dst (make-string (/ len 2) 0))
- (idx 0)(pos 0))
- (while (< pos len)
-;;; logior and lsh are not byte-coded.
-;;; (aset dst idx (logior (lsh (hex-char-to-num (aref string pos)) 4)
-;;; (hex-char-to-num (aref string (1+ pos)))))
- (aset dst idx (+ (* (hex-char-to-num (aref string pos)) 16)
- (hex-char-to-num (aref string (1+ pos)))))
- (setq idx (1+ idx)
- pos (+ 2 pos)))
- dst))
-
-(defun encode-hex-string (string)
- "Encode octet STRING to hexadecimal string."
- (let* ((len (length string))
- (dst (make-string (* len 2) 0))
- (idx 0)(pos 0))
- (while (< pos len)
-;;; logand and lsh are not byte-coded.
-;;; (aset dst idx (num-to-hex-char (logand (lsh (aref string pos) -4) 15)))
- (aset dst idx (num-to-hex-char (/ (aref string pos) 16)))
- (setq idx (1+ idx))
-;;; (aset dst idx (num-to-hex-char (logand (aref string pos) 15)))
- (aset dst idx (num-to-hex-char (% (aref string pos) 16)))
- (setq idx (1+ idx)
- pos (1+ pos)))
- dst))
-
-(provide 'hex-util)
-
-;;; arch-tag: fe8aaa79-6c86-400e-813f-5a8cc4cb3859
-;;; hex-util.el ends here
diff --git a/html/Account-settings.html b/html/Account-settings.html
new file mode 100644
index 0000000..f0dd9ac
--- /dev/null
+++ b/html/Account-settings.html
@@ -0,0 +1,69 @@
+<html lang="en">
+<head>
+<title>Account settings - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Customization.html#Customization" title="Customization">
+<link rel="next" href="Connection-settings.html#Connection-settings" title="Connection settings">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Account-settings"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Connection-settings.html#Connection-settings">Connection settings</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Customization.html#Customization">Customization</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.1 Account settings</h3>
+
+<p><a name="index-jabber_002dusername-158"></a><a name="index-jabber_002dserver-159"></a><a name="index-jabber_002dpassword-160"></a><a name="index-jabber_002dresource-161"></a><a name="index-jabber_002ddefault_002dpriority-162"></a><a name="index-jabber_002dnickname-163"></a><a name="index-Username-164"></a><a name="index-Resource-165"></a>
+<code>jabber-username</code> is the username part of your JID.
+
+ <p><code>jabber-server</code> is the JID of your server, i.e. the hostname part
+of your JID. This is usually, but not necessarily, the same as the
+hostname of the server.
+
+ <p><code>jabber-password</code> is your password. You have the option to set
+it here, in which case it will be stored in cleartext in your
+<span class="file">.emacs</span> file. If this is set to <code>nil</code>, you will be prompted for
+your password every time you connect.
+
+ <p><code>jabber-resource</code> is the resource you want to log in under. This
+only matters if you are connected to the same account from different
+clients or different computers, since each connection must have a
+unique resource. You might want to set this to your hostname.
+
+ <p><code>jabber-default-priority</code> is the default priority sent with your
+presence. Regardless of what you have here, you can change your
+priority during a session with <code>jabber-send-presence</code>.
+See <a href="Presence.html#Presence">Presence</a>, for more information on priority.
+
+ <p><code>jabber-nickname</code> is your default nickname for groupchats.
+
+ </body></html>
+
diff --git a/html/Ad_002dHoc-Commands.html b/html/Ad_002dHoc-Commands.html
new file mode 100644
index 0000000..ce57985
--- /dev/null
+++ b/html/Ad_002dHoc-Commands.html
@@ -0,0 +1,77 @@
+<html lang="en">
+<head>
+<title>Ad-Hoc Commands - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Services.html#Services" title="Services">
+<link rel="prev" href="Searching.html#Searching" title="Searching">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Ad_002dHoc-Commands"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Searching.html#Searching">Searching</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Services.html#Services">Services</a>
+<hr><br>
+</div>
+
+<h3 class="section">6.4 Ad-Hoc Commands</h3>
+
+<p><a name="index-Ad_002dHoc-Commands-82"></a><a name="index-jabber_002dahc_002dget_002dlist-83"></a><a name="index-jabber_002dahc_002dexecute_002dcommand-84"></a>
+jabber.el supports a subset of XEP-0050, the standard for Ad-Hoc
+Commands. As the name implies, this can be used for just about
+anything. It has been used for remote-controlling clients (e.g. Psi),
+and administering services (e.g. PyMSNt).
+
+ <p>Currently, jabber.el uses ad-hoc commands for setting presence remotely.
+If you realize that you forgot to set your client to &ldquo;away&rdquo; with a low
+priority, you can do it remotely.<a rel="footnote" href="#fn-1" name="fnd-1"><sup>1</sup></a>
+
+ <p>The commands for executing ad-hoc commands are available under the
+Service menu, which is opened by typing <kbd>C-c C-s</kbd>.
+
+ <p>To find which commands are available, run &ldquo;Request command-list&rdquo;
+(<code>jabber-ahc-get-list</code>).<a rel="footnote" href="#fn-2" name="fnd-2"><sup>2</sup></a>
+
+ <p>To run a command from the list, put point over it and run &ldquo;Execute
+command&rdquo; (<code>jabber-ahc-execute-command</code>), accepting the defaults
+for JID and node. (If you already know those, you could of course
+enter them yourself) The form you get should hopefully be
+self-explanatory.
+
+ <div class="footnote">
+<hr>
+<h4>Footnotes</h4><p class="footnote"><small>[<a name="fn-1" href="#fnd-1">1</a>]</small> Most Jabber servers also
+support kicking a client off the net by logging in with another client
+with exactly the same resource.</p>
+
+ <p class="footnote"><small>[<a name="fn-2" href="#fnd-2">2</a>]</small> This is the same thing as a
+disco items request to the node
+<code>http://jabber.org/protocol/commands</code>.</p>
+
+ <p><hr></div>
+
+ </body></html>
+
diff --git a/html/Autoaway.html b/html/Autoaway.html
new file mode 100644
index 0000000..6916b6d
--- /dev/null
+++ b/html/Autoaway.html
@@ -0,0 +1,72 @@
+<html lang="en">
+<head>
+<title>Autoaway - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="prev" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="next" href="Modeline-status.html#Modeline-status" title="Modeline status">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Autoaway"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Modeline-status.html#Modeline-status">Modeline status</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Useful-features.html#Useful-features">Useful features</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Useful-features.html#Useful-features">Useful features</a>
+<hr><br>
+</div>
+
+<h3 class="section">10.1 Autoaway</h3>
+
+<p><a name="index-autoaway-100"></a><a name="index-idle-101"></a><a name="index-xprintidle-102"></a><a name="index-jabber_002dautoaway_002dmethod-103"></a>
+It is possible to automatically set your status to &ldquo;away&rdquo; when you
+haven't used your computer for a while. This lets your contacts know
+that you might not answer immediately.
+
+ <p>To activate this feature, add <code>jabber-autoaway-start</code> to
+<code>jabber-post-connect-hook</code>, e.g:
+<pre class="example"> (add-hook 'jabber-post-connect-hook 'jabber-autoaway-start)
+</pre>
+ <p>There are different methods to find how long you have been &ldquo;idle&rdquo;.
+The method to use is specified by <code>jabber-autoaway-method</code>. The
+value of this variable should be a function that returns the number of
+seconds you have been idle. Three functions are provided.
+
+ <p>If you are running Emacs 22 and thus have the <code>current-idle-time</code>
+function, it is used by default. Note that this method only measures
+the time since you last interacted with Emacs, and thus disregards
+activity in other programs.
+
+ <p>If you are using the X Window System, you can use the
+<a href="http://www.dtek.chalmers.se/~henoch/text/xprintidle.html">xprintidle</a> program. Make sure that <code>jabber-xprintidle-program</code> is
+set to the correct file name. This uses the same method as XScreensaver
+to find your idle time.
+
+ <p>If you are using Emacs on a GNU/Linux terminal, the function
+<code>jabber-termatime-get-idle-time</code> is used by default.
+
+ </body></html>
+
diff --git a/html/Automation.html b/html/Automation.html
new file mode 100644
index 0000000..dd117c2
--- /dev/null
+++ b/html/Automation.html
@@ -0,0 +1,56 @@
+<html lang="en">
+<head>
+<title>Automation - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Groupchat.html#Groupchat" title="Groupchat">
+<link rel="prev" href="Groupchat.html#Groupchat" title="Groupchat">
+<link rel="next" href="Invitations.html#Invitations" title="Invitations">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Automation"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Invitations.html#Invitations">Invitations</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Groupchat.html#Groupchat">Groupchat</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Groupchat.html#Groupchat">Groupchat</a>
+<hr><br>
+</div>
+
+<h3 class="section">3.1 Automation</h3>
+
+<p><a name="index-jabber_002dmuc_002ddefault_002dnicknames-38"></a><a name="index-jabber_002dmuc_002dautojoin-39"></a><a name="index-jabber_002dmuc_002dautojoin-40"></a><a name="index-Default-MUC-nickname-41"></a><a name="index-Autojoin-chat-rooms-42"></a>
+You can select a default nickname by setting <code>jabber-nickname</code>.
+Additionally, you can set different nicknames for different groups, by
+customizing <code>jabber-muc-default-nicknames</code>. There you specify
+the JID of the group, and your preferred nickname.
+
+ <p>If you want to automatically join certain rooms when connecting, you
+can set <code>jabber-muc-autojoin</code> to a list containing the JIDs of
+the rooms you want to enter. To disable this feature, remove
+<code>jabber-muc-autojoin</code> from <code>jabber-post-connect-hook</code>.
+
+ </body></html>
+
diff --git a/html/Avatars.html b/html/Avatars.html
new file mode 100644
index 0000000..64315bb
--- /dev/null
+++ b/html/Avatars.html
@@ -0,0 +1,61 @@
+<html lang="en">
+<head>
+<title>Avatars - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Personal-information.html#Personal-information" title="Personal information">
+<link rel="next" href="Time-queries.html#Time-queries" title="Time queries">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Avatars"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Time-queries.html#Time-queries">Time queries</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Personal-information.html#Personal-information">Personal information</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">8 Avatars</h2>
+
+<p><a name="index-avatars-89"></a><a name="index-jabber_002dvcard_002davatars_002dretrieve-90"></a><a name="index-jabber_002dvcard_002davatars_002dpublish-91"></a><a name="index-jabber_002davatar_002dcache_002ddirectory-92"></a>
+jabber.el supports viewing and publishing avatars according to XEP-0153,
+vCard-Based Avatars. By default, if you have an avatar in your vCard
+(see <a href="Personal-information.html#Personal-information">Personal information</a>), it will be published for others to see,
+and if other people publish their avatars, they will be displayed in the
+roster buffer and in the header line of chat buffers, assuming that your
+Emacs can display images.
+
+ <p>To disable retrieval of other people's avatars, set
+<code>jabber-vcard-avatars-retrieve</code> to nil. To disable publishing of
+your own avatar, set <code>jabber-vcard-avatars-publish</code> to nil.
+
+ <p>Avatars are cached in the directory specified by
+<code>jabber-avatar-cache-directory</code>, by default
+<span class="file">~/.jabber-avatars/</span>. The cache is never cleaned, so you might
+want to do that yourself from time to time.
+
+ </body></html>
+
diff --git a/html/Basic-operation.html b/html/Basic-operation.html
new file mode 100644
index 0000000..c6399dd
--- /dev/null
+++ b/html/Basic-operation.html
@@ -0,0 +1,61 @@
+<html lang="en">
+<head>
+<title>Basic operation - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Introduction.html#Introduction" title="Introduction">
+<link rel="next" href="Groupchat.html#Groupchat" title="Groupchat">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Basic-operation"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Groupchat.html#Groupchat">Groupchat</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Introduction.html#Introduction">Introduction</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">2 Basic operation</h2>
+
+<p>This chapter is intended as an introduction to basic usage of
+jabber.el. If you have used Jabber before and are familiar with the
+terminology, you might find it a bit too basic &mdash; in that case, just
+skim it, making sure to pick up the commands mentioned.
+
+ <p>There are a handful of global keybindings for common commands. They
+start with <kbd>C-x C-j</kbd>, and you can get a list of them by typing
+<kbd>C-x C-j C-h</kbd>.
+
+<ul class="menu">
+<li><a accesskey="1" href="Connecting.html#Connecting">Connecting</a>
+<li><a accesskey="2" href="Chatting.html#Chatting">Chatting</a>
+<li><a accesskey="3" href="Presence.html#Presence">Presence</a>
+<li><a accesskey="4" href="Presence-subscription.html#Presence-subscription">Presence subscription</a>
+<li><a accesskey="5" href="Roster-buffer.html#Roster-buffer">Roster buffer</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Chat-printers.html b/html/Chat-printers.html
new file mode 100644
index 0000000..8daeb27
--- /dev/null
+++ b/html/Chat-printers.html
@@ -0,0 +1,67 @@
+<html lang="en">
+<head>
+<title>Chat printers - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="prev" href="Extending-service-discovery.html#Extending-service-discovery" title="Extending service discovery">
+<link rel="next" href="Stanza-chains.html#Stanza-chains" title="Stanza chains">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Chat-printers"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Stanza-chains.html#Stanza-chains">Stanza chains</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Extending-service-discovery.html#Extending-service-discovery">Extending service discovery</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<hr><br>
+</div>
+
+<h3 class="section">16.6 Chat printers</h3>
+
+<p><a name="index-jabber_002dchat_002dprinters-244"></a><a name="index-jabber_002dmuc_002dprinters-245"></a><a name="index-jabber_002dbody_002dprinters-246"></a><a name="index-Chat-printers-247"></a><a name="index-Body-printers-248"></a>
+Chat printers are functions that print a certain aspect of an incoming
+message in a chat buffer. Included are functions for printing subjects
+(<code>jabber-chat-print-subject</code>), bodies
+(<code>jabber-chat-print-body</code>, and <code>jabber:x:oob</code>-style URLs
+(<code>jabber-chat-print-url</code>). The functions in
+<code>jabber-chat-printers</code> are called in order, with the entire
+<code>&lt;message/&gt;</code> stanza as argument, and are expected to call
+<code>insert</code> if they have anything to add.
+
+ <p>For MUC, the functions in <code>jabber-muc-printers</code> are prepended to
+those in <code>jabber-chat-printers</code>.
+
+ <p>Body printers are a subgroup of chat printers. They are exclusive; only
+one of them applies to any given message. The idea is that
+&ldquo;higher-quality&rdquo; parts of the message override pieces included for
+backwards compatibility. Included are <code>jabber-muc-print-invite</code>
+and <code>jabber-chat-normal-body</code>; functions for XHTML-IM and PGP
+encrypted messages may be written in the future. The functions in
+<code>jabber-body-printers</code> are called in order until one of them
+returns non-nil.
+
+ </body></html>
+
diff --git a/html/Chatting.html b/html/Chatting.html
new file mode 100644
index 0000000..4bd3196
--- /dev/null
+++ b/html/Chatting.html
@@ -0,0 +1,66 @@
+<html lang="en">
+<head>
+<title>Chatting - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link rel="prev" href="Connecting.html#Connecting" title="Connecting">
+<link rel="next" href="Presence.html#Presence" title="Presence">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Chatting"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Presence.html#Presence">Presence</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Connecting.html#Connecting">Connecting</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Basic-operation.html#Basic-operation">Basic operation</a>
+<hr><br>
+</div>
+
+<h3 class="section">2.2 Chatting</h3>
+
+<p><a name="index-Chatting-5"></a><a name="index-jabber_002dchat_002dwith-6"></a>
+There are several ways to open a chat buffer. The shortest way is to
+put point over the person you want to chat with in the roster display
+and hit RET.
+
+ <p>You can also use menus to access commands. In the roster display, you
+can access several menus through keystrokes or mouse clicks. You can
+bring one big menu up by pressing the second mouse button, or you can
+bring up the &ldquo;chat menu&rdquo; by typing <kbd>C-c C-c</kbd>. If you do the
+latter while point is on a roster entry, that entry will be the
+default value when you are asked for whom to chat with.
+
+ <p>You can also use the function <code>jabber-chat-with</code>, which is what the
+menu item is bound to. This function is bound to <kbd>C-x C-j C-j</kbd> in
+the global keymap.
+
+ <p>Now, try opening a chat with someone. A buffer named
+<code>*-jabber-chat-:-</code><var>person</var><code>-*</code> will be created and selected.
+Type your message at the end of the buffer, and hit <kbd>RET</kbd> to send
+it. To include a newline in your message, use <kbd>C-j</kbd>.
+
+ </body></html>
+
diff --git a/html/Composing-messages.html b/html/Composing-messages.html
new file mode 100644
index 0000000..af2a0ff
--- /dev/null
+++ b/html/Composing-messages.html
@@ -0,0 +1,55 @@
+<html lang="en">
+<head>
+<title>Composing messages - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Groupchat.html#Groupchat" title="Groupchat">
+<link rel="next" href="File-transfer.html#File-transfer" title="File transfer">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Composing-messages"></a>Next:&nbsp;<a rel="next" accesskey="n" href="File-transfer.html#File-transfer">File transfer</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Groupchat.html#Groupchat">Groupchat</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">4 Composing messages</h2>
+
+<p><a name="index-jabber_002dcompose-55"></a><a name="index-composing-messages-56"></a><a name="index-message-composition-57"></a>
+The chat buffer interface can be inconvenient for some purposes. As you
+can't use <kbd>RET</kbd> to insert a newline (use <kbd>C-j</kbd> for that),
+writing a longer message can be painful. Also, it is not possible to
+include a subject in the message, or send the message to multiple
+recipients.
+
+ <p>These features are implemented by the message composing tool. Type
+<kbd>M-x jabber-compose</kbd> to start it. In the buffer that comes up, you
+can specify recipients, enter a subject, and type your message.
+
+ </body></html>
+
diff --git a/html/Concept-index.html b/html/Concept-index.html
new file mode 100644
index 0000000..82444b1
--- /dev/null
+++ b/html/Concept-index.html
@@ -0,0 +1,153 @@
+<html lang="en">
+<head>
+<title>Concept index - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="next" href="Function-index.html#Function-index" title="Function index">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Concept-index"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Function-index.html#Function-index">Function index</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Protocol-support.html#Protocol-support">Protocol support</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="unnumbered">Concept index</h2>
+
+<ul class="index-cp" compact>
+<li><a href="Registering.html#index-Account-removal-77">Account removal</a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Tracking-activity.html#index-Activity-114">Activity</a>: <a href="Tracking-activity.html#Tracking-activity">Tracking activity</a></li>
+<li><a href="Ad_002dHoc-Commands.html#index-Ad_002dHoc-Commands-82">Ad-Hoc Commands</a>: <a href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands">Ad-Hoc Commands</a></li>
+<li><a href="MUC-Administration.html#index-Affiliations_002c-MUC-53">Affiliations, MUC</a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="Customizing-alerts.html#index-Alert-hooks-207">Alert hooks</a>: <a href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a></li>
+<li><a href="Standard-alerts.html#index-Alerts-209">Alerts</a>: <a href="Standard-alerts.html#Standard-alerts">Standard alerts</a></li>
+<li><a href="Autoaway.html#index-autoaway-100">autoaway</a>: <a href="Autoaway.html#Autoaway">Autoaway</a></li>
+<li><a href="Automation.html#index-Autojoin-chat-rooms-42">Autojoin chat rooms</a>: <a href="Automation.html#Automation">Automation</a></li>
+<li><a href="Avatars.html#index-avatars-89">avatars</a>: <a href="Avatars.html#Avatars">Avatars</a></li>
+<li><a href="Message-history.html#index-Backlog-127">Backlog</a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="MUC-Administration.html#index-Banning_002c-MUC-54">Banning, MUC</a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="Chat-printers.html#index-Body-printers-248">Body printers</a>: <a href="Chat-printers.html#Chat-printers">Chat printers</a></li>
+<li><a href="Services.html#index-Browse-buffers-66">Browse buffers</a>: <a href="Services.html#Services">Services</a></li>
+<li><a href="XMPP-URIs.html#index-browser-integration-154">browser integration</a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="Service-discovery-and-browsing.html#index-Browsing-68">Browsing</a>: <a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a></li>
+<li><a href="Registering.html#index-Cancelling-registration-73">Cancelling registration</a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Groupchat.html#index-Changing-nickname-29">Changing nickname</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Registering.html#index-Changing-password-74">Changing password</a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-Chat-buffer-189">Chat buffer</a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Chat-printers.html#index-Chat-printers-247">Chat printers</a>: <a href="Chat-printers.html#Chat-printers">Chat printers</a></li>
+<li><a href="Groupchat.html#index-Chatrooms-26">Chatrooms</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Chatting.html#index-Chatting-5">Chatting</a>: <a href="Chatting.html#Chatting">Chatting</a></li>
+<li><a href="Message-events.html#index-Composing-137">Composing</a>: <a href="Message-events.html#Message-events">Message events</a></li>
+<li><a href="Composing-messages.html#index-composing-messages-56">composing messages</a>: <a href="Composing-messages.html#Composing-messages">Composing messages</a></li>
+<li><a href="Connecting.html#index-Connecting-3">Connecting</a>: <a href="Connecting.html#Connecting">Connecting</a></li>
+<li><a href="Connection-settings.html#index-Connection-settings-170">Connection settings</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Customization.html#index-Customization-157">Customization</a>: <a href="Customization.html#Customization">Customization</a></li>
+<li><a href="Automation.html#index-Default-MUC-nickname-41">Default MUC nickname</a>: <a href="Automation.html#Automation">Automation</a></li>
+<li><a href="Message-events.html#index-Delivered-138">Delivered</a>: <a href="Message-events.html#Message-events">Message events</a></li>
+<li><a href="Keepalive.html#index-Detecting-lost-connections-109">Detecting lost connections</a>: <a href="Keepalive.html#Keepalive">Keepalive</a></li>
+<li><a href="Presence.html#index-directed-presence-14">directed presence</a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Message-events.html#index-Displayed-139">Displayed</a>: <a href="Message-events.html#Message-events">Message events</a></li>
+<li><a href="Roster-import-and-export.html#index-Export-roster-146">Export roster</a>: <a href="Roster-import-and-export.html#Roster-import-and-export">Roster import and export</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-Faces_002c-chat-buffer-191">Faces, chat buffer</a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="File-transfer.html#index-File-transfer-58">File transfer</a>: <a href="File-transfer.html#File-transfer">File transfer</a></li>
+<li><a href="Sending-files.html#index-file-transfer-proxy-61">file transfer proxy</a>: <a href="Sending-files.html#Sending-files">Sending files</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-Filling-long-lines-in-chat-buffer-206">Filling long lines in chat buffer</a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Spell-checking.html#index-flyspell-124">flyspell</a>: <a href="Spell-checking.html#Spell-checking">Spell checking</a></li>
+<li><a href="Registering.html#index-Gateway-registration-75">Gateway registration</a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Connection-settings.html#index-GnuTLS-176">GnuTLS</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Groupchat.html#index-Groupchat-24">Groupchat</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Message-history.html#index-History-126">History</a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Autoaway.html#index-idle-101">idle</a>: <a href="Autoaway.html#Autoaway">Autoaway</a></li>
+<li><a href="Time-queries.html#index-idle-time_002c-query-98">idle time, query</a>: <a href="Time-queries.html#Time-queries">Time queries</a></li>
+<li><a href="Roster-import-and-export.html#index-Import-roster-147">Import roster</a>: <a href="Roster-import-and-export.html#Roster-import-and-export">Roster import and export</a></li>
+<li><a href="Invitations.html#index-Invitations-43">Invitations</a>: <a href="Invitations.html#Invitations">Invitations</a></li>
+<li><a href="Groupchat.html#index-Joining-a-groupchat-28">Joining a groupchat</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Keepalive.html#index-Keepalive-108">Keepalive</a>: <a href="Keepalive.html#Keepalive">Keepalive</a></li>
+<li><a href="Roster-buffer.html#index-Key-bindings-22">Key bindings</a>: <a href="Roster-buffer.html#Roster-buffer">Roster buffer</a></li>
+<li><a href="MUC-Administration.html#index-Kicking_002c-MUC-48">Kicking, MUC</a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="Time-queries.html#index-last-online-95">last online</a>: <a href="Time-queries.html#Time-queries">Time queries</a></li>
+<li><a href="XMPP-URIs.html#index-links-150">links</a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="Roster-buffer.html#index-Menus-21">Menus</a>: <a href="Roster-buffer.html#Roster-buffer">Roster buffer</a></li>
+<li><a href="Miscellaneous-settings.html#index-Menus-179">Menus</a>: <a href="Miscellaneous-settings.html#Miscellaneous-settings">Miscellaneous settings</a></li>
+<li><a href="Composing-messages.html#index-message-composition-57">message composition</a>: <a href="Composing-messages.html#Composing-messages">Composing messages</a></li>
+<li><a href="Modeline-status.html#index-Modeline-104">Modeline</a>: <a href="Modeline-status.html#Modeline-status">Modeline status</a></li>
+<li><a href="MUC-Administration.html#index-Moderator_002c-MUC-50">Moderator, MUC</a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="XMPP-URIs.html#index-Mozilla-integration-152">Mozilla integration</a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="Groupchat.html#index-MUC-25">MUC</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Connection-settings.html#index-Network-settings-171">Network settings</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Groupchat.html#index-Nickname_002c-changing-30">Nickname, changing</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Watch-buddies.html#index-Online-notifications-121">Online notifications</a>: <a href="Watch-buddies.html#Watch-buddies">Watch buddies</a></li>
+<li><a href="Connection-settings.html#index-OpenSSL-177">OpenSSL</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Registering.html#index-Password-change-76">Password change</a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Personal-information.html#index-Personal-information-86">Personal information</a>: <a href="Personal-information.html#Personal-information">Personal information</a></li>
+<li><a href="Presence.html#index-Presence-7">Presence</a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Presence-subscription.html#index-Presence-subscription-17">Presence subscription</a>: <a href="Presence-subscription.html#Presence-subscription">Presence subscription</a></li>
+<li><a href="Private-messages.html#index-Private-MUC-messages-45">Private MUC messages</a>: <a href="Private-messages.html#Private-messages">Private messages</a></li>
+<li><a href="Sending-files.html#index-proxy_002c-file-transfer-60">proxy, file transfer</a>: <a href="Sending-files.html#Sending-files">Sending files</a></li>
+<li><a href="Groupchat.html#index-query-groupchat-31">query groupchat</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Connecting.html#index-Registering-an-account-4">Registering an account</a>: <a href="Connecting.html#Connecting">Connecting</a></li>
+<li><a href="Registering.html#index-Registration-72">Registration</a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Registering.html#index-Removing-an-account-78">Removing an account</a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Account-settings.html#index-Resource-165">Resource</a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="MUC-Administration.html#index-Roles_002c-MUC-51">Roles, MUC</a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="Roster-buffer.html#index-Roster-buffer_002c-basics-20">Roster buffer, basics</a>: <a href="Roster-buffer.html#Roster-buffer">Roster buffer</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-Roster-buffer_002c-customizing-187">Roster buffer, customizing</a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Message-history.html#index-Rotation-128">Rotation</a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Standard-alerts.html#index-Scroll-210">Scroll</a>: <a href="Standard-alerts.html#Standard-alerts">Standard alerts</a></li>
+<li><a href="Searching.html#index-Searching-80">Searching</a>: <a href="Searching.html#Searching">Searching</a></li>
+<li><a href="Presence.html#index-send-directed-presence-15">send directed presence</a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="File-transfer.html#index-Sending-files-59">Sending files</a>: <a href="File-transfer.html#File-transfer">File transfer</a></li>
+<li><a href="Presence.html#index-Sending-presence-8">Sending presence</a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Service-discovery-and-browsing.html#index-Service-discovery-67">Service discovery</a>: <a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-Sorting-the-roster-188">Sorting the roster</a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Spell-checking.html#index-Spell-checking-125">Spell checking</a>: <a href="Spell-checking.html#Spell-checking">Spell checking</a></li>
+<li><a href="Connection-settings.html#index-SRV-records-175">SRV records</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Connection-settings.html#index-SSL-172">SSL</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Connection-settings.html#index-STARTTLS-174">STARTTLS</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Presence-subscription.html#index-Subscribing-to-someone_0027s-presence-18">Subscribing to someone's presence</a>: <a href="Presence-subscription.html#Presence-subscription">Presence subscription</a></li>
+<li><a href="Protocol-support.html#index-Supported-protocols-252">Supported protocols</a>: <a href="Protocol-support.html#Protocol-support">Protocol support</a></li>
+<li><a href="Time-queries.html#index-time-query-93">time query</a>: <a href="Time-queries.html#Time-queries">Time queries</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-Timestamps-190">Timestamps</a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Connection-settings.html#index-TLS-173">TLS</a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Groupchat.html#index-Topic_002c-MUC-33">Topic, MUC</a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Time-queries.html#index-uptime_002c-query-97">uptime, query</a>: <a href="Time-queries.html#Time-queries">Time queries</a></li>
+<li><a href="XMPP-URIs.html#index-URIs-148">URIs</a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="XMPP-URIs.html#index-URLs-149">URLs</a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="Account-settings.html#index-Username-164">Username</a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="Personal-information.html#index-vCard-85">vCard</a>: <a href="Personal-information.html#Personal-information">Personal information</a></li>
+<li><a href="MUC-Administration.html#index-Voice_002c-MUC-49">Voice, MUC</a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="Watch-buddies.html#index-Watch-120">Watch</a>: <a href="Watch-buddies.html#Watch-buddies">Watch buddies</a></li>
+<li><a href="XMPP-URIs.html#index-web-browser-integration-153">web browser integration</a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="Sending-files.html#index-XEP_002d0065-proxy-62">XEP-0065 proxy</a>: <a href="Sending-files.html#Sending-files">Sending files</a></li>
+<li><a href="Debug-options.html#index-XML-log-227">XML log</a>: <a href="Debug-options.html#Debug-options">Debug options</a></li>
+<li><a href="XML-representation.html#index-XML-representation-228">XML representation</a>: <a href="XML-representation.html#XML-representation">XML representation</a></li>
+<li><a href="XMPP-URIs.html#index-xmpp_003a-links-151">xmpp: links</a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="Autoaway.html#index-xprintidle-102">xprintidle</a>: <a href="Autoaway.html#Autoaway">Autoaway</a></li>
+ </ul></body></html>
+
diff --git a/html/Connecting.html b/html/Connecting.html
new file mode 100644
index 0000000..3c2c53e
--- /dev/null
+++ b/html/Connecting.html
@@ -0,0 +1,81 @@
+<html lang="en">
+<head>
+<title>Connecting - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link rel="prev" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link rel="next" href="Chatting.html#Chatting" title="Chatting">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Connecting"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Chatting.html#Chatting">Chatting</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Basic-operation.html#Basic-operation">Basic operation</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Basic-operation.html#Basic-operation">Basic operation</a>
+<hr><br>
+</div>
+
+<h3 class="section">2.1 Connecting</h3>
+
+<p><a name="index-jabber_002dconnect-1"></a><a name="index-jabber_002ddisconnect-2"></a>
+<a name="index-Connecting-3"></a><a name="index-Registering-an-account-4"></a>
+I'll assume that you have already successfully installed jabber.el; if
+not, consult the <span class="file">README</span> file. Also, make sure you have
+<code>(require 'jabber)</code> in your <span class="file">.emacs</span>.
+
+ <p>Now, type <kbd>M-x jabber-customize</kbd>. This brings up a customize
+buffer for jabber.el. The most important variables to customize are
+<code>jabber-username</code> and
+<code>jabber-server</code>.<a rel="footnote" href="#fn-1" name="fnd-1"><sup>1</sup></a> Save your changes, and type
+<kbd>M-x jabber-connect</kbd> to connect.
+
+ <p>If you do not yet have a Jabber account, you can register one. Enter
+your desired username for <code>jabber-username</code> and the server you wish
+to use for <code>jabber-server</code>, save, and type <kbd>C-u M-x
+jabber-connect</kbd> or <kbd>C-u C-x C-j C-c</kbd>. If the server supports
+in-band registration, you will be presented with a registration form to
+fill out and send. There the username you chose will be prefilled.
+Don't change it, otherwise jabber.el will be confused.
+
+ <p>If you successfully connect, jabber.el will download your roster and
+display it in a buffer called <code>*-jabber-*</code>.
+
+ <p>By default, you will appear as &ldquo;online&rdquo; to your contacts. To change
+this to e.g. &ldquo;away&rdquo;, type <kbd>M-x jabber-send-presence</kbd> or <kbd>C-x
+C-j C-p</kbd>. See <a href="Presence.html#Presence">Presence</a>, for more information.
+
+ <p>To disconnect, type <kbd>M-x jabber-disconnect</kbd> or <kbd>C-x C-j C-d</kbd>.
+
+ <div class="footnote">
+<hr>
+<h4>Footnotes</h4><p class="footnote"><small>[<a name="fn-1" href="#fnd-1">1</a>]</small> See <a href="Connection-settings.html#Connection-settings">Connection settings</a>, for other
+things you might have to change.</p>
+
+ <p><hr></div>
+
+ </body></html>
+
diff --git a/html/Connection-settings.html b/html/Connection-settings.html
new file mode 100644
index 0000000..c4297f9
--- /dev/null
+++ b/html/Connection-settings.html
@@ -0,0 +1,74 @@
+<html lang="en">
+<head>
+<title>Connection settings - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Account-settings.html#Account-settings" title="Account settings">
+<link rel="next" href="Miscellaneous-settings.html#Miscellaneous-settings" title="Miscellaneous settings">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Connection-settings"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Miscellaneous-settings.html#Miscellaneous-settings">Miscellaneous settings</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Account-settings.html#Account-settings">Account settings</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.2 Connection settings</h3>
+
+<p><a name="index-jabber_002dnetwork_002dserver-166"></a><a name="index-jabber_002dport-167"></a><a name="index-jabber_002dconnection_002dtype-168"></a><a name="index-jabber_002dconnection_002dssl_002dprogram-169"></a><a name="index-Connection-settings-170"></a><a name="index-Network-settings-171"></a><a name="index-SSL-172"></a><a name="index-TLS-173"></a><a name="index-STARTTLS-174"></a><a name="index-SRV-records-175"></a>
+<code>jabber-network-server</code> is the hostname or IP address of your
+server. If it is set to <code>nil</code>, jabber.el will use the name in
+<code>jabber-server</code>.
+
+ <p><code>jabber-port</code> is the TCP port of the server to connect to. If
+<code>nil</code>, the default port is selected based on the chosen
+connection method.
+
+ <p>If both <code>jabber-network-server</code> and <code>jabber-port</code> are nil, and
+a sufficiently modern <code>dns.el</code> is available, jabber.el will use SRV
+records to find the right hostname and port.
+
+ <p><code>jabber-connection-type</code> specifies what kind of connection to
+use. <code>network</code> means normal unencrypted network connection
+(usually on port 5222), and <code>ssl</code> means encrypted connection
+through GnuTLS or OpenSSL (port 5223), while <code>starttls</code> will
+initiate an unencrypted connection and switch to encrypted if offered
+by the server. You can change the settings of the encryption program
+through <kbd>M-x customize-group RET tls</kbd>, <kbd>M-x customize-group RET starttls</kbd>
+or <kbd>M-x customize-group RET ssl</kbd>, respectively.
+
+ <p><a name="index-GnuTLS-176"></a><a name="index-OpenSSL-177"></a>By default, GnuTLS will be used if the <code>tls</code> library is available,
+and if that fails, OpenSSL will be used if the <code>ssl</code> library is
+available. You can force the use of either program by setting
+<code>jabber-connection-ssl-program</code> to <code>gnutls</code> or <code>openssl</code>,
+respectively. If you use <code>starttls</code> the library with the same name is
+required, and it depends on the GnuTLS command line client.
+
+ </body></html>
+
diff --git a/html/Contact.html b/html/Contact.html
new file mode 100644
index 0000000..71b9687
--- /dev/null
+++ b/html/Contact.html
@@ -0,0 +1,50 @@
+<html lang="en">
+<head>
+<title>Contact - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Introduction.html#Introduction" title="Introduction">
+<link rel="prev" href="Introduction.html#Introduction" title="Introduction">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Contact"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Introduction.html#Introduction">Introduction</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Introduction.html#Introduction">Introduction</a>
+<hr><br>
+</div>
+
+<h3 class="section">1.1 Contact</h3>
+
+<p>jabber.el is developed by Tom Berger (e-mail
+<a href="mailto:object@intellectronica.net">object@intellectronica.net</a>, JID <code>object@jabber.org.uk</code>) and
+Magnus Henoch (e-mail <a href="mailto:mange@freemail.hu">mange@freemail.hu</a>, JID
+<code>legoscia@jabber.cd.chalmers.se</code>). There is a web page at
+<a href="http://intellectronica.net/emacs-jabber/">http://intellectronica.net/emacs-jabber/</a>, and a Sourceforge
+project page at <a href="http://sourceforge.net/projects/emacs-jabber">http://sourceforge.net/projects/emacs-jabber</a>.
+
+ </body></html>
+
diff --git a/html/Customization.html b/html/Customization.html
new file mode 100644
index 0000000..28d41ee
--- /dev/null
+++ b/html/Customization.html
@@ -0,0 +1,60 @@
+<html lang="en">
+<head>
+<title>Customization - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="XMPP-URIs.html#XMPP-URIs" title="XMPP URIs">
+<link rel="next" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Customization"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">15 Customization</h2>
+
+<p><a name="index-jabber_002dcustomize-156"></a><a name="index-Customization-157"></a>
+jabber.el is intended to be customizable for many tastes. After all,
+this is Emacs. To open a customization buffer for jabber.el, type
+<kbd>M-x jabber-customize</kbd>.
+
+<ul class="menu">
+<li><a accesskey="1" href="Account-settings.html#Account-settings">Account settings</a>
+<li><a accesskey="2" href="Connection-settings.html#Connection-settings">Connection settings</a>
+<li><a accesskey="3" href="Miscellaneous-settings.html#Miscellaneous-settings">Miscellaneous settings</a>
+<li><a accesskey="4" href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a>
+<li><a accesskey="5" href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a>
+<li><a accesskey="6" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>
+<li><a accesskey="7" href="Hooks.html#Hooks">Hooks</a>
+<li><a accesskey="8" href="Debug-options.html#Debug-options">Debug options</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Customizing-alerts.html b/html/Customizing-alerts.html
new file mode 100644
index 0000000..4b59695
--- /dev/null
+++ b/html/Customizing-alerts.html
@@ -0,0 +1,96 @@
+<html lang="en">
+<head>
+<title>Customizing alerts - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer" title="Customizing the chat buffer">
+<link rel="next" href="Hooks.html#Hooks" title="Hooks">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Customizing-alerts"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Hooks.html#Hooks">Hooks</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.6 Customizing alerts</h3>
+
+<p><a name="index-Alert-hooks-207"></a><a name="index-define_002djabber_002dalert-208"></a>
+When an event happens (currently including presence changes, incoming
+messages, and completed queries) you will usually want to be
+notified. Since tastes in this area vary wildly, these alerts are
+implemented as hooks, so you can choose which ones you want, or write
+your own if none fit.
+
+ <p>Actually, if you don't want to write your own, stop reading this
+section and just read <a href="Standard-alerts.html#Standard-alerts">Standard alerts</a>.
+
+ <p>Many kinds of alerts consist in displaying a text message through a
+certain mechanism. This text message is provided by a function which
+you can rewrite or replace. If this function returns <code>nil</code>, no
+message is displayed, and non-textual alerts refrain from action.
+
+ <p>If you want to write alert hooks that do nothing except displaying the
+supplied message in some way, use the macro
+<code>define-jabber-alert</code>. For example, if <var>foo</var> is a function
+that takes a string as an argument, write
+<pre class="example"> (define-jabber-alert foo
+ "Display a message in a fooish way"
+ 'foo)
+</pre>
+ <p>and all details will be taken care of for you.
+
+ <p>The hooks take different arguments depending on category. However,
+they all have in common that the last argument is the result of the
+message function. The message function for each category takes the
+same arguments as the corresponding hooks, except for that last
+argument.
+
+ <p>Alert hook contributions are very welcome. You can send them to the
+mailing list, or to the Sourceforge patch tracker.
+
+ <p>Alert hooks are meant for optional UI things, that are subject to
+varying user tastes, and that can be toggled by simply adding or
+removing the function to and from the hook. For other things, there
+are corresponding general hooks, that are defvars instead of
+defcustoms, and that are to be managed by Lisp code. They have the
+same name as the alert hooks minus the <code>-alert</code> part,
+i.e. <code>jabber-message-hooks</code> vs <code>jabber-alert-message-hooks</code>,
+etc.
+
+<ul class="menu">
+<li><a accesskey="1" href="Standard-alerts.html#Standard-alerts">Standard alerts</a>
+<li><a accesskey="2" href="Presence-alerts.html#Presence-alerts">Presence alerts</a>
+<li><a accesskey="3" href="Message-alerts.html#Message-alerts">Message alerts</a>
+<li><a accesskey="4" href="MUC-alerts.html#MUC-alerts">MUC alerts</a>
+<li><a accesskey="5" href="Info-alerts.html#Info-alerts">Info alerts</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Customizing-the-chat-buffer.html b/html/Customizing-the-chat-buffer.html
new file mode 100644
index 0000000..8803400
--- /dev/null
+++ b/html/Customizing-the-chat-buffer.html
@@ -0,0 +1,96 @@
+<html lang="en">
+<head>
+<title>Customizing the chat buffer - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer" title="Customizing the roster buffer">
+<link rel="next" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Customizing-the-chat-buffer"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.5 Customizing the chat buffer</h3>
+
+<p><a name="index-Chat-buffer-189"></a><a name="index-Timestamps-190"></a><a name="index-Faces_002c-chat-buffer-191"></a>
+You can customize the look of the prompts in the chat buffer. There
+are separate settings for local (i.e. your own messages) and foreign
+prompts.
+
+ <p><a name="index-jabber_002dchat_002dtext_002dlocal-192"></a><a name="index-jabber_002dchat_002dtext_002dforeign-193"></a><code>jabber-chat-text-local</code> and <code>jabber-chat-text-foreign</code>
+determine the faces used for chat messages.
+
+ <p><a name="index-jabber_002dchat_002dprompt_002dlocal-194"></a><a name="index-jabber_002dchat_002dprompt_002dforeign-195"></a><code>jabber-chat-prompt-local</code> and <code>jabber-chat-prompt-foreign</code>
+determine the faces used for the prompts.
+
+ <p><a name="index-jabber_002dchat_002dlocal_002dprompt_002dformat-196"></a><a name="index-jabber_002dchat_002dforeign_002dprompt_002dformat-197"></a><code>jabber-chat-local-prompt-format</code> and
+<code>jabber-chat-foreign-prompt-format</code> determine what text is
+displayed in the prompts. They are format strings, with the following
+special sequences defined:
+
+ <dl>
+<dt><code>%t</code><dd>The time when the message was sent or received
+<br><dt><code>%n</code><dd>The nickname of the user. For the foreign prompt, this is the name of
+the contact in the roster, or the JID if no name set. For the local
+prompt, this is the username part of your JID.
+<br><dt><code>%u</code><dd>The username of the user.
+<br><dt><code>%r</code><dd>The resource.
+<br><dt><code>%j</code><dd>The bare JID of the user
+</dl>
+
+ <p><a name="index-jabber_002dchat_002dtime_002dformat-198"></a><code>jabber-chat-time-format</code> defines how <code>%t</code> shows time. Its
+format is identical to that passed to <code>format-time-string</code>.
+See <a href="../elisp/Time-Conversion.html#Time-Conversion">Time Conversion (GNU Emacs Lisp Reference Manual)</a>.
+
+ <p><a name="index-jabber_002dchat_002ddelayed_002dtime_002dformat-199"></a><code>jabber-chat-delayed-time-format</code> is used instead of
+<code>jabber-chat-time-format</code> for delayed messages (messages sent while
+you were offline, or fetched from history). This way you can have short
+timestamps everywhere except where you need long ones. You can always
+see the complete timestamp in a tooltip by hovering over the prompt with
+the mouse.
+
+ <p><a name="index-jabber_002dprint_002drare_002dtime-200"></a><a name="index-jabber_002drare_002dtime_002dformat-201"></a><a name="index-jabber_002dchat_002dtext_002dlocalBy-default_002c-timestamps-are-printed-in-the-chat-buffer-every-hour-_0028at-202"></a>&ldquo;rare&rdquo; times). This can be toggled with
+<code>jabber-print-rare-time</code>. You can customize the displayed time by
+setting <code>jabber-rare-time-format</code>. Rare timestamps will be printed
+whenever time formatted by that format string would change.
+
+ <p><a name="index-jabber_002dchat_002dheader_002dline_002dformat-203"></a><a name="index-jabber_002dmuc_002dheader_002dline_002dformat-204"></a>You can also customize the header line of chat buffers, by modifying
+the variable <code>jabber-chat-header-line-format</code>. The format of
+that variable is the same as that of <code>mode-line-format</code> and
+<code>header-line-format</code>. See <a href="../elisp/Mode-Line-Format.html#Mode-Line-Format">Mode-Line Format (GNU Emacs Lisp Reference Manual)</a>. For MUC buffers,
+<code>jabber-muc-header-line-format</code> is used instead.
+
+ <p><a name="index-jabber_002dchat_002dfill_002dlong_002dlines-205"></a><a name="index-Filling-long-lines-in-chat-buffer-206"></a>The variable <code>jabber-chat-fill-long-lines</code> controls whether long
+lines in the chat buffer are filled.
+
+ </body></html>
+
diff --git a/html/Customizing-the-roster-buffer.html b/html/Customizing-the-roster-buffer.html
new file mode 100644
index 0000000..e61e38a
--- /dev/null
+++ b/html/Customizing-the-roster-buffer.html
@@ -0,0 +1,89 @@
+<html lang="en">
+<head>
+<title>Customizing the roster buffer - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Miscellaneous-settings.html#Miscellaneous-settings" title="Miscellaneous settings">
+<link rel="next" href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer" title="Customizing the chat buffer">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Customizing-the-roster-buffer"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Miscellaneous-settings.html#Miscellaneous-settings">Miscellaneous settings</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.4 Customizing the roster buffer</h3>
+
+<p><a name="index-jabber_002droster_002dsort_002dfunctions-180"></a><a name="index-jabber_002dsort_002dorder-181"></a><a name="index-jabber_002dshow_002dresources-182"></a><a name="index-jabber_002droster_002dline_002dformat-183"></a><a name="index-jabber_002dresource_002dline_002dformat-184"></a><a name="index-jabber_002droster_002dbuffer-185"></a><a name="index-jabber_002droster_002dshow_002dbindings-186"></a><a name="index-Roster-buffer_002c-customizing-187"></a>
+<a name="index-Sorting-the-roster-188"></a><code>jabber-roster-sort-functions</code> controls how roster items are
+sorted. By default, contacts are sorted first by presence, and then
+alphabetically by displayed name.
+
+ <p><code>jabber-sort-order</code> controls how roster items are sorted by
+presence. It is a list containing strings corresponding to show
+status (see <a href="Presence.html#Presence">Presence</a>) or <code>nil</code>, which represents offline.
+
+ <p><code>jabber-show-resources</code> controls when your contacts' resources
+are shown in the roster buffer. The default is to show resources when
+a contact has more than one connected resource.
+
+ <p><code>jabber-roster-line-format</code> specifies how the entry for each
+contact looks. It is a string where some characters are special if
+preceded by a percent sign:
+
+ <dl>
+<dt><code>%a</code><dd>Avatar of contact, if any
+<br><dt><code>%c</code><dd>"*" if the contact is connected, or " " if not
+<br><dt><code>%u</code><dd>Subscription state - see below
+<br><dt><code>%n</code><dd>Nickname of contact, or JID if no nickname
+<br><dt><code>%j</code><dd>Bare JID of contact (without resource)
+<br><dt><code>%r</code><dd>Highest-priority resource of contact
+<br><dt><code>%s</code><dd>Availability of contact as string ("Online", "Away" etc)
+<br><dt><code>%S</code><dd>Status string specified by contact
+</dl>
+
+ <p><code>jabber-resource-line-format</code> is nearly identical, except that
+the values correspond to the values of the resource in question, and
+that the <code>%p</code> escape is available, which inserts the priority of
+the resource.
+
+ <p><code>jabber-roster-buffer</code> specifies the name of the roster buffer.
+If you change this, the new name will be used the next time you
+connect.
+
+ <p><code>jabber-roster-show-bindings</code> controls whether to show a list of
+keybindings at the top of the roster buffer. You need to run <kbd>M-x
+jabber-display-roster</kbd> after changing this variable to update the display.
+
+ <p><code>%u</code> is replaced by one of the strings given by
+`jabber-roster-subscription-display'.
+
+ </body></html>
+
diff --git a/html/Debug-options.html b/html/Debug-options.html
new file mode 100644
index 0000000..a2d4af6
--- /dev/null
+++ b/html/Debug-options.html
@@ -0,0 +1,51 @@
+<html lang="en">
+<head>
+<title>Debug options - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Hooks.html#Hooks" title="Hooks">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Debug-options"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Hooks.html#Hooks">Hooks</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.8 Debug options</h3>
+
+<p><a name="index-jabber_002ddebug_002dlog_002dxml-226"></a><a name="index-XML-log-227"></a>
+These settings provide a lot of information which is usually not very
+interesting, but can be useful for debugging various things.
+
+ <p><code>jabber-debug-log-xml</code> activates XML logging. All XML stanzas
+sent and received are logged in the buffer <code>*-jabber-xml-log-*</code>
+in list format. See <a href="XML-representation.html#XML-representation">XML representation</a>.
+
+ </body></html>
+
diff --git a/html/Extending-service-discovery.html b/html/Extending-service-discovery.html
new file mode 100644
index 0000000..3fe9b83
--- /dev/null
+++ b/html/Extending-service-discovery.html
@@ -0,0 +1,71 @@
+<html lang="en">
+<head>
+<title>Extending service discovery - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="prev" href="Sending-new-requests.html#Sending-new-requests" title="Sending new requests">
+<link rel="next" href="Chat-printers.html#Chat-printers" title="Chat printers">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Extending-service-discovery"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Chat-printers.html#Chat-printers">Chat printers</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Sending-new-requests.html#Sending-new-requests">Sending new requests</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<hr><br>
+</div>
+
+<h3 class="section">16.5 Service discovery</h3>
+
+<p><a name="index-jabber_002dadvertised_002dfeatures-240"></a><a name="index-jabber_002ddisco_002ditems_002dnodes-241"></a><a name="index-jabber_002ddisco_002dinfo_002dnodes-242"></a><a name="index-jabber_002dmy_002djid_002dp-243"></a>
+Your new handlers will likely want to advertise their existence
+through service discovery.
+
+ <p>To have an additional feature reported in response to disco info
+requests, add a string to <code>jabber-advertised-features</code>.
+
+ <p>By default, the service discovery functions reject all requests
+containing a node identifier with an &ldquo;Item not found&rdquo; error. To
+make them respond, add the appropriate entries to
+<code>jabber-disco-items-nodes</code> and <code>jabber-disco-info-nodes</code>.
+Both variables work in the same way. They are alists, where the keys
+are the node names, and the values are lists of two items.
+
+ <p>The first item is the data to return &mdash; either a list or a function
+taking the entire IQ stanza and returning a list, this list containing
+the XML nodes to include in the <code>&lt;query/&gt;</code> node in the response.
+
+ <p>The second item is the access control function. An access control
+function receives the JID as its only argument, and returns non-nil if
+access is to be granted. If nil is specified instead of a function,
+access is always granted. One such function is provided,
+<code>jabber-my-jid-p</code>, which grants access for JIDs where the
+username and server (not necessarily resource) are equal to those of
+the user.
+
+ </body></html>
+
diff --git a/html/File-transfer.html b/html/File-transfer.html
new file mode 100644
index 0000000..0ba416c
--- /dev/null
+++ b/html/File-transfer.html
@@ -0,0 +1,69 @@
+<html lang="en">
+<head>
+<title>File transfer - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Composing-messages.html#Composing-messages" title="Composing messages">
+<link rel="next" href="Services.html#Services" title="Services">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="File-transfer"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Services.html#Services">Services</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Composing-messages.html#Composing-messages">Composing messages</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">5 File transfer</h2>
+
+<p><a name="index-File-transfer-58"></a><a name="index-Sending-files-59"></a>
+jabber.el has limited support for file transfer. The most important
+limit is that files sent and received are kept in buffers, so Emacs must
+be able to allocate enough memory for the entire file, and the file size
+must be smaller than the maximum buffer size.<a rel="footnote" href="#fn-1" name="fnd-1"><sup>1</sup></a>
+
+ <p>jabber.el is able to exchange files with most Jabber clients (and also
+some MSN transports), but notably not with the official Google Talk
+client. The Google Talk client uses a different file transfer protocol
+that, at the time of this release, has not been published.
+
+<ul class="menu">
+<li><a accesskey="1" href="Receiving-files.html#Receiving-files">Receiving files</a>
+<li><a accesskey="2" href="Sending-files.html#Sending-files">Sending files</a>
+</ul>
+
+ <div class="footnote">
+<hr>
+<h4>Footnotes</h4><p class="footnote"><small>[<a name="fn-1" href="#fnd-1">1</a>]</small> The maximum
+buffer size is kept in the variable <code>most-positive-fixnum</code>. On
+most 32-bit systems, this is 128 or 256 megabytes, depending on your
+Emacs version.</p>
+
+ <p><hr></div>
+
+ </body></html>
+
diff --git a/html/Function-index.html b/html/Function-index.html
new file mode 100644
index 0000000..1159de9
--- /dev/null
+++ b/html/Function-index.html
@@ -0,0 +1,104 @@
+<html lang="en">
+<head>
+<title>Function index - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Concept-index.html#Concept-index" title="Concept index">
+<link rel="next" href="Variable-index.html#Variable-index" title="Variable index">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Function-index"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Variable-index.html#Variable-index">Variable index</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Concept-index.html#Concept-index">Concept index</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="unnumbered">Function index</h2>
+
+
+
+<ul class="index-fn" compact>
+<li><a href="Customizing-alerts.html#index-define_002djabber_002dalert-208"><code>define-jabber-alert</code></a>: <a href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a></li>
+<li><a href="Tracking-activity.html#index-jabber_002dactivity_002dmode-115"><code>jabber-activity-mode</code></a>: <a href="Tracking-activity.html#Tracking-activity">Tracking activity</a></li>
+<li><a href="Ad_002dHoc-Commands.html#index-jabber_002dahc_002dexecute_002dcommand-84"><code>jabber-ahc-execute-command</code></a>: <a href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands">Ad-Hoc Commands</a></li>
+<li><a href="Ad_002dHoc-Commands.html#index-jabber_002dahc_002dget_002dlist-83"><code>jabber-ahc-get-list</code></a>: <a href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands">Ad-Hoc Commands</a></li>
+<li><a href="Chatting.html#index-jabber_002dchat_002dwith-6"><code>jabber-chat-with</code></a>: <a href="Chatting.html#Chatting">Chatting</a></li>
+<li><a href="Composing-messages.html#index-jabber_002dcompose-55"><code>jabber-compose</code></a>: <a href="Composing-messages.html#Composing-messages">Composing messages</a></li>
+<li><a href="Connecting.html#index-jabber_002dconnect-1"><code>jabber-connect</code></a>: <a href="Connecting.html#Connecting">Connecting</a></li>
+<li><a href="Customization.html#index-jabber_002dcustomize-156"><code>jabber-customize</code></a>: <a href="Customization.html#Customization">Customization</a></li>
+<li><a href="Connecting.html#index-jabber_002ddisconnect-2"><code>jabber-disconnect</code></a>: <a href="Connecting.html#Connecting">Connecting</a></li>
+<li><a href="Roster-buffer.html#index-jabber_002ddisplay_002droster-23"><code>jabber-display-roster</code></a>: <a href="Roster-buffer.html#Roster-buffer">Roster buffer</a></li>
+<li><a href="Roster-import-and-export.html#index-jabber_002dexport_002droster-144"><code>jabber-export-roster</code></a>: <a href="Roster-import-and-export.html#Roster-import-and-export">Roster import and export</a></li>
+<li><a href="Sending-files.html#index-jabber_002dft_002dsend-65"><code>jabber-ft-send</code></a>: <a href="Sending-files.html#Sending-files">Sending files</a></li>
+<li><a href="Service-discovery-and-browsing.html#index-jabber_002dget_002dbrowse-69"><code>jabber-get-browse</code></a>: <a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a></li>
+<li><a href="Service-discovery-and-browsing.html#index-jabber_002dget_002ddisco_002dinfo-71"><code>jabber-get-disco-info</code></a>: <a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a></li>
+<li><a href="Service-discovery-and-browsing.html#index-jabber_002dget_002ddisco_002ditems-70"><code>jabber-get-disco-items</code></a>: <a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a></li>
+<li><a href="Time-queries.html#index-jabber_002dget_002didle_002dtime-99"><code>jabber-get-idle-time</code></a>: <a href="Time-queries.html#Time-queries">Time queries</a></li>
+<li><a href="Time-queries.html#index-jabber_002dget_002dlast_002donline-96"><code>jabber-get-last-online</code></a>: <a href="Time-queries.html#Time-queries">Time queries</a></li>
+<li><a href="Registering.html#index-jabber_002dget_002dregister-79"><code>jabber-get-register</code></a>: <a href="Registering.html#Registering">Registering</a></li>
+<li><a href="Searching.html#index-jabber_002dget_002dsearch-81"><code>jabber-get-search</code></a>: <a href="Searching.html#Searching">Searching</a></li>
+<li><a href="Time-queries.html#index-jabber_002dget_002dtime-94"><code>jabber-get-time</code></a>: <a href="Time-queries.html#Time-queries">Time queries</a></li>
+<li><a href="Groupchat.html#index-jabber_002dgroupchat_002dget_002dconfig-36"><code>jabber-groupchat-get-config</code></a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Groupchat.html#index-jabber_002dgroupchat_002djoin-27"><code>jabber-groupchat-join</code></a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Groupchat.html#index-jabber_002dgroupchat_002dleave-35"><code>jabber-groupchat-leave</code></a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="XMPP-URIs.html#index-jabber_002dhandle_002duri-155"><code>jabber-handle-uri</code></a>: <a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a></li>
+<li><a href="Roster-import-and-export.html#index-jabber_002dimport_002droster-145"><code>jabber-import-roster</code></a>: <a href="Roster-import-and-export.html#Roster-import-and-export">Roster import and export</a></li>
+<li><a href="Info-alerts.html#index-jabber_002dinfo_002ddefault_002dmessage-220"><code>jabber-info-default-message</code></a>: <a href="Info-alerts.html#Info-alerts">Info alerts</a></li>
+<li><a href="Keepalive.html#index-jabber_002dkeepalive_002dstart-110"><code>jabber-keepalive-start</code></a>: <a href="Keepalive.html#Keepalive">Keepalive</a></li>
+<li><a href="Keepalive.html#index-jabber_002dkeepalive_002dstop-111"><code>jabber-keepalive-stop</code></a>: <a href="Keepalive.html#Keepalive">Keepalive</a></li>
+<li><a href="Miscellaneous-settings.html#index-jabber_002dmenu-178"><code>jabber-menu</code></a>: <a href="Miscellaneous-settings.html#Miscellaneous-settings">Miscellaneous settings</a></li>
+<li><a href="Message-alerts.html#index-jabber_002dmessage_002ddefault_002dmessage-214"><code>jabber-message-default-message</code></a>: <a href="Message-alerts.html#Message-alerts">Message alerts</a></li>
+<li><a href="Modeline-status.html#index-jabber_002dmode_002dline_002dmode-105"><code>jabber-mode-line-mode</code></a>: <a href="Modeline-status.html#Modeline-status">Modeline status</a></li>
+<li><a href="Automation.html#index-jabber_002dmuc_002dautojoin-40"><code>jabber-muc-autojoin</code></a>: <a href="Automation.html#Automation">Automation</a></li>
+<li><a href="MUC-alerts.html#index-jabber_002dmuc_002ddefault_002dmessage-218"><code>jabber-muc-default-message</code></a>: <a href="MUC-alerts.html#MUC-alerts">MUC alerts</a></li>
+<li><a href="Invitations.html#index-jabber_002dmuc_002dinvite-44"><code>jabber-muc-invite</code></a>: <a href="Invitations.html#Invitations">Invitations</a></li>
+<li><a href="Groupchat.html#index-jabber_002dmuc_002dnames-37"><code>jabber-muc-names</code></a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Private-messages.html#index-jabber_002dmuc_002dprivate-46"><code>jabber-muc-private</code></a>: <a href="Private-messages.html#Private-messages">Private messages</a></li>
+<li><a href="MUC-Administration.html#index-jabber_002dmuc_002dset_002daffiliation-52"><code>jabber-muc-set-affiliation</code></a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="MUC-Administration.html#index-jabber_002dmuc_002dset_002drole-47"><code>jabber-muc-set-role</code></a>: <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a></li>
+<li><a href="Groupchat.html#index-jabber_002dmuc_002dset_002dtopic-34"><code>jabber-muc-set-topic</code></a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Extending-service-discovery.html#index-jabber_002dmy_002djid_002dp-243"><code>jabber-my-jid-p</code></a>: <a href="Extending-service-discovery.html#Extending-service-discovery">Extending service discovery</a></li>
+<li><a href="Presence-alerts.html#index-jabber_002dpresence_002ddefault_002dmessage-212"><code>jabber-presence-default-message</code></a>: <a href="Presence-alerts.html#Presence-alerts">Presence alerts</a></li>
+<li><a href="Sending-new-requests.html#index-jabber_002dprocess_002ddata-239"><code>jabber-process-data</code></a>: <a href="Sending-new-requests.html#Sending-new-requests">Sending new requests</a></li>
+<li><a href="Listening-for-new-requests.html#index-jabber_002dprocess_002diq-232"><code>jabber-process-iq</code></a>: <a href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a></li>
+<li><a href="Sending-new-requests.html#index-jabber_002dprocess_002diq-237"><code>jabber-process-iq</code></a>: <a href="Sending-new-requests.html#Sending-new-requests">Sending new requests</a></li>
+<li><a href="Sending-new-requests.html#index-jabber_002dreport_002dsuccess-238"><code>jabber-report-success</code></a>: <a href="Sending-new-requests.html#Sending-new-requests">Sending new requests</a></li>
+<li><a href="Presence.html#index-jabber_002dsend_002ddefault_002dpresence-10"><code>jabber-send-default-presence</code></a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Presence.html#index-jabber_002dsend_002ddirected_002dpresence-16"><code>jabber-send-directed-presence</code></a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Sending-new-requests.html#index-jabber_002dsend_002diq-236"><code>jabber-send-iq</code></a>: <a href="Sending-new-requests.html#Sending-new-requests">Sending new requests</a></li>
+<li><a href="Listening-for-new-requests.html#index-jabber_002dsend_002diq-231"><code>jabber-send-iq</code></a>: <a href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a></li>
+<li><a href="Presence.html#index-jabber_002dsend_002dpresence-9"><code>jabber-send-presence</code></a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Presence-subscription.html#index-jabber_002dsend_002dsubscription_002drequest-19"><code>jabber-send-subscription-request</code></a>: <a href="Presence-subscription.html#Presence-subscription">Presence subscription</a></li>
+<li><a href="Listening-for-new-requests.html#index-jabber_002dsignal_002derror-233"><code>jabber-signal-error</code></a>: <a href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a></li>
+<li><a href="Sending-files.html#index-jabber_002dsocks5_002dquery_002dall_002dproxies-64"><code>jabber-socks5-query-all-proxies</code></a>: <a href="Sending-files.html#Sending-files">Sending files</a></li>
+<li><a href="Personal-information.html#index-jabber_002dvcard_002dedit-88"><code>jabber-vcard-edit</code></a>: <a href="Personal-information.html#Personal-information">Personal information</a></li>
+<li><a href="Personal-information.html#index-jabber_002dvcard_002dget-87"><code>jabber-vcard-get</code></a>: <a href="Personal-information.html#Personal-information">Personal information</a></li>
+<li><a href="Watch-buddies.html#index-jabber_002dwatch_002dadd-122"><code>jabber-watch-add</code></a>: <a href="Watch-buddies.html#Watch-buddies">Watch buddies</a></li>
+<li><a href="Watch-buddies.html#index-jabber_002dwatch_002dremove-123"><code>jabber-watch-remove</code></a>: <a href="Watch-buddies.html#Watch-buddies">Watch buddies</a></li>
+ </ul></body></html>
+
diff --git a/html/Groupchat.html b/html/Groupchat.html
new file mode 100644
index 0000000..55eacb0
--- /dev/null
+++ b/html/Groupchat.html
@@ -0,0 +1,91 @@
+<html lang="en">
+<head>
+<title>Groupchat - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link rel="next" href="Composing-messages.html#Composing-messages" title="Composing messages">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Groupchat"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Composing-messages.html#Composing-messages">Composing messages</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Basic-operation.html#Basic-operation">Basic operation</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">3 Groupchat</h2>
+
+<p><a name="index-Groupchat-24"></a><a name="index-MUC-25"></a><a name="index-Chatrooms-26"></a>
+The groupchat menu can be accessed by typing <kbd>C-c C-m</kbd> in the
+roster buffer. You can also type the commands directly, as will be
+shown here.
+
+ <p><a name="index-jabber_002dgroupchat_002djoin-27"></a><a name="index-Joining-a-groupchat-28"></a><a name="index-Changing-nickname-29"></a><a name="index-Nickname_002c-changing-30"></a>To join a groupchat, type <kbd>M-x jabber-groupchat-join</kbd>. You will
+be prompted for the groupchat to join, and your nickname in the
+groupchat. This nickname doesn't need to have any correlation to your
+JID; in fact, groupchats are usually (but not always) configured such
+that only moderators can see your JID. You can change your nickname
+with <kbd>M-x jabber-muc-nick</kbd>. See <a href="Automation.html#Automation">Automation</a>, for setting default
+nicknames.
+
+ <p><a name="index-query-groupchat-31"></a><a name="index-jabber_002dmuc_002ddisable_002ddisco_002dcheck-32"></a>When trying to join a room, jabber.el first sends a service discovery
+info request to the room, to find out whether it exists and what
+features are enabled (in particular whether the room is
+password-protected). However, this can cause problems with some buggy
+MUC services (or services that respond in a way that jabber.el doesn't
+expect). A workaround for that is to set
+<code>jabber-muc-disable-disco-check</code> to t; however, the bug should be
+unearthed and fixed.
+
+ <p>Groupchat messages will be displayed in a buffer called
+<code>*-jabber-groupchat-:-</code><var>groupchat</var><code>-*</code>. It works much like the
+chat buffer.
+
+ <p><a name="index-Topic_002c-MUC-33"></a><a name="index-jabber_002dmuc_002dset_002dtopic-34"></a>To change the topic of a groupchat, type <kbd>M-x jabber-muc-set-topic</kbd>.
+The current topic is shown in the header line.
+
+ <p><a name="index-jabber_002dgroupchat_002dleave-35"></a>To leave a groupchat, type <kbd>M-x jabber-groupchat-leave</kbd>.
+
+ <p><a name="index-jabber_002dgroupchat_002dget_002dconfig-36"></a>If you are the owner of a groupchat, you can change its configuration
+by typing <kbd>M-x jabber-groupchat-get-config</kbd>. A configuration form
+will be rendered in new buffer.
+
+ <p><a name="index-jabber_002dmuc_002dnames-37"></a>To see which people are in a groupchat, type <kbd>M-x
+jabber-muc-names</kbd>. This gives a list of nicknames, &ldquo;roles&rdquo;,
+&ldquo;affiliations&rdquo;, and possibly JIDs. See <a href="MUC-Administration.html#MUC-Administration">MUC Administration</a>, for
+the meaning of roles and affiliations.
+
+<ul class="menu">
+<li><a accesskey="1" href="Automation.html#Automation">Automation</a>
+<li><a accesskey="2" href="Invitations.html#Invitations">Invitations</a>
+<li><a accesskey="3" href="Private-messages.html#Private-messages">Private messages</a>
+<li><a accesskey="4" href="MUC-Administration.html#MUC-Administration">MUC Administration</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Hacking-and-extending.html b/html/Hacking-and-extending.html
new file mode 100644
index 0000000..e45346d
--- /dev/null
+++ b/html/Hacking-and-extending.html
@@ -0,0 +1,59 @@
+<html lang="en">
+<head>
+<title>Hacking and extending - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Customization.html#Customization" title="Customization">
+<link rel="next" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Hacking-and-extending"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Protocol-support.html#Protocol-support">Protocol support</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Customization.html#Customization">Customization</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">16 Hacking and extending</h2>
+
+<p>This part of the manual is an attempt to explain parts of the source
+code. It is not meant to discourage you from reading the code
+yourself and trying to figure it out, but as a guide on where to
+look. Knowledge of Jabber protocols is assumed.
+
+<ul class="menu">
+<li><a accesskey="1" href="XML-representation.html#XML-representation">XML representation</a>
+<li><a accesskey="2" href="Roster-structure.html#Roster-structure">Roster structure</a>
+<li><a accesskey="3" href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a>
+<li><a accesskey="4" href="Sending-new-requests.html#Sending-new-requests">Sending new requests</a>
+<li><a accesskey="5" href="Extending-service-discovery.html#Extending-service-discovery">Extending service discovery</a>
+<li><a accesskey="6" href="Chat-printers.html#Chat-printers">Chat printers</a>
+<li><a accesskey="7" href="Stanza-chains.html#Stanza-chains">Stanza chains</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Hooks.html b/html/Hooks.html
new file mode 100644
index 0000000..99654c7
--- /dev/null
+++ b/html/Hooks.html
@@ -0,0 +1,68 @@
+<html lang="en">
+<head>
+<title>Hooks - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link rel="next" href="Debug-options.html#Debug-options" title="Debug options">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Hooks"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Debug-options.html#Debug-options">Debug options</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.7 Hooks</h3>
+
+<p>jabber.el provides various hooks that you can use for whatever
+purpose.
+
+
+<a name="index-jabber_002dpost_002dconnect_002dhook-221"></a>
+<dl><dt><code>jabber-post-connect-hook</code><dd>This hook is called after successful connection and authentication.
+By default it contains <code>jabber-send-default-presence</code>
+(see <a href="Presence.html#Presence">Presence</a>).
+
+ <p><a name="index-jabber_002dlost_002dconnection_002dhook-222"></a><br><dt><code>jabber-lost-connection-hook</code><dd>This hook is called when you have been disconnected for unknown
+reasons. Usually this isn't noticed for quite a long time.
+
+ <p><a name="index-jabber_002dpre_002ddisconnect_002dhook-223"></a><br><dt><code>jabber-pre-disconnect-hook</code><dd>This hook is called just before voluntary disconnection. This might
+be due to failed authentication, so check
+<code>*jabber-authenticated*</code> if you want to send a stanza.
+
+ <p><a name="index-jabber_002dpost_002ddisconnect_002dhook-224"></a><br><dt><code>jabber-post-disconnect-hook</code><dd>This hook is called after disconnection of any kind, possibly just
+after <code>jabber-lost-connection-hook</code>.
+
+ <p><a name="index-jabber_002dchat_002dmode_002dhook-225"></a><br><dt><code>jabber-chat-mode-hook</code><dd>This hook is called when a new chat buffer is created.
+
+ </dl>
+
+ </body></html>
+
diff --git a/html/Info-alerts.html b/html/Info-alerts.html
new file mode 100644
index 0000000..7c7513d
--- /dev/null
+++ b/html/Info-alerts.html
@@ -0,0 +1,53 @@
+<html lang="en">
+<head>
+<title>Info alerts - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link rel="prev" href="MUC-alerts.html#MUC-alerts" title="MUC alerts">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Info-alerts"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="MUC-alerts.html#MUC-alerts">MUC alerts</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>
+<hr><br>
+</div>
+
+<h4 class="subsection">15.6.5 Info alerts</h4>
+
+<p><a name="index-jabber_002dalert_002dinfo_002dmessage_002dfunction-219"></a><a name="index-jabber_002dinfo_002ddefault_002dmessage-220"></a>
+Info alerts are sadly underdeveloped. The message function,
+<code>jabber-alert-info-message-function</code>, takes two arguments,
+<var>infotype</var> and <var>buffer</var>. <var>buffer</var> is the buffer where
+something happened, and <var>infotype</var> is either <code>'roster</code> for
+roster updates, or <code>'browse</code> for anything that uses the browse
+buffer (basically anything except chatting).
+
+ <p>The info alert hooks take an extra argument, as could be expected.
+
+ </body></html>
+
diff --git a/html/Introduction.html b/html/Introduction.html
new file mode 100644
index 0000000..f5f0d11
--- /dev/null
+++ b/html/Introduction.html
@@ -0,0 +1,63 @@
+<html lang="en">
+<head>
+<title>Introduction - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="index.html#Top" title="Top">
+<link rel="next" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Introduction"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Basic-operation.html#Basic-operation">Basic operation</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="index.html#Top">Top</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">1 Introduction</h2>
+
+<p>jabber.el is a Jabber client running under Emacs. For more
+information on the open-protocol instant messaging network Jabber,
+please visit <a href="http://www.jabber.org">http://www.jabber.org</a>.
+
+ <p>As a Jabber client, jabber.el is mostly just a face in the crowd,
+except that it uses buffers where GUI clients have windows. There is
+a roster buffer, and to chat with someone you open a chat buffer, and
+there are browse buffers (increasingly inexactly named) for
+interaction with servers and services. Then again, jabber.el delivers
+excellent console performance and customizable hooks (if you have
+speech synthesizer software, hook it up to your presence alerts).
+
+ <p>jabber.el does not yet support GPG, sending and receiving
+roster items, and various other things.
+
+<ul class="menu">
+<li><a accesskey="1" href="Contact.html#Contact">Contact</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Invitations.html b/html/Invitations.html
new file mode 100644
index 0000000..79ede6e
--- /dev/null
+++ b/html/Invitations.html
@@ -0,0 +1,57 @@
+<html lang="en">
+<head>
+<title>Invitations - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Groupchat.html#Groupchat" title="Groupchat">
+<link rel="prev" href="Automation.html#Automation" title="Automation">
+<link rel="next" href="Private-messages.html#Private-messages" title="Private messages">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Invitations"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Private-messages.html#Private-messages">Private messages</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Automation.html#Automation">Automation</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Groupchat.html#Groupchat">Groupchat</a>
+<hr><br>
+</div>
+
+<h3 class="section">3.2 Invitations</h3>
+
+<p><a name="index-Invitations-43"></a><a name="index-jabber_002dmuc_002dinvite-44"></a>
+You can invite someone to a groupchat with <kbd>M-x jabber-muc-invite</kbd>
+(also available in the MUC menu). Pay attention to the order of the
+arguments &mdash; as both users and rooms are just JIDs, it is technically
+possible to invite a room to a user, but that's probably not what you
+want.
+
+ <p>When you receive an invitation, it appears in the chat buffer along
+with two buttons, &ldquo;Accept&rdquo; and &ldquo;Decline&rdquo;. Pressing &ldquo;Accept&rdquo;
+enters the room, as you would expect. Pressing &ldquo;Decline&rdquo; gives you
+an opportunity to state the reason why you're not joining.
+
+ </body></html>
+
diff --git a/html/Keepalive.html b/html/Keepalive.html
new file mode 100644
index 0000000..63f8afd
--- /dev/null
+++ b/html/Keepalive.html
@@ -0,0 +1,64 @@
+<html lang="en">
+<head>
+<title>Keepalive - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="prev" href="Modeline-status.html#Modeline-status" title="Modeline status">
+<link rel="next" href="Tracking-activity.html#Tracking-activity" title="Tracking activity">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Keepalive"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Tracking-activity.html#Tracking-activity">Tracking activity</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Modeline-status.html#Modeline-status">Modeline status</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Useful-features.html#Useful-features">Useful features</a>
+<hr><br>
+</div>
+
+<h3 class="section">10.3 Keepalive</h3>
+
+<p><a name="index-Keepalive-108"></a><a name="index-Detecting-lost-connections-109"></a><a name="index-jabber_002dkeepalive_002dstart-110"></a><a name="index-jabber_002dkeepalive_002dstop-111"></a><a name="index-jabber_002dkeepalive_002dinterval-112"></a><a name="index-jabber_002dkeepalive_002dtimeout-113"></a>
+Sometimes network connections are lost without you noticing. This is
+especially true with Jabber, as it is quite reasonable to keep the
+connection open for a long time without either sending or receiving
+any data.
+
+ <p>If you want to detect a lost connection earlier, you can use the
+keepalive functions. Type <kbd>M-x jabber-keepalive-start</kbd> to start
+it, and <kbd>M-x jabber-keepalive-stop</kbd> to stop it.
+
+ <p>These functions work by asking your server for the time once in a
+while (by default every ten minutes), and considering the connection
+lost if the server doesn't answer within reasonable time (by default
+20 seconds).
+
+ <p>You can customize the interval and the timeout with the variables
+<code>jabber-keepalive-interval</code> and <code>jabber-keepalive-timeout</code>,
+respectively.
+
+ </body></html>
+
diff --git a/html/Listening-for-new-requests.html b/html/Listening-for-new-requests.html
new file mode 100644
index 0000000..010d2d6
--- /dev/null
+++ b/html/Listening-for-new-requests.html
@@ -0,0 +1,67 @@
+<html lang="en">
+<head>
+<title>Listening for new requests - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="prev" href="Roster-structure.html#Roster-structure" title="Roster structure">
+<link rel="next" href="Sending-new-requests.html#Sending-new-requests" title="Sending new requests">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Listening-for-new-requests"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Sending-new-requests.html#Sending-new-requests">Sending new requests</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Roster-structure.html#Roster-structure">Roster structure</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<hr><br>
+</div>
+
+<h3 class="section">16.3 Listening for new requests</h3>
+
+<p><a name="index-jabber_002dsend_002diq-231"></a><a name="index-jabber_002dprocess_002diq-232"></a><a name="index-jabber_002dsignal_002derror-233"></a><a name="index-jabber_002diq_002dget_002dxmlns_002dalist-234"></a><a name="index-jabber_002diq_002dset_002dxmlns_002dalist-235"></a>
+To listen for new IQ requests, add the appropriate entry in
+<code>jabber-iq-get-xmlns-alist</code> or <code>jabber-iq-set-xmlns-alist</code>.
+The key is the namespace of the request, and the value is a function
+that takes one argument, the entire IQ stanza in list format.
+<code>jabber-process-iq</code> reads these alists to determine which
+function to call on incoming packets.
+
+ <p>For example, the Ad-Hoc Commands module contains the following:
+
+<pre class="example"> (add-to-list 'jabber-iq-set-xmlns-alist
+ (cons "http://jabber.org/protocol/commands" 'jabber-ahc-process))
+</pre>
+ <p>To send a response to an IQ request, use <span class="samp">(jabber-send-iq
+</span><var>sender</var><span class="samp"> "result" </span><var>query</var><span class="samp"> nil nil nil nil </span><var>id</var><span class="samp">)</span>, where
+<var>query</var> is the query in list format. <code>jabber-send-iq</code> will
+encapsulate the query in an IQ packet with the specified id.
+
+ <p>To return an error to the Jabber entity that sent the query, use
+<code>jabber-signal-error</code>. The signal is caught by
+<code>jabber-process-iq</code>, which takes care of sending the error.
+
+ </body></html>
+
diff --git a/html/MUC-Administration.html b/html/MUC-Administration.html
new file mode 100644
index 0000000..a73e18d
--- /dev/null
+++ b/html/MUC-Administration.html
@@ -0,0 +1,91 @@
+<html lang="en">
+<head>
+<title>MUC Administration - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Groupchat.html#Groupchat" title="Groupchat">
+<link rel="prev" href="Private-messages.html#Private-messages" title="Private messages">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="MUC-Administration"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Private-messages.html#Private-messages">Private messages</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Groupchat.html#Groupchat">Groupchat</a>
+<hr><br>
+</div>
+
+<h3 class="section">3.4 Administration</h3>
+
+<p>Administration of a MUC room mostly consists of managing roles and
+affiliations. Roles are temporary, and apply until the user leaves the
+room. Affiliations are permanent, and based on JIDs.
+
+<h4 class="subsection">3.4.1 Roles</h4>
+
+<p><a name="index-jabber_002dmuc_002dset_002drole-47"></a><a name="index-Kicking_002c-MUC-48"></a><a name="index-Voice_002c-MUC-49"></a><a name="index-Moderator_002c-MUC-50"></a><a name="index-Roles_002c-MUC-51"></a>If you have moderator privileges, you can change the role of a
+participant with <kbd>M-x jabber-muc-set-role</kbd>. Kicking means setting
+the role to &ldquo;none&rdquo;. Granting and revoking voice are &ldquo;participant&rdquo;
+and &ldquo;visitor&rdquo;, respectively. &ldquo;moderator&rdquo; gives moderator
+privileges, obviously.
+
+ <p>The possible roles are:
+
+ <dl>
+<dt><span class="samp">moderator</span><dd>Has voice, can change other people's roles.
+
+ <br><dt><span class="samp">participant</span><dd>Has voice.
+
+ <br><dt><span class="samp">visitor</span><dd>Doesn't have voice (can't send messages to everyone, but can send
+private messages)
+
+ <br><dt><span class="samp">none</span><dd>Not in room.
+</dl>
+
+<h4 class="subsection">3.4.2 Affiliations</h4>
+
+<p><a name="index-jabber_002dmuc_002dset_002daffiliation-52"></a><a name="index-Affiliations_002c-MUC-53"></a><a name="index-Banning_002c-MUC-54"></a>If you have admin or owner privileges, you can change the affiliation of
+a user with <kbd>M-x jabber-muc-set-affiliation</kbd>. Affiliation is
+persistent, and based on JIDs. Depending of your affiliation and the
+MUC implementation, you might not be allowed to perform all kinds of
+changes, and maybe not in one step.
+
+ <p>Affiliations are:
+
+ <dl>
+<dt><span class="samp">owner</span><dd>Can destroy room, appoint admins, make people members, ban people.
+
+ <br><dt><span class="samp">admin</span><dd>Can make people members or ban people.
+
+ <br><dt><span class="samp">member</span><dd>Can enter the room, and has voice by default.
+
+ <br><dt><span class="samp">none</span><dd>Rights depend on room configuration. The room might be members-only, or
+grant voice only to members.
+
+ <br><dt><span class="samp">outcast</span><dd>Banned from the room
+</dl>
+
+ </body></html>
+
diff --git a/html/MUC-alerts.html b/html/MUC-alerts.html
new file mode 100644
index 0000000..909b2e4
--- /dev/null
+++ b/html/MUC-alerts.html
@@ -0,0 +1,68 @@
+<html lang="en">
+<head>
+<title>MUC alerts - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link rel="prev" href="Message-alerts.html#Message-alerts" title="Message alerts">
+<link rel="next" href="Info-alerts.html#Info-alerts" title="Info alerts">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="MUC-alerts"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Info-alerts.html#Info-alerts">Info alerts</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Message-alerts.html#Message-alerts">Message alerts</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>
+<hr><br>
+</div>
+
+<h4 class="subsection">15.6.4 MUC alerts</h4>
+
+<p><a name="index-jabber_002dalert_002dmuc_002dfunction-216"></a><a name="index-jabber_002dmuc_002dalert_002dself-217"></a><a name="index-jabber_002dmuc_002ddefault_002dmessage-218"></a>
+Set <code>jabber-alert-muc-function</code> to your desired
+function. This function should look like:
+
+<pre class="example"> (defun <var>function</var> (<var>nick</var> <var>group</var> <var>buffer</var> <var>text</var>)
+ ...
+ )
+</pre>
+ <p><var>nick</var> is the nickname, <var>group</var> is the JID of the group,
+<var>buffer</var> is the buffer where the message is displayed, and
+<var>text</var> is the text of the message.
+
+ <p>The default function, <code>jabber-muc-default-message</code>, returns
+&ldquo;Message from <var>nick</var> in <var>group</var>&rdquo; or &ldquo;Message in
+<var>group</var>&rdquo;, the latter for messages from the room itself.
+
+ <p>All MUC alert hooks take the same arguments plus the additional
+<var>proposed-alert</var>, which is the result of the specified message
+function.
+
+ <p>By default, no alert is made for messages from yourself. To change
+that, customize the variable <code>jabber-muc-alert-self</code>.
+
+ </body></html>
+
diff --git a/html/Message-alerts.html b/html/Message-alerts.html
new file mode 100644
index 0000000..29f37d8
--- /dev/null
+++ b/html/Message-alerts.html
@@ -0,0 +1,79 @@
+<html lang="en">
+<head>
+<title>Message alerts - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link rel="prev" href="Presence-alerts.html#Presence-alerts" title="Presence alerts">
+<link rel="next" href="MUC-alerts.html#MUC-alerts" title="MUC alerts">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Message-alerts"></a>Next:&nbsp;<a rel="next" accesskey="n" href="MUC-alerts.html#MUC-alerts">MUC alerts</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Presence-alerts.html#Presence-alerts">Presence alerts</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>
+<hr><br>
+</div>
+
+<h4 class="subsection">15.6.3 Message alerts</h4>
+
+<p><a name="index-jabber_002dalert_002dmessage_002dfunction-213"></a><a name="index-jabber_002dmessage_002ddefault_002dmessage-214"></a><a name="index-jabber_002dmessage_002dalert_002dsame_002dbuffer-215"></a>
+If you don't want message alerts when the chat buffer in question is
+already the current buffer, set <code>jabber-message-alert-same-buffer</code>
+to nil. This affects the behaviour of the default message function, so
+you'll have to reimplement this functionality if you write your own
+message function.
+
+ <p>Set <code>jabber-alert-message-function</code> to your desired
+function.<a rel="footnote" href="#fn-1" name="fnd-1"><sup>1</sup></a> This function should look like:
+
+<pre class="example"> (defun <var>function</var> (<var>from</var> <var>buffer</var> <var>text</var>)
+ ...
+ )
+</pre>
+ <p><var>from</var> is the JID symbol (see <a href="Roster-structure.html#Roster-structure">Roster structure</a>), <var>buffer</var>
+is the buffer where the message is displayed, and <var>text</var> is the
+text of the message.
+
+ <p>The default function, <code>jabber-message-default-message</code>, returns
+&ldquo;Message from <var>person</var>&rdquo;, where <var>person</var> is the name of the
+person if specified in the roster, otherwise the JID.
+
+ <p>All message alert hooks take the same arguments plus the additional
+<var>proposed-alert</var>, which is the result of the specified message
+function.
+
+ <div class="footnote">
+<hr>
+<h4>Footnotes</h4><p class="footnote"><small>[<a name="fn-1" href="#fnd-1">1</a>]</small> Logically it should be
+<code>jabber-alert-message-message-function</code>, but that would be
+really ugly.</p>
+
+ <p><hr></div>
+
+ </body></html>
+
diff --git a/html/Message-events.html b/html/Message-events.html
new file mode 100644
index 0000000..6d9edf6
--- /dev/null
+++ b/html/Message-events.html
@@ -0,0 +1,71 @@
+<html lang="en">
+<head>
+<title>Message events - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Message-history.html#Message-history" title="Message history">
+<link rel="next" href="Roster-import-and-export.html#Roster-import-and-export" title="Roster import and export">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Message-events"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Roster-import-and-export.html#Roster-import-and-export">Roster import and export</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Message-history.html#Message-history">Message history</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">12 Message events</h2>
+
+<p><a name="index-Composing-137"></a><a name="index-Delivered-138"></a><a name="index-Displayed-139"></a><a name="index-jabber_002devents_002drequest_002dthese-140"></a><a name="index-jabber_002devents_002dconfirm_002ddelivered-141"></a><a name="index-jabber_002devents_002dconfirm_002ddisplayed-142"></a><a name="index-jabber_002devents_002dconfirm_002dcomposing-143"></a>
+In the status line of the chat buffer, you can sometimes see
+notifications about the progress of the message you just sent. These
+states are possible:
+
+ <ul>
+<li>Delivered to offline storage (the user will receive it on next logon)
+
+ <li>Delivered to user's client (but not necessarily displayed)
+
+ <li>Displayed to user
+
+ <li>User is composing a reply
+
+ </ul>
+
+ <p>The first state is only reported by servers; the other three are
+reported by clients. jabber.el can report all three of them, and can
+display all four; not all clients support all states, though.
+
+ <p>If you don't want jabber.el to send out this information about you, set
+the variables <code>jabber-events-confirm-delivered</code>,
+<code>jabber-events-confirm-displayed</code>, and/or
+<code>jabber-events-confirm-composing</code> to nil. You can make jabber.el
+not to request such information by customizing
+<code>jabber-events-request-these</code>.
+
+ </body></html>
+
diff --git a/html/Message-history.html b/html/Message-history.html
new file mode 100644
index 0000000..3b59854
--- /dev/null
+++ b/html/Message-history.html
@@ -0,0 +1,83 @@
+<html lang="en">
+<head>
+<title>Message history - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="next" href="Message-events.html#Message-events" title="Message events">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Message-history"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Message-events.html#Message-events">Message events</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Useful-features.html#Useful-features">Useful features</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">11 Message history</h2>
+
+<p><a name="index-History-126"></a><a name="index-Backlog-127"></a><a name="index-Rotation-128"></a><a name="index-jabber_002dhistory_002denabled-129"></a><a name="index-jabber_002dglobal_002dhistory_002dfilename-130"></a><a name="index-jabber_002duse_002dglobal_002dhistory-131"></a><a name="index-jabber_002dhistory_002ddir-132"></a><a name="index-jabber_002dhistory_002denable_002drotation-133"></a><a name="index-jabber_002dhistory_002dsize_002dlimit-134"></a><a name="index-jabber_002dbacklog_002dnumber-135"></a><a name="index-jabber_002dbacklog_002ddays-136"></a>
+If you want a record of messages sent and received, set
+<code>jabber-history-enabled</code> to t. By default all messages to will
+be saved to a global history file specified by
+<code>jabber-global-history-filename</code>
+(<span class="file">~/.jabber_global_message_log</span> by default). If you prefer to
+store your chats' history in per-contact files, you can set the
+<code>jabber-use-global-history</code> variable to <code>nil</code>. When using
+per-contact history, files are named by the contact JID and saved
+under the directory specified by the variable
+<code>jabber-history-dir</code> (default is <span class="file">~/.emacs-jabber</span>).
+
+ <p>There is no facility for reading old messages yet, but just reading
+the file as text should be enough for many purposes.
+
+ <p>When you open a new chat buffer and have entries in your history file,
+the last few messages you recently exchanged with the contact in
+question will be inserted. You can control how many messages with
+<code>jabber-backlog-number</code> (by default 10), and how old messages
+with <code>jabber-backlog-days</code> (by default 3 days).
+
+ <p>If you worry about your history file(s) size, you can enable history
+rotation feature by setting the variable
+<code>jabber-history-enable-rotation</code> to <code>t</code> (default is
+<code>nil</code>). This feature &ldquo;rotates&rdquo; your history files according to
+the following rule: When <code>jabber-history-size-limit</code> (in
+kilobytes) is reached, the history file is renamed to
+&lt;history-file&gt;-&lt;number&gt;, where &lt;number&gt; is 1 or the smallest number
+after the last rotation. For example, suppose you set the
+<code>jabber-history-size-limit</code> variable to 512 and you chat with
+your buddy foo@jabber.server using the per-contact strategy to store
+history files. So, when the history file (<span class="file">foo@jabber-server</span>)
+reaches 512K bytes, it will be renamed to <span class="file">foo@jabber-server-1</span>
+and <span class="file">foo@jabber-server</span> will be set empty. Next time
+<span class="file">foo@jabber-server</span> grows to 512K bytes, it will be saved as
+<span class="file">foo@jabber-server-2</span> and so on. Although the example was
+presented with the per-contact history file strategy, history rotation
+works for both per-contact and global history logging strategies.
+
+ </body></html>
+
diff --git a/html/Miscellaneous-settings.html b/html/Miscellaneous-settings.html
new file mode 100644
index 0000000..d2b1484
--- /dev/null
+++ b/html/Miscellaneous-settings.html
@@ -0,0 +1,52 @@
+<html lang="en">
+<head>
+<title>Miscellaneous settings - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customization.html#Customization" title="Customization">
+<link rel="prev" href="Connection-settings.html#Connection-settings" title="Connection settings">
+<link rel="next" href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer" title="Customizing the roster buffer">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Miscellaneous-settings"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Connection-settings.html#Connection-settings">Connection settings</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customization.html#Customization">Customization</a>
+<hr><br>
+</div>
+
+<h3 class="section">15.3 Miscellaneous settings</h3>
+
+<p><a name="index-jabber_002dmenu-178"></a><a name="index-Menus-179"></a>
+If you want a Jabber menu on the menu bar with some common commands,
+type <kbd>M-x jabber-menu</kbd>. You can remove it again with <kbd>C-u M-x
+jabber-menu</kbd>. Unfortunately, this cannot be changed through Customize
+settings, so you need to add <code>(jabber-menu)</code> to your <span class="file">.emacs</span>
+to enable it permanently.
+
+ </body></html>
+
diff --git a/html/Modeline-status.html b/html/Modeline-status.html
new file mode 100644
index 0000000..d906665
--- /dev/null
+++ b/html/Modeline-status.html
@@ -0,0 +1,58 @@
+<html lang="en">
+<head>
+<title>Modeline status - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="prev" href="Autoaway.html#Autoaway" title="Autoaway">
+<link rel="next" href="Keepalive.html#Keepalive" title="Keepalive">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Modeline-status"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Keepalive.html#Keepalive">Keepalive</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Autoaway.html#Autoaway">Autoaway</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Useful-features.html#Useful-features">Useful features</a>
+<hr><br>
+</div>
+
+<h3 class="section">10.2 Modeline status</h3>
+
+<p><a name="index-Modeline-104"></a><a name="index-jabber_002dmode_002dline_002dmode-105"></a><a name="index-jabber_002dmode_002dline_002dmode-106"></a><a name="index-jabber_002dmode_002dline_002dcompact-107"></a>
+By typing <kbd>M-x jabber-mode-line-mode</kbd> you toggle display of some
+status in mode lines. The information is your own presence status,
+and some numbers showing the status of your roster contacts. By
+default, there are three numbers, for &ldquo;online&rdquo; (chatty and online),
+&ldquo;away&rdquo; (away, extended away and do not disturb) and offline
+contacts.
+
+ <p>If you set <code>jabber-mode-line-compact</code> to nil, you get a complete
+breakdown of presence status. That gives you six numbers indicating
+the number of chatty, online, away, extended away, dnd, and offline
+contacts, respectively.
+
+ </body></html>
+
diff --git a/html/Personal-information.html b/html/Personal-information.html
new file mode 100644
index 0000000..66fe866
--- /dev/null
+++ b/html/Personal-information.html
@@ -0,0 +1,60 @@
+<html lang="en">
+<head>
+<title>Personal information - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Services.html#Services" title="Services">
+<link rel="next" href="Avatars.html#Avatars" title="Avatars">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Personal-information"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Avatars.html#Avatars">Avatars</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Services.html#Services">Services</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">7 Personal information</h2>
+
+<p><a name="index-vCard-85"></a><a name="index-Personal-information-86"></a><a name="index-jabber_002dvcard_002dget-87"></a><a name="index-jabber_002dvcard_002dedit-88"></a>
+The Jabber way of handling personal information (name, addresses,
+phone numbers, etc) is &ldquo;vCards&rdquo; encoded in XML. You can get
+information about a user by running <kbd>M-x jabber-vcard-get</kbd>, and
+you can edit your own information by running <kbd>M-x
+jabber-vcard-edit</kbd>.
+
+ <p>The form for editing your information can be slightly confusing &mdash;
+you are allowed to enter any number of addresses, phone numbers and
+e-mail addresses, each of which has a set of orthogonal properties.
+You can add and remove items with the [INS] and [DEL] buttons,
+respectively.
+
+ <p>This is also where you set your avatar (see <a href="Avatars.html#Avatars">Avatars</a>). The size of
+your avatar file is limited to 8 kilobytes.
+
+ </body></html>
+
diff --git a/html/Presence-alerts.html b/html/Presence-alerts.html
new file mode 100644
index 0000000..fba3bda
--- /dev/null
+++ b/html/Presence-alerts.html
@@ -0,0 +1,69 @@
+<html lang="en">
+<head>
+<title>Presence alerts - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link rel="prev" href="Standard-alerts.html#Standard-alerts" title="Standard alerts">
+<link rel="next" href="Message-alerts.html#Message-alerts" title="Message alerts">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Presence-alerts"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Message-alerts.html#Message-alerts">Message alerts</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Standard-alerts.html#Standard-alerts">Standard alerts</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>
+<hr><br>
+</div>
+
+<h4 class="subsection">15.6.2 Presence alerts</h4>
+
+<p><a name="index-jabber_002dalert_002dpresence_002dmessage_002dfunction-211"></a><a name="index-jabber_002dpresence_002ddefault_002dmessage-212"></a>
+Set <code>jabber-alert-presence-message-function</code> to your desired
+function. This function should look like:
+
+<pre class="example"> (defun <var>function</var> (<var>who</var> <var>oldstatus</var> <var>newstatus</var> <var>statustext</var>)
+ ...
+ )
+</pre>
+ <p><var>who</var> is the JID symbol (see <a href="Roster-structure.html#Roster-structure">Roster structure</a>),
+<var>oldstatus</var> and <var>newstatus</var> are the previous and current
+stati, respectively, and <var>statustext</var> is the status message if
+provided, otherwise nil.
+
+ <p><var>newstatus</var> can also be one of <code>"subscribe"</code>,
+<code>"subscribed"</code>, <code>"unsubscribe"</code> and <code>"unsubscribed"</code>.
+
+ <p>The default function, <code>jabber-presence-default-message</code>, returns
+<code>nil</code> if <var>oldstatus</var> and <var>newstatus</var> are the same, and in
+other cases constructs a message from the given data.
+
+ <p>All presence alert hooks take the same arguments plus the additional
+<var>proposed-alert</var>, which is the result of the specified message
+function. This last argument is usually the only one they use.
+
+ </body></html>
+
diff --git a/html/Presence-subscription.html b/html/Presence-subscription.html
new file mode 100644
index 0000000..7402dc5
--- /dev/null
+++ b/html/Presence-subscription.html
@@ -0,0 +1,63 @@
+<html lang="en">
+<head>
+<title>Presence subscription - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link rel="prev" href="Presence.html#Presence" title="Presence">
+<link rel="next" href="Roster-buffer.html#Roster-buffer" title="Roster buffer">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Presence-subscription"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Roster-buffer.html#Roster-buffer">Roster buffer</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Presence.html#Presence">Presence</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Basic-operation.html#Basic-operation">Basic operation</a>
+<hr><br>
+</div>
+
+<h3 class="section">2.4 Presence subscription</h3>
+
+<p><a name="index-Presence-subscription-17"></a><a name="index-Subscribing-to-someone_0027s-presence-18"></a><a name="index-jabber_002dsend_002dsubscription_002drequest-19"></a>
+Having permission to view the presence status of a person is called
+<dfn>subscribing to his presence</dfn>. Presence subscription between two
+persons can be asymmetric.
+
+ <p>When jabber.el receives a presence subscription request, it will
+present it to you in an alert requiring immediate response, and offer
+you to send a subscription request back to that person.
+
+ <p>To request subscription to someone, type <kbd>M-x
+jabber-send-subscription-request</kbd>. You will be prompted for the JID
+to send it to. This command can also be accessed through the Roster
+menu, by typing <kbd>C-c C-r</kbd> in the roster buffer. After that, you
+will probably want to give the contact a more readable name. The
+command for that is <code>jabber-roster-change</code>, which is also
+available in the Roster menu or by typing <kbd>e</kbd> on a person in the
+roster buffer.
+
+ </body></html>
+
diff --git a/html/Presence.html b/html/Presence.html
new file mode 100644
index 0000000..d720a38
--- /dev/null
+++ b/html/Presence.html
@@ -0,0 +1,91 @@
+<html lang="en">
+<head>
+<title>Presence - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link rel="prev" href="Chatting.html#Chatting" title="Chatting">
+<link rel="next" href="Presence-subscription.html#Presence-subscription" title="Presence subscription">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Presence"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Presence-subscription.html#Presence-subscription">Presence subscription</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Chatting.html#Chatting">Chatting</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Basic-operation.html#Basic-operation">Basic operation</a>
+<hr><br>
+</div>
+
+<h3 class="section">2.3 Presence</h3>
+
+<p><a name="index-Presence-7"></a><a name="index-Sending-presence-8"></a><a name="index-jabber_002dsend_002dpresence-9"></a><a name="index-jabber_002dsend_002ddefault_002dpresence-10"></a><a name="index-jabber_002ddefault_002dshow-11"></a><a name="index-jabber_002ddefault_002dstatus-12"></a><a name="index-jabber_002ddefault_002dpriority-13"></a>
+&ldquo;Presence&rdquo; is the Jabber term for letting other people know that you
+are online, and additionally how &ldquo;available&rdquo; you are. There are
+three elements to presence: availability status (called &ldquo;show&rdquo;),
+status message, and priority.
+
+ <p>Your show status may either be empty (meaning simply &ldquo;online&rdquo;), or
+one of <code>away</code>, <code>xa</code>, <code>dnd</code> and <code>chat</code>, meaning
+&ldquo;away&rdquo;, &ldquo;extended away&rdquo; (i.e. away for an extended period), &ldquo;do
+not disturb&rdquo;, and &ldquo;free for chat&rdquo;, respectively. This information
+is available to everyone subscribing to your presence, but technically
+it does not restrict anyone's actions. You can chat with people even
+if you claim to be away.
+
+ <p>The status message is a short text complementing your show status,
+such as &ldquo;at home&rdquo;, &ldquo;working&rdquo;, &ldquo;phone&rdquo;, &ldquo;playing games&rdquo; or
+whatever you want. It is sent to everyone subscribing to your
+presence, but not all clients prominently display it to the user.
+
+ <p>The priority is only interesting if you are running more than one
+Jabber client at a time accessing the same account. In that case,
+messages sent to you without an indication of which client to send to
+are sent to the client with the highest priority.
+
+ <p>To set your presence, use the function <code>jabber-send-presence</code>.
+It can be called both interactively and in Lisp code. For the latter
+case, use something like <code>(jabber-send-presence "away" "idle for
+10 minutes" 10)</code>.
+
+ <p>By default, jabber.el sets your presence when you connect. If you
+want it not to do that, remove <code>jabber-send-default-presence</code>
+from <code>jabber-post-connect-hook</code>. If you want to change the
+presence that is sent, change the variables
+<code>jabber-default-show</code>, <code>jabber-default-status</code> and
+<code>jabber-default-priority</code>.
+
+ <p>With jabber.el, you can set your presence remotely. See <a href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands">Ad-Hoc Commands</a>.
+
+ <p><a name="index-directed-presence-14"></a><a name="index-send-directed-presence-15"></a><a name="index-jabber_002dsend_002ddirected_002dpresence-16"></a>You can send &ldquo;directed presence&rdquo; with <kbd>M-x
+jabber-send-directed-presence</kbd>. This is mostly useful to manage
+transports&mdash;sending directed presence is a way to turn them on and
+off. You can also send directed presence to an annoying contact to
+appear as away or offline to that contact. Note, however, that in both
+of these cases, all subscribed entities will get your next global
+presence update.
+
+ </body></html>
+
diff --git a/html/Private-messages.html b/html/Private-messages.html
new file mode 100644
index 0000000..106cfef
--- /dev/null
+++ b/html/Private-messages.html
@@ -0,0 +1,57 @@
+<html lang="en">
+<head>
+<title>Private messages - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Groupchat.html#Groupchat" title="Groupchat">
+<link rel="prev" href="Invitations.html#Invitations" title="Invitations">
+<link rel="next" href="MUC-Administration.html#MUC-Administration" title="MUC Administration">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Private-messages"></a>Next:&nbsp;<a rel="next" accesskey="n" href="MUC-Administration.html#MUC-Administration">MUC Administration</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Invitations.html#Invitations">Invitations</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Groupchat.html#Groupchat">Groupchat</a>
+<hr><br>
+</div>
+
+<h3 class="section">3.3 Private messages</h3>
+
+<p><a name="index-Private-MUC-messages-45"></a><a name="index-jabber_002dmuc_002dprivate-46"></a>
+You can open a private chat with a participant in a chat room with
+<kbd>M-x jabber-muc-private</kbd> (or by using the MUC menu). This creates
+a buffer with the name
+<code>*-jabber-muc-priv-</code><var>group</var><code>-</code><var>nickname</var><code>-*</code> (customizable by
+<code>jabber-muc-private-buffer-format</code>), which behaves mostly like an
+ordinary chat buffer. This buffer will also be created if someone
+sends a private message to you.
+
+ <p>Private MUC messages use the same alerts as normal chat messages.
+See <a href="Message-alerts.html#Message-alerts">Message alerts</a>.
+
+ </body></html>
+
diff --git a/html/Protocol-support.html b/html/Protocol-support.html
new file mode 100644
index 0000000..4448210
--- /dev/null
+++ b/html/Protocol-support.html
@@ -0,0 +1,77 @@
+<html lang="en">
+<head>
+<title>Protocol support - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="next" href="Concept-index.html#Concept-index" title="Concept index">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Protocol-support"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Concept-index.html#Concept-index">Concept index</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="appendix">Appendix A Protocol support</h2>
+
+<p><a name="index-Supported-protocols-252"></a>
+These are the protocols currently supported (in full or partially) by
+jabber.el.
+
+<ul class="menu">
+<li><a accesskey="1" href="RFC-3920.html#RFC-3920">RFC 3920</a>: XMPP-CORE
+<li><a accesskey="2" href="RFC-3921.html#RFC-3921">RFC 3921</a>: XMPP-IM
+<li><a accesskey="3" href="XEP_002d0004.html#XEP_002d0004">XEP-0004</a>: Data Forms
+<li><a accesskey="4" href="XEP_002d0012.html#XEP_002d0012">XEP-0012</a>: Last Activity
+<li><a accesskey="5" href="XEP_002d0020.html#XEP_002d0020">XEP-0020</a>: Feature Negotiation
+<li><a accesskey="6" href="XEP_002d0022.html#XEP_002d0022">XEP-0022</a>: Message Events
+<li><a accesskey="7" href="XEP_002d0030.html#XEP_002d0030">XEP-0030</a>: Service Discovery
+<li><a accesskey="8" href="XEP_002d0045.html#XEP_002d0045">XEP-0045</a>: Multi-User Chat
+<li><a accesskey="9" href="XEP_002d0049.html#XEP_002d0049">XEP-0049</a>: Private XML Storage
+<li><a href="XEP_002d0050.html#XEP_002d0050">XEP-0050</a>: Ad-Hoc Commands
+<li><a href="XEP_002d0054.html#XEP_002d0054">XEP-0054</a>: vcard-temp
+<li><a href="XEP_002d0055.html#XEP_002d0055">XEP-0055</a>: Jabber Search
+<li><a href="XEP_002d0065.html#XEP_002d0065">XEP-0065</a>: SOCKS5 Bytestreams
+<li><a href="XEP_002d0066.html#XEP_002d0066">XEP-0066</a>: Out of Band Data
+<li><a href="XEP_002d0068.html#XEP_002d0068">XEP-0068</a>: Field Standardization for Data Forms
+<li><a href="XEP_002d0077.html#XEP_002d0077">XEP-0077</a>: In-Band Registration
+<li><a href="XEP_002d0078.html#XEP_002d0078">XEP-0078</a>: Non-SASL Authentication
+<li><a href="XEP_002d0082.html#XEP_002d0082">XEP-0082</a>: Jabber Date and Time Profiles
+<li><a href="XEP_002d0086.html#XEP_002d0086">XEP-0086</a>: Error Condition Mappings
+<li><a href="XEP_002d0090.html#XEP_002d0090">XEP-0090</a>: Entity Time
+<li><a href="XEP_002d0091.html#XEP_002d0091">XEP-0091</a>: Delayed Delivery
+<li><a href="XEP_002d0092.html#XEP_002d0092">XEP-0092</a>: Software Version
+<li><a href="XEP_002d0095.html#XEP_002d0095">XEP-0095</a>: Stream Initiation
+<li><a href="XEP_002d0096.html#XEP_002d0096">XEP-0096</a>: File Transfer
+<li><a href="XEP_002d0146.html#XEP_002d0146">XEP-0146</a>: Remote Controlling Clients
+<li><a href="XEP_002d0153.html#XEP_002d0153">XEP-0153</a>: vCard-Based Avatars
+</ul>
+
+ </body></html>
+
diff --git a/html/RFC-3920.html b/html/RFC-3920.html
new file mode 100644
index 0000000..f442dd8
--- /dev/null
+++ b/html/RFC-3920.html
@@ -0,0 +1,60 @@
+<html lang="en">
+<head>
+<title>RFC 3920 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="next" href="RFC-3921.html#RFC-3921" title="RFC 3921">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="RFC-3920"></a>Next:&nbsp;<a rel="next" accesskey="n" href="RFC-3921.html#RFC-3921">RFC 3921</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Protocol-support.html#Protocol-support">Protocol support</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.1 RFC 3920 (XMPP-CORE)</h3>
+
+<p>Most of RFC 3920 is supported, with the following exceptions.
+
+ <p>SASL is supported only when an external SASL library from FLIM or Gnus
+is present. As SASL is an essential part to XMPP, jabber.el will send
+pre-XMPP stream headers if it is not available.
+
+ <p>None of the stringprep profiles are implemented. jabber.el changes
+JIDs to lowercase internally; that's all.
+
+ <p>jabber.el doesn't interpret namespace prefixes.
+
+ <p>The <code>xml:lang</code> attribute is neither interpreted nor generated.
+
+ <p>SRV records are used if a modern version of <code>dns.el</code> is installed.
+
+ </body></html>
+
diff --git a/html/RFC-3921.html b/html/RFC-3921.html
new file mode 100644
index 0000000..38702b1
--- /dev/null
+++ b/html/RFC-3921.html
@@ -0,0 +1,58 @@
+<html lang="en">
+<head>
+<title>RFC 3921 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="RFC-3920.html#RFC-3920" title="RFC 3920">
+<link rel="next" href="XEP_002d0004.html#XEP_002d0004" title="XEP-0004">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="RFC-3921"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0004.html#XEP_002d0004">XEP-0004</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="RFC-3920.html#RFC-3920">RFC 3920</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.2 RFC 3921 (XMPP-IM)</h3>
+
+<p>Most of RFC 3921 is supported, with the following exceptions.
+
+ <p>Messages of type &ldquo;headline&rdquo; are not treated in any special way.
+
+ <p>The <code>&lt;thread/&gt;</code> element is not used or generated.
+
+ <p>Sending &ldquo;directed presence&rdquo; is supported; however, presence stanzas
+received from contacts not in roster are ignored.
+
+ <p>Privacy lists are not supported at all.
+
+ <p>jabber.el doesn't support XMPP-E2E or &ldquo;im:&rdquo; CPIM URIs.
+
+ </body></html>
+
diff --git a/html/Receiving-files.html b/html/Receiving-files.html
new file mode 100644
index 0000000..a01a036
--- /dev/null
+++ b/html/Receiving-files.html
@@ -0,0 +1,67 @@
+<html lang="en">
+<head>
+<title>Receiving files - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="File-transfer.html#File-transfer" title="File transfer">
+<link rel="prev" href="File-transfer.html#File-transfer" title="File transfer">
+<link rel="next" href="Sending-files.html#Sending-files" title="Sending files">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Receiving-files"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Sending-files.html#Sending-files">Sending files</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="File-transfer.html#File-transfer">File transfer</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="File-transfer.html#File-transfer">File transfer</a>
+<hr><br>
+</div>
+
+<h3 class="section">5.1 Receiving files</h3>
+
+<p>Receiving files requires no configuration. When someone wants to send a
+file to you, you are asked (through <code>yes-or-no-p</code>) whether you want
+to accept the file. If you answer yes, you get to choose where to save
+the file.
+
+ <p>If the sender's client is correctly configured (this is often not the
+case; see below), the file transfer will start. Currently, the only way
+to watch the progress is to inspect the buffer of the file being
+transfered; <kbd>C-x C-b</kbd> is one way of doing that. See <a href="../emacs/List-Buffers.html#List-Buffers">Listing Existing Buffers (GNU Emacs Manual)</a>. When the transfer
+is done, the message &ldquo;<var>file</var> downloaded&rdquo; appears in the echo area,
+and the buffer is killed.
+
+ <p>If this doesn't happen, it is most likely the sender's fault. The
+sender needs to have a public IP address, either directly, through port
+forwarding (in which case the client needs to be configured with the
+real public IP address), or through an XEP-0065 proxy. If you have
+activated XML logging (see <a href="Debug-options.html#Debug-options">Debug options</a>), you can see the IP
+address that the other client is asking you to connect to there. Often
+you will find that this is an internal IP address (often starts with
+<code>192.168</code>). See the documentation of the sender's client for
+setting this up.
+
+ </body></html>
+
diff --git a/html/Registering.html b/html/Registering.html
new file mode 100644
index 0000000..8dd7642
--- /dev/null
+++ b/html/Registering.html
@@ -0,0 +1,78 @@
+<html lang="en">
+<head>
+<title>Registering - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Services.html#Services" title="Services">
+<link rel="prev" href="Service-discovery-and-browsing.html#Service-discovery-and-browsing" title="Service discovery and browsing">
+<link rel="next" href="Searching.html#Searching" title="Searching">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Registering"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Searching.html#Searching">Searching</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Services.html#Services">Services</a>
+<hr><br>
+</div>
+
+<h3 class="section">6.2 Registering</h3>
+
+<p><a name="index-Registration-72"></a><a name="index-Cancelling-registration-73"></a><a name="index-Changing-password-74"></a><a name="index-Gateway-registration-75"></a><a name="index-Password-change-76"></a><a name="index-Account-removal-77"></a><a name="index-Removing-an-account-78"></a><a name="index-jabber_002dget_002dregister-79"></a>
+Some services, in particular user directories and gateways to legacy
+IM systems, require registration. To register with such a service,
+either type <kbd>M-x jabber-get-register</kbd> or select it from the
+Service menu, which is opened by typing <kbd>C-c C-s</kbd>. You have to
+know the service's JID, possibly from service discovery.
+(see <a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a>)
+
+ <p>This is also the way to change your registration details, e.g. your
+password &mdash; just ask to register with that service again. To change
+the password of your Jabber account, ask to register with your Jabber
+server.
+
+ <p>Please note that any passwords sent in this way will be sent in
+cleartext to your Jabber server, unless you have enabled SSL encryption
+(see <a href="Connection-settings.html#Connection-settings">Connection settings</a>), and possibly sent in cleartext from your
+server to the server hosting the service.
+
+ <p>jabber.el will then request a registration form from that service. If
+for some reason the service does not answer (maybe network problems,
+or some services neither support registration nor report errors about
+that) that will be the last thing you saw about it. jabber.el will
+not report timeout errors, but rather simply wait until you shut it
+down.
+
+ <p>Once the response arrives, the form will be rendered in a browse
+buffer. Just fill out the fields, and hit Submit. You will receive
+confirmation of your registration in the echo area.
+
+ <p>To cancel an existing registration (and also for cancelling your
+Jabber account, if you sent a registration request to your server),
+hit Cancel. The unregistration will be confirmed in the echo area.
+
+ </body></html>
+
diff --git a/html/Roster-buffer.html b/html/Roster-buffer.html
new file mode 100644
index 0000000..616b5a2
--- /dev/null
+++ b/html/Roster-buffer.html
@@ -0,0 +1,77 @@
+<html lang="en">
+<head>
+<title>Roster buffer - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Basic-operation.html#Basic-operation" title="Basic operation">
+<link rel="prev" href="Presence-subscription.html#Presence-subscription" title="Presence subscription">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Roster-buffer"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Presence-subscription.html#Presence-subscription">Presence subscription</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Basic-operation.html#Basic-operation">Basic operation</a>
+<hr><br>
+</div>
+
+<h3 class="section">2.5 The roster buffer</h3>
+
+<p><a name="index-Roster-buffer_002c-basics-20"></a><a name="index-Menus-21"></a><a name="index-Key-bindings-22"></a><a name="index-jabber_002ddisplay_002droster-23"></a>
+The roster buffer is called <code>*-jabber-*</code>. It simply contains a
+list of the contacts on your roster.
+
+ <p>In the roster buffer, any command which requires a JID will default to
+the JID under point when called. These commands can be called through
+either keyboard menus or mouse menus. To open a menu with the mouse,
+simply press the second mouse button over the JID in
+question.<a rel="footnote" href="#fn-1" name="fnd-1"><sup>1</sup></a> This will bring up a menu with all available
+actions. The keyboard menus are split into categories: Chat, Roster,
+Information, MUC (Multi-User Chat, or groupchat) and Services, opened
+by <kbd>C-c C-c</kbd>, <kbd>C-c C-r</kbd>, <kbd>C-c C-i</kbd>, <kbd>C-c C-m</kbd> and
+<kbd>C-c C-s</kbd>, respectively.
+
+ <p>A list of keybindings is displayed at the top of the roster buffer.
+You can turn it off by setting <code>jabber-roster-show-bindings</code> to
+nil.
+
+ <p>You can call <code>jabber-display-roster</code> to redisplay your roster
+according to changed preferences (see <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a>). This will not refetch your roster from the server.
+Refetching the roster is usually not needed, since updates are pushed
+to clients automatically.
+
+ <p>You can choose not to have the roster updated automatically on
+presence changes (see <a href="Presence-alerts.html#Presence-alerts">Presence alerts</a>). In that case, you need to
+call <code>jabber-display-roster</code> manually.
+
+ <div class="footnote">
+<hr>
+<h4>Footnotes</h4><p class="footnote"><small>[<a name="fn-1" href="#fnd-1">1</a>]</small> For some reason, mouse menus don't work in XEmacs.
+Patches welcome.</p>
+
+ <p><hr></div>
+
+ </body></html>
+
diff --git a/html/Roster-import-and-export.html b/html/Roster-import-and-export.html
new file mode 100644
index 0000000..362ba93
--- /dev/null
+++ b/html/Roster-import-and-export.html
@@ -0,0 +1,62 @@
+<html lang="en">
+<head>
+<title>Roster import and export - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Message-events.html#Message-events" title="Message events">
+<link rel="next" href="XMPP-URIs.html#XMPP-URIs" title="XMPP URIs">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Roster-import-and-export"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Message-events.html#Message-events">Message events</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">13 Roster import and export</h2>
+
+<p><a name="index-jabber_002dexport_002droster-144"></a><a name="index-jabber_002dimport_002droster-145"></a><a name="index-Export-roster-146"></a><a name="index-Import-roster-147"></a>
+Your roster is saved on the Jabber server, and usually not in the
+client. However, you might want to save the roster to a file anyway.
+The most common reason for this is probably to copy it to another
+account.
+
+ <p>To export your roster to a file, type <kbd>M-x jabber-export-roster</kbd>.
+A buffer will appear in which you can edit the data to be exported.
+Changes done in that buffer will not affect your real roster.
+
+ <p>To import your roster from a file, type <kbd>M-x jabber-import-roster</kbd>.
+You will be able to edit the data before importing it. Items not in the
+roster will be added; items in the roster will be modified to match
+imported data. Subscriptions will be updated.
+
+ <p>The format of the roster files is the XML used by roster pushes in the
+XMPP protocol, in UTF-8 encoding.
+
+ </body></html>
+
diff --git a/html/Roster-structure.html b/html/Roster-structure.html
new file mode 100644
index 0000000..ba0fdd3
--- /dev/null
+++ b/html/Roster-structure.html
@@ -0,0 +1,81 @@
+<html lang="en">
+<head>
+<title>Roster structure - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="prev" href="XML-representation.html#XML-representation" title="XML representation">
+<link rel="next" href="Listening-for-new-requests.html#Listening-for-new-requests" title="Listening for new requests">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Roster-structure"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XML-representation.html#XML-representation">XML representation</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<hr><br>
+</div>
+
+<h3 class="section">16.2 Roster structure</h3>
+
+<p><a name="index-_002ajabber_002droster_002a-229"></a><a name="index-jabber_002djid_002dobarray-230"></a>
+Roster entries are contained in the list <code>*jabber-roster*</code>.
+
+ <p>A roster entry is a symbol. Its name is the JID, and it is interned
+in <code>jabber-jid-obarray</code>. A roster entry can have the following
+properties:
+
+ <dl>
+<dt><code>xml</code><dd>The XML tag received from the server on roster update
+
+ <br><dt><code>name</code><dd>The name of the roster item (just like the XML attribute)
+
+ <br><dt><code>subscription</code><dd>The subscription state (also copied)
+
+ <br><dt><code>ask</code><dd>The ask state (copied)
+
+ <br><dt><code>groups</code><dd>A list of strings (possibly empty) containing all the groups the
+contact is in
+
+ <br><dt><code>connected</code><dd>Boolean, true if any resource is connected
+
+ <br><dt><code>show</code><dd>Presence show status for highest-priority connected resource
+
+ <br><dt><code>status</code><dd>Presence status message for highest-priority connected resource
+
+ <br><dt><code>resources</code><dd>Alist. Keys are strings (resource names), values are plists with
+properties <code>connected</code>, <code>show</code>, <code>status</code> and
+<code>priority</code>.
+
+ </dl>
+
+ <p>Incoming presence information is inserted in <code>resources</code>, and the
+information from the resource with the highest priority is inserted in
+<code>show</code> and <code>status</code> by the function
+<code>jabber-prioritize-resources</code>.
+
+ </body></html>
+
diff --git a/html/Searching.html b/html/Searching.html
new file mode 100644
index 0000000..0be0e38
--- /dev/null
+++ b/html/Searching.html
@@ -0,0 +1,59 @@
+<html lang="en">
+<head>
+<title>Searching - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Services.html#Services" title="Services">
+<link rel="prev" href="Registering.html#Registering" title="Registering">
+<link rel="next" href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands" title="Ad-Hoc Commands">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Searching"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands">Ad-Hoc Commands</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Registering.html#Registering">Registering</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Services.html#Services">Services</a>
+<hr><br>
+</div>
+
+<h3 class="section">6.3 Searching</h3>
+
+<p><a name="index-Searching-80"></a><a name="index-jabber_002dget_002dsearch-81"></a>
+Some services, notably user directories and gateways to legacy IM
+systems, allow searching. Searching in Jabber generally means
+searching for someone's JID, but the protocol is general enough to
+support most databases.
+
+ <p>To search a service, either type <kbd>M-x jabber-get-search</kbd> or select
+it from the Service menu, which is opened by typing <kbd>C-c C-s</kbd>.
+
+ <p>Just like with registration, this command sends a request for a search
+form, and displays it if and when the response arrives. Enter your
+search and submit it. Search results will be displayed in a different
+browse buffer.
+
+ </body></html>
+
diff --git a/html/Sending-files.html b/html/Sending-files.html
new file mode 100644
index 0000000..6685489
--- /dev/null
+++ b/html/Sending-files.html
@@ -0,0 +1,82 @@
+<html lang="en">
+<head>
+<title>Sending files - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="File-transfer.html#File-transfer" title="File transfer">
+<link rel="prev" href="Receiving-files.html#Receiving-files" title="Receiving files">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Sending-files"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Receiving-files.html#Receiving-files">Receiving files</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="File-transfer.html#File-transfer">File transfer</a>
+<hr><br>
+</div>
+
+<h3 class="section">5.2 Sending files</h3>
+
+<p><a name="index-proxy_002c-file-transfer-60"></a><a name="index-file-transfer-proxy-61"></a><a name="index-XEP_002d0065-proxy-62"></a>
+To send a file to someone, you need an XEP-0065 proxy.<a rel="footnote" href="#fn-1" name="fnd-1"><sup>1</sup></a> If your Jabber server hosts such a proxy, it will be found
+automatically, otherwise it needs to be manually configured.
+
+ <p>You can check whether your Jabber server has a proxy with <kbd>M-x
+jabber-get-disco-items</kbd>; see <a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a>.
+
+ <p><a name="index-jabber_002dsocks5_002dproxies-63"></a><a name="index-jabber_002dsocks5_002dquery_002dall_002dproxies-64"></a>To configure a proxy manually, customize the variable
+<code>jabber-socks5-proxies</code>. Putting <code>proxy.jabber.se</code> there
+should work. Type <kbd>M-x jabber-socks5-query-all-proxies</kbd> to see if
+the proxies answer.
+
+ <p><a name="index-jabber_002dft_002dsend-65"></a>Now, you can type <kbd>M-x jabber-ft-send</kbd> to send a file to someone.
+You need to enter the correct full JID, including resource, to get this
+right. If the contact is logged in with only one client, and you can
+see it online, just typing the JID or roster name is enough. If you run
+the command from a chat buffer, the JID of the contact is given as
+the default value.
+
+ <p>If the contact has several clients online, you probably want to send the
+file to a particular one. If you run this command from within a chat
+buffer, the default target will be the one that last sent a message to
+you. If you just type a bare JID or a roster name, the client with the
+highest priority will get the file.
+
+ <p>If the contact accepts the file, and the contact's client succeeds in
+connecting to the proxy, jabber.el will send the file through the
+proxy. During this time, your Emacs will be blocked, so you might want
+to avoid sending large files over slow connections.
+
+ <div class="footnote">
+<hr>
+<h4>Footnotes</h4><p class="footnote"><small>[<a name="fn-1" href="#fnd-1">1</a>]</small> This
+requirement is not inherent in the protocol, only in the current file
+transfer implementation of jabber.el, and in Emacs versions earlier than
+22.</p>
+
+ <p><hr></div>
+
+ </body></html>
+
diff --git a/html/Sending-new-requests.html b/html/Sending-new-requests.html
new file mode 100644
index 0000000..e77c2d3
--- /dev/null
+++ b/html/Sending-new-requests.html
@@ -0,0 +1,86 @@
+<html lang="en">
+<head>
+<title>Sending new requests - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="prev" href="Listening-for-new-requests.html#Listening-for-new-requests" title="Listening for new requests">
+<link rel="next" href="Extending-service-discovery.html#Extending-service-discovery" title="Extending service discovery">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Sending-new-requests"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Extending-service-discovery.html#Extending-service-discovery">Extending service discovery</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<hr><br>
+</div>
+
+<h3 class="section">16.4 Sending new requests</h3>
+
+<p><a name="index-jabber_002dsend_002diq-236"></a><a name="index-jabber_002dprocess_002diq-237"></a><a name="index-jabber_002dreport_002dsuccess-238"></a><a name="index-jabber_002dprocess_002ddata-239"></a>
+To send an IQ request, use <code>jabber-send-iq</code>. It will generate an
+id, and create a mapping for it for use when the response comes. The
+syntax is:
+
+<pre class="example"> (jabber-send-iq <var>to</var> <var>type</var> <var>query</var>
+ <var>success-callback</var> <var>success-closure</var>
+ <var>failure-callback</var> <var>failure-closure</var>)
+</pre>
+ <p>Both callbacks take two arguments, the IQ stanza returned and the
+closure item mentioned here.
+
+ <p>Two standard callbacks are provided. <code>jabber-report-success</code>
+takes a string as closure item, and reports success or failure in the
+echo area. <code>jabber-process-data</code> prepares a browse buffer. If
+its closure argument is a function, it calls that function with point
+in this browse buffer. If it's a string, it prints that string along
+with the error message in the IQ response. If it's anything else
+(e.g. <code>nil</code>), it just dumps the XML in the browse buffer.
+
+ <p>Examples follow. This is the hypothetical Jabber protocol &ldquo;frob&rdquo;,
+for which only success report is needed:
+<pre class="example"> (jabber-send-iq "someone@somewhere.org" "set"
+ '(query ((xmlns . "frob")))
+ 'jabber-report-success "Frobbing"
+ 'jabber-report-success "Frobbing")
+</pre>
+ <p>This will print &ldquo;Frobbing succeeded&rdquo; or &ldquo;Frobbing failed: reason&rdquo;,
+respectively, in the echo area.
+
+ <p>The protocol &ldquo;investigate&rdquo; needs to parse results and show them in a
+browse buffer:
+<pre class="example"> (jabber-send-iq "someone@somewhere.org" "get"
+ '(query ((xmlns . "investigate")))
+ 'jabber-process-data 'jabber-process-investigate
+ 'jabber-process-data "Investigation failed")
+</pre>
+ <p>Of course, the previous example could have used
+<code>jabber-report-success</code> for the error message. It's a matter of
+UI taste.
+
+ </body></html>
+
diff --git a/html/Service-discovery-and-browsing.html b/html/Service-discovery-and-browsing.html
new file mode 100644
index 0000000..54f28a8
--- /dev/null
+++ b/html/Service-discovery-and-browsing.html
@@ -0,0 +1,68 @@
+<html lang="en">
+<head>
+<title>Service discovery and browsing - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Services.html#Services" title="Services">
+<link rel="prev" href="Services.html#Services" title="Services">
+<link rel="next" href="Registering.html#Registering" title="Registering">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Service-discovery-and-browsing"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Registering.html#Registering">Registering</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Services.html#Services">Services</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Services.html#Services">Services</a>
+<hr><br>
+</div>
+
+<h3 class="section">6.1 Service discovery and browsing</h3>
+
+<p><a name="index-Service-discovery-67"></a><a name="index-Browsing-68"></a><a name="index-jabber_002dget_002dbrowse-69"></a><a name="index-jabber_002dget_002ddisco_002ditems-70"></a><a name="index-jabber_002dget_002ddisco_002dinfo-71"></a>
+To find services you want to use, you need to discover them first.
+This can be done with either service discovery or browsing. Service
+discovery is the newer and preferred protocol, while browsing is still
+used by much software. The use of both is very similar.
+
+ <p>The most common use of service discovery is to browse your home
+server, to see what services are provided locally. Note, however,
+that this is no restriction; you can use services from all over the
+network.
+
+ <p>For service discovery there are two commands,
+<code>jabber-get-disco-items</code> and <code>jabber-get-disco-info</code>,
+depending on whether you want information about that specific JID or
+about services related to it, respectively. To start browsing, type
+<kbd>M-x jabber-get-browse</kbd> and enter the JID you want to browse.
+
+ <p>These commands can be accessed from the Info menu, which is opened by
+typing <kbd>C-c C-i</kbd>.
+
+ <p>If you think that the interface to service discovery is awkward and
+should be replaced with something better, you are completely right.
+
+ </body></html>
+
diff --git a/html/Services.html b/html/Services.html
new file mode 100644
index 0000000..904c4e0
--- /dev/null
+++ b/html/Services.html
@@ -0,0 +1,63 @@
+<html lang="en">
+<head>
+<title>Services - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="File-transfer.html#File-transfer" title="File transfer">
+<link rel="next" href="Personal-information.html#Personal-information" title="Personal information">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Services"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Personal-information.html#Personal-information">Personal information</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="File-transfer.html#File-transfer">File transfer</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">6 Services</h2>
+
+<p><a name="index-Browse-buffers-66"></a>
+Not every Jabber entity is a physical person. There are many
+automatic entities, called servers, services, components, agents,
+transports and other names. The use of these is described here.
+
+ <p>The functions described in this chapter use <dfn>browse buffers</dfn>.
+Browse buffers are named <code>*-jabber-browse-:-</code><var>service</var><code>-*</code>,
+sometimes with a numerical suffix. The different menus have the same
+keybindings as in the roster buffer, and if you call a function
+operating on a JID while point is over a JID, that JID will be the
+default value, so you don't have to type it or copy it yourself.
+
+<ul class="menu">
+<li><a accesskey="1" href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">Service discovery and browsing</a>
+<li><a accesskey="2" href="Registering.html#Registering">Registering</a>
+<li><a accesskey="3" href="Searching.html#Searching">Searching</a>
+<li><a accesskey="4" href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands">Ad-Hoc Commands</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Spell-checking.html b/html/Spell-checking.html
new file mode 100644
index 0000000..4ecef4b
--- /dev/null
+++ b/html/Spell-checking.html
@@ -0,0 +1,51 @@
+<html lang="en">
+<head>
+<title>Spell checking - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="prev" href="Watch-buddies.html#Watch-buddies" title="Watch buddies">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Spell-checking"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Watch-buddies.html#Watch-buddies">Watch buddies</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Useful-features.html#Useful-features">Useful features</a>
+<hr><br>
+</div>
+
+<h3 class="section">10.6 Spell checking</h3>
+
+<p><a name="index-flyspell-124"></a><a name="index-Spell-checking-125"></a>
+You can activate spell checking in a chat buffer with <kbd>M-x
+flyspell-mode</kbd>. It will check only what you are currently writing, not
+what you receive or what you have already sent. You may want to add
+<code>flyspell-mode</code> to <code>jabber-chat-mode-hook</code>.
+
+ <p>For more information about Emacs spell checking, See <a href="../emacs/Spelling.html#Spelling">Checking and Correcting Spelling (GNU Emacs Manual)</a>.
+
+ </body></html>
+
diff --git a/html/Standard-alerts.html b/html/Standard-alerts.html
new file mode 100644
index 0000000..6d40bd5
--- /dev/null
+++ b/html/Standard-alerts.html
@@ -0,0 +1,101 @@
+<html lang="en">
+<head>
+<title>Standard alerts - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link rel="prev" href="Customizing-alerts.html#Customizing-alerts" title="Customizing alerts">
+<link rel="next" href="Presence-alerts.html#Presence-alerts" title="Presence alerts">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Standard-alerts"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Presence-alerts.html#Presence-alerts">Presence alerts</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Customizing-alerts.html#Customizing-alerts">Customizing alerts</a>
+<hr><br>
+</div>
+
+<h4 class="subsection">15.6.1 Standard alerts</h4>
+
+<p><a name="index-Alerts-209"></a><a name="index-Scroll-210"></a>
+Eight alerts are already written for all four alert categories. These
+all obey the result from the corresponding message function.
+
+ <p>The <code>beep</code> alerts simply sound the terminal bell by calling
+<code>ding</code>. They are disabled by default.
+
+ <p>The <code>echo</code> alerts display a message in the echo area by calling
+<code>message</code>. They are enabled by default.
+
+ <p>The <code>switch</code> alerts switch to the buffer where the event occurred
+(chat buffer for incoming messages, roster buffer for presence
+changes, browse buffer for completed queries). They are disabled by
+default. Take care when using them, as they may interrupt your
+editing.
+
+ <p>The <code>display</code> alerts display but do not select the buffer in
+question, using the function <code>display-buffer</code>. See <a href="../elisp/Choosing-Window.html#Choosing-Window">Choosing a Window for Display (GNU Emacs Lisp Reference Manual)</a>, for information about customizing its behaviour.
+This is enabled by default for info requests.
+
+ <p>The <code>wave</code> alerts play a sound file by calling
+<code>play-sound-file</code>. No sound files are provided. To use this,
+enter the names of the sound files in
+<code>jabber-alert-message-wave</code>, <code>jabber-alert-presence-wave</code>
+and <code>jabber-alert-info-wave</code>, respectively. You can specify
+specific sound files for contacts matching a regexp in the variables
+<code>jabber-alert-message-wave-alist</code> and
+<code>jabber-alert-presence-wave-alist</code>.
+
+ <p>The <code>screen</code> alerts send a message through the Screen terminal
+manager (see <a href="http://www.gnu.org/software/screen/">http://www.gnu.org/software/screen/</a>). They do no
+harm if called when you don't use Screen.
+
+ <p>The <code>ratpoison</code> alerts send a message through the Ratpoison
+window manager (see <a href="http://ratpoison.sourceforge.net/">http://ratpoison.sourceforge.net/</a>). They
+do no harm if used when you're not running X, but if you are running X
+with another window manager, the ratpoison processes will never exit.
+You can look at them with <code>list-processes</code>.
+
+ <p>The <code>sawfish</code> alerts send a message through the Sawfish window
+manager.
+
+ <p>The <code>festival</code> alerts speak the message using the Emacs interface
+of the Festival speech synthesis system (see
+<a href="http://www.cstr.ed.ac.uk/projects/festival/">http://www.cstr.ed.ac.uk/projects/festival/</a>).
+
+ <p>Additionally, for one-to-one and MUC messages, there are <code>scroll</code>
+alerts (enabled by default), that aim to do the right thing with chat
+buffers that are visible but not active. Sometimes you want point to
+scroll down, and sometimes not. These functions should do what you
+mean; if they don't, it's a bug.
+
+ <p>Some of these functions are in the <span class="file">jabber-alert.el</span> file, and the
+others are in their own files. You can use them as templates or
+inspiration for your own alerts.
+
+ </body></html>
+
diff --git a/html/Stanza-chains.html b/html/Stanza-chains.html
new file mode 100644
index 0000000..27cac6f
--- /dev/null
+++ b/html/Stanza-chains.html
@@ -0,0 +1,52 @@
+<html lang="en">
+<head>
+<title>Stanza chains - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="prev" href="Chat-printers.html#Chat-printers" title="Chat printers">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Stanza-chains"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Chat-printers.html#Chat-printers">Chat printers</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<hr><br>
+</div>
+
+<h3 class="section">16.7 Stanza chains</h3>
+
+<p><a name="index-jabber_002dmessage_002dchain-249"></a><a name="index-jabber_002diq_002dchain-250"></a><a name="index-jabber_002dpresence_002dchain-251"></a>
+If you really need to get under the skin of jabber.el, you can add
+functions to the lists <code>jabber-message-chain</code>,
+<code>jabber-iq-chain</code> and <code>jabber-presence-chain</code>. The functions
+in these lists will be called in order when an XML stanza of the
+corresponding type arrives, with the entire XML stanza passed as the
+only argument. Earlier functions can modify the stanza to change the
+behaviour of downstream functions.
+
+ </body></html>
+
diff --git a/html/Time-queries.html b/html/Time-queries.html
new file mode 100644
index 0000000..08760bc
--- /dev/null
+++ b/html/Time-queries.html
@@ -0,0 +1,56 @@
+<html lang="en">
+<head>
+<title>Time queries - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Avatars.html#Avatars" title="Avatars">
+<link rel="next" href="Useful-features.html#Useful-features" title="Useful features">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Time-queries"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Useful-features.html#Useful-features">Useful features</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Avatars.html#Avatars">Avatars</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">9 Time queries</h2>
+
+<p><a name="index-time-query-93"></a><a name="index-jabber_002dget_002dtime-94"></a>With <kbd>M-x jabber-get-time</kbd>, you can ask what time an entity (client,
+server or component) thinks it is, and what time zone it thinks it is
+in.
+
+ <p><a name="index-last-online-95"></a><a name="index-jabber_002dget_002dlast_002donline-96"></a>You can query a server about when a certain user was last seen online.
+Use <kbd>M-x jabber-get-last-online</kbd> for that.
+
+ <p><a name="index-uptime_002c-query-97"></a><a name="index-idle-time_002c-query-98"></a><a name="index-jabber_002dget_002didle_002dtime-99"></a>You can also ask a client about how long a user has been idle with
+<kbd>M-x jabber-get-idle-time</kbd>. Not all clients support this,
+e.g. jabber.el doesn't. This command can also tell the uptime of a
+server or component.
+
+ </body></html>
+
diff --git a/html/Tracking-activity.html b/html/Tracking-activity.html
new file mode 100644
index 0000000..a50d380
--- /dev/null
+++ b/html/Tracking-activity.html
@@ -0,0 +1,77 @@
+<html lang="en">
+<head>
+<title>Tracking activity - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="prev" href="Keepalive.html#Keepalive" title="Keepalive">
+<link rel="next" href="Watch-buddies.html#Watch-buddies" title="Watch buddies">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Tracking-activity"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Watch-buddies.html#Watch-buddies">Watch buddies</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Keepalive.html#Keepalive">Keepalive</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Useful-features.html#Useful-features">Useful features</a>
+<hr><br>
+</div>
+
+<h3 class="section">10.4 Tracking activity</h3>
+
+<p><a name="index-Activity-114"></a><a name="index-jabber_002dactivity_002dmode-115"></a><a name="index-jabber_002dactivity_002dmake_002dstrings-116"></a><a name="index-jabber_002dactivity_002dquery_002dunread-117"></a><a name="index-jabber_002dactivity_002dcount_002din_002dtitle-118"></a><a name="index-jabber_002dactivity_002dcount_002din_002dtitle_002dformat-119"></a>
+When you're working on something important you might want to delay
+responding to incoming messages. However, when you're done working,
+will you remember them? If you're anything like me, you'll have a lot
+of buffers in your Emacs session, and a jabber chat buffer can easily
+get lost.
+
+ <p>When you type <kbd>M-x jabber-activity-mode</kbd> Emacs starts keeping
+track of the buddies which have messaged you since last you visited
+their buffer, and will display them in mode line. As soon as you
+visit their buffer they disappear from the mode line, indicating that
+you've read their message.
+
+ <p>If your mode line fills over because of these notifications, you can
+customize <code>jabber-activity-make-strings</code> to shorten them to the
+shortest possibly unambiguous form.
+
+ <p>If you try to exit Emacs while you still have unread messages, you
+will be notified and asked about this. If you don't like that, set
+<code>jabber-activity-query-unread</code> to nil.
+
+ <p>If you want to display the number of unread buffers in the frame title,
+set <code>jabber-activity-count-in-title</code> to t. The format of the
+number can be changed through
+<code>jabber-activity-count-in-title-format</code>.
+
+ <p>For complete customizability, write a hook function for
+<code>jabber-activity-update-hook</code>. From that function, you can take
+action based on <code>jabber-activity-jids</code>,
+<code>jabber-activity-mode-string</code>, and
+<code>jabber-activity-count-string</code>.
+
+ </body></html>
+
diff --git a/html/Useful-features.html b/html/Useful-features.html
new file mode 100644
index 0000000..7277744
--- /dev/null
+++ b/html/Useful-features.html
@@ -0,0 +1,56 @@
+<html lang="en">
+<head>
+<title>Useful features - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Time-queries.html#Time-queries" title="Time queries">
+<link rel="next" href="Message-history.html#Message-history" title="Message history">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Useful-features"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Message-history.html#Message-history">Message history</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Time-queries.html#Time-queries">Time queries</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">10 Useful features</h2>
+
+<p>jabber.el includes a number of features meant to improve the user
+interface and do other useful things.
+
+<ul class="menu">
+<li><a accesskey="1" href="Autoaway.html#Autoaway">Autoaway</a>
+<li><a accesskey="2" href="Modeline-status.html#Modeline-status">Modeline status</a>
+<li><a accesskey="3" href="Keepalive.html#Keepalive">Keepalive</a>
+<li><a accesskey="4" href="Tracking-activity.html#Tracking-activity">Tracking activity</a>
+<li><a accesskey="5" href="Watch-buddies.html#Watch-buddies">Watch buddies</a>
+<li><a accesskey="6" href="Spell-checking.html#Spell-checking">Spell checking</a>
+</ul>
+
+ </body></html>
+
diff --git a/html/Variable-index.html b/html/Variable-index.html
new file mode 100644
index 0000000..f745fa3
--- /dev/null
+++ b/html/Variable-index.html
@@ -0,0 +1,132 @@
+<html lang="en">
+<head>
+<title>Variable index - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Function-index.html#Function-index" title="Function index">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Variable-index"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="Function-index.html#Function-index">Function index</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="unnumbered">Variable index</h2>
+
+
+
+<ul class="index-vr" compact>
+<li><a href="Roster-structure.html#index-_002ajabber_002droster_002a-229"><code>*jabber-roster*</code></a>: <a href="Roster-structure.html#Roster-structure">Roster structure</a></li>
+<li><a href="Tracking-activity.html#index-jabber_002dactivity_002dcount_002din_002dtitle-118"><code>jabber-activity-count-in-title</code></a>: <a href="Tracking-activity.html#Tracking-activity">Tracking activity</a></li>
+<li><a href="Tracking-activity.html#index-jabber_002dactivity_002dcount_002din_002dtitle_002dformat-119"><code>jabber-activity-count-in-title-format</code></a>: <a href="Tracking-activity.html#Tracking-activity">Tracking activity</a></li>
+<li><a href="Tracking-activity.html#index-jabber_002dactivity_002dmake_002dstrings-116"><code>jabber-activity-make-strings</code></a>: <a href="Tracking-activity.html#Tracking-activity">Tracking activity</a></li>
+<li><a href="Tracking-activity.html#index-jabber_002dactivity_002dquery_002dunread-117"><code>jabber-activity-query-unread</code></a>: <a href="Tracking-activity.html#Tracking-activity">Tracking activity</a></li>
+<li><a href="Extending-service-discovery.html#index-jabber_002dadvertised_002dfeatures-240"><code>jabber-advertised-features</code></a>: <a href="Extending-service-discovery.html#Extending-service-discovery">Extending service discovery</a></li>
+<li><a href="Info-alerts.html#index-jabber_002dalert_002dinfo_002dmessage_002dfunction-219"><code>jabber-alert-info-message-function</code></a>: <a href="Info-alerts.html#Info-alerts">Info alerts</a></li>
+<li><a href="Message-alerts.html#index-jabber_002dalert_002dmessage_002dfunction-213"><code>jabber-alert-message-function</code></a>: <a href="Message-alerts.html#Message-alerts">Message alerts</a></li>
+<li><a href="MUC-alerts.html#index-jabber_002dalert_002dmuc_002dfunction-216"><code>jabber-alert-muc-function</code></a>: <a href="MUC-alerts.html#MUC-alerts">MUC alerts</a></li>
+<li><a href="Presence-alerts.html#index-jabber_002dalert_002dpresence_002dmessage_002dfunction-211"><code>jabber-alert-presence-message-function</code></a>: <a href="Presence-alerts.html#Presence-alerts">Presence alerts</a></li>
+<li><a href="Autoaway.html#index-jabber_002dautoaway_002dmethod-103"><code>jabber-autoaway-method</code></a>: <a href="Autoaway.html#Autoaway">Autoaway</a></li>
+<li><a href="Avatars.html#index-jabber_002davatar_002dcache_002ddirectory-92"><code>jabber-avatar-cache-directory</code></a>: <a href="Avatars.html#Avatars">Avatars</a></li>
+<li><a href="Message-history.html#index-jabber_002dbacklog_002ddays-136"><code>jabber-backlog-days</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Message-history.html#index-jabber_002dbacklog_002dnumber-135"><code>jabber-backlog-number</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Chat-printers.html#index-jabber_002dbody_002dprinters-246"><code>jabber-body-printers</code></a>: <a href="Chat-printers.html#Chat-printers">Chat printers</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002ddelayed_002dtime_002dformat-199"><code>jabber-chat-delayed-time-format</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dfill_002dlong_002dlines-205"><code>jabber-chat-fill-long-lines</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dforeign_002dprompt_002dformat-197"><code>jabber-chat-foreign-prompt-format</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dheader_002dline_002dformat-203"><code>jabber-chat-header-line-format</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dlocal_002dprompt_002dformat-196"><code>jabber-chat-local-prompt-format</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Hooks.html#index-jabber_002dchat_002dmode_002dhook-225"><code>jabber-chat-mode-hook</code></a>: <a href="Hooks.html#Hooks">Hooks</a></li>
+<li><a href="Chat-printers.html#index-jabber_002dchat_002dprinters-244"><code>jabber-chat-printers</code></a>: <a href="Chat-printers.html#Chat-printers">Chat printers</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dprompt_002dforeign-195"><code>jabber-chat-prompt-foreign</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dprompt_002dlocal-194"><code>jabber-chat-prompt-local</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dtext_002dforeign-193"><code>jabber-chat-text-foreign</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dtext_002dlocal-192"><code>jabber-chat-text-local</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dtext_002dlocalBy-default_002c-timestamps-are-printed-in-the-chat-buffer-every-hour-_0028at-202"><code>jabber-chat-text-localBy default, timestamps are printed in the chat buffer every hour (at</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dchat_002dtime_002dformat-198"><code>jabber-chat-time-format</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Connection-settings.html#index-jabber_002dconnection_002dssl_002dprogram-169"><code>jabber-connection-ssl-program</code></a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Connection-settings.html#index-jabber_002dconnection_002dtype-168"><code>jabber-connection-type</code></a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Debug-options.html#index-jabber_002ddebug_002dlog_002dxml-226"><code>jabber-debug-log-xml</code></a>: <a href="Debug-options.html#Debug-options">Debug options</a></li>
+<li><a href="Account-settings.html#index-jabber_002ddefault_002dpriority-162"><code>jabber-default-priority</code></a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="Presence.html#index-jabber_002ddefault_002dpriority-13"><code>jabber-default-priority</code></a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Presence.html#index-jabber_002ddefault_002dshow-11"><code>jabber-default-show</code></a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Presence.html#index-jabber_002ddefault_002dstatus-12"><code>jabber-default-status</code></a>: <a href="Presence.html#Presence">Presence</a></li>
+<li><a href="Extending-service-discovery.html#index-jabber_002ddisco_002dinfo_002dnodes-242"><code>jabber-disco-info-nodes</code></a>: <a href="Extending-service-discovery.html#Extending-service-discovery">Extending service discovery</a></li>
+<li><a href="Extending-service-discovery.html#index-jabber_002ddisco_002ditems_002dnodes-241"><code>jabber-disco-items-nodes</code></a>: <a href="Extending-service-discovery.html#Extending-service-discovery">Extending service discovery</a></li>
+<li><a href="Message-events.html#index-jabber_002devents_002dconfirm_002dcomposing-143"><code>jabber-events-confirm-composing</code></a>: <a href="Message-events.html#Message-events">Message events</a></li>
+<li><a href="Message-events.html#index-jabber_002devents_002dconfirm_002ddelivered-141"><code>jabber-events-confirm-delivered</code></a>: <a href="Message-events.html#Message-events">Message events</a></li>
+<li><a href="Message-events.html#index-jabber_002devents_002dconfirm_002ddisplayed-142"><code>jabber-events-confirm-displayed</code></a>: <a href="Message-events.html#Message-events">Message events</a></li>
+<li><a href="Message-events.html#index-jabber_002devents_002drequest_002dthese-140"><code>jabber-events-request-these</code></a>: <a href="Message-events.html#Message-events">Message events</a></li>
+<li><a href="Message-history.html#index-jabber_002dglobal_002dhistory_002dfilename-130"><code>jabber-global-history-filename</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Message-history.html#index-jabber_002dhistory_002ddir-132"><code>jabber-history-dir</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Message-history.html#index-jabber_002dhistory_002denable_002drotation-133"><code>jabber-history-enable-rotation</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Message-history.html#index-jabber_002dhistory_002denabled-129"><code>jabber-history-enabled</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Message-history.html#index-jabber_002dhistory_002dsize_002dlimit-134"><code>jabber-history-size-limit</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Stanza-chains.html#index-jabber_002diq_002dchain-250"><code>jabber-iq-chain</code></a>: <a href="Stanza-chains.html#Stanza-chains">Stanza chains</a></li>
+<li><a href="Listening-for-new-requests.html#index-jabber_002diq_002dget_002dxmlns_002dalist-234"><code>jabber-iq-get-xmlns-alist</code></a>: <a href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a></li>
+<li><a href="Listening-for-new-requests.html#index-jabber_002diq_002dset_002dxmlns_002dalist-235"><code>jabber-iq-set-xmlns-alist</code></a>: <a href="Listening-for-new-requests.html#Listening-for-new-requests">Listening for new requests</a></li>
+<li><a href="Roster-structure.html#index-jabber_002djid_002dobarray-230"><code>jabber-jid-obarray</code></a>: <a href="Roster-structure.html#Roster-structure">Roster structure</a></li>
+<li><a href="Keepalive.html#index-jabber_002dkeepalive_002dinterval-112"><code>jabber-keepalive-interval</code></a>: <a href="Keepalive.html#Keepalive">Keepalive</a></li>
+<li><a href="Keepalive.html#index-jabber_002dkeepalive_002dtimeout-113"><code>jabber-keepalive-timeout</code></a>: <a href="Keepalive.html#Keepalive">Keepalive</a></li>
+<li><a href="Hooks.html#index-jabber_002dlost_002dconnection_002dhook-222"><code>jabber-lost-connection-hook</code></a>: <a href="Hooks.html#Hooks">Hooks</a></li>
+<li><a href="Message-alerts.html#index-jabber_002dmessage_002dalert_002dsame_002dbuffer-215"><code>jabber-message-alert-same-buffer</code></a>: <a href="Message-alerts.html#Message-alerts">Message alerts</a></li>
+<li><a href="Stanza-chains.html#index-jabber_002dmessage_002dchain-249"><code>jabber-message-chain</code></a>: <a href="Stanza-chains.html#Stanza-chains">Stanza chains</a></li>
+<li><a href="Modeline-status.html#index-jabber_002dmode_002dline_002dcompact-107"><code>jabber-mode-line-compact</code></a>: <a href="Modeline-status.html#Modeline-status">Modeline status</a></li>
+<li><a href="Modeline-status.html#index-jabber_002dmode_002dline_002dmode-106"><code>jabber-mode-line-mode</code></a>: <a href="Modeline-status.html#Modeline-status">Modeline status</a></li>
+<li><a href="MUC-alerts.html#index-jabber_002dmuc_002dalert_002dself-217"><code>jabber-muc-alert-self</code></a>: <a href="MUC-alerts.html#MUC-alerts">MUC alerts</a></li>
+<li><a href="Automation.html#index-jabber_002dmuc_002dautojoin-39"><code>jabber-muc-autojoin</code></a>: <a href="Automation.html#Automation">Automation</a></li>
+<li><a href="Automation.html#index-jabber_002dmuc_002ddefault_002dnicknames-38"><code>jabber-muc-default-nicknames</code></a>: <a href="Automation.html#Automation">Automation</a></li>
+<li><a href="Groupchat.html#index-jabber_002dmuc_002ddisable_002ddisco_002dcheck-32"><code>jabber-muc-disable-disco-check</code></a>: <a href="Groupchat.html#Groupchat">Groupchat</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dmuc_002dheader_002dline_002dformat-204"><code>jabber-muc-header-line-format</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Chat-printers.html#index-jabber_002dmuc_002dprinters-245"><code>jabber-muc-printers</code></a>: <a href="Chat-printers.html#Chat-printers">Chat printers</a></li>
+<li><a href="Connection-settings.html#index-jabber_002dnetwork_002dserver-166"><code>jabber-network-server</code></a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Account-settings.html#index-jabber_002dnickname-163"><code>jabber-nickname</code></a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="Account-settings.html#index-jabber_002dpassword-160"><code>jabber-password</code></a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="Connection-settings.html#index-jabber_002dport-167"><code>jabber-port</code></a>: <a href="Connection-settings.html#Connection-settings">Connection settings</a></li>
+<li><a href="Hooks.html#index-jabber_002dpost_002dconnect_002dhook-221"><code>jabber-post-connect-hook</code></a>: <a href="Hooks.html#Hooks">Hooks</a></li>
+<li><a href="Hooks.html#index-jabber_002dpost_002ddisconnect_002dhook-224"><code>jabber-post-disconnect-hook</code></a>: <a href="Hooks.html#Hooks">Hooks</a></li>
+<li><a href="Hooks.html#index-jabber_002dpre_002ddisconnect_002dhook-223"><code>jabber-pre-disconnect-hook</code></a>: <a href="Hooks.html#Hooks">Hooks</a></li>
+<li><a href="Stanza-chains.html#index-jabber_002dpresence_002dchain-251"><code>jabber-presence-chain</code></a>: <a href="Stanza-chains.html#Stanza-chains">Stanza chains</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002dprint_002drare_002dtime-200"><code>jabber-print-rare-time</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Customizing-the-chat-buffer.html#index-jabber_002drare_002dtime_002dformat-201"><code>jabber-rare-time-format</code></a>: <a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">Customizing the chat buffer</a></li>
+<li><a href="Account-settings.html#index-jabber_002dresource-161"><code>jabber-resource</code></a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-jabber_002dresource_002dline_002dformat-184"><code>jabber-resource-line-format</code></a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-jabber_002droster_002dbuffer-185"><code>jabber-roster-buffer</code></a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-jabber_002droster_002dline_002dformat-183"><code>jabber-roster-line-format</code></a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-jabber_002droster_002dshow_002dbindings-186"><code>jabber-roster-show-bindings</code></a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-jabber_002droster_002dsort_002dfunctions-180"><code>jabber-roster-sort-functions</code></a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Account-settings.html#index-jabber_002dserver-159"><code>jabber-server</code></a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-jabber_002dshow_002dresources-182"><code>jabber-show-resources</code></a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Sending-files.html#index-jabber_002dsocks5_002dproxies-63"><code>jabber-socks5-proxies</code></a>: <a href="Sending-files.html#Sending-files">Sending files</a></li>
+<li><a href="Customizing-the-roster-buffer.html#index-jabber_002dsort_002dorder-181"><code>jabber-sort-order</code></a>: <a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">Customizing the roster buffer</a></li>
+<li><a href="Message-history.html#index-jabber_002duse_002dglobal_002dhistory-131"><code>jabber-use-global-history</code></a>: <a href="Message-history.html#Message-history">Message history</a></li>
+<li><a href="Account-settings.html#index-jabber_002dusername-158"><code>jabber-username</code></a>: <a href="Account-settings.html#Account-settings">Account settings</a></li>
+<li><a href="Avatars.html#index-jabber_002dvcard_002davatars_002dpublish-91"><code>jabber-vcard-avatars-publish</code></a>: <a href="Avatars.html#Avatars">Avatars</a></li>
+<li><a href="Avatars.html#index-jabber_002dvcard_002davatars_002dretrieve-90"><code>jabber-vcard-avatars-retrieve</code></a>: <a href="Avatars.html#Avatars">Avatars</a></li>
+ </ul></body></html>
+
diff --git a/html/Watch-buddies.html b/html/Watch-buddies.html
new file mode 100644
index 0000000..7fa43ff
--- /dev/null
+++ b/html/Watch-buddies.html
@@ -0,0 +1,57 @@
+<html lang="en">
+<head>
+<title>Watch buddies - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Useful-features.html#Useful-features" title="Useful features">
+<link rel="prev" href="Tracking-activity.html#Tracking-activity" title="Tracking activity">
+<link rel="next" href="Spell-checking.html#Spell-checking" title="Spell checking">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="Watch-buddies"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Spell-checking.html#Spell-checking">Spell checking</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Tracking-activity.html#Tracking-activity">Tracking activity</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Useful-features.html#Useful-features">Useful features</a>
+<hr><br>
+</div>
+
+<h3 class="section">10.5 Watch buddies</h3>
+
+<p><a name="index-Watch-120"></a><a name="index-Online-notifications-121"></a><a name="index-jabber_002dwatch_002dadd-122"></a><a name="index-jabber_002dwatch_002dremove-123"></a>
+Sometimes you might be waiting for a certain person to come online,
+and you don't want that occasion to get lost in the noise. To get an
+obtrusive message when that happens, type <kbd>M-x jabber-watch-add</kbd>
+and select the person in question. You can enter a comment, to
+remember why you added the watch.
+
+ <p>You will get a message whenever that person goes from offline to
+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
+of it, type <kbd>M-x jabber-watch-remove</kbd>.
+
+ </body></html>
+
diff --git a/html/XEP_002d0004.html b/html/XEP_002d0004.html
new file mode 100644
index 0000000..bd9c3d4
--- /dev/null
+++ b/html/XEP_002d0004.html
@@ -0,0 +1,61 @@
+<html lang="en">
+<head>
+<title>XEP-0004 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="RFC-3921.html#RFC-3921" title="RFC 3921">
+<link rel="next" href="XEP_002d0012.html#XEP_002d0012" title="XEP-0012">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0004"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0012.html#XEP_002d0012">XEP-0012</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="RFC-3921.html#RFC-3921">RFC 3921</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.3 XEP-0004 (Data Forms)</h3>
+
+<p>XEP-0004 support is good enough for many purposes. Limitations are
+the following.
+
+ <p>Forms in incoming messages are not interpreted. See each specific
+protocol for whether forms are accepted in that context.
+
+ <p>&ldquo;Cancel&rdquo; messages are probably not consistently generated when they
+should be. This is partly a paradigm clash, as jabber.el doesn't use
+modal dialog boxes but buffers which can easily be buried.
+
+ <p><code>&lt;required/&gt;</code> elements are not enforced.
+
+ <p>The field types &ldquo;jid-single&rdquo;, &ldquo;jid-multi&rdquo; and &ldquo;list-multi&rdquo; are
+not implemented, due to programmer laziness. Let us know if you need
+them.
+
+ </body></html>
+
diff --git a/html/XEP_002d0012.html b/html/XEP_002d0012.html
new file mode 100644
index 0000000..30aabdd
--- /dev/null
+++ b/html/XEP_002d0012.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0012 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0004.html#XEP_002d0004" title="XEP-0004">
+<link rel="next" href="XEP_002d0020.html#XEP_002d0020" title="XEP-0020">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0012"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0020.html#XEP_002d0020">XEP-0020</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0004.html#XEP_002d0004">XEP-0004</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.4 XEP-0012 (Last Activity)</h3>
+
+<p>jabber.el can generate all three query types described in the protocol.
+However, it does not answer to such requests.
+
+ </body></html>
+
diff --git a/html/XEP_002d0020.html b/html/XEP_002d0020.html
new file mode 100644
index 0000000..e83a877
--- /dev/null
+++ b/html/XEP_002d0020.html
@@ -0,0 +1,47 @@
+<html lang="en">
+<head>
+<title>XEP-0020 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0012.html#XEP_002d0012" title="XEP-0012">
+<link rel="next" href="XEP_002d0022.html#XEP_002d0022" title="XEP-0022">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0020"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0022.html#XEP_002d0022">XEP-0022</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0012.html#XEP_002d0012">XEP-0012</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.5 XEP-0020 (Feature Negotiation)</h3>
+
+<p>There are no known limitations or bugs in XEP-0020 support.
+
+ </body></html>
+
diff --git a/html/XEP_002d0022.html b/html/XEP_002d0022.html
new file mode 100644
index 0000000..992868b
--- /dev/null
+++ b/html/XEP_002d0022.html
@@ -0,0 +1,50 @@
+<html lang="en">
+<head>
+<title>XEP-0022 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0020.html#XEP_002d0020" title="XEP-0020">
+<link rel="next" href="XEP_002d0030.html#XEP_002d0030" title="XEP-0030">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0022"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0030.html#XEP_002d0030">XEP-0030</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0020.html#XEP_002d0020">XEP-0020</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.6 XEP-0022 (Message Events)</h3>
+
+<p>jabber.el understands all four specified kinds of message events
+(offline, delivered, displayed, and composing) and by default requests
+all of them. It also reports those three events that make sense for
+clients.
+
+ </body></html>
+
diff --git a/html/XEP_002d0030.html b/html/XEP_002d0030.html
new file mode 100644
index 0000000..3eb6cdf
--- /dev/null
+++ b/html/XEP_002d0030.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0030 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0022.html#XEP_002d0022" title="XEP-0022">
+<link rel="next" href="XEP_002d0045.html#XEP_002d0045" title="XEP-0045">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0030"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0045.html#XEP_002d0045">XEP-0045</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0022.html#XEP_002d0022">XEP-0022</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.7 XEP-0030 (Service Discovery)</h3>
+
+<p>Service discovery is supported, both as client and server. When used in
+the code, service discovery results are cached indefinitely.
+
+ </body></html>
+
diff --git a/html/XEP_002d0045.html b/html/XEP_002d0045.html
new file mode 100644
index 0000000..562edcd
--- /dev/null
+++ b/html/XEP_002d0045.html
@@ -0,0 +1,51 @@
+<html lang="en">
+<head>
+<title>XEP-0045 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0030.html#XEP_002d0030" title="XEP-0030">
+<link rel="next" href="XEP_002d0049.html#XEP_002d0049" title="XEP-0049">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0045"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0049.html#XEP_002d0049">XEP-0049</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0030.html#XEP_002d0030">XEP-0030</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.8 XEP-0045 (Multi-User Chat)</h3>
+
+<p>jabber.el supports parts of XEP-0045. Entering, leaving and chatting
+work. So do invitations and private messages. Room configuration is
+supported. Changing roles of participants (basic moderation) is
+implemented, as is changing affiliations, but requesting affiliation
+lists is not yet supported.
+
+ </body></html>
+
diff --git a/html/XEP_002d0049.html b/html/XEP_002d0049.html
new file mode 100644
index 0000000..cc3dbba
--- /dev/null
+++ b/html/XEP_002d0049.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0049 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0045.html#XEP_002d0045" title="XEP-0045">
+<link rel="next" href="XEP_002d0050.html#XEP_002d0050" title="XEP-0050">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0049"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0050.html#XEP_002d0050">XEP-0050</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0045.html#XEP_002d0045">XEP-0045</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.9 XEP-0049 (Private XML Storage)</h3>
+
+<p>jabber.el contains an implementation of XEP-0049; however it is not used
+for anything right now.
+
+ </body></html>
+
diff --git a/html/XEP_002d0050.html b/html/XEP_002d0050.html
new file mode 100644
index 0000000..cfa24a2
--- /dev/null
+++ b/html/XEP_002d0050.html
@@ -0,0 +1,49 @@
+<html lang="en">
+<head>
+<title>XEP-0050 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0049.html#XEP_002d0049" title="XEP-0049">
+<link rel="next" href="XEP_002d0054.html#XEP_002d0054" title="XEP-0054">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0050"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0054.html#XEP_002d0054">XEP-0054</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0049.html#XEP_002d0049">XEP-0049</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.10 XEP-0050 (Ad-Hoc Commands)</h3>
+
+<p>jabber.el is probably the first implementation of XEP-0050 (see
+<a href="http://article.gmane.org/gmane.network.jabber.devel/21413">post on jdev from 2004-03-10</a>). Both the client and server parts are
+supported.
+
+ </body></html>
+
diff --git a/html/XEP_002d0054.html b/html/XEP_002d0054.html
new file mode 100644
index 0000000..fe2bdbf
--- /dev/null
+++ b/html/XEP_002d0054.html
@@ -0,0 +1,49 @@
+<html lang="en">
+<head>
+<title>XEP-0054 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0050.html#XEP_002d0050" title="XEP-0050">
+<link rel="next" href="XEP_002d0055.html#XEP_002d0055" title="XEP-0055">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0054"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0055.html#XEP_002d0055">XEP-0055</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0050.html#XEP_002d0050">XEP-0050</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.11 XEP-0054 (vcard-temp)</h3>
+
+<p>Both displaying other users' vCards and editing your own vCard are
+supported. The implementation tries to follow the schema in the XEP
+accurately.
+
+ </body></html>
+
diff --git a/html/XEP_002d0055.html b/html/XEP_002d0055.html
new file mode 100644
index 0000000..af32d82
--- /dev/null
+++ b/html/XEP_002d0055.html
@@ -0,0 +1,50 @@
+<html lang="en">
+<head>
+<title>XEP-0055 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0054.html#XEP_002d0054" title="XEP-0054">
+<link rel="next" href="XEP_002d0065.html#XEP_002d0065" title="XEP-0065">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0055"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0065.html#XEP_002d0065">XEP-0065</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0054.html#XEP_002d0054">XEP-0054</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.12 XEP-0055 (Jabber Search)</h3>
+
+<p>XEP-0055 is supported, both with traditional fields and with Data Forms
+(see <a href="XEP_002d0004.html#XEP_002d0004">XEP-0004</a>). As the traditional fields specified by the XEP is a
+subset of those allowed in XEP-0077, handling of those two form types
+are merged. See <a href="XEP_002d0077.html#XEP_002d0077">XEP-0077</a>.
+
+ </body></html>
+
diff --git a/html/XEP_002d0065.html b/html/XEP_002d0065.html
new file mode 100644
index 0000000..85ec52b
--- /dev/null
+++ b/html/XEP_002d0065.html
@@ -0,0 +1,54 @@
+<html lang="en">
+<head>
+<title>XEP-0065 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0055.html#XEP_002d0055" title="XEP-0055">
+<link rel="next" href="XEP_002d0066.html#XEP_002d0066" title="XEP-0066">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0065"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0066.html#XEP_002d0066">XEP-0066</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0055.html#XEP_002d0055">XEP-0055</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.13 XEP-0065 (SOCKS5 Bytestreams)</h3>
+
+<p>XEP-0065 is supported. Currently jabber.el cannot act as a server, not
+even on on Emacsen that support server sockets (GNU Emacs 22 and up).
+Therefore it relies on proxies. Proxies have to be entered and queried
+manually.
+
+ <p>Psi's &ldquo;fast mode&rdquo;
+(<a href="http://delta.affinix.com/specs/stream.html">http://delta.affinix.com/specs/stream.html</a>), which gives
+greater flexibility with regards to NAT, is not implemented.
+
+ </body></html>
+
diff --git a/html/XEP_002d0066.html b/html/XEP_002d0066.html
new file mode 100644
index 0000000..4c2da3f
--- /dev/null
+++ b/html/XEP_002d0066.html
@@ -0,0 +1,50 @@
+<html lang="en">
+<head>
+<title>XEP-0066 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0065.html#XEP_002d0065" title="XEP-0065">
+<link rel="next" href="XEP_002d0068.html#XEP_002d0068" title="XEP-0068">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0066"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0068.html#XEP_002d0068">XEP-0068</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0065.html#XEP_002d0065">XEP-0065</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.14 XEP-0066 (Out of Band Data)</h3>
+
+<p>jabber.el will display URLs sent in message stanzas qualified by
+the <code>jabber:x:oob</code> namespace, as described in this XEP. Sending
+such URLs or doing anything with iq stanzas (using the
+<code>jabber:iq:oob</code> namespace) is not supported.
+
+ </body></html>
+
diff --git a/html/XEP_002d0068.html b/html/XEP_002d0068.html
new file mode 100644
index 0000000..ed27e6c
--- /dev/null
+++ b/html/XEP_002d0068.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0068 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0066.html#XEP_002d0066" title="XEP-0066">
+<link rel="next" href="XEP_002d0077.html#XEP_002d0077" title="XEP-0077">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0068"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0077.html#XEP_002d0077">XEP-0077</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0066.html#XEP_002d0066">XEP-0066</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.15 XEP-0068 (Field Standardization for Data Forms)</h3>
+
+<p>XEP-0068 is only used in the context of creating a new Jabber account,
+to prefill the username field of the registration form.
+
+ </body></html>
+
diff --git a/html/XEP_002d0077.html b/html/XEP_002d0077.html
new file mode 100644
index 0000000..9a82526
--- /dev/null
+++ b/html/XEP_002d0077.html
@@ -0,0 +1,54 @@
+<html lang="en">
+<head>
+<title>XEP-0077 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0068.html#XEP_002d0068" title="XEP-0068">
+<link rel="next" href="XEP_002d0078.html#XEP_002d0078" title="XEP-0078">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0077"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0078.html#XEP_002d0078">XEP-0078</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0068.html#XEP_002d0068">XEP-0068</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.16 XEP-0077 (In-Band Registration)</h3>
+
+<p>In-band registration is supported for all purposes. That means
+registering a new Jabber account, changing Jabber password, removing a
+Jabber account, registering with a service, and cancelling
+registration to a service. Data forms are supported as well. URL
+redirections are not.
+
+ <p>jabber.el will not prevent or alert a user trying to change a password
+over an unencrypted connection.
+
+ </body></html>
+
diff --git a/html/XEP_002d0078.html b/html/XEP_002d0078.html
new file mode 100644
index 0000000..3b73985
--- /dev/null
+++ b/html/XEP_002d0078.html
@@ -0,0 +1,49 @@
+<html lang="en">
+<head>
+<title>XEP-0078 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0077.html#XEP_002d0077" title="XEP-0077">
+<link rel="next" href="XEP_002d0082.html#XEP_002d0082" title="XEP-0082">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0078"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0082.html#XEP_002d0082">XEP-0082</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0077.html#XEP_002d0077">XEP-0077</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.17 XEP-0078 (Non-SASL Authentication)</h3>
+
+<p>Non-SASL authentication is supported, both plaintext and digest.
+Digest is preferred, and a warning is displayed to the user if only
+plaintext is available.
+
+ </body></html>
+
diff --git a/html/XEP_002d0082.html b/html/XEP_002d0082.html
new file mode 100644
index 0000000..3613f00
--- /dev/null
+++ b/html/XEP_002d0082.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0082 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0078.html#XEP_002d0078" title="XEP-0078">
+<link rel="next" href="XEP_002d0086.html#XEP_002d0086" title="XEP-0086">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0082"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0086.html#XEP_002d0086">XEP-0086</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0078.html#XEP_002d0078">XEP-0078</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.18 XEP-0082 (Jabber Date and Time Profiles)</h3>
+
+<p>The DateTime profile of XEP-0082 is supported. Currently this is only
+used for file transfer.
+
+ </body></html>
+
diff --git a/html/XEP_002d0086.html b/html/XEP_002d0086.html
new file mode 100644
index 0000000..e5fcd1d
--- /dev/null
+++ b/html/XEP_002d0086.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0086 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0082.html#XEP_002d0082" title="XEP-0082">
+<link rel="next" href="XEP_002d0090.html#XEP_002d0090" title="XEP-0090">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0086"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0090.html#XEP_002d0090">XEP-0090</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0082.html#XEP_002d0082">XEP-0082</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.19 XEP-0086 (Error Condition Mappings)</h3>
+
+<p>Legacy errors are interpreted, but never generated. XMPP style error
+messages take precedence when errors are reported to the user.
+
+ </body></html>
+
diff --git a/html/XEP_002d0090.html b/html/XEP_002d0090.html
new file mode 100644
index 0000000..b80b5ab
--- /dev/null
+++ b/html/XEP_002d0090.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0090 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0086.html#XEP_002d0086" title="XEP-0086">
+<link rel="next" href="XEP_002d0091.html#XEP_002d0091" title="XEP-0091">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0090"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0091.html#XEP_002d0091">XEP-0091</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0086.html#XEP_002d0086">XEP-0086</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.20 XEP-0090 (Entity Time)</h3>
+
+<p>jabber.el can query other entities for their time, and return the
+current time to those who ask.
+
+ </body></html>
+
diff --git a/html/XEP_002d0091.html b/html/XEP_002d0091.html
new file mode 100644
index 0000000..605f7ec
--- /dev/null
+++ b/html/XEP_002d0091.html
@@ -0,0 +1,48 @@
+<html lang="en">
+<head>
+<title>XEP-0091 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0090.html#XEP_002d0090" title="XEP-0090">
+<link rel="next" href="XEP_002d0092.html#XEP_002d0092" title="XEP-0092">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0091"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0092.html#XEP_002d0092">XEP-0092</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0090.html#XEP_002d0090">XEP-0090</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.21 XEP-0091 (Delayed Delivery)</h3>
+
+<p>The time specified on delayed incoming messages is interpreted, and
+displayed in chat buffers instead of the current time.
+
+ </body></html>
+
diff --git a/html/XEP_002d0092.html b/html/XEP_002d0092.html
new file mode 100644
index 0000000..600b606
--- /dev/null
+++ b/html/XEP_002d0092.html
@@ -0,0 +1,49 @@
+<html lang="en">
+<head>
+<title>XEP-0092 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0091.html#XEP_002d0091" title="XEP-0091">
+<link rel="next" href="XEP_002d0095.html#XEP_002d0095" title="XEP-0095">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0092"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0095.html#XEP_002d0095">XEP-0095</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0091.html#XEP_002d0091">XEP-0091</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.22 XEP-0092 (Software Version)</h3>
+
+<p>The user can request the version of any entity. jabber.el answers
+version requests to anyone, giving &ldquo;jabber.el&rdquo; as name, and the
+Emacs version as OS.
+
+ </body></html>
+
diff --git a/html/XEP_002d0095.html b/html/XEP_002d0095.html
new file mode 100644
index 0000000..265f961
--- /dev/null
+++ b/html/XEP_002d0095.html
@@ -0,0 +1,49 @@
+<html lang="en">
+<head>
+<title>XEP-0095 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0092.html#XEP_002d0092" title="XEP-0092">
+<link rel="next" href="XEP_002d0096.html#XEP_002d0096" title="XEP-0096">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0095"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0096.html#XEP_002d0096">XEP-0096</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0092.html#XEP_002d0092">XEP-0092</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.23 XEP-0095 (Stream Initiation)</h3>
+
+<p>XEP-0095 is supported, both incoming and outgoing, except that jabber.el
+doesn't check service discovery results before sending a stream
+initiation request.
+
+ </body></html>
+
diff --git a/html/XEP_002d0096.html b/html/XEP_002d0096.html
new file mode 100644
index 0000000..b30b5a9
--- /dev/null
+++ b/html/XEP_002d0096.html
@@ -0,0 +1,51 @@
+<html lang="en">
+<head>
+<title>XEP-0096 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0095.html#XEP_002d0095" title="XEP-0095">
+<link rel="next" href="XEP_002d0146.html#XEP_002d0146" title="XEP-0146">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0096"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0146.html#XEP_002d0146">XEP-0146</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0095.html#XEP_002d0095">XEP-0095</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.24 XEP-0096 (File Transfer)</h3>
+
+<p>Both sending and receiving files is supported. If a suitable program is
+found, MD5 hashes of outgoing files are calculated and sent. However,
+hashes of received files are not checked. Ranged transfers are not
+supported. In-band bytestreams are not yet supported, even though
+XEP-0096 requires them.
+
+ </body></html>
+
diff --git a/html/XEP_002d0146.html b/html/XEP_002d0146.html
new file mode 100644
index 0000000..8f0ed3b
--- /dev/null
+++ b/html/XEP_002d0146.html
@@ -0,0 +1,47 @@
+<html lang="en">
+<head>
+<title>XEP-0146 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0096.html#XEP_002d0096" title="XEP-0096">
+<link rel="next" href="XEP_002d0153.html#XEP_002d0153" title="XEP-0153">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0146"></a>Next:&nbsp;<a rel="next" accesskey="n" href="XEP_002d0153.html#XEP_002d0153">XEP-0153</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0096.html#XEP_002d0096">XEP-0096</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.25 XEP-0146 (Remote Controlling Clients)</h3>
+
+<p>The &ldquo;set-status&rdquo; command in XEP-0146 is supported.
+
+ </body></html>
+
diff --git a/html/XEP_002d0153.html b/html/XEP_002d0153.html
new file mode 100644
index 0000000..0289524
--- /dev/null
+++ b/html/XEP_002d0153.html
@@ -0,0 +1,46 @@
+<html lang="en">
+<head>
+<title>XEP-0153 - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Protocol-support.html#Protocol-support" title="Protocol support">
+<link rel="prev" href="XEP_002d0146.html#XEP_002d0146" title="XEP-0146">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XEP_002d0153"></a>Previous:&nbsp;<a rel="previous" accesskey="p" href="XEP_002d0146.html#XEP_002d0146">XEP-0146</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Protocol-support.html#Protocol-support">Protocol support</a>
+<hr><br>
+</div>
+
+<h3 class="section">A.26 XEP-0153 (vCard-Based Avatars)</h3>
+
+<p>vCard-based avatars are supported, both publishing and displaying. The
+pixel size limits on avatars are not enforced.
+
+ </body></html>
+
diff --git a/html/XML-representation.html b/html/XML-representation.html
new file mode 100644
index 0000000..0eecc87
--- /dev/null
+++ b/html/XML-representation.html
@@ -0,0 +1,71 @@
+<html lang="en">
+<head>
+<title>XML representation - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="up" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="prev" href="Hacking-and-extending.html#Hacking-and-extending" title="Hacking and extending">
+<link rel="next" href="Roster-structure.html#Roster-structure" title="Roster structure">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XML-representation"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Roster-structure.html#Roster-structure">Roster structure</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<hr><br>
+</div>
+
+<h3 class="section">16.1 XML representation</h3>
+
+<p><a name="index-XML-representation-228"></a>
+The XML representation is the one generated by <span class="file">xml.el</span> in Emacs,
+namely the following. Each tag is a list. The first element of the
+list is a symbol, the name of which is the name of the tag. The
+second element is an alist of attributes, where the keys are the
+attribute names in symbol form, and the values are strings. The
+remaining elements are the tags and data contained within the tag.
+
+ <p>For example,
+<pre class="example"> &lt;foo bar='baz'&gt;
+ &lt;frobozz/&gt;Fnord
+ &lt;/foo&gt;
+</pre>
+ <p>is represented as
+<pre class="example"> (foo ((bar . "baz")) (frobozz nil "") "Fnord
+ ")
+</pre>
+ <p>Note the empty string as the third element of the <code>frobozz</code>
+list. It is not present in newer (post-21.3) versions of
+<span class="file">xml.el</span>, but it's probably best to assume it might be there.
+
+ <p>If you want to see what an XML tag would look like, use
+<code>jabber-sexp2xml</code>, which takes a tag and returns a string. You
+will usually not need it in your code, as you can use
+<code>jabber-send-sexp</code> to send away your tags to the server.
+
+ </body></html>
+
diff --git a/html/XMPP-URIs.html b/html/XMPP-URIs.html
new file mode 100644
index 0000000..2333076
--- /dev/null
+++ b/html/XMPP-URIs.html
@@ -0,0 +1,84 @@
+<html lang="en">
+<head>
+<title>XMPP URIs - jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="index.html#Top">
+<link rel="prev" href="Roster-import-and-export.html#Roster-import-and-export" title="Roster import and export">
+<link rel="next" href="Customization.html#Customization" title="Customization">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<div class="node">
+<p>
+<a name="XMPP-URIs"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Customization.html#Customization">Customization</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="Roster-import-and-export.html#Roster-import-and-export">Roster import and export</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="index.html#Top">Top</a>
+<hr><br>
+</div>
+
+<h2 class="chapter">14 XMPP URIs</h2>
+
+<p><a name="index-URIs-148"></a><a name="index-URLs-149"></a><a name="index-links-150"></a><a name="index-xmpp_003a-links-151"></a><a name="index-Mozilla-integration-152"></a><a name="index-web-browser-integration-153"></a><a name="index-browser-integration-154"></a><a name="index-jabber_002dhandle_002duri-155"></a>
+Many web page authors use links starting with <span class="samp">xmpp:</span> for JIDs.
+Your web browser could be made to pass such links to jabber.el, so that
+such links are actually useful and not just decoration. How to do that
+depends on your operating system and web browser.
+
+<h3 class="section">14.1 Mozilla and Unix</h3>
+
+<p>If you use a Mozilla-based web browser on a Unix-like operating system,
+follow these steps.
+
+ <ol type=1 start=1>
+<li>Make sure you are running the Emacs server. See <a href="../emacs/Emacs-Server.html#Emacs-Server">Using Emacs as a Server (GNU Emacs Manual)</a>.
+
+ <li>Note the path of the <span class="file">xmppuri.sh</span> file in the jabber.el
+distribution, and make sure it is executable.
+
+ <li>Set the Mozilla preference <span class="samp">network.protocol-handler.app.xmpp</span> to
+the path of <span class="file">xmppuri.sh</span>. There are two ways to do this:
+
+ <ul>
+<li>Go to the URL <span class="samp">about:config</span>, right-click in the list, choose &ldquo;New
+string&rdquo;, and enter <span class="samp">network.protocol-handler.app.xmpp</span> and the
+path in the following dialogs.
+
+ <li>Open or create the file <span class="file">user.js</span> in your Mozilla profile directory
+(in the same directory as <span class="file">prefs.js</span>), and add the following line:
+
+ <pre class="example"> user_pref("network.protocol-handler.app.xmpp", "<var>/path/to</var>/xmppuri.sh");
+ </pre>
+ <p>Restart Mozilla for this change to take effect.
+</ul>
+ </ol>
+
+<h3 class="section">14.2 Other systems</h3>
+
+<p>If you know how to pass an XMPP URI from your browser to the function
+<code>jabber-handle-uri</code>, your contribution for this section would be
+appreciated.
+
+ </body></html>
+
diff --git a/html/index.html b/html/index.html
new file mode 100644
index 0000000..6f5f585
--- /dev/null
+++ b/html/index.html
@@ -0,0 +1,201 @@
+<html lang="en">
+<head>
+<title>jabber.el manual 0.7.1</title>
+<meta http-equiv="Content-Type" content="text/html">
+<meta name="description" content="jabber.el manual 0.7.1">
+<meta name="generator" content="makeinfo 4.7">
+<link title="Top" rel="start" href="#Top">
+<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
+<!--
+This manual is for jabber.el, version 0.7.1.
+
+Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+ -->
+<meta http-equiv="Content-Style-Type" content="text/css">
+<style type="text/css"><!--
+ pre.display { font-family:inherit }
+ pre.format { font-family:inherit }
+ pre.smalldisplay { font-family:inherit; font-size:smaller }
+ pre.smallformat { font-family:inherit; font-size:smaller }
+ pre.smallexample { font-size:smaller }
+ pre.smalllisp { font-size:smaller }
+ span.sc { font-variant:small-caps }
+ span.roman { font-family: serif; font-weight: normal; }
+--></style>
+</head>
+<body>
+<h1 class="settitle">jabber.el manual 0.7.1</h1>
+<div class="contents">
+<h2>Table of Contents</h2>
+<ul>
+<li><a name="toc_Top" href="index.html#Top">jabber.el manual</a>
+<li><a name="toc_Introduction" href="Introduction.html#Introduction">1 Introduction</a>
+<ul>
+<li><a href="Contact.html#Contact">1.1 Contact</a>
+</li></ul>
+<li><a name="toc_Basic-operation" href="Basic-operation.html#Basic-operation">2 Basic operation</a>
+<ul>
+<li><a href="Connecting.html#Connecting">2.1 Connecting</a>
+<li><a href="Chatting.html#Chatting">2.2 Chatting</a>
+<li><a href="Presence.html#Presence">2.3 Presence</a>
+<li><a href="Presence-subscription.html#Presence-subscription">2.4 Presence subscription</a>
+<li><a href="Roster-buffer.html#Roster-buffer">2.5 The roster buffer</a>
+</li></ul>
+<li><a name="toc_Groupchat" href="Groupchat.html#Groupchat">3 Groupchat</a>
+<ul>
+<li><a href="Automation.html#Automation">3.1 Automation</a>
+<li><a href="Invitations.html#Invitations">3.2 Invitations</a>
+<li><a href="Private-messages.html#Private-messages">3.3 Private messages</a>
+<li><a href="MUC-Administration.html#MUC-Administration">3.4 Administration</a>
+<ul>
+<li><a href="MUC-Administration.html#MUC-Administration">3.4.1 Roles</a>
+<li><a href="MUC-Administration.html#MUC-Administration">3.4.2 Affiliations</a>
+</li></ul>
+</li></ul>
+<li><a name="toc_Composing-messages" href="Composing-messages.html#Composing-messages">4 Composing messages</a>
+<li><a name="toc_File-transfer" href="File-transfer.html#File-transfer">5 File transfer</a>
+<ul>
+<li><a href="Receiving-files.html#Receiving-files">5.1 Receiving files</a>
+<li><a href="Sending-files.html#Sending-files">5.2 Sending files</a>
+</li></ul>
+<li><a name="toc_Services" href="Services.html#Services">6 Services</a>
+<ul>
+<li><a href="Service-discovery-and-browsing.html#Service-discovery-and-browsing">6.1 Service discovery and browsing</a>
+<li><a href="Registering.html#Registering">6.2 Registering</a>
+<li><a href="Searching.html#Searching">6.3 Searching</a>
+<li><a href="Ad_002dHoc-Commands.html#Ad_002dHoc-Commands">6.4 Ad-Hoc Commands</a>
+</li></ul>
+<li><a name="toc_Personal-information" href="Personal-information.html#Personal-information">7 Personal information</a>
+<li><a name="toc_Avatars" href="Avatars.html#Avatars">8 Avatars</a>
+<li><a name="toc_Time-queries" href="Time-queries.html#Time-queries">9 Time queries</a>
+<li><a name="toc_Useful-features" href="Useful-features.html#Useful-features">10 Useful features</a>
+<ul>
+<li><a href="Autoaway.html#Autoaway">10.1 Autoaway</a>
+<li><a href="Modeline-status.html#Modeline-status">10.2 Modeline status</a>
+<li><a href="Keepalive.html#Keepalive">10.3 Keepalive</a>
+<li><a href="Tracking-activity.html#Tracking-activity">10.4 Tracking activity</a>
+<li><a href="Watch-buddies.html#Watch-buddies">10.5 Watch buddies</a>
+<li><a href="Spell-checking.html#Spell-checking">10.6 Spell checking</a>
+</li></ul>
+<li><a name="toc_Message-history" href="Message-history.html#Message-history">11 Message history</a>
+<li><a name="toc_Message-events" href="Message-events.html#Message-events">12 Message events</a>
+<li><a name="toc_Roster-import-and-export" href="Roster-import-and-export.html#Roster-import-and-export">13 Roster import and export</a>
+<li><a name="toc_XMPP-URIs" href="XMPP-URIs.html#XMPP-URIs">14 XMPP URIs</a>
+<ul>
+<li><a href="XMPP-URIs.html#XMPP-URIs">14.1 Mozilla and Unix</a>
+<li><a href="XMPP-URIs.html#XMPP-URIs">14.2 Other systems</a>
+</li></ul>
+<li><a name="toc_Customization" href="Customization.html#Customization">15 Customization</a>
+<ul>
+<li><a href="Account-settings.html#Account-settings">15.1 Account settings</a>
+<li><a href="Connection-settings.html#Connection-settings">15.2 Connection settings</a>
+<li><a href="Miscellaneous-settings.html#Miscellaneous-settings">15.3 Miscellaneous settings</a>
+<li><a href="Customizing-the-roster-buffer.html#Customizing-the-roster-buffer">15.4 Customizing the roster buffer</a>
+<li><a href="Customizing-the-chat-buffer.html#Customizing-the-chat-buffer">15.5 Customizing the chat buffer</a>
+<li><a href="Customizing-alerts.html#Customizing-alerts">15.6 Customizing alerts</a>
+<ul>
+<li><a href="Standard-alerts.html#Standard-alerts">15.6.1 Standard alerts</a>
+<li><a href="Presence-alerts.html#Presence-alerts">15.6.2 Presence alerts</a>
+<li><a href="Message-alerts.html#Message-alerts">15.6.3 Message alerts</a>
+<li><a href="MUC-alerts.html#MUC-alerts">15.6.4 MUC alerts</a>
+<li><a href="Info-alerts.html#Info-alerts">15.6.5 Info alerts</a>
+</li></ul>
+<li><a href="Hooks.html#Hooks">15.7 Hooks</a>
+<li><a href="Debug-options.html#Debug-options">15.8 Debug options</a>
+</li></ul>
+<li><a name="toc_Hacking-and-extending" href="Hacking-and-extending.html#Hacking-and-extending">16 Hacking and extending</a>
+<ul>
+<li><a href="XML-representation.html#XML-representation">16.1 XML representation</a>
+<li><a href="Roster-structure.html#Roster-structure">16.2 Roster structure</a>
+<li><a href="Listening-for-new-requests.html#Listening-for-new-requests">16.3 Listening for new requests</a>
+<li><a href="Sending-new-requests.html#Sending-new-requests">16.4 Sending new requests</a>
+<li><a href="Extending-service-discovery.html#Extending-service-discovery">16.5 Service discovery</a>
+<li><a href="Chat-printers.html#Chat-printers">16.6 Chat printers</a>
+<li><a href="Stanza-chains.html#Stanza-chains">16.7 Stanza chains</a>
+</li></ul>
+<li><a name="toc_Protocol-support" href="Protocol-support.html#Protocol-support">Appendix A Protocol support</a>
+<ul>
+<li><a href="RFC-3920.html#RFC-3920">A.1 RFC 3920 (XMPP-CORE)</a>
+<li><a href="RFC-3921.html#RFC-3921">A.2 RFC 3921 (XMPP-IM)</a>
+<li><a href="XEP_002d0004.html#XEP_002d0004">A.3 XEP-0004 (Data Forms)</a>
+<li><a href="XEP_002d0012.html#XEP_002d0012">A.4 XEP-0012 (Last Activity)</a>
+<li><a href="XEP_002d0020.html#XEP_002d0020">A.5 XEP-0020 (Feature Negotiation)</a>
+<li><a href="XEP_002d0022.html#XEP_002d0022">A.6 XEP-0022 (Message Events)</a>
+<li><a href="XEP_002d0030.html#XEP_002d0030">A.7 XEP-0030 (Service Discovery)</a>
+<li><a href="XEP_002d0045.html#XEP_002d0045">A.8 XEP-0045 (Multi-User Chat)</a>
+<li><a href="XEP_002d0049.html#XEP_002d0049">A.9 XEP-0049 (Private XML Storage)</a>
+<li><a href="XEP_002d0050.html#XEP_002d0050">A.10 XEP-0050 (Ad-Hoc Commands)</a>
+<li><a href="XEP_002d0054.html#XEP_002d0054">A.11 XEP-0054 (vcard-temp)</a>
+<li><a href="XEP_002d0055.html#XEP_002d0055">A.12 XEP-0055 (Jabber Search)</a>
+<li><a href="XEP_002d0065.html#XEP_002d0065">A.13 XEP-0065 (SOCKS5 Bytestreams)</a>
+<li><a href="XEP_002d0066.html#XEP_002d0066">A.14 XEP-0066 (Out of Band Data)</a>
+<li><a href="XEP_002d0068.html#XEP_002d0068">A.15 XEP-0068 (Field Standardization for Data Forms)</a>
+<li><a href="XEP_002d0077.html#XEP_002d0077">A.16 XEP-0077 (In-Band Registration)</a>
+<li><a href="XEP_002d0078.html#XEP_002d0078">A.17 XEP-0078 (Non-SASL Authentication)</a>
+<li><a href="XEP_002d0082.html#XEP_002d0082">A.18 XEP-0082 (Jabber Date and Time Profiles)</a>
+<li><a href="XEP_002d0086.html#XEP_002d0086">A.19 XEP-0086 (Error Condition Mappings)</a>
+<li><a href="XEP_002d0090.html#XEP_002d0090">A.20 XEP-0090 (Entity Time)</a>
+<li><a href="XEP_002d0091.html#XEP_002d0091">A.21 XEP-0091 (Delayed Delivery)</a>
+<li><a href="XEP_002d0092.html#XEP_002d0092">A.22 XEP-0092 (Software Version)</a>
+<li><a href="XEP_002d0095.html#XEP_002d0095">A.23 XEP-0095 (Stream Initiation)</a>
+<li><a href="XEP_002d0096.html#XEP_002d0096">A.24 XEP-0096 (File Transfer)</a>
+<li><a href="XEP_002d0146.html#XEP_002d0146">A.25 XEP-0146 (Remote Controlling Clients)</a>
+<li><a href="XEP_002d0153.html#XEP_002d0153">A.26 XEP-0153 (vCard-Based Avatars)</a>
+</li></ul>
+<li><a name="toc_Concept-index" href="Concept-index.html#Concept-index">Concept index</a>
+<li><a name="toc_Function-index" href="Function-index.html#Function-index">Function index</a>
+<li><a name="toc_Variable-index" href="Variable-index.html#Variable-index">Variable index</a>
+</li></ul>
+</div>
+
+
+
+<div class="node">
+<p>
+<a name="Top"></a>Next:&nbsp;<a rel="next" accesskey="n" href="Introduction.html#Introduction">Introduction</a>,
+Previous:&nbsp;<a rel="previous" accesskey="p" href="../index.html#dir">(dir)</a>,
+Up:&nbsp;<a rel="up" accesskey="u" href="../index.html#dir">(dir)</a>
+<hr><br>
+</div>
+
+<h2 class="unnumbered">jabber.el manual</h2>
+
+<p>This manual is for jabber.el, version 0.7.1.
+
+ <p>Copyright &copy; 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ <blockquote>
+Permission is granted to make and distribute verbatim copies or
+modified versions of this manual, provided the copyright notice and
+this permission notice are preserved on all copies.
+</blockquote>
+
+<ul class="menu">
+<li><a accesskey="1" href="Introduction.html#Introduction">Introduction</a>
+<li><a accesskey="2" href="Basic-operation.html#Basic-operation">Basic operation</a>
+<li><a accesskey="3" href="Groupchat.html#Groupchat">Groupchat</a>
+<li><a accesskey="4" href="Composing-messages.html#Composing-messages">Composing messages</a>
+<li><a accesskey="5" href="File-transfer.html#File-transfer">File transfer</a>
+<li><a accesskey="6" href="Services.html#Services">Services</a>
+<li><a accesskey="7" href="Personal-information.html#Personal-information">Personal information</a>
+<li><a accesskey="8" href="Avatars.html#Avatars">Avatars</a>
+<li><a accesskey="9" href="Time-queries.html#Time-queries">Time queries</a>
+<li><a href="Useful-features.html#Useful-features">Useful features</a>
+<li><a href="Message-history.html#Message-history">Message history</a>
+<li><a href="Message-events.html#Message-events">Message events</a>
+<li><a href="Roster-import-and-export.html#Roster-import-and-export">Roster import and export</a>
+<li><a href="XMPP-URIs.html#XMPP-URIs">XMPP URIs</a>
+<li><a href="Customization.html#Customization">Customization</a>
+<li><a href="Hacking-and-extending.html#Hacking-and-extending">Hacking and extending</a>
+<li><a href="Protocol-support.html#Protocol-support">Protocol support</a>
+<li><a href="Concept-index.html#Concept-index">Concept index</a>
+<li><a href="Function-index.html#Function-index">Function index</a>
+<li><a href="Variable-index.html#Variable-index">Variable index</a>
+</ul>
+
+ </body></html>
+
diff --git a/jabber-activity.el b/jabber-activity.el
index d9cc861..c01b8f2 100644
--- a/jabber-activity.el
+++ b/jabber-activity.el
@@ -237,11 +237,14 @@ on JIDs where `jabber-activity-show-p'"
(jabber-propertize
(cdr x)
'face 'jabber-activity-face
- 'local-map (make-mode-line-mouse-map
- 'mouse-1 `(lambda ()
- (interactive)
- (jabber-activity-switch-to
- ,(car x))))
+ ;; XXX: XEmacs doesn't have make-mode-line-mouse-map.
+ ;; Is there another way to make this work?
+ 'local-map (when (fboundp 'make-mode-line-mouse-map)
+ (make-mode-line-mouse-map
+ 'mouse-1 `(lambda ()
+ (interactive)
+ (jabber-activity-switch-to
+ ,(car x)))))
'help-echo (concat "Jump to "
(jabber-jid-displayname (car x))
"'s buffer"))))
diff --git a/jabber-ahc-presence.el b/jabber-ahc-presence.el
index 8239e45..6e0fa65 100644
--- a/jabber-ahc-presence.el
+++ b/jabber-ahc-presence.el
@@ -21,7 +21,7 @@
(require 'jabber-ahc)
-(defconst jabber-ahc-presence-node "presence"
+(defconst jabber-ahc-presence-node "http://jabber.org/protocol/rc#set-status"
"Node used by jabber-ahc-presence")
(jabber-ahc-add jabber-ahc-presence-node "Set presence" 'jabber-ahc-presence
@@ -52,8 +52,10 @@
(type . "form"))
(title nil ,(format "Set presence of %s@%s/%s" jabber-username jabber-server jabber-resource))
(instructions nil "Select new presence status.")
- (field ((var . "show")
- (label . "Show")
+ (field ((var . "FORM_TYPE") (type . "hidden"))
+ (value nil "http://jabber.org/protocol/rc"))
+ (field ((var . "status")
+ (label . "Status")
(type . "list-single"))
(value nil ,(if (string= *jabber-current-show* "")
"online"
@@ -63,11 +65,11 @@
(option ((label . "Away")) (value nil "away"))
(option ((label . "Extended away")) (value nil "xa"))
(option ((label . "Do not disturb")) (value nil "dnd")))
- (field ((var . "status")
- (label . "Status text")
+ (field ((var . "status-message")
+ (label . "Message")
(type . "text-single"))
(value nil ,*jabber-current-status*))
- (field ((var . "priority")
+ (field ((var . "status-priority")
(label . "Priority")
(type . "text-single"))
(value nil ,(int-to-string *jabber-current-priority*))))))
@@ -85,14 +87,14 @@
;; by this
(value (car (jabber-xml-node-children (car (jabber-xml-get-children field 'value))))))
(cond
- ((string= var "show")
+ ((string= var "status")
(setq new-show (if (string= value "online")
""
value)))
- ((string= var "status")
+ ((string= var "status-message")
(setq new-status value))
- ((string= var "priority")
- (setq new-priority (string-to-int value))))))
+ ((string= var "status-priority")
+ (setq new-priority (string-to-number value))))))
(jabber-send-presence new-show new-status new-priority))
`(command ((xmlns . "http://jabber.org/protocol/commands")
(sessionid . ,sessionid)
diff --git a/jabber-alert.el b/jabber-alert.el
index 5709e14..1517e7c 100644
--- a/jabber-alert.el
+++ b/jabber-alert.el
@@ -186,10 +186,19 @@ and BUFFER, a buffer containing the result."
:group 'jabber-alerts)
(defcustom jabber-alert-message-wave ""
- "a sound file to play when a message arrived"
+ "A sound file to play when a message arrived.
+See `jabber-alert-message-wave-alist' if you want other sounds
+for specific contacts."
:type 'file
:group 'jabber-alerts)
+(defcustom jabber-alert-message-wave-alist nil
+ "Specific sound files for messages from specific contacts.
+The keys are regexps matching the JID, and the values are sound
+files."
+ :type '(alist :key-type regexp :value-type file)
+ :group 'jabber-alerts)
+
(defcustom jabber-alert-muc-wave ""
"a sound file to play when a MUC message arrived"
:type 'file
@@ -200,6 +209,13 @@ and BUFFER, a buffer containing the result."
:type 'file
:group 'jabber-alerts)
+(defcustom jabber-alert-presence-wave-alist nil
+ "Specific sound files for presence from specific contacts.
+The keys are regexps matching the JID, and the values are sound
+files."
+ :type '(alist :key-type regexp :value-type file)
+ :group 'jabber-alerts)
+
(defcustom jabber-alert-info-wave ""
"a sound file to play when an info query result arrived"
:type 'file
@@ -278,10 +294,22 @@ Examples:
:type 'boolean
:group 'jabber-alerts)
+(defcustom jabber-muc-alert-self nil
+ "If nil, don't display MUC alerts for your own messages."
+ :type 'boolean
+ :group 'jabber-alerts)
+
(defun jabber-message-wave (from buffer text proposed-alert)
"Play the wave file specified in `jabber-alert-message-wave'"
(when proposed-alert
- (jabber-play-sound-file jabber-alert-message-wave)))
+ (let* ((case-fold-search t)
+ (bare-jid (jabber-jid-user from))
+ (sound-file (or (dolist (entry jabber-alert-message-wave-alist)
+ (when (string-match (car entry) bare-jid)
+ (return (cdr entry))))
+ jabber-alert-message-wave)))
+ (unless (equal sound-file "")
+ (play-sound-file sound-file)))))
(defun jabber-message-display (from buffer text proposed-alert)
"Display the buffer where a new message has arrived."
@@ -319,14 +347,16 @@ Examples:
(when (or jabber-message-alert-same-buffer
(not (memq (selected-window) (get-buffer-window-list buffer))))
(if nick
- (format "Message from %s in %s" nick (jabber-jid-displayname
- group))
+ (when (or jabber-muc-alert-self
+ (not (string= nick (cdr (assoc group *jabber-active-groupchats*)))))
+ (format "Message from %s in %s" nick (jabber-jid-displayname
+ group)))
(format "Message in %s" (jabber-jid-displayname group)))))
(defun jabber-muc-wave (nick group buffer text proposed-alert)
"Play the wave file specified in `jabber-alert-muc-wave'"
(when proposed-alert
- (jabber-play-sound-file jabber-alert-muc-wave)))
+ (play-sound-file jabber-alert-muc-wave)))
(defun jabber-muc-display (nick group buffer text proposed-alert)
"Display the buffer where a new message has arrived."
@@ -370,14 +400,21 @@ This function is not called directly, but is the default for
newstatus))))
(formattedtext
(if (> (length statustext) 0)
- (concat " (" (jabber-unescape-xml statustext) ")")
+ (concat " (" statustext ")")
"")))
(concat formattedname formattedstatus formattedtext)))))
(defun jabber-presence-wave (who oldstatus newstatus statustext proposed-alert)
"Play the wave file specified in `jabber-alert-presence-wave'"
- (if proposed-alert
- (jabber-play-sound-file jabber-alert-presence-wave)))
+ (when proposed-alert
+ (let* ((case-fold-search t)
+ (bare-jid (symbol-name who))
+ (sound-file (or (dolist (entry jabber-alert-presence-wave-alist)
+ (when (string-match (car entry) bare-jid)
+ (return (cdr entry))))
+ jabber-alert-presence-wave)))
+ (unless (equal sound-file "")
+ (play-sound-file sound-file)))))
;; This is now defined in jabber-roster.el.
;; (defun jabber-presence-update-roster (who oldstatus newstatus statustext proposed-alert)
@@ -407,7 +444,7 @@ This function uses `jabber-info-message-alist' to find a message."
(defun jabber-info-wave (infotype buffer proposed-alert)
"Play the wave file specified in `jabber-alert-info-wave'"
(if proposed-alert
- (jabber-play-sound-file jabber-alert-info-wave)))
+ (play-sound-file jabber-alert-info-wave)))
(defun jabber-info-display (infotype buffer proposed-alert)
"Display buffer of completed request"
diff --git a/jabber-autoaway.el b/jabber-autoaway.el
new file mode 100644
index 0000000..badb607
--- /dev/null
+++ b/jabber-autoaway.el
@@ -0,0 +1,182 @@
+;;; jabber-autoaway.el --- change status to away after idleness
+
+;; Copyright (C) 2006 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(eval-when-compile (require 'cl))
+(require 'time-date)
+
+(defgroup jabber-autoaway nil
+ "Change status to away after idleness"
+ :group 'jabber)
+
+(defcustom jabber-autoaway-method (cond
+ ((fboundp 'current-idle-time)
+ 'jabber-current-idle-time)
+ ((getenv "DISPLAY")
+ 'jabber-xprintidle-get-idle-time)
+ ((null window-system)
+ 'jabber-termatime-get-idle-time))
+ "Method used to keep track of idleness.
+This is a function that takes no arguments, and returns the
+number of seconds since the user was active, or nil on error."
+ :group 'jabber-autoaway
+ :type '(choice (const :tag "Use `current-idle-time' function"
+ jabber-current-idle-time)
+ (const :tag "xprintidle"
+ jabber-xprintidle-get-idle-time)
+ (const :tag "Watch atime of terminal"
+ jabber-termatime-get-idle-time)
+ function
+ (const :tag "None" nil)))
+
+(defcustom jabber-autoaway-timeout 5
+ "Minutes of inactivity before changing status to away"
+ :group 'jabber-autoaway
+ :type 'number)
+
+(defcustom jabber-autoaway-status "Idle"
+ "Status string for autoaway"
+ :group 'jabber-autoaway
+ :type 'string)
+
+(defcustom jabber-autoaway-priority nil
+ "Priority for autoaway.
+If nil, don't change priority. See the manual for more
+information about priority."
+ :group 'jabber-autoaway
+ :type '(choice (const :tag "Don't change")
+ (integer :tag "Priority"))
+ :link '(info-link "(jabber)Presence"))
+
+(defcustom jabber-xprintidle-program (executable-find "xprintidle")
+ "Name of the xprintidle program"
+ :group 'jabber-autoaway
+ :type 'string)
+
+(defcustom jabber-autoaway-verbose nil
+ "If nil, don't print autoaway status messages."
+ :group 'jabber-autoaway
+ :type 'boolean)
+
+(defvar jabber-autoaway-timer nil)
+
+(defvar jabber-autoaway-last-idle-time nil
+ "Seconds of idle time the last time we checked.
+This is used to detect whether the user has become unidle.")
+
+(defun jabber-autoaway-message (&rest args)
+ (when jabber-autoaway-verbose
+ (apply #'message args)))
+
+(defun jabber-autoaway-start ()
+ "Start autoaway timer."
+ (interactive)
+ (when jabber-autoaway-timer
+ (jabber-cancel-timer jabber-autoaway-timer))
+ (setq jabber-autoaway-timer
+ (run-with-timer (* jabber-autoaway-timeout 60) nil #'jabber-autoaway-timer))
+ (jabber-autoaway-message "Autoaway timer started"))
+
+(defun jabber-autoaway-stop ()
+ "Stop autoaway timer."
+ (interactive)
+ (when jabber-autoaway-timer
+ (jabber-cancel-timer jabber-autoaway-timer)
+ (setq jabber-autoaway-timer nil)
+ (jabber-autoaway-message "Autoaway timer stopped")))
+
+(defun jabber-autoaway-get-idle-time ()
+ "Get idle time in seconds according to chosen method.
+Return nil on error."
+ (when jabber-autoaway-method (funcall jabber-autoaway-method)))
+
+(defun jabber-autoaway-timer ()
+ ;; We use one-time timers, so reset the variable.
+ (setq jabber-autoaway-timer nil)
+ (let ((idle-time (jabber-autoaway-get-idle-time)))
+ (when (numberp idle-time)
+ ;; Has "idle timeout" passed?
+ (if (> idle-time (* 60 jabber-autoaway-timeout))
+ ;; If so, mark ourselves idle.
+ (jabber-autoaway-set-idle)
+ ;; Else, start a timer for the remaining amount.
+ (setq jabber-autoaway-timer
+ (run-with-timer (- (* 60 jabber-autoaway-timeout) idle-time)
+ nil #'jabber-autoaway-timer))))))
+
+(defun jabber-autoaway-set-idle ()
+ (jabber-autoaway-message "Autoaway triggered")
+ ;; Send presence, unless the user has set a custom presence
+ (unless (member *jabber-current-show* '("away" "xa" "dnd"))
+ (jabber-send-presence
+ "away"
+ jabber-autoaway-status
+ (or jabber-autoaway-priority *jabber-current-priority*)))
+
+ (setq jabber-autoaway-last-idle-time (jabber-autoaway-get-idle-time))
+ ;; Run unidle timer every 10 seconds
+ (setq jabber-autoaway-timer (run-with-timer 10 10
+ #'jabber-autoaway-maybe-unidle)))
+
+(defun jabber-autoaway-maybe-unidle ()
+ (let ((idle-time (jabber-autoaway-get-idle-time)))
+ (jabber-autoaway-message "Idle for %d seconds" idle-time)
+ ;; As long as idle time increases monotonically, stay idle.
+ (if (> idle-time jabber-autoaway-last-idle-time)
+ (progn
+ (setq jabber-autoaway-last-idle-time idle-time))
+ ;; But if it doesn't, go back to unidle state.
+ ;; But don't mess with the user's custom presence.
+ (when (string= *jabber-current-status* jabber-autoaway-status)
+ (jabber-send-default-presence))
+ (jabber-autoaway-start))))
+
+(defun jabber-xprintidle-get-idle-time ()
+ "Get idle time through the xprintidle program."
+ (when jabber-xprintidle-program
+ (with-temp-buffer
+ (when (zerop (call-process jabber-xprintidle-program
+ nil t))
+ (/ (string-to-number (buffer-string)) 1000.0)))))
+
+(defun jabber-termatime-get-idle-time ()
+ "Get idle time through atime of terminal.
+The method for finding the terminal only works on GNU/Linux."
+ (let ((terminal (cond
+ ((file-exists-p "/proc/self/fd/0")
+ "/proc/self/fd/0")
+ (t
+ nil))))
+ (when terminal
+ (let* ((atime-of-tty (nth 4 (file-attributes terminal)))
+ (diff (time-to-seconds (time-since atime-of-tty))))
+ (when (> diff 0)
+ diff)))))
+
+(defun jabber-current-idle-time ()
+ "Get idle time through `current-idle-time'.
+`current-idle-time' was introduced in Emacs 22."
+ (let ((idle-time (current-idle-time)))
+ (if (null idle-time)
+ 0
+ (float-time idle-time))))
+
+(provide 'jabber-autoaway)
+;; arch-tag: 5bcea14c-842d-11da-a120-000a95c2fcd0
diff --git a/jabber-avatar.el b/jabber-avatar.el
new file mode 100644
index 0000000..beb74f9
--- /dev/null
+++ b/jabber-avatar.el
@@ -0,0 +1,205 @@
+;;; jabber-avatar.el --- generic functions for avatars
+
+;; Copyright (C) 2006 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; There are several methods for transporting avatars in Jabber
+;; (JEP-0008, JEP-0084, JEP-0153). They all have in common that they
+;; identify avatars by their SHA1 checksum, and (at least partially)
+;; use Base64-encoded image data. Thus this library of support
+;; functions for interpreting and caching avatars.
+
+;; A contact with an avatar has the image in the avatar property of
+;; the JID symbol. Use `jabber-avatar-set' to set it.
+
+;;; Code:
+
+(eval-when-compile (require 'cl))
+
+;;;; Variables
+
+(defgroup jabber-avatar nil
+ "Avatar related settings"
+ :group 'jabber)
+
+(defcustom jabber-avatar-cache-directory "~/.jabber-avatars/"
+ "Directory to use for cached avatars"
+ :group 'jabber-avatar
+ :type 'directory)
+
+;;;; Avatar data handling
+
+(defstruct avatar sha1-sum mime-type url base64-data height width bytes)
+
+(defun jabber-avatar-from-url (url)
+ "Construct an avatar structure from the given URL.
+Retrieves the image to find info about it."
+ (with-current-buffer (let ((coding-system-for-read 'binary))
+ (url-retrieve-synchronously url))
+ (let* ((case-fold-search t)
+ (mime-type (ignore-errors
+ (search-forward-regexp "^content-type:[ \t]*\\(.*\\)$")
+ (match-string 1)))
+ (data (progn
+ (search-forward "\n\n")
+ (buffer-substring (point) (point-max)))))
+ (prog1
+ (jabber-avatar-from-data data nil mime-type)
+ (kill-buffer nil)))))
+
+(defun jabber-avatar-from-file (filename)
+ "Construct an avatar structure from FILENAME."
+ (require 'mailcap)
+ (let ((data (with-temp-buffer
+ (insert-file-contents-literally filename)
+ (buffer-string)))
+ (mime-type (progn (string-match "\\.[^.]+$" filename)
+ (mailcap-extension-to-mime (match-string 0 filename)))))
+ (jabber-avatar-from-data data nil mime-type)))
+
+(defun jabber-avatar-from-base64-string (base64-string &optional mime-type)
+ "Construct an avatar stucture from BASE64-STRING.
+If MIME-TYPE is not specified, try to find it from the image data."
+ (jabber-avatar-from-data nil base64-string mime-type))
+
+(defun jabber-avatar-from-data (raw-data base64-string &optional mime-type)
+ "Construct an avatar structure from RAW-DATA and/or BASE64-STRING.
+If either is not provided, it is computed.
+If MIME-TYPE is not specified, try to find it from the image data."
+ (let* ((data (or raw-data (base64-decode-string base64-string)))
+ (bytes (length data))
+ (sha1-sum (sha1 data))
+ (base64-data (or base64-string (base64-encode-string raw-data)))
+ (type (or mime-type
+ (cdr (assq (get :type (cdr (create-image data nil t)))
+ '((png "image/png")
+ (jpeg "image/jpeg")
+ (gif "image/gif")))))))
+ (jabber-avatar-compute-size
+ (make-avatar :mime-type mime-type :sha1-sum sha1-sum :base64-data base64-data :bytes bytes))))
+
+;; XXX: This function is based on an outdated version of JEP-0084.
+;; (defun jabber-avatar-from-data-node (data-node)
+;; "Construct an avatar structure from the given <data/> node."
+;; (jabber-xml-let-attributes
+;; (content-type id bytes height width) data-node
+;; (let ((base64-data (car (jabber-xml-node-children data-node))))
+;; (make-avatar :mime-type content-type :sha1-sum id :bytes bytes
+;; :height height :width width :base64-data base64-data))))
+
+(defun jabber-avatar-image (avatar)
+ "Create an image from AVATAR.
+Return nil if images of this type are not supported."
+ (create-image (with-temp-buffer
+ (set-buffer-multibyte nil)
+ (insert (avatar-base64-data avatar))
+ (base64-decode-region (point-min) (point-max))
+ (buffer-string))
+ nil
+ t))
+
+(defun jabber-avatar-compute-size (avatar)
+ "Compute and set the width and height fields of AVATAR.
+Return AVATAR."
+ ;; image-size only works when there is a window system.
+ ;; But display-graphic-p doesn't exist on XEmacs...
+ (let ((size (and (fboundp 'display-graphic-p)
+ (display-graphic-p)
+ (let ((image (jabber-avatar-image avatar)))
+ (and image
+ (image-size image t))))))
+ (when size
+ (setf (avatar-width avatar) (car size))
+ (setf (avatar-height avatar) (cdr size)))
+ avatar))
+
+;;;; Avatar cache
+
+(defun jabber-avatar-find-cached (sha1-sum)
+ "Return file name of cached image for avatar identified by SHA1-SUM.
+If there is no cached image, return nil."
+ ;; XXX: file-expand-wildcards doesn't exist in XEmacs
+ (car (file-expand-wildcards (concat (file-name-as-directory jabber-avatar-cache-directory)
+ sha1-sum
+ ".*"))))
+
+(defun jabber-avatar-cache (avatar)
+ "Cache the AVATAR."
+ (let* ((id (avatar-sha1-sum avatar))
+ (base64-data (avatar-base64-data avatar))
+ (mime-type (avatar-mime-type avatar))
+ (extension
+ (cond
+ ((string= mime-type "image/png")
+ ".png")
+ ((string= mime-type "image/jpeg")
+ ".jpg")
+ ((string= mime-type "image/gif")
+ ".gif")
+ (t
+ ".dat")))
+ (filename (expand-file-name (concat id extension) jabber-avatar-cache-directory))
+ (buffer (create-file-buffer filename)))
+ (unless (file-directory-p jabber-avatar-cache-directory)
+ (make-directory jabber-avatar-cache-directory))
+
+ (with-current-buffer buffer
+ (let ((require-final-newline nil))
+ (setq buffer-file-coding-system 'binary)
+ (if (fboundp 'set-buffer-multibyte)
+ (set-buffer-multibyte nil))
+ (set-visited-file-name filename t)
+ (insert base64-data)
+ (base64-decode-region (point-min) (point-max))
+ (basic-save-buffer)))
+ (kill-buffer buffer)))
+
+;;;; Set avatar for contact
+
+(defun jabber-avatar-set (jid avatar)
+ "Set the avatar of JID to be AVATAR.
+JID is a string containing a bare JID.
+AVATAR may be one of:
+* An avatar structure.
+* The SHA1 sum of a cached avatar.
+* nil, meaning no avatar."
+ ;; We want to optimize for the case of same avatar.
+ ;; Loading an image is expensive, so do it lazily.
+ (let ((jid-symbol (jabber-jid-symbol jid))
+ image hash)
+ (cond
+ ((avatar-p avatar)
+ (setq hash (avatar-sha1-sum avatar))
+ (setq image (lambda () (jabber-avatar-image avatar))))
+ ((stringp avatar)
+ (setq hash avatar)
+ (setq image (lambda () (create-image (jabber-avatar-find-cached avatar)))))
+ (t
+ (setq hash nil)
+ (setq image #'ignore)))
+
+ (unless (string= hash (get jid-symbol 'avatar-hash))
+ (put jid-symbol 'avatar (funcall image))
+ (put jid-symbol 'avatar-hash hash)
+ (jabber-presence-update-roster jid-symbol))))
+
+(provide 'jabber-avatar)
+;; arch-tag: 2405c3f8-8eaa-11da-826c-000a95c2fcd0
diff --git a/jabber-browse.el b/jabber-browse.el
index b391a62..3900617 100644
--- a/jabber-browse.el
+++ b/jabber-browse.el
@@ -80,7 +80,7 @@
(version . "Version:\t")))
(let ((data (jabber-xml-get-attribute item (car attr))))
(if (> (length data) 0)
- (insert (cdr attr) (jabber-unescape-xml data) "\n"))))
+ (insert (cdr attr) data "\n"))))
(dolist (ns (jabber-xml-get-children item 'ns))
(if (stringp (car (jabber-xml-node-children ns)))
diff --git a/jabber-chat.el b/jabber-chat.el
index 67652ae..255e436 100644
--- a/jabber-chat.el
+++ b/jabber-chat.el
@@ -22,6 +22,9 @@
(require 'jabber-chatbuffer)
(require 'jabber-history)
+(require 'ewoc)
+(eval-when-compile (require 'cl))
+
(defgroup jabber-chat nil "chat display options"
:group 'jabber)
@@ -38,7 +41,10 @@ with):
:group 'jabber-chat)
(defcustom jabber-chat-header-line-format
- '(" " (:eval (jabber-jid-displayname jabber-chatting-with))
+ '("" (:eval (let ((buddy (jabber-jid-symbol jabber-chatting-with)))
+ (jabber-propertize " "
+ 'display (get buddy 'avatar))))
+ (:eval (jabber-jid-displayname jabber-chatting-with))
"\t" (:eval (let ((buddy (jabber-jid-symbol jabber-chatting-with)))
(propertize
(or
@@ -47,7 +53,7 @@ with):
'face
(or (cdr (assoc (get buddy 'show) jabber-presence-faces))
'jabber-roster-user-online))))
- "\t" (:eval (get (jabber-jid-symbol jabber-chatting-with) 'status))
+ "\t" (:eval (jabber-fix-status (get (jabber-jid-symbol jabber-chatting-with) 'status)))
"\t" jabber-events-message) ;see jabber-events.el
"The specification for the header line of chat buffers.
@@ -90,10 +96,6 @@ rare time printed."
"face for displaying the rare time info"
:group 'jabber-chat)
-(defvar jabber-rare-time ""
- "Latest rare time printed")
-(make-variable-buffer-local 'jabber-rare-time)
-
(defcustom jabber-chat-local-prompt-format "[%t] %n> "
"The format specification for lines you type in the chat buffer.
@@ -142,11 +144,11 @@ These fields are available:
"face used for system and special messages"
:group 'jabber-chat)
-(defface jabber-chat-text-local nil
+(defface jabber-chat-text-local '((t ()))
"Face used for text you write"
:group 'jabber-chat)
-(defface jabber-chat-text-foreign nil
+(defface jabber-chat-text-foreign '((t ()))
"Face used for text others write"
:group 'jabber-chat)
@@ -163,14 +165,24 @@ These fields are available:
jabber-chat-print-url
jabber-chat-goto-address)
"List of functions that may be able to print part of a message.
-Each function receives the entire <message/> stanza as argument.")
+Each function receives these arguments:
+
+XML-DATA The entire message stanza
+WHO :local or :foreign, for sent or received stanza, respectively
+MODE :insert or :printp. For :insert, insert text at point.
+ For :printp, return non-nil if function would insert text.")
(defvar jabber-body-printers '(jabber-chat-normal-body)
"List of functions that may be able to print a body for a message.
-Each function receives the entire <message/> stanza as argument, and
-should either output a representation of the body part of the message
-and return non-nil, or output nothing and return nil. These functions
-are called in order, until one of them returns non-nil.
+Each function receives these arguments:
+
+XML-DATA The entire message stanza
+WHO :local, :foreign or :error
+MODE :insert or :printp. For :insert, insert text at point.
+ For :printp, return non-nil if function would insert text.
+
+These functions are called in order, until one of them returns
+non-nil.
Add a function to the beginning of this list if the tag it handles
replaces the contents of the <body/> tag.")
@@ -201,42 +213,51 @@ Either a string or a buffer is returned, so use `get-buffer' or
"Prepare a buffer for chatting with CHAT-WITH.
This function is idempotent."
(with-current-buffer (get-buffer-create (jabber-chat-get-buffer chat-with))
- (if (not (eq major-mode 'jabber-chat-mode)) (jabber-chat-mode))
+ (unless (eq major-mode 'jabber-chat-mode)
+ (jabber-chat-mode #'jabber-chat-pp))
+
(make-local-variable 'jabber-chatting-with)
(setq jabber-chatting-with chat-with)
(setq jabber-send-function 'jabber-chat-send)
(setq header-line-format jabber-chat-header-line-format)
-
+
(make-local-variable 'jabber-chat-earliest-backlog)
-
+
;; insert backlog
- (when (zerop (buffer-size))
+ (when (null jabber-chat-earliest-backlog)
(let ((backlog-entries (jabber-history-backlog chat-with)))
- (when backlog-entries
+ (if (null backlog-entries)
+ (setq jabber-chat-earliest-backlog (jabber-float-time))
(setq jabber-chat-earliest-backlog
(jabber-float-time (jabber-parse-time
(aref (car backlog-entries) 0))))
- (mapc 'jabber-chat-insert-backlog-entry backlog-entries))))
+ (mapc 'jabber-chat-insert-backlog-entry (nreverse backlog-entries)))))
(current-buffer)))
(defun jabber-chat-insert-backlog-entry (msg)
- "Insert backlog entry MSG at point."
- (if (string= (aref msg 1) "in")
- (let ((fake-stanza `(message ((from . ,(aref msg 2)))
- (body nil ,(aref msg 4))
- (x ((xmlns . "jabber:x:delay")
- (stamp . ,(jabber-encode-legacy-time (jabber-parse-time (aref msg 0)))))))))
- (jabber-chat-buffer-display-at-point 'jabber-chat-print-prompt
- fake-stanza
- jabber-chat-printers
- fake-stanza))
- (jabber-chat-buffer-display-at-point 'jabber-chat-self-prompt
- (jabber-parse-time (aref msg 0))
- '(insert)
- (jabber-propertize
- (aref msg 4)
- 'face 'jabber-chat-text-local))))
+ "Insert backlog entry MSG at beginning of buffer."
+ ;; Rare timestamps are especially important in backlog. We risk
+ ;; having superfluous timestamps if we just add before each backlog
+ ;; entry.
+ (let* ((message-time (jabber-parse-time (aref msg 0)))
+ (fake-stanza `(message ((from . ,(aref msg 2)))
+ (body nil ,(aref msg 4))
+ (x ((xmlns . "jabber:x:delay")
+ (stamp . ,(jabber-encode-legacy-time message-time))))))
+ (node-data (list (if (string= (aref msg 1) "in") :foreign :local)
+ fake-stanza :delayed t)))
+
+ ;; Insert after existing rare timestamp?
+ (if (and jabber-print-rare-time
+ (ewoc-nth jabber-chat-ewoc 0)
+ (eq (car (ewoc-data (ewoc-nth jabber-chat-ewoc 0))) :rare-time)
+ (not (jabber-rare-time-needed message-time (cadr (ewoc-data (ewoc-nth jabber-chat-ewoc 0))))))
+ (ewoc-enter-after jabber-chat-ewoc (ewoc-nth jabber-chat-ewoc 0) node-data)
+ ;; Insert first.
+ (ewoc-enter-first jabber-chat-ewoc node-data)
+ (when jabber-print-rare-time
+ (ewoc-enter-first jabber-chat-ewoc (list :rare-time message-time))))))
(add-to-list 'jabber-jid-chat-menu
(cons "Display more context" 'jabber-chat-display-more-backlog))
@@ -254,7 +275,7 @@ This function is idempotent."
(aref (car backlog-entries) 0))))
(save-excursion
(goto-char (point-min))
- (mapc 'jabber-chat-insert-backlog-entry backlog-entries)))))
+ (mapc 'jabber-chat-insert-backlog-entry (nreverse backlog-entries))))))
(add-to-list 'jabber-message-chain 'jabber-process-chat)
@@ -275,15 +296,11 @@ This function is idempotent."
(jabber-jid-resource from))
(jabber-chat-create-buffer from))
;; Call alert hooks only when something is output
- (when
- (jabber-chat-buffer-display (if (jabber-muc-sender-p from)
- 'jabber-muc-private-print-prompt
- 'jabber-chat-print-prompt)
- xml-data
- (if error-p
- '(jabber-chat-print-error)
- jabber-chat-printers)
- xml-data)
+ (when (or error-p
+ (run-hook-with-args-until-success 'jabber-chat-printers xml-data :foreign :printp))
+ (let ((node
+ (ewoc-enter-last jabber-chat-ewoc (list (if error-p :error :foreign) xml-data :time (current-time)))))
+ (jabber-maybe-print-rare-time node))
(dolist (hook '(jabber-message-hooks jabber-alert-message-hooks))
(run-hook-with-args hook
@@ -293,46 +310,120 @@ This function is idempotent."
(defun jabber-chat-send (body)
"Send BODY, and display it in chat buffer."
+ ;; Build the stanza...
(let* ((id (apply 'format "emacs-msg-%d.%d.%d" (current-time)))
(stanza-to-send `(message
((to . ,jabber-chatting-with)
(type . "chat")
(id . ,id))
- (body () ,(jabber-escape-xml body)))))
+ (body () ,body))))
+ ;; ...add additional elements...
(dolist (hook jabber-chat-send-hooks)
(nconc stanza-to-send (funcall hook body id)))
- (jabber-send-sexp stanza-to-send))
-
- ;; Note that we pass a string, not an XML stanza,
- ;; to the print functions.
- (jabber-chat-buffer-display 'jabber-chat-self-prompt
- nil
- '(insert)
- (jabber-propertize
- body
- 'face 'jabber-chat-text-local)))
-
-(defun jabber-maybe-print-rare-time (timestamp)
- "Print rare time, if changed since last time printed."
- (let ((new-time (format-time-string jabber-rare-time-format timestamp)))
- (unless (string= new-time jabber-rare-time)
- (setq jabber-rare-time new-time)
- (when jabber-print-rare-time
- (let ((inhibit-read-only t))
- (goto-char jabber-point-insert)
- (insert (jabber-propertize jabber-rare-time 'face 'jabber-rare-time-face) "\n")
- (setq jabber-point-insert (point)))))))
-
-(defun jabber-chat-print-prompt (xml-data)
- "Print prompt for received message in XML-DATA."
+ ;; ...display it, if it would be displayed.
+ (when (run-hook-with-args-until-success 'jabber-chat-printers stanza-to-send :local :printp)
+ (jabber-maybe-print-rare-time
+ (ewoc-enter-last jabber-chat-ewoc (list :local stanza-to-send :time (current-time)))))
+ ;; ...and send it...
+ (jabber-send-sexp stanza-to-send)))
+
+(defun jabber-chat-pp (data)
+ "Pretty-print a <message/> stanza.
+\(car data) is either :local, :foreign, :error or :notice.
+\(cadr data) is the <message/> stanza.
+This function is used as an ewoc prettyprinter."
+ (let* ((beg (point))
+ (original-timestamp (when (listp (cadr data))
+ (jabber-xml-path (cadr data) '(("jabber:x:delay" . "x")))))
+ (internal-time
+ (plist-get (cddr data) :time)))
+
+ ;; Print prompt...
+ (let ((delayed (or original-timestamp (plist-get (cddr data) :delayed))))
+ (case (car data)
+ (:local
+ (jabber-chat-self-prompt (or (jabber-x-delay original-timestamp)
+ internal-time)
+ delayed))
+ (:foreign
+ ;; For :error and :notice, this might be a string... beware
+ (jabber-chat-print-prompt (when (listp (cadr data)) (cadr data))
+ (or (jabber-x-delay original-timestamp)
+ internal-time)
+ delayed))
+ ((:error :notice)
+ (jabber-chat-system-prompt (or (jabber-x-delay original-timestamp)
+ internal-time)))
+ (:muc-local
+ (jabber-muc-print-prompt (cadr data) t))
+ (:muc-foreign
+ (jabber-muc-print-prompt (cadr data)))
+ ((:muc-notice :muc-error)
+ (jabber-muc-system-prompt))))
+
+ ;; ...and body
+ (case (car data)
+ ((:local :foreign)
+ (run-hook-with-args 'jabber-chat-printers (cadr data) (car data) :insert))
+ ((:muc-local :muc-foreign)
+ (let ((printers (append jabber-muc-printers jabber-chat-printers)))
+ (run-hook-with-args 'printers (cadr data) (car data) :insert)))
+ ((:error :muc-error)
+ (if (stringp (cadr data))
+ (insert (jabber-propertize (cadr data) 'face 'jabber-chat-error))
+ (jabber-chat-print-error (cadr data))))
+ ((:notice :muc-notice)
+ (insert (cadr data)))
+ (:rare-time
+ (insert (jabber-propertize (format-time-string jabber-rare-time-format (cadr data))
+ 'face 'jabber-rare-time-face))))
+
+ (when jabber-chat-fill-long-lines
+ (save-restriction
+ (narrow-to-region beg (point))
+ (jabber-chat-buffer-fill-long-lines)))
+
+ (put-text-property beg (point) 'read-only t)
+ (put-text-property beg (point) 'front-sticky t)
+ (put-text-property beg (point) 'rear-nonsticky t)))
+
+(defun jabber-rare-time-needed (time1 time2)
+ "Return non-nil if a timestamp should be printed between TIME1 and TIME2."
+ (not (string= (format-time-string jabber-rare-time-format time1)
+ (format-time-string jabber-rare-time-format time2))))
+
+(defun jabber-message-time (entry)
+ "Return time of ENTRY, a message in internal format."
+ (or (when (listp (cadr entry))
+ (jabber-x-delay (jabber-xml-path (cadr entry) '(("jabber:x:delay" . "x")))))
+ (plist-get (cddr entry) :time)))
+
+(defun jabber-maybe-print-rare-time (node)
+ "Print rare time before NODE, if appropriate."
+ (let* ((prev (ewoc-prev jabber-chat-ewoc node))
+ (data (ewoc-data node))
+ (prev-data (when prev (ewoc-data prev))))
+ (when (and jabber-print-rare-time
+ (or (null prev)
+ (jabber-rare-time-needed (jabber-message-time prev-data)
+ (jabber-message-time data))))
+ (ewoc-enter-before jabber-chat-ewoc node (list :rare-time (jabber-message-time data))))))
+
+(defun jabber-chat-print-prompt (xml-data timestamp delayed)
+ "Print prompt for received message in XML-DATA.
+TIMESTAMP is the timestamp to print, or nil to get it
+from a jabber:x:delay element.
+If DELAYED is true, print long timestamp
+\(`jabber-chat-delayed-time-format' as opposed to
+`jabber-chat-time-format')."
(let ((from (jabber-xml-get-attribute xml-data 'from))
- (timestamp (car (delq nil (mapcar 'jabber-x-delay (jabber-xml-get-children xml-data 'x))))))
- (jabber-maybe-print-rare-time timestamp)
+ (timestamp (or timestamp
+ (car (delq nil (mapcar 'jabber-x-delay (jabber-xml-get-children xml-data 'x)))))))
(insert (jabber-propertize
(format-spec jabber-chat-foreign-prompt-format
(list
(cons ?t (format-time-string
- (if timestamp
+ (if delayed
jabber-chat-delayed-time-format
jabber-chat-time-format)
timestamp))
@@ -344,15 +435,31 @@ This function is idempotent."
'help-echo
(concat (format-time-string "On %Y-%m-%d %H:%M:%S" timestamp) " from " from)))))
-(defun jabber-chat-self-prompt (timestamp)
+(defun jabber-chat-system-prompt (timestamp)
+ (insert (jabber-propertize
+ (format-spec jabber-chat-foreign-prompt-format
+ (list
+ (cons ?t (format-time-string jabber-chat-time-format
+ timestamp))
+ (cons ?n "")
+ (cons ?u "")
+ (cons ?r "")
+ (cons ?j "")))
+ 'face 'jabber-chat-prompt-system
+ 'help-echo
+ (concat (format-time-string "System message on %Y-%m-%d %H:%M:%S" timestamp)))))
+
+(defun jabber-chat-self-prompt (timestamp delayed)
"Print prompt for sent message.
-TIMESTAMP is the timestamp to print, or nil for now."
- (jabber-maybe-print-rare-time timestamp)
+TIMESTAMP is the timestamp to print, or nil for now.
+If DELAYED is true, print long timestamp
+\(`jabber-chat-delayed-time-format' as opposed to
+`jabber-chat-time-format')."
(insert (jabber-propertize
(format-spec jabber-chat-local-prompt-format
(list
(cons ?t (format-time-string
- (if timestamp
+ (if delayed
jabber-chat-delayed-time-format
jabber-chat-time-format)
timestamp))
@@ -372,65 +479,83 @@ TIMESTAMP is the timestamp to print, or nil for now."
(concat "Error: " (jabber-parse-error the-error))
'face 'jabber-chat-error))))
-(defun jabber-chat-print-subject (xml-data)
+(defun jabber-chat-print-subject (xml-data who mode)
"Print subject of given <message/>, if any."
(let ((subject (car
(jabber-xml-node-children
(car
(jabber-xml-get-children xml-data 'subject))))))
(when (not (zerop (length subject)))
- (insert (jabber-propertize
- "Subject: " 'face 'jabber-chat-prompt-system)
- (jabber-propertize
- subject
- 'face 'jabber-chat-text-foreign)
- "\n"))))
-
-(defun jabber-chat-print-body (xml-data)
- (run-hook-with-args-until-success 'jabber-body-printers xml-data))
-
-(defun jabber-chat-normal-body (xml-data)
+ (case mode
+ (:printp
+ t)
+ (:insert
+ (insert (jabber-propertize
+ "Subject: " 'face 'jabber-chat-prompt-system)
+ (jabber-propertize
+ subject
+ 'face 'jabber-chat-text-foreign)
+ "\n"))))))
+
+(defun jabber-chat-print-body (xml-data who mode)
+ (run-hook-with-args-until-success 'jabber-body-printers xml-data who mode))
+
+(defun jabber-chat-normal-body (xml-data who mode)
"Print body for received message in XML-DATA."
(let ((body (car
(jabber-xml-node-children
(car
(jabber-xml-get-children xml-data 'body))))))
(when body
- (if (string-match "^/me \\(.*\\)$" body)
- (let ((action (match-string 1 body))
- (nick (if (jabber-muc-message-p xml-data)
- (jabber-jid-resource (jabber-xml-get-attribute xml-data 'from))
- (jabber-jid-displayname (jabber-xml-get-attribute xml-data 'from)))))
- (insert (jabber-propertize
- (concat nick
- " "
- action)
- 'face 'jabber-chat-prompt-system)))
- (insert (jabber-propertize body
- 'face 'jabber-chat-text-foreign)))
+
+ (when (eql mode :insert)
+ (if (string-match "^/me \\(.*\\)$" body)
+ (let ((action (match-string 1 body))
+ (nick (cond
+ ((eq who :local)
+ jabber-nickname)
+ ((jabber-muc-message-p xml-data)
+ (jabber-jid-resource (jabber-xml-get-attribute xml-data 'from)))
+ (t
+ (jabber-jid-displayname (jabber-xml-get-attribute xml-data 'from))))))
+ (insert (jabber-propertize
+ (concat nick
+ " "
+ action)
+ 'face 'jabber-chat-prompt-system)))
+ (insert (jabber-propertize
+ body
+ 'face (case who
+ (:foreign 'jabber-chat-text-foreign)
+ (:local 'jabber-chat-text-local))))))
t)))
-(defun jabber-chat-print-url (xml-data)
+(defun jabber-chat-print-url (xml-data who mode)
"Print URLs provided in jabber:x:oob namespace."
- (dolist (x (jabber-xml-node-children xml-data))
- (when (and (listp x) (eq (jabber-xml-node-name x) 'x)
- (string= (jabber-xml-get-attribute x 'xmlns) "jabber:x:oob"))
-
- (let ((url (car (jabber-xml-node-children
- (car (jabber-xml-get-children x 'url)))))
- (desc (car (jabber-xml-node-children
- (car (jabber-xml-get-children x 'desc))))))
- (insert (jabber-propertize
- "URL: " 'face 'jabber-chat-prompt-system))
- (insert (format "%s <%s>" desc url))
- (insert "\n")))))
+ (let ((foundp nil))
+ (dolist (x (jabber-xml-node-children xml-data))
+ (when (and (listp x) (eq (jabber-xml-node-name x) 'x)
+ (string= (jabber-xml-get-attribute x 'xmlns) "jabber:x:oob"))
+ (setq foundp t)
+
+ (when (eql mode :insert)
+ (let ((url (car (jabber-xml-node-children
+ (car (jabber-xml-get-children x 'url)))))
+ (desc (car (jabber-xml-node-children
+ (car (jabber-xml-get-children x 'desc))))))
+ (insert (jabber-propertize
+ "URL: " 'face 'jabber-chat-prompt-system))
+ (insert (format "%s <%s>" desc url))
+ (insert "\n")))))
+ foundp))
(defun jabber-chat-goto-address (&rest ignore)
"Call `goto-address' on the newly written text."
(goto-address))
+;; jabber-compose is autoloaded in jabber.el
(add-to-list 'jabber-jid-chat-menu
- (cons "Send message" 'jabber-send-message))
+ (cons "Compose message" 'jabber-compose))
(defun jabber-send-message (to subject body type)
"send a message tag to the server"
@@ -442,9 +567,9 @@ TIMESTAMP is the timestamp to print, or nil for now."
,(if (> (length type) 0)
`(type . ,type)))
,(if (> (length subject) 0)
- `(subject () ,(jabber-escape-xml subject)))
+ `(subject () ,subject))
,(if (> (length body) 0)
- `(body () ,(jabber-escape-xml body)))))
+ `(body () ,body))))
(if (and jabber-history-enabled (not (string= type "groupchat")))
(jabber-history-log-message "out" nil to body (current-time))))
@@ -453,7 +578,8 @@ TIMESTAMP is the timestamp to print, or nil for now."
(defun jabber-chat-with (jid &optional other-window)
"Open an empty chat window for chatting with JID.
-With a prefix argument, open buffer in other window."
+With a prefix argument, open buffer in other window.
+Returns the chat buffer."
(interactive (list (jabber-read-jid-completing "chat with:")
current-prefix-arg))
(let ((buffer (jabber-chat-create-buffer jid)))
diff --git a/jabber-chatbuffer.el b/jabber-chatbuffer.el
index e729bb1..2001517 100644
--- a/jabber-chatbuffer.el
+++ b/jabber-chatbuffer.el
@@ -38,7 +38,10 @@ window or at `fill-column', whichever is shorter."
:group 'jabber-chat
:type 'boolean)
-(defun jabber-chat-mode ()
+(defvar jabber-chat-ewoc nil
+ "The ewoc showing the messages of this chat buffer.")
+
+(defun jabber-chat-mode (ewoc-pp)
"\\{jabber-chat-mode-map}"
(kill-all-local-variables)
;; Make sure to set this variable somewhere
@@ -48,7 +51,16 @@ window or at `fill-column', whichever is shorter."
(setq scroll-conservatively 5)
(make-local-variable 'jabber-point-insert)
- (setq jabber-point-insert (point-min))
+ (make-local-variable 'jabber-chat-ewoc)
+ (unless jabber-chat-ewoc
+ (setq jabber-chat-ewoc
+ (ewoc-create ewoc-pp nil "---"))
+ (goto-char (point-max))
+ (put-text-property (point-min) (point) 'read-only t)
+ (let ((inhibit-read-only t))
+ (put-text-property (point-min) (point) 'front-sticky t)
+ (put-text-property (point-min) (point) 'rear-nonsticky t))
+ (setq jabber-point-insert (point-marker)))
;;(setq header-line-format jabber-chat-header-line-format)
@@ -83,60 +95,6 @@ window or at `fill-column', whichever is shorter."
(unless (zerop (length body))
(funcall jabber-send-function body))))
-(defun jabber-chat-buffer-display (prompt-function prompt-data output-functions output-data)
- "Display a message in current buffer.
-PROMPT-FUNCTION is a function that prints the correct prompt at
-point. It is called with PROMPT-DATA as argument.
-OUTPUT-FUNCTIONS is a list of functions that may or may not print something
-at point. They are called in order with OUTPUT-DATA as argument.
-If the OUTPUT-FUNCTIONS produce any output, PROMPT-FUNCTION is called
-with point before that output. If there is no output, there is
-no prompt. Return non-nil if there is output.
-
-If point is at or after jabber-point-insert, it is advanced.
-If point is before jabber-point-insert, it is not moved."
- (let ((at-insert-point (eq (point) jabber-point-insert))
- outputp)
- (save-excursion
- (goto-char jabber-point-insert)
- (setq outputp
- (jabber-chat-buffer-display-at-point prompt-function prompt-data output-functions output-data))
- (setq jabber-point-insert (point))
- (set-text-properties jabber-point-insert (point-max) nil))
-
- (when at-insert-point
- (goto-char jabber-point-insert))
- outputp))
-
-(defun jabber-chat-buffer-display-at-point (prompt-function prompt-data output-functions output-data)
- "Display a message at point.
-Arguments are as to `jabber-chat-buffer-display'.
-Return non-nil if any data was inserted."
- (let ((inhibit-read-only t)
- (beg (point))
- (point-insert (set-marker (make-marker) jabber-point-insert)))
- (set-marker-insertion-type point-insert t)
-
- (dolist (printer output-functions)
- (funcall printer output-data)
- (unless (bolp)
- (insert "\n")))
-
- (unless (eq (point) beg)
- (let ((end (point-marker)))
- (goto-char beg)
- (funcall prompt-function prompt-data)
- (goto-char end)
- (put-text-property beg end 'read-only t)
- (put-text-property beg end 'front-sticky t)
- (put-text-property beg end 'rear-nonsticky t)
- (when jabber-chat-fill-long-lines
- (save-restriction
- (narrow-to-region beg end)
- (jabber-chat-buffer-fill-long-lines)))
- ;; this is always non-nil, so we return that
- (setq jabber-point-insert (marker-position point-insert))))))
-
(defun jabber-chat-buffer-fill-long-lines ()
"Fill lines that are wider than the window width."
;; This was mostly stolen from article-fill-long-lines
diff --git a/jabber-compose.el b/jabber-compose.el
new file mode 100644
index 0000000..946f165
--- /dev/null
+++ b/jabber-compose.el
@@ -0,0 +1,80 @@
+;;; jabber-compose.el --- compose a Jabber message in a buffer
+
+;; Copyright (C) 2006 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+;; Keywords:
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Code:
+
+;;;###autoload
+(defun jabber-compose (&optional recipient)
+ "Create a buffer for composing a Jabber message."
+ (interactive (list (jabber-read-jid-completing "To whom? ")))
+
+ (with-current-buffer (get-buffer-create
+ (generate-new-buffer-name
+ (concat
+ "Jabber-Compose"
+ (when recipient
+ (format "-%s" (jabber-jid-displayname recipient))))))
+ (set (make-local-variable 'jabber-widget-alist) nil)
+ (use-local-map widget-keymap)
+
+ (insert (jabber-propertize "Compose Jabber message\n" 'face 'jabber-title-large))
+
+ (insert (substitute-command-keys "\\<widget-field-keymap>Completion available with \\[widget-complete].\n"))
+ (push (cons :recipients
+ (widget-create '(repeat :tag "Recipients" jid)
+ :value (when recipient
+ (list recipient))))
+ jabber-widget-alist)
+
+ (insert "\nSubject: ")
+ (push (cons :subject
+ (widget-create 'editable-field :value ""))
+ jabber-widget-alist)
+
+ (insert "\nText:\n")
+ (push (cons :text
+ (widget-create 'text :value ""))
+ jabber-widget-alist)
+
+ (insert "\n")
+ (widget-create 'push-button :notify #'jabber-compose-send "Send")
+
+ (widget-setup)
+
+ (switch-to-buffer (current-buffer))
+ (goto-char (point-min))))
+
+(defun jabber-compose-send (&rest ignore)
+ (let ((recipients (widget-value (cdr (assq :recipients jabber-widget-alist))))
+ (subject (widget-value (cdr (assq :subject jabber-widget-alist))))
+ (text (widget-value (cdr (assq :text jabber-widget-alist)))))
+ (when (null recipients)
+ (error "No recipients specified"))
+
+ (dolist (to recipients)
+ (jabber-send-message to subject text nil))
+
+ (bury-buffer)
+ (message "Message sent")))
+
+(provide 'jabber-compose)
+;; arch-tag: 59032c00-994d-11da-8d97-000a95c2fcd0
diff --git a/jabber-conn.el b/jabber-conn.el
index f3488ef..07d3c52 100644
--- a/jabber-conn.el
+++ b/jabber-conn.el
@@ -3,6 +3,9 @@
;; Copyright (C) 2005 - Georg Lehner - jorge@magma.com.ni
;; mostly inspired by Gnus.
+;; Copyright (C) 2005 - Carl Henrik Lunde - chlunde+jabber+@ping.uio.no
+;; (starttls)
+
;; This file is a part of jabber.el.
;; This program is free software; you can redistribute it and/or modify
@@ -28,6 +31,10 @@
(or (ignore-errors (require 'tls))
(ignore-errors (require 'ssl)))
+(ignore-errors (require 'starttls))
+
+(require 'srv)
+
;; TODO: Add custom flag, to not complain about plain-text passwords
;; in encrypted connections
;;
@@ -54,9 +61,21 @@ and 5223 for SSL connections."
(integer :tag "Port number"))
:group 'jabber-conn)
-(defcustom jabber-connection-type 'network
+(defcustom jabber-connection-type
+ (cond
+ ;; Use STARTTLS if we can...
+ ((and (featurep 'starttls)
+ (or (and (bound-and-true-p starttls-gnutls-program)
+ (executable-find starttls-gnutls-program))
+ (and (bound-and-true-p starttls-program)
+ (executable-find starttls-program))))
+ 'starttls)
+ ;; ...else default to unencrypted connection.
+ (t
+ 'network))
"Type of connection to the jabber server, ssl or network most likely."
:type '(radio (const :tag "Encrypted connection, SSL" ssl)
+ (const :tag "Negotiate encrypted connection when available (STARTTLS)" starttls)
(const :tag "Standard TCP/IP connection" network))
:group 'jabber-conn)
@@ -72,6 +91,7 @@ nil means prefer gnutls but fall back to openssl.
(defvar jabber-connect-methods
'((network jabber-network-connect jabber-network-send)
+ (starttls jabber-starttls-connect jabber-ssl-send)
(ssl jabber-ssl-connect jabber-ssl-send))
"Alist of connection methods and functions.
First item is the symbol naming the method.
@@ -89,16 +109,36 @@ Third item is the send function.")
(setq jabber-connect-function (nth 1 entry))
(setq jabber-conn-send-function (nth 2 entry))))
+(defun jabber-srv-targets ()
+ "Find host and port to connect to.
+If we can't find SRV records, use standard defaults."
+ ;; If the user has specified a host or a port, obey that.
+ (if (or jabber-network-server jabber-port)
+ (list (cons (or jabber-network-server jabber-server)
+ (or jabber-port 5222)))
+ (or (condition-case nil
+ (srv-lookup (concat "_xmpp-client._tcp." jabber-server))
+ (error nil))
+ (list (cons jabber-server 5222)))))
+
;; Plain TCP/IP connection
(defun jabber-network-connect ()
- (let ((coding-system-for-read 'utf-8)
- (coding-system-for-write 'utf-8))
- (setq *jabber-connection*
- (open-network-stream
- "jabber"
- jabber-process-buffer
- (or jabber-network-server jabber-server)
- (or jabber-port 5222)))))
+ (let ((coding-system-for-read 'utf-8)
+ (coding-system-for-write 'utf-8)
+ (targets (jabber-srv-targets)))
+ (catch 'connected
+ (dolist (target targets)
+ (condition-case e
+ (when (setq *jabber-connection*
+ (open-network-stream
+ "jabber"
+ jabber-process-buffer
+ (car target)
+ (cdr target)))
+ (throw 'connected t))
+ (error
+ (message "Couldn't connect to %s: %s" target
+ (error-message-string e))))))))
(defun jabber-network-send (string)
"Send a string via a plain TCP/IP connection to the Jabber Server."
@@ -121,6 +161,7 @@ Third item is the send function.")
'open-ssl-stream)
(t
(error "Neither TLS nor SSL connect functions available")))))
+ (setq *jabber-encrypted* t)
(setq *jabber-connection*
(funcall connect-function
"jabber"
@@ -134,5 +175,56 @@ Third item is the send function.")
(process-send-string *jabber-connection* string)
(process-send-string *jabber-connection* "\n"))
+(defun jabber-starttls-connect ()
+ "connect via GnuTLS to a Jabber Server"
+ (let ((coding-system-for-read 'utf-8)
+ (coding-system-for-write 'utf-8)
+ (targets (jabber-srv-targets)))
+ (unless (fboundp 'starttls-open-stream)
+ (error "starttls.el not available"))
+ (catch 'connected
+ (dolist (target targets)
+ (condition-case e
+ (when (setq *jabber-connection*
+ (starttls-open-stream
+ "jabber"
+ (get-buffer-create jabber-process-buffer)
+ (car target)
+ (cdr target)))
+ (throw 'connected t))
+ (error
+ (message "Couldn't connect to %s: %s" target
+ (error-message-string e))))))))
+
+(defun jabber-starttls-initiate ()
+ "Initiate a starttls connection"
+ (setq jabber-short-circuit-input #'jabber-starttls-process-input)
+ (jabber-send-sexp
+ '(starttls ((xmlns . "urn:ietf:params:xml:ns:xmpp-tls")))))
+
+(defun jabber-starttls-process-input (xml-data)
+ "Process result of starttls request"
+ (cond
+ ((eq (car xml-data) 'proceed)
+ (message "STARTTLS result:\n%s\n" (starttls-negotiate *jabber-connection*)))
+ ((eq (car xml-data) 'failure)
+ (ding)
+ (message "STARTTLS negotiation failure: %s"
+ (jabber-xml-node-name (car (jabber-xml-node-children xml-data))))
+ (sit-for 3)
+ (jabber-disconnect)))
+
+ (setq jabber-short-circuit-input nil)
+ (setq *jabber-encrypted* t)
+
+ ;; Now, we send another stream header.
+ (funcall jabber-conn-send-function
+ (concat
+ "<stream:stream to='"
+ jabber-server
+ "' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>"))
+ ;; now see what happens
+ )
+
(provide 'jabber-conn)
;; arch-tag: f95ec240-8cd3-11d9-9dbf-000a95c2fcd0
diff --git a/jabber-core.el b/jabber-core.el
index 257cd14..eb9d07f 100644
--- a/jabber-core.el
+++ b/jabber-core.el
@@ -46,6 +46,9 @@
(defvar *jabber-authenticated* nil
"boolean - are we authenticated")
+(defvar *jabber-encrypted* nil
+ "boolean - is the connection encrypted")
+
(defvar *jabber-disconnecting* nil
"boolean - are we in the process of disconnecting by free will")
@@ -241,6 +244,7 @@ Call this function after disconnection."
(jabber-clear-roster)
(setq *xmlq* "")
(setq *jabber-authenticated* nil)
+ (setq *jabber-encrypted* nil)
(setq *jabber-connected* nil)
(setq *jabber-active-groupchats* nil)
(setq jabber-session-id nil)
@@ -410,14 +414,22 @@ submit a bug report, including the information below.
(presence . jabber-presence-chain)
(message . jabber-message-chain)
(stream:error . jabber-stream-error-chain)))))))
- ;; Special treatment of the stream:features tag. The first time we get it,
- ;; it means that we should authenticate. The second time, we should
- ;; establish a session. (The zeroth time it's STARTTLS, but that's not
- ;; implemented yet.)
+
+ ;; Special treatment of the stream:features tag, which we get up
+ ;; to three times, in the following order:
+ ;; - To initiate STARTTLS (we can skip this step)
+ ;; - To authenticate
+ ;; - To establish a session
(if (eq tag 'stream:features)
- (if *jabber-authenticated*
- (jabber-bind-and-establish-session xml-data)
- (funcall jabber-call-on-connection xml-data))
+ (cond
+ ((and (not *jabber-encrypted*)
+ (eq jabber-connection-type 'starttls)
+ (jabber-xml-get-children xml-data 'starttls))
+ (jabber-starttls-initiate))
+ (*jabber-authenticated*
+ (jabber-bind-and-establish-session xml-data))
+ (t
+ (funcall jabber-call-on-connection xml-data)))
(if jabber-short-circuit-input
(funcall jabber-short-circuit-input xml-data)
(dolist (f functions)
@@ -480,9 +492,7 @@ submit a bug report, including the information below.
"get"
'(query ((xmlns . "jabber:iq:roster")))
#'jabber-process-roster 'initial
- #'jabber-report-success "Roster retrieval")
-
- (run-hooks 'jabber-post-connect-hook))
+ #'jabber-report-success "Roster retrieval"))
(defun jabber-clear-roster ()
"Clean up the roster."
diff --git a/jabber-disco.el b/jabber-disco.el
index 226be6e..00a9d9c 100644
--- a/jabber-disco.el
+++ b/jabber-disco.el
@@ -46,7 +46,7 @@ called and its return value is used; if it is a list, that list is
used. The list should be the XML data to be returned inside the
<query/> element, like this:
-((item ((name . \"Name of first item\")
+\((item ((name . \"Name of first item\")
(jid . \"first.item\")
(node . \"node\"))))
@@ -66,7 +66,7 @@ called and its return value is used; if it is a list, that list is
used. The list should be the XML data to be returned inside the
<query/> element, like this:
-((identity ((category . \"client\")
+\((identity ((category . \"client\")
(type . \"pc\")
(name . \"Jabber client\")))
(feature ((var . \"some-feature\"))))
@@ -86,9 +86,9 @@ nil, access is always granted.")
(category (jabber-xml-get-attribute x 'category))
(type (jabber-xml-get-attribute x 'type)))
(insert (jabber-propertize (if name
- (jabber-unescape-xml name)
- "Unnamed")
- 'face 'jabber-title-medium)
+ name
+ "Unnamed")
+ 'face 'jabber-title-medium)
"\n\nCategory:\t" category "\n")
(if type
(insert "Type:\t\t" type "\n"))
@@ -113,7 +113,7 @@ nil, access is always granted.")
(jabber-propertize
(concat jid "\n" (if node (format "Node: %s\n" node)))
'face 'jabber-title-medium)
- (jabber-unescape-xml name) "\n\n")
+ name "\n\n")
'jabber-jid jid
'jabber-node node))))
(insert "No items found.\n"))))
@@ -147,7 +147,9 @@ See JEP-0030."
(funcall func xml-data)
func)))
(jabber-send-iq to "result"
- `(query ((xmlns . ,xmlns))
+ `(query ((xmlns . ,xmlns)
+ ,@(when node
+ (list (cons 'node node))))
,@result)
nil nil nil nil id)))
diff --git a/jabber-events.el b/jabber-events.el
index b9fc556..750175f 100644
--- a/jabber-events.el
+++ b/jabber-events.el
@@ -135,7 +135,7 @@ and it hasn't been sent before."
(setq jabber-events-display-confirmed t))))
(defun jabber-events-after-change ()
- (let ((composing-now (not (eq (point-max) jabber-point-insert))))
+ (let ((composing-now (not (= (point-max) jabber-point-insert))))
(when (and jabber-events-confirm-composing
jabber-chatting-with
(not (eq composing-now jabber-events-composing-sent)))
@@ -149,17 +149,27 @@ and it hasn't been sent before."
;;; COMMON
-(add-to-list 'jabber-chat-printers 'jabber-handle-incoming-message-events)
+;; Add function last in chain, so a chat buffer is already created.
+(add-to-list 'jabber-message-chain 'jabber-handle-incoming-message-events t)
(defun jabber-handle-incoming-message-events (xml-data)
- (let ((x (find "jabber:x:event"
- (jabber-xml-get-children xml-data 'x)
- :key #'(lambda (x) (jabber-xml-get-attribute x 'xmlns))
- :test #'string=)))
- ;; If there's a body, it's not an incoming message event.
- (if (jabber-xml-get-children xml-data 'body)
- ;; User is done composing, obviously.
- (progn
+ (when (and (not (jabber-muc-message-p xml-data))
+ (get-buffer (jabber-chat-get-buffer (jabber-xml-get-attribute xml-data 'from))))
+ (with-current-buffer (jabber-chat-get-buffer (jabber-xml-get-attribute xml-data 'from))
+ (let ((x (find "jabber:x:event"
+ (jabber-xml-get-children xml-data 'x)
+ :key #'(lambda (x) (jabber-xml-get-attribute x 'xmlns))
+ :test #'string=)))
+ (cond
+ ;; If we get an error message, we shouldn't report any
+ ;; events, as the requests are mirrored from us.
+ ((string= (jabber-xml-get-attribute xml-data 'type) "error")
+ (remove-hook 'post-command-hook 'jabber-events-after-change t)
+ (setq jabber-events-requested nil))
+
+ ;; If there's a body, it's not an incoming message event.
+ ((jabber-xml-get-children xml-data 'body)
+ ;; User is done composing, obviously.
(setq jabber-events-composing-p nil)
(jabber-events-update-message)
@@ -204,24 +214,25 @@ and it hasn't been sent before."
(memq 'composing jabber-events-requested))
(add-hook 'post-command-hook 'jabber-events-after-change
nil t))))
- ;; So it has no body. If it's a message event,
- ;; the <x/> node should be the only child of the
- ;; message, and it should contain an <id/> node.
- ;; We check the latter.
- (when (and x (jabber-xml-get-children x 'id))
- ;; Currently we don't care about the <id/> node.
+ (t
+ ;; So it has no body. If it's a message event,
+ ;; the <x/> node should be the only child of the
+ ;; message, and it should contain an <id/> node.
+ ;; We check the latter.
+ (when (and x (jabber-xml-get-children x 'id))
+ ;; Currently we don't care about the <id/> node.
- ;; There's only one node except for the id.
- (unless
- (dolist (possible-node '(offline delivered displayed))
- (when (jabber-xml-get-children x possible-node)
- (setq jabber-events-arrived possible-node)
- (jabber-events-update-message)
- (return t)))
- ;; Or maybe even zero, which is a negative composing node.
- (setq jabber-events-composing-p
- (not (null (jabber-xml-get-children x 'composing))))
- (jabber-events-update-message))))))
+ ;; There's only one node except for the id.
+ (unless
+ (dolist (possible-node '(offline delivered displayed))
+ (when (jabber-xml-get-children x possible-node)
+ (setq jabber-events-arrived possible-node)
+ (jabber-events-update-message)
+ (return t)))
+ ;; Or maybe even zero, which is a negative composing node.
+ (setq jabber-events-composing-p
+ (not (null (jabber-xml-get-children x 'composing))))
+ (jabber-events-update-message)))))))))
(provide 'jabber-events)
;; arch-tag: 7b6e61fe-a9b3-11d9-afca-000a95c2fcd0
diff --git a/jabber-ft-client.el b/jabber-ft-client.el
index c3b9434..64d26bb 100644
--- a/jabber-ft-client.el
+++ b/jabber-ft-client.el
@@ -18,12 +18,16 @@
;; 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 'cl))
+
(require 'jabber-si-client)
(require 'jabber-util)
+(require 'jabber-ft-common)
+
(defun jabber-ft-send (jid filename desc)
"Attempt to send FILENAME to JID."
- (interactive (list (jabber-read-jid-completing "Send file to: ")
+ (interactive (list (jabber-read-jid-completing "Send file to: " nil nil nil 'full)
(read-file-name "Send which file: " nil nil t)
(jabber-read-with-input-method "Description (optional): ")))
(if (zerop (length desc)) (setq desc nil))
@@ -32,23 +36,32 @@
(let* ((attributes (file-attributes filename))
(size (nth 7 attributes))
- (date (nth 5 attributes)))
+ (date (nth 5 attributes))
+ (hash (jabber-ft-get-md5 filename)))
(jabber-si-initiate jid "http://jabber.org/protocol/si/profile/file-transfer"
`(file ((xmlns . "http://jabber.org/protocol/si/profile/file-transfer")
(name . ,(file-name-nondirectory filename))
(size . ,size)
- (date . ,(jabber-encode-time date)))
+ (date . ,(jabber-encode-time date))
+ ,@(when hash
+ (list (cons 'hash hash))))
(desc () ,desc))
- `(lambda (jid sid send-data-function)
- (jabber-ft-do-send jid sid send-data-function ,filename)))))
+ (lexical-let ((filename filename))
+ (lambda (jid sid send-data-function)
+ (jabber-ft-do-send
+ jid sid send-data-function filename))))))
(defun jabber-ft-do-send (jid sid send-data-function filename)
- (with-temp-buffer
- (insert-file-contents-literally filename)
-
- ;; Ever heard of buffering?
- (funcall send-data-function (buffer-string))
- (message "File transfer completed")))
+ (if (stringp send-data-function)
+ (message "File sending failed: %s" send-data-function)
+ (with-temp-buffer
+ (insert-file-contents-literally filename)
+
+ ;; Ever heard of buffering?
+ (funcall send-data-function (buffer-string))
+ (message "File transfer completed")))
+ ;; File transfer is monodirectional, so ignore received data.
+ #'ignore)
(provide 'jabber-ft-client)
;;; arch-tag: fba686d5-37b5-4165-86c5-49b76fa0ea6e
diff --git a/jabber-ft-common.el b/jabber-ft-common.el
new file mode 100644
index 0000000..55673ec
--- /dev/null
+++ b/jabber-ft-common.el
@@ -0,0 +1,44 @@
+;;; jabber-ft-common.el --- Common functions for sending and receiving files (JEP-0096)
+
+;; Copyright (C) 2006 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(defcustom jabber-ft-md5sum-program (or (when (executable-find "md5")
+ (list (executable-find "md5") "-n"))
+ (when (executable-find "md5sum")
+ (list (executable-find "md5sum"))))
+ "The program to use to calculate MD5 sums of files.
+It should accept the file name as the only argument."
+ :type 'string
+ :group 'jabber)
+
+(defun jabber-ft-get-md5 (file-name)
+ "Get MD5 sum of FILE-NAME, and return as hex string.
+Return nil if no MD5 summing program is available."
+ (when jabber-ft-md5sum-program
+ (with-temp-buffer
+ (apply 'call-process (car jabber-ft-md5sum-program) nil t nil
+ (append (cdr jabber-ft-md5sum-program) (list file-name)))
+ ;; Output is "hexsum filename"
+ (goto-char (point-min))
+ (forward-word 1)
+ (buffer-substring (point-min) (point)))))
+
+(provide 'jabber-ft-common)
+;; arch-tag: 1ce4cce0-8360-11da-a5ba-000a95c2fcd0
diff --git a/jabber-ft-server.el b/jabber-ft-server.el
index 09405f9..0a0e72f 100644
--- a/jabber-ft-server.el
+++ b/jabber-ft-server.el
@@ -33,7 +33,7 @@
(add-to-list 'jabber-si-profiles
(list "http://jabber.org/protocol/si/profile/file-transfer"
'jabber-ft-accept
- 'jabber-ft-data))
+ 'jabber-ft-server-connected))
(defun jabber-ft-accept (xml-data)
"Receive IQ stanza containing file transfer request, ask user"
@@ -70,6 +70,7 @@
(buffer (create-file-buffer file-name)))
(message "Starting download of %s..." (file-name-nondirectory file-name))
(with-current-buffer buffer
+ (kill-all-local-variables)
(setq buffer-file-coding-system 'binary)
;; For Emacs, switch buffer to unibyte _before_ anything goes into it,
;; otherwise binary files are corrupted. For XEmacs, it isn't needed,
@@ -85,6 +86,14 @@
;; to support range, return something sensible here
nil))
+(defun jabber-ft-server-connected (jid sid send-data-function)
+ ;; We don't really care about the send-data-function. But if it's
+ ;; a string, it means that we have no connection.
+ (if (stringp send-data-function)
+ (message "File receiving failed: %s" send-data-function)
+ ;; On success, we just return our data receiving function.
+ 'jabber-ft-data))
+
(defun jabber-ft-data (jid sid data)
"Receive chunk of transferred file."
(let ((buffer (cdr (assoc (list sid jid) jabber-ft-sessions))))
@@ -92,12 +101,15 @@
;; If data is nil, there is no more data.
;; But maybe the remote entity doesn't close the stream -
;; then we have to keep track of file size to know when to stop.
+ ;; Return value is whether to keep connection open.
(when data
(insert data))
(if (and data (< (buffer-size) jabber-ft-size))
t
(basic-save-buffer)
- (message "%s downloaded" (file-name-nondirectory buffer-file-name))))))
+ (message "%s downloaded" (file-name-nondirectory buffer-file-name))
+ (kill-buffer buffer)
+ nil))))
(provide 'jabber-ft-server)
diff --git a/jabber-history.el b/jabber-history.el
index 669fe2a..78f57f1 100644
--- a/jabber-history.el
+++ b/jabber-history.el
@@ -139,14 +139,16 @@ Jabber history files."
(setq body (replace-match "\\n" nil t body nil)))
(while (string-match "\r" body)
(setq body (replace-match "\\r" nil t body nil)))
- (insert (format "[\"%s\" \"%s\" \"%s\" \"%s\" %s]\n"
+ (insert (format "[\"%s\" \"%s\" %s %s %s]\n"
(jabber-encode-time (or timestamp (current-time)))
(or direction
"in")
- (or from
- "me")
- (or to
- "me")
+ (or (when from
+ (prin1-to-string from))
+ "\"me\"")
+ (or (when to
+ (prin1-to-string to))
+ "\"me\"")
body))
(let ((coding-system-for-write 'utf-8)
(history-file (jabber-history-filename (or from to))))
diff --git a/jabber-iq.el b/jabber-iq.el
index a165517..4992fc9 100644
--- a/jabber-iq.el
+++ b/jabber-iq.el
@@ -140,7 +140,7 @@ See section 9.3 of XMPP Core."
(,condition ((xmlns . "urn:ietf:params:xml:ns:xmpp-stanzas")))
,(if text
`(text ((xmlns . "urn:ietf:params:xml:ns:xmpp-stanzas"))
- ,text))
+ ,text))
,@app-specific))))
(defun jabber-process-data (xml-data closure-data)
@@ -158,19 +158,21 @@ See section 9.3 of XMPP Core."
(insert (jabber-propertize from
'face 'jabber-title-large) "\n\n")
- ;; If closure-data is a function, call it. If it is a string,
- ;; output it along with a description of the error. For other
- ;; values (e.g. nil), just dump the XML.
- (cond
- ((functionp closure-data)
- (funcall closure-data xml-data))
- ((stringp closure-data)
- (insert closure-data ": " (jabber-parse-error (jabber-iq-error xml-data)) "\n\n"))
- (t
- (insert (format "%S\n\n" xml-data))))
-
- (dolist (hook '(jabber-info-message-hooks jabber-alert-info-message-hooks))
- (run-hook-with-args hook 'browse (current-buffer) (funcall jabber-alert-info-message-function 'browse (current-buffer)))))))
+ ;; Put point at beginning of data
+ (save-excursion
+ ;; If closure-data is a function, call it. If it is a string,
+ ;; output it along with a description of the error. For other
+ ;; values (e.g. nil), just dump the XML.
+ (cond
+ ((functionp closure-data)
+ (funcall closure-data xml-data))
+ ((stringp closure-data)
+ (insert closure-data ": " (jabber-parse-error (jabber-iq-error xml-data)) "\n\n"))
+ (t
+ (insert (format "%S\n\n" xml-data))))
+
+ (dolist (hook '(jabber-info-message-hooks jabber-alert-info-message-hooks))
+ (run-hook-with-args hook 'browse (current-buffer) (funcall jabber-alert-info-message-function 'browse (current-buffer))))))))
(provide 'jabber-iq)
diff --git a/jabber-keymap.el b/jabber-keymap.el
index f8b50f4..3049b05 100644
--- a/jabber-keymap.el
+++ b/jabber-keymap.el
@@ -48,6 +48,7 @@
(define-key map "\C-a" 'jabber-send-away-presence)
(define-key map "\C-o" 'jabber-send-default-presence)
(define-key map "\C-x" 'jabber-send-xa-presence)
+ (define-key map "\C-p" 'jabber-send-presence)
map)
"Global Jabber keymap (usually under C-x C-j)")
diff --git a/jabber-logon.el b/jabber-logon.el
index f87aceb..194de50 100644
--- a/jabber-logon.el
+++ b/jabber-logon.el
@@ -45,7 +45,9 @@
(let ((passwd (jabber-read-passwd)))
(if passwd
(setq auth `(digest () ,(sha1 (concat jabber-session-id passwd))))))
- (if (yes-or-no-p "Jabber server only allows cleartext password transmission! Continue? ")
+ ;; Plaintext passwords - allow on encrypted connections
+ (if (or *jabber-encrypted*
+ (yes-or-no-p "Jabber server only allows cleartext password transmission! Continue? "))
(let ((passwd (jabber-read-passwd)))
(if passwd
(setq auth `(password () ,passwd))))))
@@ -75,9 +77,7 @@ CLOSURE-DATA should be t on success and nil on failure."
"get"
'(query ((xmlns . "jabber:iq:roster")))
#'jabber-process-roster 'initial
- #'jabber-report-success "Roster retrieval")
-
- (run-hooks 'jabber-post-connect-hook))
+ #'jabber-report-success "Roster retrieval"))
;; Logon failure
(jabber-report-success xml-data "Logon")
diff --git a/jabber-muc.el b/jabber-muc.el
index b09fe15..16ccaca 100644
--- a/jabber-muc.el
+++ b/jabber-muc.el
@@ -21,6 +21,7 @@
(require 'jabber-chat)
(require 'jabber-widget)
+(require 'jabber-newdisco)
(require 'cl)
@@ -29,6 +30,12 @@
Keys are strings, the bare JID of the room.
Values are strings.")
+(defvar jabber-pending-groupchats (make-hash-table)
+ "Hash table of groupchats and nicknames.
+Keys are JID symbols; values are strings.
+This table records the last nickname used to join the particular
+chat room. Items are thus never removed.")
+
(defvar jabber-muc-participants nil
"alist of groupchats and participants
Keys are strings, the bare JID of the room.
@@ -53,6 +60,14 @@ Values are lists of nickname strings.")
:group 'jabber-chat
:type '(repeat (string :tag "JID of room")))
+(defcustom jabber-muc-disable-disco-check nil
+ "If non-nil, disable checking disco#info of rooms before joining them.
+Disco information can tell whether the room exists and whether it is
+password protected, but some servers do not support it. If you want
+to join chat rooms on such servers, set this variable to t."
+ :group 'jabber-chat
+ :type 'boolean)
+
(defcustom jabber-groupchat-buffer-format "*-jabber-groupchat-%n-*"
"The format specification for the name of groupchat buffers.
@@ -116,7 +131,7 @@ The format is that of `mode-line-format' and `header-line-format'."
:type 'sexp
:group 'jabber-chat)
-(defvar jabber-muc-printers '(jabber-muc-snarf-topic)
+(defvar jabber-muc-printers '()
"List of functions that may be able to print part of a MUC message.
This gets prepended to `jabber-chat-printers', which see.")
@@ -133,10 +148,11 @@ Either a string or a buffer is returned, so use `get-buffer' or
"Prepare a buffer for chatroom GROUP.
This function is idempotent."
(with-current-buffer (get-buffer-create (jabber-muc-get-buffer group))
- (if (not (eq major-mode 'jabber-chat-mode)) (jabber-chat-mode))
- (make-local-variable 'jabber-group)
+ (unless (eq major-mode 'jabber-chat-mode)
+ (jabber-chat-mode #'jabber-chat-pp))
+
+ (set (make-local-variable 'jabber-group) group)
(make-local-variable 'jabber-muc-topic)
- (setq jabber-group group)
(setq jabber-send-function 'jabber-muc-send)
(setq header-line-format jabber-muc-header-line-format)
(current-buffer)))
@@ -154,9 +170,10 @@ Either a string or a buffer is returned, so use `get-buffer' or
"Prepare a buffer for chatting with NICKNAME in GROUP.
This function is idempotent."
(with-current-buffer (get-buffer-create (jabber-muc-private-get-buffer group nickname))
- (if (not (eq major-mode 'jabber-chat-mode)) (jabber-chat-mode))
- (make-local-variable 'jabber-chatting-with)
- (setq jabber-chatting-with (concat group "/" nickname))
+ (unless (eq major-mode 'jabber-chat-mode)
+ (jabber-chat-mode #'jabber-chat-pp))
+
+ (set (make-local-variable 'jabber-chatting-with) (concat group "/" nickname))
(setq jabber-send-function 'jabber-chat-send)
(setq header-line-format jabber-muc-private-header-line-format)
@@ -169,7 +186,7 @@ This function is idempotent."
(jabber-send-sexp `(message
((to . ,jabber-group)
(type . "groupchat"))
- (body () ,(jabber-escape-xml body)))))
+ (body () ,body))))
(defun jabber-muc-add-groupchat (group nickname)
"Remember participating in GROUP under NICKNAME."
@@ -203,12 +220,82 @@ Return nil if nothing known about that combination."
;; and maybe this participant is already in the list
(if participant
;; if so, just update role, affiliation, etc.
- ;; XXX: calculate delta and report to user? e.g. "X was given voice"
(setf (cdr participant) new-plist)
(push (cons nickname new-plist) (cdr participants))))
;; or we don't
(push (cons group (list (cons nickname new-plist))) jabber-muc-participants))))
+(defun jabber-muc-report-delta (nickname old-plist new-plist reason actor)
+ "Compare OLD-PLIST and NEW-PLIST, and return a string explaining the change.
+Return nil if nothing noteworthy has happened.
+NICKNAME is the user experiencing the change. REASON and ACTOR, if non-nil,
+are the corresponding presence fields.
+
+This function is only concerned with presence stanzas resulting
+in the user entering/staying in the room."
+ ;; The keys in the plist are affiliation, role and jid.
+ (cond
+ ((null old-plist)
+ ;; User enters the room
+ (concat nickname " enters the room ("
+ (plist-get new-plist 'role)
+ (unless (string= (plist-get new-plist 'affiliation) "none")
+ (concat ", " (plist-get new-plist 'affiliation)))
+ ")"))
+
+ ;; If affiliation changes, the role change is usually the logical
+ ;; one, so don't report it separately.
+ ((not (string= (plist-get old-plist 'affiliation)
+ (plist-get new-plist 'affiliation)))
+ (let ((actor-reason (concat (when actor
+ (concat " by " actor))
+ (when reason
+ (concat ": " reason))))
+ (from (plist-get old-plist 'affiliation))
+ (to (plist-get new-plist 'affiliation)))
+ ;; There are many ways to express these transitions in English.
+ ;; This one favors eloquence over regularity and consistency.
+ (cond
+ ;; Higher affiliation
+ ((or (and (member from '("outcast" "none" "member"))
+ (member to '("admin" "owner")))
+ (and (string= from "admin") (string= to "owner")))
+ (concat nickname " has been promoted to " to actor-reason))
+ ;; Lower affiliation
+ ((or (and (member from '("owner" "admin"))
+ (string= to "member"))
+ (and (string= from "owner") (string= to "admin")))
+ (concat nickname " has been demoted to " to actor-reason))
+ ;; Become member
+ ((string= to "member")
+ (concat nickname " has been granted membership" actor-reason))
+ ;; Lose membership
+ ((string= to "none")
+ (concat nickname " has been deprived of membership" actor-reason)))))
+
+ ;; Role changes
+ ((not (string= (plist-get old-plist 'role)
+ (plist-get new-plist 'role)))
+ (let ((actor-reason (concat (when actor
+ (concat " by " actor))
+ (when reason
+ (concat ": " reason))))
+ (from (plist-get old-plist 'role))
+ (to (plist-get new-plist 'role)))
+ ;; Possible roles are "none" (not in room, hence not of interest
+ ;; in this function), "visitor" (no voice), "participant" (has
+ ;; voice), and "moderator".
+ (cond
+ ((string= to "moderator")
+ (concat nickname " has been granted moderator privileges" actor-reason))
+ ((and (string= from "moderator")
+ (string= to "participant"))
+ (concat nickname " had moderator privileges revoked" actor-reason))
+ ((string= to "participant")
+ (concat nickname " has been granted voice" actor-reason))
+ ((string= to "visitor")
+ (concat nickname " has been denied voice" actor-reason)))))))
+
(defun jabber-muc-remove-participant (group nickname)
"Forget everything about NICKNAME in GROUP."
(let ((participants (assoc group jabber-muc-participants)))
@@ -216,15 +303,17 @@ Return nil if nothing known about that combination."
(let ((participant (assoc nickname (cdr participants))))
(setf (cdr participants) (delq participant (cdr participants)))))))
-(defun jabber-muc-read-completing (prompt)
- "Read the name of a joined chatroom, or use chatroom of current buffer, if any."
+(defun jabber-muc-read-completing (prompt &optional allow-not-joined)
+ "Read the name of a joined chatroom, or use chatroom of current buffer, if any.
+If ALLOW-NOT-JOINED is provided and true, permit choosing any
+JID; only provide completion as a guide."
(or jabber-group
(jabber-read-jid-completing prompt
(if (null *jabber-active-groupchats*)
(error "You haven't joined any group")
(mapcar (lambda (x) (jabber-jid-symbol (car x)))
*jabber-active-groupchats*))
- t
+ (not allow-not-joined)
jabber-group)))
(defun jabber-muc-read-nickname (group prompt)
@@ -238,7 +327,7 @@ Return nil if nothing known about that combination."
(cons "Configure groupchat" 'jabber-groupchat-get-config))
(defun jabber-groupchat-get-config (group)
"Ask for MUC configuration form"
- (interactive (list (jabber-muc-read-completing "Configure group: ")))
+ (interactive (list (jabber-muc-read-completing "Configure group: " t)))
(jabber-send-iq group
"get"
'(query ((xmlns . "http://jabber.org/protocol/muc#owner")))
@@ -290,24 +379,80 @@ Return nil if nothing known about that combination."
(add-to-list 'jabber-jid-muc-menu
(cons "Join groupchat" 'jabber-groupchat-join))
-(defun jabber-groupchat-join (group nickname)
- "join a groupchat, or change nick"
+(defun jabber-groupchat-join (group nickname &optional popup)
+ "join a groupchat, or change nick.
+In interactive calls, or if POPUP is true, switch to the
+groupchat buffer."
(interactive
(let ((group (jabber-read-jid-completing "group: ")))
- (list group (jabber-muc-read-my-nickname group))))
+ (list group (jabber-muc-read-my-nickname group) t)))
+
+ ;; If the user is already in the room, we don't need as many checks.
+ (if (or (assoc group *jabber-active-groupchats*)
+ ;; Or if the users asked us not to check disco info.
+ jabber-muc-disable-disco-check)
+ (jabber-groupchat-join-3 group nickname nil popup)
+ ;; Else, send a disco request to find out what we are connecting
+ ;; to.
+ (jabber-disco-get-info group nil #'jabber-groupchat-join-2
+ (list group nickname popup))))
+
+(defun jabber-groupchat-join-2 (closure result)
+ (destructuring-bind (group nickname popup) closure
+ (let ( ;; Either success...
+ (identities (car result))
+ (features (cadr result))
+ ;; ...or error
+ (condition (when (eq (car result) 'error) (jabber-error-condition result))))
+ (cond
+ ;; Maybe the room doesn't exist yet.
+ ((eq condition 'item-not-found)
+ (unless (y-or-n-p (format "%s doesn't exist. Create it? " (jabber-jid-displayname group)))
+ (error "Non-existent groupchat")))
+
+ ;; Maybe the room doesn't support disco.
+ ((eq condition 'feature-not-implemented)
+ t ;whatever...
+ )
+ ;; Maybe another error occurred.
+ (condition
+ (error "Couldn't query groupchat: %s" (jabber-parse-error result)))
+
+ ;; Maybe it isn't a chat room.
+ ((not (find "conference" identities
+ :key (lambda (i) (aref i 1))
+ :test #'string=))
+ (error "%s is not a groupchat" (jabber-jid-displayname group))))
+
+ (let ((password
+ ;; Is the room password-protected?
+ (when (member "muc_passwordprotected" features)
+ (read-passwd (format "Password for %s: " (jabber-jid-displayname group))))))
+
+ (jabber-groupchat-join-3 group nickname password popup)))))
+
+(defun jabber-groupchat-join-3 (group nickname password popup)
+
;; Remember that this is a groupchat _before_ sending the stanza.
;; The response might come quicker than you think.
- (let ((whichgroup (assoc group *jabber-active-groupchats*)))
- (if whichgroup
- (setcdr whichgroup nickname)
- (add-to-list '*jabber-active-groupchats* (cons group nickname))))
+
+ (puthash (jabber-jid-symbol group) nickname jabber-pending-groupchats)
(jabber-send-sexp `(presence ((to . ,(format "%s/%s" group nickname)))
- (x ((xmlns . "http://jabber.org/protocol/muc")))))
-
- (let ((buffer (jabber-muc-create-buffer group)))
- ;; We don't want to switch to autojoined groupchats
- (when (interactive-p)
+ (x ((xmlns . "http://jabber.org/protocol/muc"))
+ ,@(when password
+ `((password () ,password))))
+ ,@(jabber-presence-children)))
+
+ ;; There, stanza sent. Now we just wait for the MUC service to
+ ;; mirror the stanza. This is handled in
+ ;; `jabber-muc-process-presence', where a buffer will be created for
+ ;; the room.
+
+ ;; But if the user interactively asked to join, he/she probably
+ ;; wants the buffer to pop up right now.
+ (when popup
+ (let ((buffer (jabber-muc-create-buffer group)))
(switch-to-buffer buffer))))
(defun jabber-muc-read-my-nickname (group)
@@ -342,14 +487,19 @@ Return nil if nothing known about that combination."
"Print names, affiliations, and roles of participants in GROUP."
(interactive (list (jabber-muc-read-completing "Group: ")))
(with-current-buffer (jabber-muc-create-buffer group)
- (let ((jabber-chat-fill-long-lines nil))
- (jabber-chat-buffer-display 'jabber-muc-system-prompt nil
- '(jabber-muc-print-names)
- (cdr (assoc group jabber-muc-participants))))))
+ (ewoc-enter-last jabber-chat-ewoc (list :notice
+ (jabber-muc-print-names
+ (cdr (assoc group jabber-muc-participants)))
+ :time (current-time)))
+ ;; (let ((jabber-chat-fill-long-lines nil))
+;; (jabber-chat-buffer-display 'jabber-muc-system-prompt nil
+;; '(jabber-muc-print-names)
+;; (cdr (assoc group jabber-muc-participants))))
+ ))
(defun jabber-muc-print-names (participants)
- "Format and insert data in PARTICIPANTS."
- (apply 'insert "Participants:\n"
+ "Format and return data in PARTICIPANTS."
+ (apply 'concat "Participants:\n"
(format "%-15s %-15s %-11s %s\n" "Nickname" "Role" "Affiliation" "JID")
(mapcar (lambda (x)
(let ((plist (cdr x)))
@@ -455,63 +605,64 @@ group, else it is a JID."
(add-to-list 'jabber-body-printers 'jabber-muc-print-invite)
-(defun jabber-muc-print-invite (xml-data)
+(defun jabber-muc-print-invite (xml-data who mode)
"Print MUC invitation"
(dolist (x (jabber-xml-get-children xml-data 'x))
(when (string= (jabber-xml-get-attribute x 'xmlns) "http://jabber.org/protocol/muc#user")
(let ((invitation (car (jabber-xml-get-children x 'invite))))
(when invitation
- (let ((group (jabber-xml-get-attribute xml-data 'from))
- (inviter (jabber-xml-get-attribute invitation 'from))
- (reason (car (jabber-xml-node-children (car (jabber-xml-get-children invitation 'reason))))))
- ;; XXX: password
- (insert "You have been invited to MUC room " (jabber-jid-displayname group))
- (when inviter
- (insert " by " (jabber-jid-displayname inviter)))
- (insert ".")
- (when reason
- (insert " Reason: " reason))
- (insert "\n\n")
-
- (let ((action
- `(lambda (&rest ignore) (interactive)
- (jabber-groupchat-join ,group
- (jabber-muc-read-my-nickname ,group)))))
- (if (fboundp 'insert-button)
- (insert-button "Accept"
- 'action action)
- ;; Simple button replacement
- (let ((keymap (make-keymap)))
- (define-key keymap "\r" action)
- (insert (jabber-propertize "Accept"
- 'keymap keymap
- 'face 'highlight))))
-
- (insert "\t")
-
- (let ((action
- `(lambda (&rest ignore) (interactive)
- (let ((reason
- (jabber-read-with-input-method
- "Reason: ")))
- (jabber-send-sexp
- (list 'message
- (list (cons 'to ,group))
- (list 'x
- (list (cons 'xmlns "http://jabber.org/protocol/muc#user"))
- (list 'decline
- (list (cons 'to ,inviter))
- (unless (zerop (length reason))
- (list 'reason nil reason))))))))))
- (if (fboundp 'insert-button)
- (insert-button "Decline"
- 'action action)
- ;; Simple button replacement
- (let ((keymap (make-keymap)))
- (define-key keymap "\r" action)
- (insert (jabber-propertize "Decline"
- 'keymap keymap
- 'face 'highlight)))))))
+ (when (eql mode :insert)
+ (let ((group (jabber-xml-get-attribute xml-data 'from))
+ (inviter (jabber-xml-get-attribute invitation 'from))
+ (reason (car (jabber-xml-node-children (car (jabber-xml-get-children invitation 'reason))))))
+ ;; XXX: password
+ (insert "You have been invited to MUC room " (jabber-jid-displayname group))
+ (when inviter
+ (insert " by " (jabber-jid-displayname inviter)))
+ (insert ".")
+ (when reason
+ (insert " Reason: " reason))
+ (insert "\n\n")
+
+ (let ((action
+ `(lambda (&rest ignore) (interactive)
+ (jabber-groupchat-join ,group
+ (jabber-muc-read-my-nickname ,group)))))
+ (if (fboundp 'insert-button)
+ (insert-button "Accept"
+ 'action action)
+ ;; Simple button replacement
+ (let ((keymap (make-keymap)))
+ (define-key keymap "\r" action)
+ (insert (jabber-propertize "Accept"
+ 'keymap keymap
+ 'face 'highlight))))
+
+ (insert "\t")
+
+ (let ((action
+ `(lambda (&rest ignore) (interactive)
+ (let ((reason
+ (jabber-read-with-input-method
+ "Reason: ")))
+ (jabber-send-sexp
+ (list 'message
+ (list (cons 'to ,group))
+ (list 'x
+ (list (cons 'xmlns "http://jabber.org/protocol/muc#user"))
+ (list 'decline
+ (list (cons 'to ,inviter))
+ (unless (zerop (length reason))
+ (list 'reason nil reason))))))))))
+ (if (fboundp 'insert-button)
+ (insert-button "Decline"
+ 'action action)
+ ;; Simple button replacement
+ (let ((keymap (make-keymap)))
+ (define-key keymap "\r" action)
+ (insert (jabber-propertize "Decline"
+ 'keymap keymap
+ 'face 'highlight))))))))
(return t))))))
(defun jabber-muc-autojoin ()
@@ -524,7 +675,8 @@ group, else it is a JID."
(defun jabber-muc-message-p (message)
"Return non-nil if MESSAGE is a groupchat message.
-That does not include private messages in a groupchat."
+That does not include private messages in a groupchat, but does
+include groupchat invites."
;; Public groupchat messages have type "groupchat" and are from
;; room@server/nick. Public groupchat errors have type "error" and
;; are from room@server.
@@ -533,7 +685,8 @@ That does not include private messages in a groupchat."
(or
(string= type "groupchat")
(and (string= type "error")
- (assoc from *jabber-active-groupchats*)))))
+ (gethash (jabber-jid-symbol from) jabber-pending-groupchats))
+ (jabber-xml-path message '(("http://jabber.org/protocol/muc#user" . "x") invite)))))
(defun jabber-muc-sender-p (jid)
"Return non-nil if JID is a full JID of an MUC participant."
@@ -561,8 +714,17 @@ That does not include private messages in a groupchat."
(defun jabber-muc-presence-p (presence)
"Return non-nil if PRESENCE is presence from groupchat."
- (let ((from (jabber-xml-get-attribute presence 'from)))
- (assoc (jabber-jid-user from) *jabber-active-groupchats*)))
+ (let ((from (jabber-xml-get-attribute presence 'from))
+ (type (jabber-xml-get-attribute presence 'type))
+ (muc-marker (find-if
+ (lambda (x) (equal (jabber-xml-get-attribute x 'xmlns)
+ "http://jabber.org/protocol/muc#user"))
+ (jabber-xml-get-children presence 'x))))
+ ;; This is MUC presence if it has an MUC-namespaced tag...
+ (or muc-marker
+ ;; ...or if it is error presence from a room we tried to join.
+ (and (string= type "error")
+ (gethash (jabber-jid-symbol from) jabber-pending-groupchats)))))
(defun jabber-muc-parse-affiliation (x-muc)
"Parse X-MUC in the muc#user namespace and return a plist.
@@ -572,11 +734,10 @@ Return nil if X-MUC is nil."
(jabber-xml-node-attributes
(car (jabber-xml-get-children x-muc 'item))))))
-(defun jabber-muc-print-prompt (xml-data)
+(defun jabber-muc-print-prompt (xml-data &optional local)
"Print MUC prompt for message in XML-DATA."
(let ((nick (jabber-jid-resource (jabber-xml-get-attribute xml-data 'from)))
(timestamp (car (delq nil (mapcar 'jabber-x-delay (jabber-xml-get-children xml-data 'x))))))
- (jabber-maybe-print-rare-time timestamp)
(if (stringp nick)
(insert (jabber-propertize
(format-spec jabber-groupchat-prompt-format
@@ -590,7 +751,8 @@ Return nil if X-MUC is nil."
(cons ?u nick)
(cons ?r nick)
(cons ?j (concat jabber-group "/" nick))))
- 'face 'jabber-chat-prompt-foreign
+ 'face (if local 'jabber-chat-prompt-local
+ 'jabber-chat-prompt-foreign)
'help-echo (concat (format-time-string "On %Y-%m-%d %H:%M:%S" timestamp) " from " nick " in " jabber-group)))
(jabber-muc-system-prompt))))
@@ -599,7 +761,6 @@ Return nil if X-MUC is nil."
(let ((nick (jabber-jid-resource (jabber-xml-get-attribute xml-data 'from)))
(group (jabber-jid-user (jabber-xml-get-attribute xml-data 'from)))
(timestamp (car (delq nil (mapcar 'jabber-x-delay (jabber-xml-get-children xml-data 'x))))))
- (jabber-maybe-print-rare-time timestamp)
(insert (jabber-propertize
(format-spec jabber-muc-private-foreign-prompt-format
(list
@@ -616,7 +777,6 @@ Return nil if X-MUC is nil."
(defun jabber-muc-system-prompt (&rest ignore)
"Print system prompt for MUC."
- (jabber-maybe-print-rare-time nil)
(insert (jabber-propertize
(format-spec jabber-groupchat-prompt-format
(list
@@ -637,19 +797,24 @@ Return nil if X-MUC is nil."
(group (jabber-jid-user from))
(nick (jabber-jid-resource from))
(error-p (jabber-xml-get-children xml-data 'error))
+ (type (cond
+ (error-p :muc-error)
+ ((string= nick (cdr (assoc group *jabber-active-groupchats*)))
+ :muc-local)
+ (t :muc-foreign)))
(body-text (car (jabber-xml-node-children
(car (jabber-xml-get-children
- xml-data 'body))))))
+ xml-data 'body)))))
+
+ (printers (append jabber-muc-printers jabber-chat-printers)))
+
(with-current-buffer (jabber-muc-create-buffer group)
+ (jabber-muc-snarf-topic xml-data)
;; Call alert hooks only when something is output
- (when
- (jabber-chat-buffer-display 'jabber-muc-print-prompt
- xml-data
- (if error-p
- '(jabber-chat-print-error)
- (append jabber-muc-printers
- jabber-chat-printers))
- xml-data)
+ (when (or error-p
+ (run-hook-with-args-until-success 'printers xml-data type :printp))
+ (jabber-maybe-print-rare-time
+ (ewoc-enter-last jabber-chat-ewoc (list type xml-data :time (current-time))))
(dolist (hook '(jabber-muc-hooks jabber-alert-muc-hooks))
(run-hook-with-args hook
@@ -659,86 +824,103 @@ Return nil if X-MUC is nil."
(defun jabber-muc-process-presence (presence)
(let* ((from (jabber-xml-get-attribute presence 'from))
- (type (jabber-xml-get-attribute presence 'type))
- (x-muc (find-if
- (lambda (x) (equal (jabber-xml-get-attribute x 'xmlns)
- "http://jabber.org/protocol/muc#user"))
- (jabber-xml-get-children presence 'x)))
- (group (jabber-jid-user from))
- (nickname (jabber-jid-resource from))
- (symbol (jabber-jid-symbol from))
- (item (car (jabber-xml-get-children x-muc 'item)))
- (actor (jabber-xml-get-attribute (car (jabber-xml-get-children item 'actor)) 'jid))
- (reason (car (jabber-xml-node-children (car (jabber-xml-get-children item 'reason)))))
- (status-code (jabber-xml-get-attribute
- (car (jabber-xml-get-children x-muc 'status))
- 'code))
- (error-node (car (jabber-xml-get-children presence 'error))))
+ (type (jabber-xml-get-attribute presence 'type))
+ (x-muc (find-if
+ (lambda (x) (equal (jabber-xml-get-attribute x 'xmlns)
+ "http://jabber.org/protocol/muc#user"))
+ (jabber-xml-get-children presence 'x)))
+ (group (jabber-jid-user from))
+ (nickname (jabber-jid-resource from))
+ (symbol (jabber-jid-symbol from))
+ (item (car (jabber-xml-get-children x-muc 'item)))
+ (actor (jabber-xml-get-attribute (car (jabber-xml-get-children item 'actor)) 'jid))
+ (reason (car (jabber-xml-node-children (car (jabber-xml-get-children item 'reason)))))
+ (status-code (jabber-xml-get-attribute
+ (car (jabber-xml-get-children x-muc 'status))
+ 'code))
+ (error-node (car (jabber-xml-get-children presence 'error))))
;; handle leaving a room
(cond
((or (string= type "unavailable") (string= type "error"))
;; are we leaving?
- (if (string= nickname (cdr (assoc group *jabber-active-groupchats*)))
- (progn
+ (if (string= nickname (gethash (jabber-jid-symbol group) jabber-pending-groupchats))
+ (let ((message (cond
+ ((string= type "error")
+ (concat "Error entering room"
+ (when error-node
+ (concat ": " (jabber-parse-error error-node)))))
+ ((equal status-code "301")
+ (concat "You have been banned"
+ (when actor (concat " by " actor))
+ (when reason (concat " - '" reason "'"))))
+ ((equal status-code "307")
+ (concat "You have been kicked"
+ (when actor (concat " by " actor))
+ (when reason (concat " - '" reason "'"))))
+ (t
+ "You have left the chatroom"))))
(jabber-muc-remove-groupchat group)
;; If there is no buffer for this groupchat, don't bother
;; creating one just to tell that user left the room.
(let ((buffer (get-buffer (jabber-muc-get-buffer group))))
- (when buffer
- (with-current-buffer buffer
- (jabber-chat-buffer-display
- 'jabber-muc-system-prompt
- nil
- '(insert)
- (cond
- ((string= type "error")
- (jabber-propertize
- (concat "Error entering room"
- (when error-node
- (concat ": " (jabber-parse-error error-node))))
- 'face 'jabber-chat-error))
- ((equal status-code "301")
- (concat "You have been banned"
- (when actor (concat " by " actor))
- (when reason (concat " - '" reason "'"))))
- ((equal status-code "307")
- (concat "You have been kicked"
- (when actor (concat " by " actor))
- (when reason (concat " - '" reason "'"))))
- (t
- "You have left the chatroom")))))))
+ (if buffer
+ (with-current-buffer buffer
+ (jabber-maybe-print-rare-time
+ (ewoc-enter-last jabber-chat-ewoc
+ (list (if (string= type "error")
+ :muc-error
+ :muc-notice)
+ message
+ :time (current-time)))))
+ (message "%s: %s" (jabber-jid-displayname group) message))))
;; or someone else?
(jabber-muc-remove-participant group nickname)
(with-current-buffer (jabber-muc-create-buffer group)
- (jabber-chat-buffer-display
- 'jabber-muc-system-prompt
- nil
- '(insert)
- (cond
- ((equal status-code "301")
- (concat nickname " has been banned"
- (when actor (concat " by " actor))
- (when reason (concat " - '" reason "'"))))
- ((equal status-code "307")
- (concat nickname " has been kicked"
- (when actor (concat " by " actor))
- (when reason (concat " - '" reason "'"))))
- ((equal status-code "303")
- (concat nickname " changes nickname to "
- (jabber-xml-get-attribute item 'nick)))
- (t
- (concat nickname " has left the chatroom")))))))
+ (jabber-maybe-print-rare-time
+ (ewoc-enter-last
+ jabber-chat-ewoc
+ (list :muc-notice
+ (cond
+ ((equal status-code "301")
+ (concat nickname " has been banned"
+ (when actor (concat " by " actor))
+ (when reason (concat " - '" reason "'"))))
+ ((equal status-code "307")
+ (concat nickname " has been kicked"
+ (when actor (concat " by " actor))
+ (when reason (concat " - '" reason "'"))))
+ ((equal status-code "303")
+ (concat nickname " changes nickname to "
+ (jabber-xml-get-attribute item 'nick)))
+ (t
+ (concat nickname " has left the chatroom")))
+ :time (current-time)))))))
(t
;; someone is entering
- (let ((new-participant (not (jabber-muc-participant-plist group nickname)))
+
+ (when (string= nickname (gethash (jabber-jid-symbol group) jabber-pending-groupchats))
+ ;; Our own nick? We just succeeded in entering the room.
+ (let ((whichgroup (assoc group *jabber-active-groupchats*)))
+ (if whichgroup
+ (setcdr whichgroup nickname)
+ (add-to-list '*jabber-active-groupchats* (cons group nickname)))))
+
+ ;; Whoever enters, we create a buffer (if it didn't already
+ ;; exist), and print a notice. This is where autojoined MUC
+ ;; rooms have buffers created for them. We also remember some
+ ;; metadata.
+ (let ((old-plist (jabber-muc-participant-plist group nickname))
(new-plist (jabber-muc-parse-affiliation x-muc)))
(jabber-muc-modify-participant group nickname new-plist)
- (when new-participant
- (with-current-buffer (jabber-muc-create-buffer group)
- (jabber-chat-buffer-display 'jabber-muc-system-prompt
- nil
- '(insert)
- (format "%s enters the chatroom" nickname)))))))))
+ (let ((report (jabber-muc-report-delta nickname old-plist new-plist
+ reason actor)))
+ (when report
+ (with-current-buffer (jabber-muc-create-buffer group)
+ (jabber-maybe-print-rare-time
+ (ewoc-enter-last
+ jabber-chat-ewoc
+ (list :muc-notice report
+ :time (current-time))))))))))))
(provide 'jabber-muc)
diff --git a/jabber-newdisco.el b/jabber-newdisco.el
new file mode 100644
index 0000000..8188ff3
--- /dev/null
+++ b/jabber-newdisco.el
@@ -0,0 +1,164 @@
+;;; jabber-newdisco.el --- caching disco API
+
+;; Copyright (C) 2005 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;---
+;; Keys are ("jid" . "node"), where "node" is nil if appropriate.
+;; Values are (identities features), where each identity is ["name"
+;; "category" "type"], and each feature is a string.
+(defvar jabber-disco-info-cache (make-hash-table :test 'equal))
+
+;; Keys are ("jid" . "node"). Values are (items), where each
+;; item is ["name" "jid" "node"] (some values may be nil).
+(defvar jabber-disco-items-cache (make-hash-table :test 'equal))
+
+;;; Info
+
+(defun jabber-disco-get-info (jid node callback closure-data &optional force)
+ "Get disco info for JID and NODE.
+Call CALLBACK with CLOSURE-DATA as first argument and result as
+second argument when result is available.
+On success, result is (IDENTITIES FEATURES), where each identity is [\"name\"
+\"category\" \"type\"], and each feature is a string.
+On error, result is the error node, recognizable by (eq (car result) 'error).
+
+If CALLBACK is nil, just fetch data. If FORCE is non-nil,
+invalidate cache and get fresh data."
+ (when force
+ (remhash (cons jid node) jabber-disco-info-cache))
+ (let ((result (gethash (cons jid node) jabber-disco-info-cache)))
+ (if result
+ (and callback (run-with-timer 0.1 nil callback closure-data result))
+ (jabber-send-iq jid
+ "get"
+ `(query ((xmlns . "http://jabber.org/protocol/disco#info")
+ ,(when node `(node . ,node))))
+ #'jabber-disco-got-info (cons callback closure-data)
+ (lambda (xml-data callback-data)
+ (when (car callback-data)
+ (funcall (car callback-data) (cdr callback-data) (jabber-iq-error xml-data))))
+ (cons callback closure-data)))))
+
+(defun jabber-disco-got-info (xml-data callback-data)
+ (let ((jid (jabber-xml-get-attribute xml-data 'from))
+ (node (jabber-xml-get-attribute (jabber-iq-query xml-data)
+ 'node))
+ (result
+ (list
+ (mapcar
+ #'(lambda (id)
+ (vector (jabber-xml-get-attribute id 'name)
+ (jabber-xml-get-attribute id 'category)
+ (jabber-xml-get-attribute id 'type)))
+ (jabber-xml-get-children (jabber-iq-query xml-data) 'identity))
+ (mapcar
+ #'(lambda (feature)
+ (jabber-xml-get-attribute feature 'var))
+ (jabber-xml-get-children (jabber-iq-query xml-data) 'feature)))))
+ (puthash (cons jid node) result jabber-disco-info-cache)
+ (when (car callback-data)
+ (funcall (car callback-data) (cdr callback-data) result))))
+
+(defun jabber-disco-get-info-immediately (jid node)
+ "Get cached disco info for JID and NODE.
+Return nil if no info available.
+
+Fill the cache with `jabber-disco-get-info'."
+ (gethash (cons jid node) jabber-disco-info-cache))
+
+;;; Items
+
+(defun jabber-disco-get-items (jid node callback closure-data &optional force)
+ "Get disco items for JID and NODE.
+Call CALLBACK with CLOSURE-DATA as first argument and items
+result as second argument when result is available.
+On success, result is a list of items, where each
+item is [\"name\" \"jid\" \"node\"] (some values may be nil).
+On error, result is the error node, recognizable by (eq (car result) 'error).
+
+If CALLBACK is nil, just fetch data. If FORCE is non-nil,
+invalidate cache and get fresh data."
+ (when force
+ (remhash (cons jid node) jabber-disco-items-cache))
+ (let ((result (gethash (cons jid node) jabber-disco-items-cache)))
+ (if result
+ (and callback (run-with-timer 0.1 nil callback closure-data result))
+ (jabber-send-iq jid
+ "get"
+ `(query ((xmlns . "http://jabber.org/protocol/disco#items")
+ ,(when node `(node . ,node))))
+ #'jabber-disco-got-items (cons callback closure-data)
+ #'(lambda (xml-data callback-data)
+ (when (car callback-data)
+ (funcall (car callback-data) (cdr callback-data) (jabber-iq-error xml-data))))
+ (cons callback closure-data)))))
+
+(defun jabber-disco-got-items (xml-data callback-data)
+ (let ((jid (jabber-xml-get-attribute xml-data 'from))
+ (node (jabber-xml-get-attribute (jabber-iq-query xml-data)
+ 'node))
+ (result
+ (mapcar
+ #'(lambda (item)
+ (vector
+ (jabber-xml-get-attribute item 'name)
+ (jabber-xml-get-attribute item 'jid)
+ (jabber-xml-get-attribute item 'node)))
+ (jabber-xml-get-children (jabber-iq-query xml-data) 'item))))
+ (puthash (cons jid node) result jabber-disco-items-cache)
+ (when (car callback-data)
+ (funcall (car callback-data) (cdr callback-data) result))))
+
+(defun jabber-disco-get-items-immediately (jid node)
+ (gethash (cons jid node) jabber-disco-items-cache))
+
+;;; Publish
+
+(defun jabber-disco-publish (node item-name item-jid item-node)
+ "Publish the given item under disco node NODE."
+ (jabber-send-iq nil
+ "set"
+ `(query ((xmlns . "http://jabber.org/protocol/disco#items")
+ ,(when node `(node . ,node)))
+ (item ((action . "update")
+ (jid . ,item-jid)
+ ,(when item-name
+ `(name . ,item-name))
+ ,(when item-node
+ `(node . ,item-node)))))
+ 'jabber-report-success "Disco publish"
+ 'jabber-report-success "Disco publish"))
+
+(defun jabber-disco-publish-remove (node item-jid item-node)
+ "Remove the given item from published disco items."
+ (jabber-send-iq nil
+ "set"
+ `(query ((xmlns . "http://jabber.org/protocol/disco#items")
+ ,(when node `(node . ,node)))
+ (item ((action . "remove")
+ (jid . ,item-jid)
+ ,(when item-node
+ `(node . ,item-node)))))
+ 'jabber-report-success "Disco removal"
+ 'jabber-report-success "Disco removal"))
+
+(provide 'jabber-newdisco)
+
+;; arch-tag: b47c06aa-cae6-11d9-b1c0-000a95c2fcd0
diff --git a/jabber-presence.el b/jabber-presence.el
index a08e680..5b77610 100644
--- a/jabber-presence.el
+++ b/jabber-presence.el
@@ -26,6 +26,11 @@
(require 'jabber-menu)
(require 'jabber-muc)
+(defvar jabber-presence-element-functions nil
+ "List of functions returning extra elements for <presence/> stanzas.
+Each function takes no arguments and returns a possibly empty list of
+extra child element of the <presence/> stanza.")
+
(add-to-list 'jabber-iq-set-xmlns-alist
(cons "jabber:iq:roster" (function (lambda (x) (jabber-process-roster x nil)))))
(defun jabber-process-roster (xml-data closure-data)
@@ -88,7 +93,13 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(jabber-display-roster)
(if (and id (string= type "set"))
(jabber-send-iq jabber-server "result" nil
- nil nil nil nil id))))
+ nil nil nil nil id)))
+
+ ;; After initial roster push, run jabber-post-connect-hook. We do
+ ;; it here and not before since we want to have the entire roster
+ ;; before we receive any presence stanzas.
+ (when (eq closure-data 'initial)
+ (run-hooks 'jabber-post-connect-hook)))
(add-to-list 'jabber-presence-chain 'jabber-process-presence)
(defun jabber-process-presence (xml-data)
@@ -127,7 +138,7 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(plist-put resource-plist 'show nil))
(setq resource-plist
(plist-put resource-plist 'status
- (jabber-unescape-xml presence-status))))
+ presence-status)))
((string= type "error")
(setq newstatus "error")
@@ -139,7 +150,7 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(plist-put resource-plist 'status
(if error
(jabber-parse-error error)
- (jabber-unescape-xml presence-status)))))
+ presence-status))))
((or
(string= type "unsubscribe")
(string= type "subscribed")
@@ -154,7 +165,7 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(plist-put resource-plist 'show (or presence-show "")))
(setq resource-plist
(plist-put resource-plist 'status
- (jabber-unescape-xml presence-status)))
+ presence-status))
(setq resource-plist
(plist-put resource-plist 'priority priority))
(setq newstatus (or presence-show ""))))
@@ -170,14 +181,12 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
buddy
oldstatus
newstatus
- (jabber-unescape-xml
- (plist-get resource-plist 'status))
+ (plist-get resource-plist 'status)
(funcall jabber-alert-presence-message-function
buddy
oldstatus
newstatus
- (jabber-unescape-xml
- (plist-get resource-plist 'status))))))))))))
+ (plist-get resource-plist 'status)))))))))))
(defun jabber-process-subscription-request (from presence-status)
"process an incoming subscription request"
@@ -189,7 +198,7 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(cons 'type
(if (yes-or-no-p (format "the user - %s - has requested to subscribe to your presence (%s). allow? "
(jabber-jid-displayname from)
- (jabber-unescape-xml presence-status)))
+ presence-status))
"subscribed"
"unsubscribed")))))
(when (yes-or-no-p (format "Do you want to subscribe to %s's presence? " from))
@@ -257,26 +266,66 @@ CLOSURE-DATA should be 'initial if initial roster push, nil otherwise."
(setq priority (int-to-string priority)))
(setq *jabber-current-status* status)
(setq *jabber-current-show* show)
- (setq *jabber-current-priority* (string-to-int priority))
- (jabber-send-sexp `(presence ()
- ,(if (> (length status) 0)
- `(status () ,(jabber-escape-xml status)))
- ,(if (> (length show) 0)
- `(show () ,(jabber-escape-xml show)))
- (priority () ,(jabber-escape-xml (int-to-string *jabber-current-priority*)))))
+ (setq *jabber-current-priority* (string-to-number priority))
+ (let ((subelements (jabber-presence-children)))
+ ;; First send presence to everyone subscribed
+ (jabber-send-sexp `(presence () ,@subelements))
+ ;; Then send to every joined MUC room
+ (dolist (groupchat *jabber-active-groupchats*)
+ (jabber-send-sexp `(presence ((to . ,(car groupchat))) ,@subelements))))
(jabber-display-roster))
-(defun jabber-send-away-presence ()
+(defun jabber-presence-children ()
+ "Return the children for a <presence/> stanza."
+ `(,(when (> (length *jabber-current-status*) 0)
+ `(status () ,*jabber-current-status*))
+ ,(when (> (length *jabber-current-show*) 0)
+ `(show () ,*jabber-current-show*))
+ (priority () ,(number-to-string *jabber-current-priority*))
+ ,@(apply 'append (mapcar 'funcall jabber-presence-element-functions))))
+
+(defun jabber-send-directed-presence (jid type)
+ "Send a directed presence stanza to JID."
+ (interactive
+ (list (jabber-read-jid-completing "Send directed presence to: ")
+ (completing-read "Type (default is online): "
+ '(("online")
+ ("away")
+ ("xa")
+ ("dnd")
+ ("chatty")
+ ("probe")
+ ("unavailable"))
+ nil t nil nil "online")))
+ (cond
+ ((member type '("probe" "unavailable"))
+ (jabber-send-sexp `(presence ((to . ,jid)
+ (type . ,type)))))
+
+ (t
+ (let ((*jabber-current-show*
+ (if (string= type "online")
+ ""
+ type))
+ (*jabber-current-status* nil))
+ (jabber-send-sexp `(presence ((to . ,jid))
+ ,@(jabber-presence-children)))))))
+
+(defun jabber-send-away-presence (&optional status)
"Set status to away.
-Status description is empty. Priority is unchanged."
- (interactive)
- (jabber-send-presence "away" "" *jabber-current-priority*))
+With prefix argument, ask for status message."
+ (interactive (list
+ (when current-prefix-arg
+ (jabber-read-with-input-method "status message: " *jabber-current-status* '*jabber-status-history*))))
+ (jabber-send-presence "away" status *jabber-current-priority*))
-(defun jabber-send-xa-presence ()
+(defun jabber-send-xa-presence (&optional status)
"Send extended away presence.
-Status description is empty. Priority is unchanged."
- (interactive)
- (jabber-send-presence "xa" "" *jabber-current-priority*))
+With prefix argument, ask for status message."
+ (interactive (list
+ (when current-prefix-arg
+ (jabber-read-with-input-method "status message: " *jabber-current-status* '*jabber-status-history*))))
+ (jabber-send-presence "xa" status *jabber-current-priority*))
(defun jabber-send-default-presence ()
"Send default presence.
@@ -291,10 +340,11 @@ and `jabber-default-status'."
"send a subscription request to jid, showing him your request text, if specified"
(interactive (list (jabber-read-jid-completing "to: ")
(jabber-read-with-input-method "request: ")))
- (jabber-send-sexp `(presence ((to . ,to)
- (type . "subscribe"))
- ,(if (and request (> (length request) 0))
- request))))
+ (jabber-send-sexp `(presence
+ ((to . ,to)
+ (type . "subscribe"))
+ ,@(when (and request (> (length request) 0))
+ (list `(status () ,request))))))
(add-to-list 'jabber-jid-roster-menu
(cons "Add/modify roster entry" 'jabber-roster-change))
diff --git a/jabber-private.el b/jabber-private.el
new file mode 100644
index 0000000..cade7f4
--- /dev/null
+++ b/jabber-private.el
@@ -0,0 +1,55 @@
+;;; jabber-private.el --- jabber:iq:private API by JEP-0049
+
+;; Copyright (C) 2005 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+(defun jabber-private-get (node-name namespace success-callback error-callback)
+ "Retrieve an item from private XML storage.
+The item to retrieve is identified by NODE-NAME (a symbol) and
+NAMESPACE (a string).
+On success, SUCCESS-CALLBACK is called with the retrieved XML fragment.
+On error, ERROR-CALLBACK is called with the entire IQ result."
+ (jabber-send-iq nil "get"
+ `(query ((xmlns . "jabber:iq:private"))
+ (,node-name ((xmlns . ,namespace))))
+ #'jabber-private-get-1 success-callback
+ #'(lambda (xml-data error-callback)
+ (funcall error-callback xml-data))
+ error-callback))
+
+(defun jabber-private-get-1 (xml-data success-callback)
+ (funcall success-callback
+ (car (jabber-xml-node-children
+ (jabber-iq-query xml-data)))))
+
+(defun jabber-private-set (fragment &optional
+ success-callback success-closure-data
+ error-callback error-closure-data)
+ "Store FRAGMENT in private XML storage.
+SUCCESS-CALLBACK, SUCCESS-CLOSURE-DATA, ERROR-CALLBACK and
+ERROR-CLOSURE-DATA are used as in `jabber-send-iq'."
+ (jabber-send-iq nil "set"
+ `(query ((xmlns . "jabber:iq:private"))
+ ,fragment)
+ success-callback success-closure-data
+ error-callback error-closure-data))
+
+(provide 'jabber-private)
+
+;; arch-tag: 065bd03e-40fa-11da-ab48-000a95c2fcd0
diff --git a/jabber-register.el b/jabber-register.el
index 4acdea2..85aca60 100644
--- a/jabber-register.el
+++ b/jabber-register.el
@@ -115,17 +115,15 @@
(defun jabber-process-register-secondtime (xml-data closure-data)
"Receive registration success or failure.
CLOSURE-DATA is either 'success or 'error."
- (setq jabber-register-p nil)
(cond
((eq closure-data 'success)
- (message "Registration successful. Your JID is %s@%s."
+ (message "Registration successful. Your JID is %s@%s. You may now connect to the server."
jabber-username jabber-server)
(sit-for 3)
- (jabber-get-auth jabber-server))
+ (jabber-disconnect))
(t
(jabber-report-success xml-data "Account registration")
- (sit-for 3)
- (jabber-disconnect))))
+ (sit-for 3))))
(defun jabber-remove-register (&rest ignore)
"Cancel registration. See `jabber-process-register-or-search'."
diff --git a/jabber-roster.el b/jabber-roster.el
index 1cd151d..3839b1b 100644
--- a/jabber-roster.el
+++ b/jabber-roster.el
@@ -28,11 +28,12 @@
(defgroup jabber-roster nil "roster display options"
:group 'jabber)
-(defcustom jabber-roster-line-format " %c %-25n %u %-8s %S\n"
+(defcustom jabber-roster-line-format " %a %c %-25n %u %-8s %S\n"
"The format specification of the lines in the roster display.
These fields are available:
+%a Avatar, if any
%c \"*\" if the contact is connected, or \" \" if not
%u sUbscription state - see below
%n Nickname of contact, or JID if no nickname
@@ -173,6 +174,9 @@ Trailing newlines are always removed, regardless of this variable."
(set-keymap-parent map jabber-common-keymap)
(define-key map [mouse-2] 'jabber-popup-combined-menu)
(define-key map (kbd "TAB") 'jabber-go-to-next-jid)
+ (define-key map (kbd "S-TAB") 'jabber-go-to-previous-jid)
+ (define-key map (kbd "M-TAB") 'jabber-go-to-previous-jid)
+ (define-key map (kbd "<backtab>") 'jabber-go-to-previous-jid)
(define-key map (kbd "RET") 'jabber-chat-with-jid-at-point)
(define-key map (kbd "C-k") 'jabber-roster-delete-jid-at-point)
@@ -186,6 +190,7 @@ Trailing newlines are always removed, regardless of this variable."
(define-key map "v" 'jabber-get-version)
(define-key map "a" 'jabber-send-presence)
(define-key map "g" 'jabber-display-roster)
+ (define-key map "S" 'jabber-ft-send)
;;(define-key map "D" 'jabber-disconnect)
map))
@@ -243,19 +248,22 @@ See `jabber-sort-order' for order used."
(defun jabber-roster-sort-by-displayname (a b)
"Sort roster items by displayed name."
- (cond
- ((string-lessp a b) -1)
- ((string= a b) 0)
- (t 1)))
+ (let ((a-name (jabber-jid-displayname a))
+ (b-name (jabber-jid-displayname b)))
+ (cond
+ ((string-lessp a-name b-name) -1)
+ ((string= a-name b-name) 0)
+ (t 1))))
(defun jabber-fix-status (status)
"Make status strings more readable"
- (when (string-match "\n+$" status)
- (setq status (replace-match "" t t status)))
- (when jabber-remove-newlines
- (while (string-match "\n" status)
- (setq status (replace-match " " t t status))))
- status)
+ (when status
+ (when (string-match "\n+$" status)
+ (setq status (replace-match "" t t status)))
+ (when jabber-remove-newlines
+ (while (string-match "\n" status)
+ (setq status (replace-match " " t t status))))
+ status))
(defvar jabber-roster-positions nil
"Alist tracking positions of items in the roster.
@@ -330,9 +338,12 @@ C-c C-s Service menu
(move-to-column current-column)))))
(defun jabber-display-roster-entry (buddy)
- "Format and insert a roster entry for BUDDY at point."
+ "Format and insert a roster entry for BUDDY at point.
+BUDDY is a JID symbol."
(let ((buddy-str (format-spec jabber-roster-line-format
(list
+ (cons ?a (jabber-propertize " "
+ 'display (get buddy 'avatar)))
(cons ?c (if (get buddy 'connected) "*" " "))
(cons ?u (cdr (assoc (or (get buddy 'subscription) "none")
jabber-roster-subscription-display)))
@@ -405,7 +416,8 @@ C-c C-s Service menu
(insert resource-str)))))))
(defun jabber-presence-update-roster (who &rest ignore)
- "Update roster without redrawing all of it, if possible."
+ "Update roster without redrawing all of it, if possible.
+WHO is a JID symbol."
(let* ((bare-jid (jabber-jid-symbol
(jabber-jid-user
@@ -451,6 +463,18 @@ C-c C-s Service menu
(if next (goto-char (1+ next))
(goto-char (point-min)))))
+(defun jabber-go-to-previous-jid ()
+ "Move the cursor to the previous jid in the buffer"
+ (interactive)
+ (let ((previous (previous-single-property-change (point) 'jabber-jid)))
+ (when (and previous
+ (not (get-text-property previous 'jabber-jid)))
+ (setq previous (previous-single-property-change previous 'jabber-jid)))
+ (unless previous
+ (setq previous (previous-single-property-change (point-max) 'jabber-jid)))
+ (if previous (goto-char previous)
+ (goto-char (point-max)))))
+
(provide 'jabber-roster)
;;; arch-tag: 096af063-0526-4dd2-90fd-bc6b5ba07d32
diff --git a/jabber-sasl.el b/jabber-sasl.el
index 9dbfdb4..4bbc71a 100644
--- a/jabber-sasl.el
+++ b/jabber-sasl.el
@@ -55,6 +55,8 @@
(lambda (tag)
(car (jabber-xml-node-children tag)))
(jabber-xml-get-children mechanisms 'mechanism)))))
+
+ ;; No suitable mechanism?
(if (null jabber-sasl-mechanism)
;; Maybe we can use legacy authentication
(let ((node (find "http://jabber.org/features/iq-auth"
@@ -67,6 +69,13 @@
(jabber-get-auth jabber-server))
(error "No suitable SASL mechanism found")))
+ ;; Watch for plaintext logins over unencrypted connections
+ (when (and (not *jabber-encrypted*)
+ (member (sasl-mechanism-name jabber-sasl-mechanism)
+ '("PLAIN" "LOGIN"))
+ (not (yes-or-no-p "Jabber server only allows cleartext password transmission! Continue? ")))
+ (error "Login cancelled"))
+
;; Start authentication.
(setq jabber-sasl-client (sasl-make-client jabber-sasl-mechanism jabber-username "xmpp" jabber-server))
(setq jabber-sasl-step (sasl-next-step jabber-sasl-client nil))
diff --git a/jabber-si-client.el b/jabber-si-client.el
index 5925698..9b517df 100644
--- a/jabber-si-client.el
+++ b/jabber-si-client.el
@@ -21,18 +21,14 @@
(require 'jabber-iq)
(require 'jabber-feature-neg)
-(defvar jabber-si-client-methods nil
- "Supported SI stream methods for initiation.
-
-Each entry is a list, containing:
- * The namespace URI of the stream method
- * A function taking three arguments: JID, SID and profile function to call")
+(require 'jabber-si-common)
(defun jabber-si-initiate (jid profile-namespace profile-data profile-function &optional mime-type)
"Try to initiate a stream to JID.
PROFILE-NAMESPACE is, well, the namespace of the profile to use.
PROFILE-DATA is the XML data to send within the SI request.
-PROFILE-FUNCTION is the function to call upon success.
+PROFILE-FUNCTION is the \"connection established\" function.
+See `jabber-si-stream-methods'.
MIME-TYPE is the MIME type to specify.
Returns the SID."
@@ -47,7 +43,7 @@ Returns the SID."
(feature ((xmlns . "http://jabber.org/protocol/feature-neg"))
,(jabber-fn-encode (list
(cons "stream-method"
- (mapcar 'car jabber-si-client-methods)))
+ (mapcar 'car jabber-si-stream-methods)))
'request)))
#'jabber-si-initiate-process (cons profile-function sid)
;; XXX: use other function here?
@@ -64,7 +60,7 @@ Returns the SID."
(feature-node (car (jabber-xml-get-children query 'feature)))
(feature-alist (jabber-fn-parse feature-node 'response))
(chosen-method (cadr (assoc "stream-method" feature-alist)))
- (method-data (assoc chosen-method jabber-si-client-methods)))
+ (method-data (assoc chosen-method jabber-si-stream-methods)))
;; Our work is done. Hand it over to the stream method.
(let ((stream-negotiate (nth 1 method-data)))
(funcall stream-negotiate from sid profile-function))))
diff --git a/jabber-si-common.el b/jabber-si-common.el
new file mode 100644
index 0000000..c5c8ff7
--- /dev/null
+++ b/jabber-si-common.el
@@ -0,0 +1,61 @@
+;;; jabber-si-common.el --- stream initiation (JEP-0095)
+
+;; Copyright (C) 2006 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(defvar jabber-si-stream-methods nil
+ "Supported SI stream methods.
+
+Each entry is a list, containing:
+ * The namespace URI of the stream method
+ * Active initiation function
+ * Passive initiation function
+
+The active initiation function should initiate the connection,
+while the passive initiation function should wait for an incoming
+connection. Both functions take the same arguments:
+
+ * JID of peer
+ * SID
+ * \"connection established\" function
+
+The \"connection established\" function should be called when the
+stream has been established and data can be transferred. It is part
+of the profile, and takes the following arguments:
+
+ * JID of peer
+ * SID
+ * Either:
+ - \"send data\" function, with one string argument
+ - an error message, when connection failed
+
+It returns an \"incoming data\" function.
+
+The \"incoming data\" function should be called when data arrives on
+the stream. It takes these arguments:
+
+ * JID of peer
+ * SID
+ * A string containing the received data, or nil on EOF
+
+If it returns nil, the stream should be closed.")
+
+(provide 'jabber-si-common)
+;; arch-tag: 9e7a5c8a-bdde-11da-8030-000a95c2fcd0
+;;; jabber-si-common.el ends here
diff --git a/jabber-si-server.el b/jabber-si-server.el
index 6c91b01..a84fb4e 100644
--- a/jabber-si-server.el
+++ b/jabber-si-server.el
@@ -23,6 +23,8 @@
(require 'jabber-disco)
(require 'jabber-feature-neg)
+(require 'jabber-si-common)
+
(add-to-list 'jabber-advertised-features "http://jabber.org/protocol/si")
;; Now, stream methods push data to profiles. It could be the other
@@ -35,17 +37,7 @@ Each entry is a list, containing:
* Accept function, taking entire IQ stanza, and signalling a 'forbidden'
error if request is declined; returning an XML node to return in
response, or nil of none needed
- * Data function, taking JID of initiator, stream ID, and string
- containing received data in binary form; receives `nil' on EOF.
- Returns non-nil to keep connection; nil to close it.")
-
-(defvar jabber-si-stream-methods nil
- "Supported SI stream methods.
-
-Each entry is a list, containing:
- * The namespace URI of the stream method
- * Accept function, taking JID of initiator, stream ID, profile
- data function (as above), preparing to accept a request")
+ * \"Connection established\" function. See `jabber-si-stream-methods'.")
(add-to-list 'jabber-iq-set-xmlns-alist
(cons "http://jabber.org/protocol/si" 'jabber-si-process))
@@ -79,12 +71,12 @@ Each entry is a list, containing:
;; accept-function might throw a "forbidden" error
;; on user cancel
(profile-response (funcall profile-accept-function xml-data))
- (profile-data-function (nth 2 profile-data))
+ (profile-connected-function (nth 2 profile-data))
(stream-method-id (nth 1 (assoc "stream-method" stream-method)))
(stream-data (assoc stream-method-id jabber-si-stream-methods))
- (stream-accept-function (nth 1 stream-data)))
+ (stream-accept-function (nth 2 stream-data)))
;; prepare stream for the transfer
- (funcall stream-accept-function to si-id profile-data-function)
+ (funcall stream-accept-function to si-id profile-connected-function)
;; return result of feature negotiation of stream type
(jabber-send-iq to "result"
`(si ((xmlns . "http://jabber.org/protocol/si"))
diff --git a/jabber-socks5.el b/jabber-socks5.el
index 2045351..9d390d7 100644
--- a/jabber-socks5.el
+++ b/jabber-socks5.el
@@ -23,6 +23,10 @@
(require 'jabber-disco)
(require 'jabber-si-server)
(require 'jabber-si-client)
+(require 'jabber-newdisco)
+
+(require 'fsm)
+(eval-when-compile (require 'cl))
(defvar jabber-socks5-pending-sessions nil
"List of pending sessions.
@@ -30,7 +34,7 @@
Each entry is a list, containing:
* Stream ID
* Full JID of initiator
- * Profile data function, to be called when data is received")
+ * State machine managing the session")
(defvar jabber-socks5-active-sessions nil
"List of active sessions.
@@ -58,12 +62,9 @@ Values are \"streamhost\" XML nodes.")
(add-to-list 'jabber-si-stream-methods
(list "http://jabber.org/protocol/bytestreams"
+ 'jabber-socks5-client-1
'jabber-socks5-accept))
-(add-to-list 'jabber-si-client-methods
- (list "http://jabber.org/protocol/bytestreams"
- 'jabber-socks5-client-1))
-
(defun jabber-socks5-set-proxies (symbol value)
"Set `jabber-socks5-proxies' and query proxies.
This is the set function of `jabber-socks5-proxies-data'."
@@ -71,21 +72,23 @@ This is the set function of `jabber-socks5-proxies-data'."
(when *jabber-connected*
(jabber-socks5-query-all-proxies)))
-(defun jabber-socks5-query-all-proxies ()
- "Ask all proxies in `jabber-socks5-proxies' for connection information."
+(defun jabber-socks5-query-all-proxies (&optional callback)
+ "Ask all proxies in `jabber-socks5-proxies' for connection information.
+If CALLBACK is non-nil, call it with no arguments when all
+proxies have answered."
(interactive)
(setq jabber-socks5-proxies-data nil)
(dolist (proxy jabber-socks5-proxies)
- (jabber-socks5-query-proxy proxy)))
+ (jabber-socks5-query-proxy proxy callback)))
-(defun jabber-socks5-query-proxy (jid)
+(defun jabber-socks5-query-proxy (jid &optional callback)
"Query the SOCKS5 proxy specified by JID for IP and port number."
(jabber-send-iq jid "get"
'(query ((xmlns . "http://jabber.org/protocol/bytestreams")))
- #'jabber-socks5-process-proxy-response t
- #'jabber-socks5-process-proxy-response nil))
+ #'jabber-socks5-process-proxy-response (list callback t)
+ #'jabber-socks5-process-proxy-response (list callback nil)))
-(defun jabber-socks5-process-proxy-response (xml-data successp)
+(defun jabber-socks5-process-proxy-response (xml-data closure-data)
"Process response from proxy query."
(let* ((query (jabber-iq-query xml-data))
(from (jabber-xml-get-attribute xml-data 'from))
@@ -96,19 +99,171 @@ This is the set function of `jabber-socks5-proxies-data'."
(setq jabber-socks5-proxies-data
(delq existing-entry jabber-socks5-proxies-data))))
- (when successp
- (setq jabber-socks5-proxies-data
- (cons (cons from streamhosts)
- jabber-socks5-proxies-data)))
- (message "%s from %s. %d of %d proxies have answered."
- (if successp "Response" "Error") from
- (length jabber-socks5-proxies-data) (length jabber-socks5-proxies))))
-
-(defun jabber-socks5-accept (jid sid profile-data-function)
+ (destructuring-bind (callback successp) closure-data
+ (when successp
+ (setq jabber-socks5-proxies-data
+ (cons (cons from streamhosts)
+ jabber-socks5-proxies-data)))
+ (message "%s from %s. %d of %d proxies have answered."
+ (if successp "Response" "Error") from
+ (length jabber-socks5-proxies-data) (length jabber-socks5-proxies))
+ (when (and callback (= (length jabber-socks5-proxies-data) (length jabber-socks5-proxies)))
+ (funcall callback)))))
+
+(define-state-machine jabber-socks5
+ :start ((jid sid profile-function role)
+ "Start JEP-0065 bytestream with JID.
+SID is the session ID used.
+PROFILE-FUNCTION is the function to call upon success. See `jabber-si-stream-methods'.
+ROLE is either :initiator or :target. The initiator sends an IQ
+set; the target waits for one."
+ (let ((new-state-data (list :jid jid
+ :sid sid
+ :profile-function profile-function
+ :role role))
+ (new-state
+ ;; We want information about proxies; it might be needed in
+ ;; various situations.
+ (cond
+ ((null jabber-socks5-proxies)
+ ;; We know no proxy addresses. Try to find them by disco.
+ 'seek-proxies)
+ ((null jabber-socks5-proxies-data)
+ ;; We need to query the proxies for addresses.
+ 'query-proxies)
+ ;; So, we have our proxies.
+ (t
+ 'initiate))))
+ (list new-state new-state-data nil))))
+
+(defun jabber-socks5-accept (jid sid profile-function)
"Remember that we are waiting for connection from JID, with stream id SID"
;; asking the user for permission is done in the profile
(add-to-list 'jabber-socks5-pending-sessions
- (list sid jid profile-data-function)))
+ (list sid jid (start-jabber-socks5 jid sid profile-function :target))))
+
+(define-enter-state jabber-socks5 seek-proxies (fsm state-data)
+ ;; Look for items at the server.
+ (jabber-disco-get-items jabber-server nil
+ (lambda (fsm result)
+ (fsm-send-sync fsm (cons :items result)))
+ fsm)
+ ;; Spend no more than five seconds looking for a proxy.
+ (list state-data 5))
+
+(define-state jabber-socks5 seek-proxies (fsm state-data event callback)
+ "Collect disco results, looking for a bytestreams proxy."
+ ;; We put the number of outstanding requests as :remaining-info in
+ ;; the state-data plist.
+ (cond
+ ;; We're not ready to handle the IQ stanza yet
+ ((eq (car-safe event) :iq)
+ :defer)
+
+ ;; Got list of items at the server.
+ ((eq (car-safe event) :items)
+ (dolist (entry (cdr event))
+ ;; Each entry is ["name" "jid" "node"]. We send a disco info
+ ;; request to everything without a node.
+ (when (null (aref entry 2))
+ (lexical-let ((jid (aref entry 1)))
+ (jabber-disco-get-info
+ jid nil
+ (lambda (fsm result)
+ (fsm-send-sync fsm (list :info jid result)))
+ fsm))))
+ ;; Remember number of requests sent. But if none, we just go on.
+ (if (cdr event)
+ (list 'seek-proxies (plist-put state-data :remaining-info (length (cdr event))) :keep)
+ (list 'initiate state-data nil)))
+
+ ;; Got disco info from an item at the server.
+ ((eq (car-safe event) :info)
+ (fsm-debug-output "got disco event")
+ ;; Count the response.
+ (plist-put state-data :remaining-info (1- (plist-get state-data :remaining-info)))
+ (unless (eq (first (third event)) 'error)
+ (let ((identities (first (third event))))
+ ;; Is it a bytestream proxy?
+ (when (dolist (identity identities)
+ (when (and (string= (aref identity 1) "proxy")
+ (string= (aref identity 2) "bytestreams"))
+ (return t)))
+ ;; Yes, it is. Add it to the list.
+ (push (second event) jabber-socks5-proxies))))
+
+ ;; Wait for more responses, if any are to be expected.
+ (if (zerop (plist-get state-data :remaining-info))
+ ;; No more... go on to querying the proxies.
+ (list 'query-proxies state-data nil)
+ ;; We expect more responses...
+ (list 'seek-proxies state-data :keep)))
+
+ ((eq event :timeout)
+ ;; We can't wait anymore...
+ (list 'query-proxies state-data nil))))
+
+(define-enter-state jabber-socks5 query-proxies (fsm state-data)
+ (jabber-socks5-query-all-proxies
+ (lexical-let ((fsm fsm))
+ (lambda () (fsm-send-sync fsm :proxies))))
+ (list state-data 5))
+
+(define-state jabber-socks5 query-proxies (fsm state-data event callback)
+ "Query proxies in `jabber-socks5-proxies'."
+ (cond
+ ;; Can't handle the iq stanza yet...
+ ((eq (car-safe event) :iq)
+ :defer)
+
+ ((eq (car-safe event) :info)
+ ;; stray event... do nothing
+ (list 'query-proxies state-data :keep))
+
+ ;; Got response/error from all proxies, or timeout
+ ((memq event '(:proxies :timeout))
+ (list 'initiate state-data nil))))
+
+(define-enter-state jabber-socks5 initiate (fsm state-data)
+ ;; Sort the alist jabber-socks5-proxies-data such that the
+ ;; keys are in the same order as in jabber-socks5-proxies.
+ (setq jabber-socks5-proxies-data
+ (sort jabber-socks5-proxies-data
+ #'(lambda (a b)
+ (> (length (member (car a) jabber-socks5-proxies))
+ (length (member (car b) jabber-socks5-proxies))))))
+
+ ;; If we're the initiator, send initiation stanza.
+ (when (eq (plist-get state-data :role) :initiator)
+ ;; This is where initiation of server sockets would go
+
+ (jabber-send-iq
+ (plist-get state-data :jid) "set"
+ `(query ((xmlns . "http://jabber.org/protocol/bytestreams")
+ (sid . ,(plist-get state-data :sid)))
+ ,@(mapcar
+ #'(lambda (proxy)
+ (mapcar
+ #'(lambda (streamhost)
+ (list 'streamhost
+ (list (cons 'jid (jabber-xml-get-attribute streamhost 'jid))
+ (cons 'host (jabber-xml-get-attribute streamhost 'host))
+ (cons 'port (jabber-xml-get-attribute streamhost 'port)))
+ ;; (proxy ((xmlns . "http://affinix.com/jabber/stream")))
+ ))
+ (cdr proxy)))
+ jabber-socks5-proxies-data)
+ ;; (fast ((xmlns . "http://affinix.com/jabber/stream")))
+ )
+ (lexical-let ((fsm fsm))
+ (lambda (xml-data closure-data)
+ (fsm-send-sync fsm (list :iq xml-data))))
+ nil
+ ;; TODO: error handling
+ #'jabber-report-success "SOCKS5 negotiation"))
+
+ ;; If we're the target, we just wait for an incoming stanza.
+ (list state-data 30))
(add-to-list 'jabber-iq-set-xmlns-alist
(cons "http://jabber.org/protocol/bytestreams" 'jabber-socks5-process))
@@ -121,189 +276,383 @@ This is the set function of `jabber-socks5-proxies-data'."
(session (dolist (pending-session jabber-socks5-pending-sessions)
(when (and (equal sid (nth 0 pending-session))
(equal jid (nth 1 pending-session)))
- (return pending-session))))
- (profile-data-function (nth 2 session)))
+ (return pending-session)))))
;; check that we really are expecting this session
(unless session
(jabber-signal-error "auth" 'not-acceptable))
(setq jabber-socks5-pending-sessions (delq session jabber-socks5-pending-sessions))
+ (fsm-send-sync (nth 2 session) (list :iq xml-data))
+
;; find streamhost to connect to
- (let* ((streamhosts (jabber-xml-get-children query 'streamhost))
- (streamhost (dolist (streamhost streamhosts)
- (let ((connection (jabber-socks5-connect streamhost sid jid (concat jabber-username "@" jabber-server "/" jabber-resource))))
- (when connection
- ;; We select the first streamhost that we are able to connect to.
- (push (list connection sid jid profile-data-function)
- jabber-socks5-active-sessions)
- ;; Now set the filter, for the rest of the output
- (set-process-filter connection #'jabber-socks5-filter)
- (set-process-sentinel connection #'jabber-socks5-sentinel)
- (return streamhost))))))
- (unless streamhost
- (jabber-signal-error "cancel" 'item-not-found))
+;; (let* ((streamhosts (jabber-xml-get-children query 'streamhost))
+;; (streamhost (dolist (streamhost streamhosts)
+;; (let ((connection (jabber-socks5-connect streamhost sid jid (concat jabber-username "@" jabber-server "/" jabber-resource))))
+;; (when connection
+;; ;; We select the first streamhost that we are able to connect to.
+;; (push (list connection sid jid profile-data-function)
+;; jabber-socks5-active-sessions)
+;; ;; Now set the filter, for the rest of the output
+;; (set-process-filter connection #'jabber-socks5-filter)
+;; (set-process-sentinel connection #'jabber-socks5-sentinel)
+;; (return streamhost))))))
+;; (unless streamhost
+;; (jabber-signal-error "cancel" 'item-not-found))
- ;; tell initiator which streamhost we use
- (jabber-send-iq jid "result"
- `(query ((xmlns . "http://jabber.org/protocol/bytestreams"))
- (streamhost-used ((jid . ,(jabber-xml-get-attribute streamhost 'jid)))))
- nil nil nil nil id)
- ;; now, as data is sent, it will be passed to the profile.
- )))
-
-(defun jabber-socks5-connect (streamhost sid initiator target)
- "Attempt to connect to STREAMHOST, authenticating with SID, INITIATOR and TARGET.
-Return nil on error. Return connection object on success.
-
-STREAMHOST has the form
-\(streamhost ((host . HOST)
- (port . PORT)))
-
-Zeroconf is not supported."
- (message "Attempting SOCKS5 connection to %s (%s->%s, %s)" streamhost initiator target sid)
- (condition-case e
- (let ((coding-system-for-read 'binary)
- (coding-system-for-write 'binary)
- (host (jabber-xml-get-attribute streamhost 'host))
- (port (string-to-number (jabber-xml-get-attribute streamhost 'port))))
- ;; is this the best way to send binary network output?
- (let ((socks5-connection (open-network-stream "socks5" (generate-new-buffer-name "socks5") host port)))
- (with-current-buffer (process-buffer socks5-connection)
- ;; version: 5. number of auth methods supported: 1.
- ;; which one: no authentication.
- (process-send-string socks5-connection (string 5 1 0))
- ;; wait for response
- (accept-process-output socks5-connection 15)
- ;; should return:
- ;; version: 5. auth method to use: none
- (unless (string= (buffer-substring 1 3) (string 5 0))
- (error "SOCKS5 authentication required"))
-
- ;; send connect command
- (let ((hash (sha1-string (concat sid initiator target))))
- (process-send-string
- socks5-connection
- (concat (string 5 1 0 3 (length hash))
- hash
- (string 0 0))))
-
- (accept-process-output socks5-connection 15)
- (unless (string= (buffer-substring 3 5) (string 5 0))
- (error "SOCKS5 failure"))
-
- (message "SOCKS5 connection established")
-
- ;; The information returned here is exactly the same that we sent...
- ;; Not very exciting. Anyway, this part is done, we have a connection.
- (let* ((address-type (aref (buffer-substring 6 7) 0))
- (address-length (aref (buffer-substring 7 8) 0))
- (address (buffer-substring 8 (+ 8 address-length)))
- (address-port-string (buffer-substring (+ 8 address-length) (+ 8 address-length 2)))
- (address-port (+
- (* 256 (aref address-port-string 0))
- (* 1 (aref address-port-string 1)))))
- ;;(message "Address type: %d\nAddress: %s\nPort: %d" address-type address address-port)
-
- ;; Delete all SOCKS5 data, leave room for the stream.
- (delete-region 1 (+ 8 address-length 2)))
-
- socks5-connection)))
- (error
- (message "SOCKS5 connection failed: %s" e)
- nil)))
-
-(defun jabber-socks5-filter (connection data)
- "Pass data from connection to profile data function"
- (let* ((session (assq connection jabber-socks5-active-sessions))
- (sid (nth 1 session))
- (jid (nth 2 session))
- (profile-data-function (nth 3 session)))
- ;; If the data function requests it, tear down the connection.
- (unless (funcall profile-data-function jid sid data)
- (jabber-socks5-sentinel connection nil))))
-
-(defun jabber-socks5-sentinel (process event-string)
- ;; Connection terminated. Shuffle together the remaining data,
- ;; and kill the buffer.
- (let* ((session (assq process jabber-socks5-active-sessions))
- (buffer (process-buffer process))
- (sid (nth 1 session))
- (jid (nth 2 session))
- (profile-data-function (nth 3 session)))
- (kill-buffer buffer)
- (delete-process process)
- (funcall profile-data-function jid sid nil)
- (setq jabber-socks5-active-sessions (delq session jabber-socks5-pending-sessions))))
+;; ;; tell initiator which streamhost we use
+;; (jabber-send-iq jid "result"
+;; `(query ((xmlns . "http://jabber.org/protocol/bytestreams"))
+;; (streamhost-used ((jid . ,(jabber-xml-get-attribute streamhost 'jid)))))
+;; nil nil nil nil id)
+;; ;; now, as data is sent, it will be passed to the profile.
+;; )
+ ))
+
+(define-state jabber-socks5 initiate (fsm state-data event callback)
+ (let* ((our-jid (concat jabber-username "@" jabber-server "/" jabber-resource))
+ (their-jid (plist-get state-data :jid))
+ (initiator-jid (if (eq (plist-get state-data :role) :initiator) our-jid their-jid))
+ (target-jid (if (eq (plist-get state-data :role) :initiator) their-jid our-jid)))
+ (cond
+ ;; Stray event...
+ ((memq (car-safe event) '(:proxy :info))
+ (list 'initiate state-data :keep))
+
+ ;; Incoming IQ
+ ((eq (car-safe event) :iq)
+ (let ((xml-data (second event)))
+ ;; This is either type "set" (with a list of streamhosts to
+ ;; use), or a "result" (indicating the streamhost finally used
+ ;; by the other party).
+ (cond
+ ((string= (jabber-xml-get-attribute xml-data 'type) "set")
+ ;; A "set" makes sense if we're the initiator and offered
+ ;; Psi's "fast mode". We don't yet, though, so this is only
+ ;; for target.
+ (dolist (streamhost (jabber-xml-get-children (jabber-iq-query xml-data) 'streamhost))
+ (jabber-xml-let-attributes
+ (jid host port) streamhost
+ ;; This is where we would attempt to support zeroconf
+ (when (and jid host port)
+ (start-jabber-socks5-connection
+ initiator-jid target-jid jid
+ (plist-get state-data :sid) host port fsm))))
+
+ (list 'wait-for-connection (plist-put state-data :iq-id (jabber-xml-get-attribute xml-data 'id)) 30))
+
+ ((string= (jabber-xml-get-attribute xml-data 'type) "result")
+ ;; The other party has decided what streamhost to use.
+ (let* ((proxy-used (jabber-xml-get-attribute (jabber-xml-path xml-data '(query streamhost-used)) 'jid))
+ ;; If JID is our own JID, we have probably already detected
+ ;; what connection to use. But that is a later problem...
+ (streamhosts (cdr (assoc proxy-used jabber-socks5-proxies-data))))
+ ;; Try to connect to all addresses of this proxy...
+ (dolist (streamhost streamhosts)
+ (jabber-xml-let-attributes
+ (jid host port) streamhost
+ (when (and jid host port)
+ (start-jabber-socks5-connection
+ initiator-jid target-jid jid
+ (plist-get state-data :sid) host port fsm)))))
+
+ (list 'wait-for-connection state-data 30))))))))
+
+(define-state-machine jabber-socks5-connection
+ :start
+ ((initiator-jid target-jid streamhost-jid sid host port socks5-fsm)
+ "Connect to a single JEP-0065 streamhost."
+ (let ((coding-system-for-read 'binary)
+ (coding-system-for-write 'binary))
+ ;; make-network-process, which we really want, for asynchronous
+ ;; connection and such, was introduced in Emacs 22.
+ (if (fboundp 'make-network-process)
+ (let ((connection
+ (make-network-process
+ :name "socks5"
+ :buffer nil
+ :host host
+ :service (string-to-number port)
+ :nowait t
+ :filter (fsm-make-filter fsm)
+ :sentinel (fsm-make-sentinel fsm))))
+ (list 'wait-for-connection
+ (list :connection connection
+ :initiator-jid initiator-jid
+ :target-jid target-jid
+ :streamhost-jid streamhost-jid
+ :sid sid
+ :socks5-fsm socks5-fsm)
+ 30))
+ ;; So we open a stream, and wait for the connection to succeed.
+ (condition-case nil
+ (let ((connection
+ (open-network-stream "socks5" nil
+ host (string-to-number port))))
+ (set-process-filter connection (fsm-make-filter fsm))
+ (set-process-sentinel connection (fsm-make-sentinel fsm))
+ (list 'authenticate
+ (list :connection connection
+ :initiator-jid initiator-jid
+ :target-jid target-jid
+ :streamhost-jid streamhost-jid
+ :sid sid
+ :socks5-fsm socks5-fsm)
+ nil))
+ (error (list 'fail '() nil)))))))
+
+(define-state jabber-socks5-connection wait-for-connection
+ (fsm state-data event callback)
+ (cond
+ ((eq (car-safe event) :sentinel)
+ (let ((string (third event)))
+ (cond
+ ;; Connection succeeded
+ ((string= (substring string 0 4) "open")
+ (list 'authenticate state-data nil))
+ ;; Connection failed
+ (t
+ (list 'fail state-data nil)))))))
+
+(define-enter-state jabber-socks5-connection authenticate
+ (fsm state-data)
+ "Send authenticate command."
+ ;; version: 5. number of auth methods supported: 1.
+ ;; which one: no authentication.
+ (process-send-string (plist-get state-data :connection) (string 5 1 0))
+ (list state-data 30))
+
+(define-state jabber-socks5-connection authenticate
+ (fsm state-data event callback)
+ "Receive response to authenticate command."
+ (cond
+ ((eq (car-safe event) :filter)
+ (let ((string (third event)))
+ ;; should return:
+ ;; version: 5. auth method to use: none
+ (if (string= string (string 5 0))
+ ;; Authenticated. Send connect command.
+ (list 'connect state-data nil)
+ ;; Authentication failed...
+ (delete-process (second event))
+ (list 'fail state-data nil))))
+
+ ((eq (car-safe event) :sentinel)
+ (list 'fail state-data nil))))
+
+(define-enter-state jabber-socks5-connection connect (fsm state-data)
+ "Send connect command."
+ (let* ((sid (plist-get state-data :sid))
+ (initiator (plist-get state-data :initiator-jid))
+ (target (plist-get state-data :target-jid))
+ (hash (sha1-string (concat sid initiator target))))
+ (process-send-string
+ (plist-get state-data :connection)
+ (concat (string 5 1 0 3 (length hash))
+ hash
+ (string 0 0)))
+ (list state-data 30)))
+
+(define-state jabber-socks5-connection connect
+ (fsm state-data event callback)
+ "Receive response to connect command."
+ (cond
+ ((eq (car-safe event) :filter)
+ (let ((string (third event)))
+ (if (string= (substring string 0 2) (string 5 0))
+ ;; connection established
+ (progn
+ (fsm-send (plist-get state-data :socks5-fsm)
+ (list :connected
+ (plist-get state-data :connection)
+ (plist-get state-data :streamhost-jid)))
+ ;; Our work is done
+ (list 'done nil))
+ (list 'fail state-data nil))))
+ ((eq (car-safe event) :sentinel)
+ (list 'fail state-data nil))))
+
+(define-state jabber-socks5-connection done
+ (fsm state-data event callback)
+ ;; ignore all events
+ (list 'done nil nil))
+
+(define-enter-state jabber-socks5-connection fail (fsm state-data)
+ ;; Notify parent fsm about failure
+ (fsm-send (plist-get state-data :socks5-fsm)
+ :not-connected)
+ (list nil nil))
+
+(define-state jabber-socks5-connection fail
+ (fsm state-data event callback)
+ ;; ignore all events
+ (list 'fail nil nil))
+
+(define-state jabber-socks5 wait-for-connection
+ (fsm state-data event callback)
+ (cond
+ ((eq (car-safe event) :connected)
+ (destructuring-bind (ignored connection streamhost-jid) event
+ (setq state-data (plist-put state-data :connection connection))
+ ;; If we are expected to tell which streamhost we chose, do so.
+ (let ((iq-id (plist-get state-data :iq-id)))
+ (when iq-id
+ (jabber-send-iq
+ (plist-get state-data :jid) "result"
+ `(query ((xmlns . "http://jabber.org/protocol/bytestreams"))
+ (streamhost-used ((jid . ,streamhost-jid))))
+ nil nil nil nil
+ iq-id)))
+
+ ;; If we are the initiator, we should activate the bytestream.
+ (if (eq (plist-get state-data :role) :initiator)
+ (progn
+ (jabber-send-iq
+ streamhost-jid "set"
+ `(query ((xmlns . "http://jabber.org/protocol/bytestreams")
+ (sid . ,(plist-get state-data :sid)))
+ (activate nil ,(plist-get state-data :jid)))
+ (lambda (xml-data fsm) (fsm-send-sync fsm :activated)) fsm
+ (lambda (xml-data fsm) (fsm-send-sync fsm :activation-failed)) fsm)
+ (list 'wait-for-activation state-data 10))
+ ;; Otherwise, we just let the data flow.
+ (list 'stream-activated state-data nil))))
+
+ ((eq event :not-connected)
+ ;; If we were counting the streamhosts, we would know when there
+ ;; are no more chances left.
+ (list 'wait-for-connection state-data :keep))
+
+ ((eq event :timeout)
+ (list 'fail (plist-put state-data :error "Timeout when connecting to streamhosts") nil))))
+
+(define-state jabber-socks5 wait-for-activation
+ (fsm state-data event callback)
+ (cond
+ ((eq event :activated)
+ (list 'stream-activated state-data nil))
+ ((eq event :activation-failed)
+ (list 'fail (plist-put state-data :error "Proxy activation failed") nil))
+
+ ;; Stray events from earlier state
+ ((eq (car-safe event) :connected)
+ ;; We just close the connection
+ (delete-process (second event))
+ (list 'wait-for-activation state-data :keep))
+ ((eq event :not-connected)
+ (list 'wait-for-activation state-data :keep))))
+
+(define-enter-state jabber-socks5 stream-activated
+ (fsm state-data)
+ (let ((connection (plist-get state-data :connection))
+ (jid (plist-get state-data :jid))
+ (sid (plist-get state-data :sid))
+ (profile-function (plist-get state-data :profile-function)))
+ (set-process-filter connection (fsm-make-filter fsm))
+ (set-process-sentinel connection (fsm-make-sentinel fsm))
+ ;; Call the profile function, passing the data send function, and
+ ;; receiving the data receiving function. Put the data receiving
+ ;; function in the plist.
+ (list (plist-put state-data
+ :profile-data-function
+ (funcall profile-function
+ jid sid
+ (lexical-let ((fsm fsm))
+ (lambda (data)
+ (fsm-send fsm (list :send data))))))
+ nil)))
+
+
+(define-state jabber-socks5 stream-activated
+ (fsm state-data event callback)
+ (let ((connection (plist-get state-data :connection))
+ (profile-data-function (plist-get state-data :profile-data-function))
+ (sid (plist-get state-data :sid))
+ (jid (plist-get state-data :jid)))
+ (cond
+ ((eq (car-safe event) :send)
+ (process-send-string connection (second event))
+ (list 'stream-activated state-data nil))
+
+ ((eq (car-safe event) :filter)
+ ;; Pass data from connection to profile data function
+ ;; If the data function requests it, tear down the connection.
+ (unless (funcall profile-data-function jid sid (third event))
+ (fsm-send fsm (list :sentinel (second event) "shutdown")))
+
+ (list 'stream-activated state-data nil))
+
+ ((eq (car-safe event) :sentinel)
+ ;; Connection terminated. Shuffle together the remaining data,
+ ;; and kill the buffer.
+ (delete-process (second event))
+ (funcall profile-data-function jid sid nil)
+ (list 'closed nil nil))
+
+ ;; Stray events from earlier state
+ ((eq (car-safe event) :connected)
+ ;; We just close the connection
+ (delete-process (second event))
+ (list 'stream-activated state-data nil))
+ ((eq event :not-connected)
+ (list 'stream-activated state-data nil)))))
+
+(define-enter-state jabber-socks5 fail (fsm state-data)
+ "Tell our caller that we failed."
+ (let ((jid (plist-get state-data :jid))
+ (sid (plist-get state-data :sid))
+ (profile-function (plist-get state-data :profile-function))
+ (iq-id (plist-get state-data :iq-id)))
+ (funcall profile-function jid sid (plist-get state-data :error))
+
+ (when iq-id
+ (jabber-send-iq-error jid iq-id nil "cancel"
+ 'remote-server-not-found)))
+ (list nil nil))
(defun jabber-socks5-client-1 (jid sid profile-function)
"Negotiate a SOCKS5 connection with JID.
-This function simply sends a request; the response is handled elsewhere."
- ;; TODO: start our own server if we can.
- (unless jabber-socks5-proxies
- (error "No proxies defined. Set `jabber-socks5-proxies'."))
- (unless jabber-socks5-proxies-data
- (error "No proxy data available. Run `jabber-socks5-query-all-proxies'."))
-
- ;; Sort the alist jabber-socks5-proxies-data such that the
- ;; keys are in the same order as in jabber-socks5-proxies.
- (setq jabber-socks5-proxies-data
- (sort jabber-socks5-proxies-data
- #'(lambda (a b)
- (> (length (member (car a) jabber-socks5-proxies))
- (length (member (car b) jabber-socks5-proxies))))))
-
- (jabber-send-iq jid "set"
- `(query ((xmlns . "http://jabber.org/protocol/bytestreams")
- (sid . ,sid))
- ,@(mapcar
- #'(lambda (proxy)
- (mapcar
- #'(lambda (streamhost)
- (list 'streamhost
- (list (cons 'jid (jabber-xml-get-attribute streamhost 'jid))
- (cons 'host (jabber-xml-get-attribute streamhost 'host))
- (cons 'port (jabber-xml-get-attribute streamhost 'port)))))
- (cdr proxy)))
- jabber-socks5-proxies-data))
- `(lambda (xml-data closure-data)
- (jabber-socks5-client-2 xml-data ,jid ,sid ,profile-function)) nil
- ;; TODO: error handling
- #'jabber-report-success "SOCKS5 negotiation"))
-
-(defun jabber-socks5-client-2 (xml-data jid sid profile-function)
- "Contact has selected a streamhost to use. Connect to the proxy."
- (let* ((query (jabber-iq-query xml-data))
- (streamhost-used (car (jabber-xml-get-children query 'streamhost-used)))
- (proxy-used (jabber-xml-get-attribute streamhost-used 'jid))
- connection)
- (let ((streamhosts-left (cdr (assoc proxy-used jabber-socks5-proxies-data))))
- (while (and streamhosts-left (not connection))
- (setq connection
- (jabber-socks5-connect (car streamhosts-left)
- sid
- (concat jabber-username "@" jabber-server "/" jabber-resource)
- jid))
- (setq streamhosts-left (cdr streamhosts-left))))
- (unless connection
- (error "Couldn't connect to proxy %s" proxy-used))
-
- ;; Activation is only needed for proxies.
- (jabber-send-iq proxy-used "set"
- `(query ((xmlns . "http://jabber.org/protocol/bytestreams")
- (sid . ,sid))
- (activate () ,jid))
- `(lambda (xml-data closure-data)
- (jabber-socks5-client-3 xml-data ,jid ,sid ,profile-function ,connection)) nil
- ;; TODO: report error to contact?
- #'jabber-report-success "Proxy activation")))
-
-(defun jabber-socks5-client-3 (xml-data jid sid profile-function proxy-connection)
- "Proxy is activated. Start the transfer."
- ;; The response from the proxy does not contain any interesting
- ;; information, beyond success confirmation.
-
- (funcall profile-function jid sid `(lambda (data)
- (process-send-string ,proxy-connection data))))
+This function simply starts a state machine."
+ (add-to-list 'jabber-socks5-pending-sessions
+ (list sid jid (start-jabber-socks5 jid sid profile-function :initiator))))
+
+;; (defun jabber-socks5-client-2 (xml-data jid sid profile-function)
+;; "Contact has selected a streamhost to use. Connect to the proxy."
+;; (let* ((query (jabber-iq-query xml-data))
+;; (streamhost-used (car (jabber-xml-get-children query 'streamhost-used)))
+;; (proxy-used (jabber-xml-get-attribute streamhost-used 'jid))
+;; connection)
+;; (let ((streamhosts-left (cdr (assoc proxy-used jabber-socks5-proxies-data))))
+;; (while (and streamhosts-left (not connection))
+;; (setq connection
+;; (jabber-socks5-connect (car streamhosts-left)
+;; sid
+;; (concat jabber-username "@" jabber-server "/" jabber-resource)
+;; jid))
+;; (setq streamhosts-left (cdr streamhosts-left))))
+;; (unless connection
+;; (error "Couldn't connect to proxy %s" proxy-used))
+
+;; ;; Activation is only needed for proxies.
+;; (jabber-send-iq proxy-used "set"
+;; `(query ((xmlns . "http://jabber.org/protocol/bytestreams")
+;; (sid . ,sid))
+;; (activate () ,jid))
+;; (lexical-let ((jid jid) (sid sid) (profile-function profile-function)
+;; (connection connection))
+;; (lambda (xml-data closure-data)
+;; (jabber-socks5-client-3 xml-data jid sid profile-function connection))) nil
+;; ;; TODO: report error to contact?
+;; #'jabber-report-success "Proxy activation")))
+
+;; (defun jabber-socks5-client-3 (xml-data jid sid profile-function proxy-connection)
+;; "Proxy is activated. Start the transfer."
+;; ;; The response from the proxy does not contain any interesting
+;; ;; information, beyond success confirmation.
+
+;; (funcall profile-function jid sid
+;; (lexical-let ((proxy-connection proxy-connection))
+;; (lambda (data)
+;; (process-send-string proxy-connection data)))))
(provide 'jabber-socks5)
diff --git a/jabber-time.el b/jabber-time.el
new file mode 100644
index 0000000..ae0eca1
--- /dev/null
+++ b/jabber-time.el
@@ -0,0 +1,133 @@
+;; jabber-time.el - time reporting by JEP-0090
+
+;; Copyright (C) 2006 - Kirill A. Kroinskiy - catap@catap.ru
+;; Copyright (C) 2006 - Magnus Henoch - mange@freemail.hu
+
+;; 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(require 'jabber-iq)
+(require 'jabber-util)
+
+(require 'time-date)
+
+(add-to-list 'jabber-jid-info-menu
+ (cons "Request time" 'jabber-get-time))
+(defun jabber-get-time (to)
+ "Request time"
+ (interactive (list (jabber-read-jid-completing "Request time of: "
+ nil nil nil 'full)))
+ (jabber-send-iq to
+ "get"
+ '(query ((xmlns . "jabber:iq:time")))
+ #'jabber-process-data #'jabber-process-time
+ #'jabber-process-data "Time request failed"))
+
+;; called by jabber-process-data
+(defun jabber-process-time (xml-data)
+ "Handle results from jabber:iq:time requests."
+ (let ((query (jabber-iq-query xml-data)))
+ (let ((display
+ (car (jabber-xml-node-children
+ (car (jabber-xml-get-children
+ query 'display)))))
+ (utc
+ (car (jabber-xml-node-children
+ (car (jabber-xml-get-children
+ query 'utc)))))
+ (tz
+ (car (jabber-xml-node-children
+ (car (jabber-xml-get-children
+ query 'tz))))))
+ (insert "Time:\t\t")
+ (cond
+ (display
+ (insert display))
+ (utc
+ (insert (format-time-string "%Y-%m-%d %T" (jabber-parse-legacy-time utc)))))
+ (insert "\n")
+ (when tz
+ (insert "Time zone:\t" tz "\n")))))
+
+;; the only difference between these two functions is the
+;; jabber-read-jid-completing call.
+(defun jabber-get-last-online (to)
+ "Request time since a user was last online, or uptime of a component."
+ (interactive (list (jabber-read-jid-completing "Get last online for: "
+ nil nil nil 'bare-or-muc)))
+ (jabber-send-iq to
+ "get"
+ '(query ((xmlns . "jabber:iq:last")))
+ #'jabber-process-data #'jabber-process-last
+ #'jabber-process-data "Last online request failed"))
+
+(defun jabber-get-idle-time (to)
+ "Request idle time of user."
+ (interactive (list (jabber-read-jid-completing "Get idle time for: "
+ nil nil nil 'full)))
+ (jabber-send-iq to
+ "get"
+ '(query ((xmlns . "jabber:iq:last")))
+ #'jabber-process-data #'jabber-process-last
+ #'jabber-process-data "Idle time request failed"))
+
+(defun jabber-process-last (xml-data)
+ "Handle resultts from jabber:iq:last requests."
+ (let* ((from (jabber-xml-get-attribute xml-data 'from))
+ (query (jabber-iq-query xml-data))
+ (seconds (jabber-xml-get-attribute query 'seconds))
+ (message (car (jabber-xml-node-children query))))
+ (cond
+ ((jabber-jid-resource from)
+ ;; Full JID: idle time
+ (insert (format "Idle for %s seconds" seconds) "\n"))
+ ((jabber-jid-username from)
+ ;; Bare JID with username: time since online
+ (insert (format "Last online %s seconds ago" seconds) "\n")
+ (let ((seconds (condition-case nil
+ (string-to-number seconds)
+ (error nil))))
+ (when (numberp seconds)
+ (insert "That is, at "
+ (format-time-string "%Y-%m-%d %T"
+ (time-subtract (current-time)
+ (seconds-to-time seconds)))
+ "\n"))))
+ (t
+ ;; Only hostname: uptime
+ (insert (format "Uptime: %s seconds" seconds) "\n")))))
+
+(add-to-list 'jabber-iq-get-xmlns-alist (cons "jabber:iq:time" 'jabber-return-time))
+(add-to-list 'jabber-advertised-features "jabber:iq:time")
+(defun jabber-return-time (xml-data)
+ "Return client time as defined in JEP-0090. Sender and ID are
+determined from the incoming packet passed in XML-DATA."
+ (let ((to (jabber-xml-get-attribute xml-data 'from))
+ (id (jabber-xml-get-attribute xml-data 'id)))
+ (jabber-send-iq to "result"
+ `(query ((xmlns . "jabber:iq:time"))
+ ;; what is ``human-readable'' format?
+ ;; the same way as formating using by tkabber
+ (display () ,(format-time-string "%a %b %d %H:%M:%S %Z %Y"))
+ (tz () ,(format-time-string "%Z"))
+ (utc () ,(jabber-encode-legacy-time nil)))
+ nil nil nil nil
+ id)))
+
+(provide 'jabber-time)
+
+;; arch-tag: 5396bfda-323a-11db-ac8d-000a95c2fcd0
diff --git a/jabber-util.el b/jabber-util.el
index 112d799..5d9dc1f 100644
--- a/jabber-util.el
+++ b/jabber-util.el
@@ -1,4 +1,4 @@
-;; jabber-util.el - various utility functions
+;; jabber-util.el - various utility functions -*- coding: utf-8; -*-
;; Copyright (C) 2002, 2003, 2004 - tom berger - object@intelectronica.net
;; Copyright (C) 2003, 2004 - Magnus Henoch - mange@freemail.hu
@@ -19,12 +19,11 @@
;; 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 'cl))
+
(defvar jabber-jid-history nil
"History of entered JIDs")
-(defvar *jabber-sound-playing* nil
- "is a sound playing right now?")
-
(cond
((fboundp 'replace-in-string)
(defsubst jabber-replace-in-string (str regexp newtext)
@@ -140,13 +139,18 @@ properties to add to the result."
(equal (jabber-jid-user jid)
(concat jabber-username "@" jabber-server)))
-(defun jabber-read-jid-completing (prompt &optional subset require-match default)
+(defun jabber-read-jid-completing (prompt &optional subset require-match default resource)
"read a jid out of the current roster from the minibuffer.
If SUBSET is non-nil, it should be a list of symbols from which
the JID is to be selected, instead of using the entire roster.
If REQUIRE-MATCH is non-nil, the JID must be in the list used.
If DEFAULT is non-nil, it's used as the default value, otherwise
-the default is inferred from context."
+the default is inferred from context.
+RESOURCE is one of the following:
+
+nil Accept full or bare JID, as entered
+full Turn bare JIDs to full ones with highest-priority resource
+bare-or-muc Turn full JIDs to bare ones, except for in MUC"
(let ((jid-at-point (or
(and default
;; default can be either a symbol or a string
@@ -159,7 +163,8 @@ the default is inferred from context."
(completion-ignore-case t)
(jid-completion-table (mapcar #'(lambda (item)
(cons (symbol-name item) item))
- (or subset *jabber-roster*))))
+ (or subset *jabber-roster*)))
+ chosen)
(dolist (item (or subset *jabber-roster*))
(if (get item 'name)
(push (cons (get item 'name) item) jid-completion-table)))
@@ -172,10 +177,32 @@ the default is inferred from context."
(format "(default %s) " jid-at-point)))
jid-completion-table
nil require-match nil 'jabber-jid-history jid-at-point)))
- (if (and input (assoc-ignore-case input jid-completion-table))
- (symbol-name (cdr (assoc-ignore-case input jid-completion-table)))
- (and (not (zerop (length input)))
- input)))))
+ (setq chosen
+ (if (and input (assoc-ignore-case input jid-completion-table))
+ (symbol-name (cdr (assoc-ignore-case input jid-completion-table)))
+ (and (not (zerop (length input)))
+ input))))
+
+ (when chosen
+ (case resource
+ (full
+ ;; If JID is bare, add the highest-priority resource.
+ (if (jabber-jid-resource chosen)
+ chosen
+ (let ((highest-resource (get (jabber-jid-symbol chosen) 'resource)))
+ (if highest-resource
+ (concat chosen "/" highest-resource)
+ chosen))))
+ (bare-or-muc
+ ;; If JID is full and non-MUC, remove resource.
+ (if (null (jabber-jid-resource chosen))
+ chosen
+ (let ((bare (jabber-jid-user chosen)))
+ (if (assoc bare *jabber-active-groupchats*)
+ chosen
+ bare))))
+ (t
+ chosen)))))
(defun jabber-read-node (prompt)
"Read node name, taking default from disco item at point."
@@ -188,7 +215,12 @@ the default is inferred from context."
(defun jabber-read-passwd (&optional prompt)
"Read Jabber password, either from customized variable or from minibuffer.
See `jabber-password'."
- (or jabber-password (read-passwd (or prompt "Jabber password: "))))
+ (if jabber-password
+ ;; Need to copy the password, as sasl.el wants to erase it. The
+ ;; variable jabber-password is a high-convenience low-security
+ ;; alternative anyway.
+ (copy-sequence jabber-password)
+ (read-passwd (or prompt "Jabber password: "))))
(defun jabber-iq-query (xml-data)
"Return the query part of an IQ stanza.
@@ -358,6 +390,15 @@ See secton 9.3, Stanza Errors, of XMPP Core, and JEP-0086, Legacy Errors."
(concat condition
(if text (format ": %s" text)))))
+(defun jabber-error-condition (error-xml)
+ "Parse the given <error/> tag and return the condition symbol."
+ (catch 'condition
+ (dolist (child (jabber-xml-node-children error-xml))
+ (when (string=
+ (jabber-xml-get-attribute child 'xmlns)
+ "urn:ietf:params:xml:ns:xmpp-stanzas")
+ (throw 'condition (jabber-xml-node-name child))))))
+
(defvar jabber-stream-error-messages
(list
(cons 'bad-format "Bad XML format")
@@ -423,21 +464,66 @@ See section 9.3 of XMPP Core."
(signal 'jabber-error
(list error-type condition text app-specific)))
-(defun jabber-play-sound-file (soundfile)
- (if (not *jabber-sound-playing*)
- (progn
- (setq *jabber-sound-playing* t)
- (run-with-idle-timer 0.01 nil
- #'(lambda (sf)
- (condition-case nil
- ;; play-sound-file might display "Could not set sample rate" in
- ;; echo area. Don't let this erase the previous message.
- (let ((old-message (current-message)))
- (play-sound-file sf)
- (setq *jabber-sound-playing* nil)
- (message "%s" old-message))
- (error (setq *jabber-sound-playing* nil))))
- soundfile))))
+(defun jabber-unhex (string)
+ "Convert a hex-encoded UTF-8 string to Emacs representation.
+For example, \"ji%C5%99i@%C4%8Dechy.example/v%20Praze\" becomes
+\"jiři@čechy.example/v Praze\"."
+ (decode-coding-string (url-unhex-string string) 'utf-8))
+
+(defun jabber-handle-uri (uri &rest ignored-args)
+ "Handle XMPP links according to draft-saintandre-xmpp-iri-04.
+See Info node `(jabber)XMPP URIs'."
+ (interactive "sEnter XMPP URI: ")
+
+ (when (string-match "//" uri)
+ (error "URIs with authority part are not supported"))
+
+ ;; This regexp handles three cases:
+ ;; xmpp:romeo@montague.net
+ ;; xmpp:romeo@montague.net?roster
+ ;; xmpp:romeo@montague.net?roster;name=Romeo%20Montague;group=Lovers
+ (unless (string-match "^xmpp:\\([^?]+\\)\\(\\?\\([a-z]+\\)\\(;\\(.*\\)\\)?\\)?" uri)
+ (error "Invalid XMPP URI '%s'" uri))
+
+ ;; We start by raising the Emacs frame.
+ (raise-frame)
+
+ (let ((jid (jabber-unhex (match-string 1 uri)))
+ (method (match-string 3 uri))
+ (args (let ((text (match-string 5 uri)))
+ ;; If there are arguments...
+ (when text
+ ;; ...split the pairs by ';'...
+ (let ((pairs (split-string text ";")))
+ (mapcar (lambda (pair)
+ ;; ...and split keys from values by '='.
+ (destructuring-bind (key value)
+ (split-string pair "=")
+ ;; Values can be hex-coded.
+ (cons key (jabber-unhex value))))
+ pairs))))))
+ ;; The full list of methods is at
+ ;; <URL:http://www.jabber.org/registrar/querytypes.html>.
+ (cond
+ ;; Join an MUC.
+ ((string= method "join")
+ (jabber-groupchat-join jid (jabber-muc-read-my-nickname jid) t))
+ ;; Register with a service.
+ ((string= method "register")
+ (jabber-get-register jid))
+ ;; Run an ad-hoc command
+ ((string= method "command")
+ ;; XXX: does the 'action' attribute make sense?
+ (jabber-ahc-execute-command jid (cdr (assoc "node" args))))
+ ;; Everything else: open a chat buffer.
+ (t
+ (jabber-chat-with jid)))))
+
+(defun url-xmpp (url)
+ "Handle XMPP URLs from internal Emacs functions."
+ ;; XXX: This parsing roundtrip is redundant, and the parser of the
+ ;; url package might lose information.
+ (jabber-handle-uri (url-recreate-url url)))
(provide 'jabber-util)
diff --git a/jabber-vcard-avatars.el b/jabber-vcard-avatars.el
new file mode 100644
index 0000000..e44a9f9
--- /dev/null
+++ b/jabber-vcard-avatars.el
@@ -0,0 +1,116 @@
+;;; jabber-vcard-avatars.el --- Avatars by JEP-0153
+
+;; Copyright (C) 2006 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'jabber-avatar)
+
+(defcustom jabber-vcard-avatars-retrieve (and (fboundp 'display-images-p)
+ (display-images-p))
+ "Automatically download vCard avatars?"
+ :group 'jabber-avatar
+ :type 'boolean)
+
+(defcustom jabber-vcard-avatars-publish t
+ "Publish your vCard photo as avatar?"
+ :group 'jabber-avatar
+ :type 'boolean)
+
+(defvar jabber-vcard-avatars-current-hash nil
+ "SHA1 hash of avatar currently published through presence.")
+
+(add-to-list 'jabber-presence-chain 'jabber-vcard-avatars-presence)
+(defun jabber-vcard-avatars-presence (xml-data)
+ "Look for vCard avatar mark in <presence/> stanza."
+ ;; Only look at ordinary presence
+ (when (and jabber-vcard-avatars-retrieve
+ (null (jabber-xml-get-attribute xml-data 'type)))
+ (let* ((from (jabber-jid-user (jabber-xml-get-attribute xml-data 'from)))
+ (photo (jabber-xml-path xml-data '(("vcard-temp:x:update" . "x") photo)))
+ (sha1-hash (car (jabber-xml-node-children photo))))
+ (if (null sha1-hash)
+ ;; User has removed avatar
+ (jabber-avatar-set from nil)
+ (if (jabber-avatar-find-cached sha1-hash)
+ ;; Avatar is cached
+ (jabber-avatar-set from sha1-hash)
+ ;; Avatar is not cached; retrieve it
+ (jabber-vcard-avatars-fetch from))))))
+
+(defun jabber-vcard-avatars-vcard (iq from)
+ "Get the photo from the vCard, and set the avatar."
+ (let ((photo (assq 'PHOTO (jabber-vcard-parse (jabber-iq-query iq)))))
+ (if photo
+ (let ((avatar (jabber-avatar-from-base64-string (nth 2 photo)
+ (nth 1 photo))))
+ (jabber-avatar-cache avatar)
+ (jabber-avatar-set from avatar))
+ (jabber-avatar-set from nil))))
+
+(defun jabber-vcard-avatars-fetch (who)
+ "Fetch WHO's vCard, and extract avatar."
+ (interactive (list (jabber-read-jid-completing "Fetch whose vCard avatar: ")))
+ (jabber-send-iq who "get" '(vCard ((xmlns . "vcard-temp")))
+ #'jabber-vcard-avatars-vcard who
+ #'ignore nil))
+
+(add-hook 'jabber-post-connect-hook 'jabber-vcard-avatars-find-current)
+(defun jabber-vcard-avatars-find-current ()
+ "Request our own vCard, to find hash of avatar."
+ (when jabber-vcard-avatars-publish
+ (jabber-send-iq nil "get" '(vCard ((xmlns . "vcard-temp")))
+ #'jabber-vcard-avatars-find-current-1 t
+ #'jabber-vcard-avatars-find-current-1 nil)))
+
+(defun jabber-vcard-avatars-find-current-1 (xml-data success)
+ (jabber-vcard-avatars-update-current
+ (and success
+ (let ((photo (assq 'PHOTO (jabber-vcard-parse (jabber-iq-query xml-data)))))
+ (when photo
+ (let ((avatar (jabber-avatar-from-base64-string (nth 2 photo)
+ (nth 1 photo))))
+ (avatar-sha1-sum avatar)))))))
+
+(defun jabber-vcard-avatars-update-current (new-hash)
+ (let ((old-hash jabber-vcard-avatars-current-hash))
+ (when (not (string= old-hash new-hash))
+ (setq jabber-vcard-avatars-current-hash new-hash)
+ (jabber-vcard-avatars-send-presence))))
+
+(defun jabber-vcard-avatars-send-presence ()
+ (jabber-send-presence *jabber-current-show* *jabber-current-status* *jabber-current-priority*))
+
+(add-to-list 'jabber-presence-element-functions 'jabber-vcard-avatars-presence-element)
+(defun jabber-vcard-avatars-presence-element ()
+ (when jabber-vcard-avatars-publish
+ (list
+ `(x ((xmlns . "vcard-temp:x:update"))
+ ;; if "not yet ready to advertise image", don't.
+ ;; that is, we haven't yet checked what avatar we have.
+ ,(when jabber-vcard-avatars-current-hash
+ `(photo () ,jabber-vcard-avatars-current-hash))))))
+
+(provide 'jabber-vcard-avatars)
+;; arch-tag: 3e50d460-8eae-11da-826c-000a95c2fcd0
diff --git a/jabber-vcard.el b/jabber-vcard.el
index 42cd1d7..7386183 100644
--- a/jabber-vcard.el
+++ b/jabber-vcard.el
@@ -28,7 +28,7 @@
;; closely.
;; Fields not implemented: GEO, LOGO, AGENT, ORG, CATEGORIES, SOUND,
-;; CLASS, KEY, PHOTO.
+;; CLASS, KEY.
;; The internal data structure used for vCards is an alist. All
;; keys are uppercase symbols.
@@ -66,6 +66,11 @@
(require 'jabber-core)
(require 'jabber-widget)
(require 'jabber-iq)
+(require 'jabber-avatar)
+
+(defvar jabber-vcard-photo nil
+ "The avatar structure for the photo in the vCard edit buffer.")
+(make-variable-buffer-local 'jabber-vcard-photo)
(defun jabber-vcard-parse (vcard)
"Parse the vCard XML structure given in VCARD.
@@ -165,15 +170,42 @@ The top node should be the `vCard' node."
(memq 'X400 types))
(push 'INTERNET types))
- (push (cons types userid) e-mails))))
+ (push (cons types userid) e-mails))))
(when e-mails
(push (cons 'EMAIL e-mails) result)))
+ ;; JEP-0153: vCard-based avatars
+ (let ((photo-tag (car (jabber-xml-get-children vcard 'PHOTO))))
+ (when photo-tag
+ (let ((type (jabber-xml-path photo-tag '(TYPE "")))
+ (binval (jabber-xml-path photo-tag '(BINVAL ""))))
+ (when (and type binval)
+ (push (list 'PHOTO type binval) result)))))
+
result))
(defun jabber-vcard-reassemble (parsed)
"Create a vCard XML structure from PARSED."
+ ;; Save photo in jabber-vcard-photo, to avoid excessive processing.
+ (let ((photo (cdr (assq 'PHOTO parsed))))
+ (cond
+ ;; No photo
+ ((null photo)
+ (setq jabber-vcard-photo nil))
+ ;; Existing photo
+ ((listp photo)
+ (setq jabber-vcard-photo
+ (jabber-avatar-from-base64-string
+ (nth 1 photo) (nth 0 photo))))
+ ;; New photo from file
+ (t
+ (access-file photo "Avatar file not found")
+ ;; Maximum allowed size is 8 kilobytes
+ (when (> (nth 7 (file-attributes photo)) 8192)
+ (error "Avatar bigger than 8 kilobytes"))
+ (setq jabber-vcard-photo (jabber-avatar-from-file photo)))))
+
`(vCard ((xmlns . "vcard-temp"))
;; Put in simple fields
,@(mapcar
@@ -211,14 +243,19 @@ The top node should be the `vCard' node."
(append '(EMAIL) '(())
(mapcar 'list (car email))
(list (list 'USERID nil (cdr email)))))
- (cdr (assq 'EMAIL parsed)))))
+ (cdr (assq 'EMAIL parsed)))
+ ;; Put in photo
+ ,@(when jabber-vcard-photo
+ `((PHOTO ()
+ (TYPE () ,(avatar-mime-type jabber-vcard-photo))
+ (BINVAL () ,(avatar-base64-data jabber-vcard-photo)))))))
(add-to-list 'jabber-jid-info-menu
(cons "Request vcard" 'jabber-vcard-get))
(defun jabber-vcard-get (jid)
"Request vcard from JID."
- (interactive (list (jabber-read-jid-completing "Request vcard from: ")))
+ (interactive (list (jabber-read-jid-completing "Request vcard from: " nil nil nil 'bare-or-muc)))
(jabber-send-iq jid
"get"
'(vCard ((xmlns . "vcard-temp")))
@@ -350,13 +387,27 @@ The top node should be the `vCard' node."
(when field
(insert (cdr address-field))
(indent-to 20)
- (insert (cdr field) "\n")))))))))
+ (insert (cdr field) "\n")))))))
+
+ ;; JEP-0153: vCard-based avatars
+ (let ((photo-type (nth 1 (assq 'PHOTO parsed)))
+ (photo-binval (nth 2 (assq 'PHOTO parsed))))
+ (when (and photo-type photo-binval)
+ (condition-case nil
+ ;; ignore the type, let create-image figure it out.
+ (let ((image (create-image (base64-decode-string photo-binval) nil t)))
+ (insert-image image "[Photo]")
+ (insert "\n"))
+ (error (insert "Couldn't display photo\n")))))))
(defun jabber-vcard-do-edit (xml-data closure-data)
- (let ((parsed (jabber-vcard-parse (jabber-iq-query xml-data))))
+ (let ((parsed (jabber-vcard-parse (jabber-iq-query xml-data)))
+ start-position)
(with-current-buffer (get-buffer-create "Edit vcard")
(jabber-init-widget-buffer nil)
+ (setq start-position (point))
+
(dolist (simple-field jabber-vcard-fields)
(widget-insert (cdr simple-field))
(indent-to 15)
@@ -448,21 +499,48 @@ The top node should be the `vCard' node."
jabber-widget-alist)
(widget-insert "\n")
+ (widget-insert "Photo/avatar:\n")
+ (let* ((photo (assq 'PHOTO parsed))
+ (avatar (when photo
+ (jabber-avatar-from-base64-string (nth 2 photo)
+ (nth 1 photo)))))
+ (push (cons
+ 'PHOTO
+ (widget-create
+ `(radio-button-choice (const :tag "None" nil)
+ ,@(when photo
+ (list
+ `(const :tag
+ ,(concat
+ "Existing: "
+ (jabber-propertize " "
+ 'display (jabber-avatar-image avatar)))
+ ,(cdr photo))))
+ (file :must-match t :tag "From file"))
+ :value (cdr photo)))
+ jabber-widget-alist))
+
+ (widget-insert "\n")
(widget-create 'push-button :notify #'jabber-vcard-submit "Submit")
(widget-setup)
(widget-minor-mode 1)
- (switch-to-buffer (current-buffer)))))
+ (switch-to-buffer (current-buffer))
+ (goto-char start-position))))
(defun jabber-vcard-submit (&rest ignore)
- (jabber-send-iq nil
- "set"
- (jabber-vcard-reassemble
- (mapcar (lambda (entry)
- (cons (car entry) (widget-value (cdr entry))))
- jabber-widget-alist))
- #'jabber-report-success "Changing vCard"
- #'jabber-report-success "Changing vCard"))
+ (let ((to-publish (jabber-vcard-reassemble
+ (mapcar (lambda (entry)
+ (cons (car entry) (widget-value (cdr entry))))
+ jabber-widget-alist))))
+ (jabber-send-iq nil
+ "set"
+ to-publish
+ #'jabber-report-success "Changing vCard"
+ #'jabber-report-success "Changing vCard")
+ (when (bound-and-true-p jabber-vcard-avatars-publish)
+ (jabber-vcard-avatars-update-current
+ (and jabber-vcard-photo (avatar-sha1-sum jabber-vcard-photo))))))
(provide 'jabber-vcard)
;; arch-tag: 65B95E9C-63BD-11D9-94A9-000A95C2FCD0
diff --git a/jabber-version.el b/jabber-version.el
index c59ca9f..8846ff0 100644
--- a/jabber-version.el
+++ b/jabber-version.el
@@ -22,14 +22,14 @@
(require 'jabber-iq)
(require 'jabber-util)
-(defconst jabber-version "0.6.1pre"
+(defconst jabber-version "0.7.1"
"version returned to those who query us")
(add-to-list 'jabber-jid-info-menu
(cons "Request software version" 'jabber-get-version))
(defun jabber-get-version (to)
"Request software version"
- (interactive (list (jabber-read-jid-completing "Request version of: ")))
+ (interactive (list (jabber-read-jid-completing "Request version of: " nil nil nil 'full)))
;; XXX: you will not get any result unless you add the resource to the JID.
(jabber-send-iq to
"get"
@@ -63,7 +63,7 @@ determined from the incoming packet passed in XML-DATA."
(version () ,jabber-version)
;; Booting... /vmemacs.el
;; Shamelessly stolen from someone's sig.
- (os () ,(jabber-escape-xml (emacs-version))))
+ (os () ,(emacs-version)))
nil nil nil nil
id)))
diff --git a/jabber-watch.el b/jabber-watch.el
index ccf14d0..dfaf991 100644
--- a/jabber-watch.el
+++ b/jabber-watch.el
@@ -21,9 +21,13 @@
(require 'jabber-util)
-(defvar jabber-watch-alist nil
+(defcustom jabber-watch-alist nil
"Alist of buddies for which an extra notification should be sent
-when they come online, with comment strings as values.")
+when they come online, with comment strings as values."
+ ;; XXX: change symbol to jid-symbol or something, and update
+ ;; documentation
+ :type '(alist :key-type symbol :value-type string)
+ :group 'jabber-watch)
(defun jabber-presence-watch (who oldstatus newstatus
statustext proposed-alert)
diff --git a/jabber-widget.el b/jabber-widget.el
index 8a58c26..d706339 100644
--- a/jabber-widget.el
+++ b/jabber-widget.el
@@ -37,6 +37,47 @@
(add-to-list 'jabber-advertised-features "jabber:x:data")
+(define-widget 'jid 'string
+ "JID widget."
+ :value-to-internal (lambda (widget value)
+ (let ((displayname (jabber-jid-rostername value)))
+ (if displayname
+ (format "%s <%s>" displayname value)
+ value)))
+ :value-to-external (lambda (widget value)
+ (if (string-match "<\\([^>]+\\)>[ \t]*$" value)
+ (match-string 1 value)
+ value))
+ :complete-function 'jid-complete)
+
+(defun jid-complete ()
+ "Perform completion on JID preceding point."
+ (interactive)
+ ;; mostly stolen from widget-color-complete
+ (let* ((prefix (buffer-substring-no-properties (widget-field-start widget)
+ (point)))
+ (list (append (mapcar #'symbol-name *jabber-roster*)
+ (delq nil
+ (mapcar #'(lambda (item)
+ (when (jabber-jid-rostername item)
+ (format "%s <%s>" (jabber-jid-rostername item)
+ (symbol-name item))))
+ *jabber-roster*))))
+ (completion (try-completion prefix list)))
+ (cond ((eq completion t)
+ (message "Exact match."))
+ ((null completion)
+ (error "Can't find completion for \"%s\"" prefix))
+ ((not (string-equal prefix completion))
+ (insert-and-inherit (substring completion (length prefix))))
+ (t
+ (message "Making completion list...")
+ (with-output-to-temp-buffer "*Completions*"
+ (display-completion-list (all-completions prefix list nil)
+ prefix))
+ (message "Making completion list...done")))))
+
+
(defun jabber-init-widget-buffer (submit-to)
"Setup buffer-local variables for widgets."
(make-local-variable 'jabber-widget-alist)
diff --git a/jabber-xml.el b/jabber-xml.el
index f782133..a81df65 100644
--- a/jabber-xml.el
+++ b/jabber-xml.el
@@ -58,7 +58,7 @@
"converts an SEXP in the format (tagname ((attribute-name . attribute-value)...) children...) and converts it to well-formatted xml."
(cond
((stringp sexp)
- sexp)
+ (jabber-escape-xml sexp))
((listp (car sexp))
(let ((xml ""))
(dolist (tag sexp)
@@ -79,7 +79,7 @@
(setq xml (concat xml
(format " %s='%s'"
(symbol-name (car attr))
- (cdr attr))))))
+ (jabber-escape-xml (cdr attr)))))))
(if (cddr sexp)
(progn
(setq xml (concat xml ">"))
@@ -153,13 +153,17 @@ CHILD-NAME should be a lower case symbol."
;; `xml-get-attribute' returns "" if the attribute is not found, which
;; is not very useful. Therefore, we use `xml-get-attribute-or-nil'
;; if present, or emulate its behavior.
-(if (fboundp 'xml-get-attribute-or-nil)
- (defalias 'jabber-xml-get-attribute 'xml-get-attribute-or-nil)
- (defsubst jabber-xml-get-attribute (node attribute)
- "Get from NODE the value of ATTRIBUTE.
+(eval-and-compile
+ (if (fboundp 'xml-get-attribute-or-nil)
+ (defsubst jabber-xml-get-attribute (node attribute)
+ "Get from NODE the value of ATTRIBUTE.
Return nil if the attribute was not found."
- (let ((result (xml-get-attribute node attribute)))
- (and (> (length result) 0) result))))
+ (xml-get-attribute-or-nil node attribute))
+ (defsubst jabber-xml-get-attribute (node attribute)
+ "Get from NODE the value of ATTRIBUTE.
+Return nil if the attribute was not found."
+ (let ((result (xml-get-attribute node attribute)))
+ (and (> (length result) 0) result)))))
(defun jabber-xml-path (xml-data path)
"Find sub-node of XML-DATA according to PATH.
diff --git a/jabber.el b/jabber.el
index 9dc1066..3ab9387 100644
--- a/jabber.el
+++ b/jabber.el
@@ -101,6 +101,13 @@
(require 'jabber-activity)
(require 'jabber-vcard)
(require 'jabber-events)
+(require 'jabber-vcard-avatars)
+(require 'jabber-autoaway)
+(require 'jabber-time)
+
+(require 'jabber-ft-client)
+(require 'jabber-ft-server)
+(require 'jabber-socks5)
;; XXX: automate this some time
(autoload 'jabber-export-roster "jabber-export"
@@ -109,6 +116,21 @@
(autoload 'jabber-import-roster "jabber-export"
"Create buffer for roster import from FILE."
t)
+(autoload 'jabber-compose "jabber-compose"
+ "Create a buffer for composing a Jabber message."
+ t)
+(autoload 'jabber-private-get "jabber-private"
+ "Retrieve an item from private XML storage.
+The item to retrieve is identified by NODE-NAME (a symbol) and
+NAMESPACE (a string).
+On success, SUCCESS-CALLBACK is called with the retrieved XML fragment.
+On error, ERROR-CALLBACK is called with the entire IQ result."
+ nil)
+(autoload 'jabber-private-set "jabber-private"
+ "Store FRAGMENT in private XML storage.
+SUCCESS-CALLBACK, SUCCESS-CLOSURE-DATA, ERROR-CALLBACK and
+ERROR-CLOSURE-DATA are used as in `jabber-send-iq'."
+ nil)
(defvar *jabber-current-status* ""
"the users current presence staus")
diff --git a/jabber.info b/jabber.info
new file mode 100644
index 0000000..c219b2b
--- /dev/null
+++ b/jabber.info
@@ -0,0 +1,2539 @@
+This is jabber.info, produced by makeinfo version 4.7 from jabber.texi.
+
+INFO-DIR-SECTION Emacs
+START-INFO-DIR-ENTRY
+* jabber.el: (jabber). Emacs Jabber client
+END-INFO-DIR-ENTRY
+
+ This manual is for jabber.el, version 0.7.1.
+
+ Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+
+
+File: jabber.info, Node: Top, Next: Introduction, Prev: (dir), Up: (dir)
+
+jabber.el manual
+****************
+
+This manual is for jabber.el, version 0.7.1.
+
+ Copyright (C) 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
+
+ Permission is granted to make and distribute verbatim copies or
+ modified versions of this manual, provided the copyright notice and
+ this permission notice are preserved on all copies.
+
+* Menu:
+
+* Introduction::
+* Basic operation::
+* Groupchat::
+* Composing messages::
+* File transfer::
+* Services::
+* Personal information::
+* Avatars::
+* Time queries::
+* Useful features::
+* Message history::
+* Message events::
+* Roster import and export::
+* XMPP URIs::
+* Customization::
+* Hacking and extending::
+* Protocol support::
+* Concept index::
+* Function index::
+* Variable index::
+
+
+File: jabber.info, Node: Introduction, Next: Basic operation, Prev: Top, Up: Top
+
+1 Introduction
+**************
+
+jabber.el is a Jabber client running under Emacs. For more information
+on the open-protocol instant messaging network Jabber, please visit
+`http://www.jabber.org'.
+
+ As a Jabber client, jabber.el is mostly just a face in the crowd,
+except that it uses buffers where GUI clients have windows. There is a
+roster buffer, and to chat with someone you open a chat buffer, and
+there are browse buffers (increasingly inexactly named) for interaction
+with servers and services. Then again, jabber.el delivers excellent
+console performance and customizable hooks (if you have speech
+synthesizer software, hook it up to your presence alerts).
+
+ jabber.el does not yet support GPG, sending and receiving roster
+items, and various other things.
+
+* Menu:
+
+* Contact::
+
+
+File: jabber.info, Node: Contact, Prev: Introduction, Up: Introduction
+
+1.1 Contact
+===========
+
+jabber.el is developed by Tom Berger (e-mail
+<object@intellectronica.net>, JID `object@jabber.org.uk') and Magnus
+Henoch (e-mail <mange@freemail.hu>, JID
+`legoscia@jabber.cd.chalmers.se'). There is a web page at
+`http://intellectronica.net/emacs-jabber/', and a Sourceforge project
+page at `http://sourceforge.net/projects/emacs-jabber'.
+
+
+File: jabber.info, Node: Basic operation, Next: Groupchat, Prev: Introduction, Up: Top
+
+2 Basic operation
+*****************
+
+This chapter is intended as an introduction to basic usage of
+jabber.el. If you have used Jabber before and are familiar with the
+terminology, you might find it a bit too basic -- in that case, just
+skim it, making sure to pick up the commands mentioned.
+
+ There are a handful of global keybindings for common commands. They
+start with `C-x C-j', and you can get a list of them by typing `C-x C-j
+C-h'.
+
+* Menu:
+
+* Connecting::
+* Chatting::
+* Presence::
+* Presence subscription::
+* Roster buffer::
+
+
+File: jabber.info, Node: Connecting, Next: Chatting, Prev: Basic operation, Up: Basic operation
+
+2.1 Connecting
+==============
+
+I'll assume that you have already successfully installed jabber.el; if
+not, consult the `README' file. Also, make sure you have `(require
+'jabber)' in your `.emacs'.
+
+ Now, type `M-x jabber-customize'. This brings up a customize buffer
+for jabber.el. The most important variables to customize are
+`jabber-username' and `jabber-server'.(1) Save your changes, and type
+`M-x jabber-connect' to connect.
+
+ If you do not yet have a Jabber account, you can register one. Enter
+your desired username for `jabber-username' and the server you wish to
+use for `jabber-server', save, and type `C-u M-x jabber-connect' or
+`C-u C-x C-j C-c'. If the server supports in-band registration, you
+will be presented with a registration form to fill out and send. There
+the username you chose will be prefilled. Don't change it, otherwise
+jabber.el will be confused.
+
+ If you successfully connect, jabber.el will download your roster and
+display it in a buffer called `*-jabber-*'.
+
+ By default, you will appear as "online" to your contacts. To change
+this to e.g. "away", type `M-x jabber-send-presence' or `C-x C-j C-p'.
+*Note Presence::, for more information.
+
+ To disconnect, type `M-x jabber-disconnect' or `C-x C-j C-d'.
+
+ ---------- Footnotes ----------
+
+ (1) *Note Connection settings::, for other things you might have to
+change.
+
+
+File: jabber.info, Node: Chatting, Next: Presence, Prev: Connecting, Up: Basic operation
+
+2.2 Chatting
+============
+
+There are several ways to open a chat buffer. The shortest way is to
+put point over the person you want to chat with in the roster display
+and hit RET.
+
+ You can also use menus to access commands. In the roster display,
+you can access several menus through keystrokes or mouse clicks. You
+can bring one big menu up by pressing the second mouse button, or you
+can bring up the "chat menu" by typing `C-c C-c'. If you do the latter
+while point is on a roster entry, that entry will be the default value
+when you are asked for whom to chat with.
+
+ You can also use the function `jabber-chat-with', which is what the
+menu item is bound to. This function is bound to `C-x C-j C-j' in the
+global keymap.
+
+ Now, try opening a chat with someone. A buffer named
+`*-jabber-chat-:-PERSON-*' will be created and selected. Type your
+message at the end of the buffer, and hit `RET' to send it. To include
+a newline in your message, use `C-j'.
+
+
+File: jabber.info, Node: Presence, Next: Presence subscription, Prev: Chatting, Up: Basic operation
+
+2.3 Presence
+============
+
+"Presence" is the Jabber term for letting other people know that you
+are online, and additionally how "available" you are. There are three
+elements to presence: availability status (called "show"), status
+message, and priority.
+
+ Your show status may either be empty (meaning simply "online"), or
+one of `away', `xa', `dnd' and `chat', meaning "away", "extended away"
+(i.e. away for an extended period), "do not disturb", and "free for
+chat", respectively. This information is available to everyone
+subscribing to your presence, but technically it does not restrict
+anyone's actions. You can chat with people even if you claim to be
+away.
+
+ The status message is a short text complementing your show status,
+such as "at home", "working", "phone", "playing games" or whatever you
+want. It is sent to everyone subscribing to your presence, but not all
+clients prominently display it to the user.
+
+ The priority is only interesting if you are running more than one
+Jabber client at a time accessing the same account. In that case,
+messages sent to you without an indication of which client to send to
+are sent to the client with the highest priority.
+
+ To set your presence, use the function `jabber-send-presence'. It
+can be called both interactively and in Lisp code. For the latter
+case, use something like `(jabber-send-presence "away" "idle for 10
+minutes" 10)'.
+
+ By default, jabber.el sets your presence when you connect. If you
+want it not to do that, remove `jabber-send-default-presence' from
+`jabber-post-connect-hook'. If you want to change the presence that is
+sent, change the variables `jabber-default-show',
+`jabber-default-status' and `jabber-default-priority'.
+
+ With jabber.el, you can set your presence remotely. *Note Ad-Hoc
+Commands::.
+
+ You can send "directed presence" with `M-x
+jabber-send-directed-presence'. This is mostly useful to manage
+transports--sending directed presence is a way to turn them on and off.
+You can also send directed presence to an annoying contact to appear
+as away or offline to that contact. Note, however, that in both of
+these cases, all subscribed entities will get your next global presence
+update.
+
+
+File: jabber.info, Node: Presence subscription, Next: Roster buffer, Prev: Presence, Up: Basic operation
+
+2.4 Presence subscription
+=========================
+
+Having permission to view the presence status of a person is called
+"subscribing to his presence". Presence subscription between two
+persons can be asymmetric.
+
+ When jabber.el receives a presence subscription request, it will
+present it to you in an alert requiring immediate response, and offer
+you to send a subscription request back to that person.
+
+ To request subscription to someone, type `M-x
+jabber-send-subscription-request'. You will be prompted for the JID to
+send it to. This command can also be accessed through the Roster menu,
+by typing `C-c C-r' in the roster buffer. After that, you will
+probably want to give the contact a more readable name. The command
+for that is `jabber-roster-change', which is also available in the
+Roster menu or by typing `e' on a person in the roster buffer.
+
+
+File: jabber.info, Node: Roster buffer, Prev: Presence subscription, Up: Basic operation
+
+2.5 The roster buffer
+=====================
+
+The roster buffer is called `*-jabber-*'. It simply contains a list of
+the contacts on your roster.
+
+ In the roster buffer, any command which requires a JID will default
+to the JID under point when called. These commands can be called
+through either keyboard menus or mouse menus. To open a menu with the
+mouse, simply press the second mouse button over the JID in
+question.(1) This will bring up a menu with all available actions.
+The keyboard menus are split into categories: Chat, Roster,
+Information, MUC (Multi-User Chat, or groupchat) and Services, opened
+by `C-c C-c', `C-c C-r', `C-c C-i', `C-c C-m' and `C-c C-s',
+respectively.
+
+ A list of keybindings is displayed at the top of the roster buffer.
+You can turn it off by setting `jabber-roster-show-bindings' to nil.
+
+ You can call `jabber-display-roster' to redisplay your roster
+according to changed preferences (*note Customizing the roster
+buffer::). This will not refetch your roster from the server.
+Refetching the roster is usually not needed, since updates are pushed
+to clients automatically.
+
+ You can choose not to have the roster updated automatically on
+presence changes (*note Presence alerts::). In that case, you need to
+call `jabber-display-roster' manually.
+
+ ---------- Footnotes ----------
+
+ (1) For some reason, mouse menus don't work in XEmacs. Patches
+welcome.
+
+
+File: jabber.info, Node: Groupchat, Next: Composing messages, Prev: Basic operation, Up: Top
+
+3 Groupchat
+***********
+
+The groupchat menu can be accessed by typing `C-c C-m' in the roster
+buffer. You can also type the commands directly, as will be shown here.
+
+ To join a groupchat, type `M-x jabber-groupchat-join'. You will be
+prompted for the groupchat to join, and your nickname in the groupchat.
+This nickname doesn't need to have any correlation to your JID; in
+fact, groupchats are usually (but not always) configured such that only
+moderators can see your JID. You can change your nickname with `M-x
+jabber-muc-nick'. *Note Automation::, for setting default nicknames.
+
+ When trying to join a room, jabber.el first sends a service discovery
+info request to the room, to find out whether it exists and what
+features are enabled (in particular whether the room is
+password-protected). However, this can cause problems with some buggy
+MUC services (or services that respond in a way that jabber.el doesn't
+expect). A workaround for that is to set
+`jabber-muc-disable-disco-check' to t; however, the bug should be
+unearthed and fixed.
+
+ Groupchat messages will be displayed in a buffer called
+`*-jabber-groupchat-:-GROUPCHAT-*'. It works much like the chat buffer.
+
+ To change the topic of a groupchat, type `M-x jabber-muc-set-topic'.
+The current topic is shown in the header line.
+
+ To leave a groupchat, type `M-x jabber-groupchat-leave'.
+
+ If you are the owner of a groupchat, you can change its configuration
+by typing `M-x jabber-groupchat-get-config'. A configuration form will
+be rendered in new buffer.
+
+ To see which people are in a groupchat, type `M-x jabber-muc-names'.
+This gives a list of nicknames, "roles", "affiliations", and possibly
+JIDs. *Note MUC Administration::, for the meaning of roles and
+affiliations.
+
+* Menu:
+
+* Automation::
+* Invitations::
+* Private messages::
+* MUC Administration::
+
+
+File: jabber.info, Node: Automation, Next: Invitations, Prev: Groupchat, Up: Groupchat
+
+3.1 Automation
+==============
+
+You can select a default nickname by setting `jabber-nickname'.
+Additionally, you can set different nicknames for different groups, by
+customizing `jabber-muc-default-nicknames'. There you specify the JID
+of the group, and your preferred nickname.
+
+ If you want to automatically join certain rooms when connecting, you
+can set `jabber-muc-autojoin' to a list containing the JIDs of the
+rooms you want to enter. To disable this feature, remove
+`jabber-muc-autojoin' from `jabber-post-connect-hook'.
+
+
+File: jabber.info, Node: Invitations, Next: Private messages, Prev: Automation, Up: Groupchat
+
+3.2 Invitations
+===============
+
+You can invite someone to a groupchat with `M-x jabber-muc-invite'
+(also available in the MUC menu). Pay attention to the order of the
+arguments -- as both users and rooms are just JIDs, it is technically
+possible to invite a room to a user, but that's probably not what you
+want.
+
+ When you receive an invitation, it appears in the chat buffer along
+with two buttons, "Accept" and "Decline". Pressing "Accept" enters the
+room, as you would expect. Pressing "Decline" gives you an opportunity
+to state the reason why you're not joining.
+
+
+File: jabber.info, Node: Private messages, Next: MUC Administration, Prev: Invitations, Up: Groupchat
+
+3.3 Private messages
+====================
+
+You can open a private chat with a participant in a chat room with `M-x
+jabber-muc-private' (or by using the MUC menu). This creates a buffer
+with the name `*-jabber-muc-priv-GROUP-NICKNAME-*' (customizable by
+`jabber-muc-private-buffer-format'), which behaves mostly like an
+ordinary chat buffer. This buffer will also be created if someone
+sends a private message to you.
+
+ Private MUC messages use the same alerts as normal chat messages.
+*Note Message alerts::.
+
+
+File: jabber.info, Node: MUC Administration, Prev: Private messages, Up: Groupchat
+
+3.4 Administration
+==================
+
+Administration of a MUC room mostly consists of managing roles and
+affiliations. Roles are temporary, and apply until the user leaves the
+room. Affiliations are permanent, and based on JIDs.
+
+3.4.1 Roles
+-----------
+
+If you have moderator privileges, you can change the role of a
+participant with `M-x jabber-muc-set-role'. Kicking means setting the
+role to "none". Granting and revoking voice are "participant" and
+"visitor", respectively. "moderator" gives moderator privileges,
+obviously.
+
+ The possible roles are:
+
+`moderator'
+ Has voice, can change other people's roles.
+
+`participant'
+ Has voice.
+
+`visitor'
+ Doesn't have voice (can't send messages to everyone, but can send
+ private messages)
+
+`none'
+ Not in room.
+
+3.4.2 Affiliations
+------------------
+
+If you have admin or owner privileges, you can change the affiliation of
+a user with `M-x jabber-muc-set-affiliation'. Affiliation is
+persistent, and based on JIDs. Depending of your affiliation and the
+MUC implementation, you might not be allowed to perform all kinds of
+changes, and maybe not in one step.
+
+ Affiliations are:
+
+`owner'
+ Can destroy room, appoint admins, make people members, ban people.
+
+`admin'
+ Can make people members or ban people.
+
+`member'
+ Can enter the room, and has voice by default.
+
+`none'
+ Rights depend on room configuration. The room might be
+ members-only, or grant voice only to members.
+
+`outcast'
+ Banned from the room
+
+
+File: jabber.info, Node: Composing messages, Next: File transfer, Prev: Groupchat, Up: Top
+
+4 Composing messages
+********************
+
+The chat buffer interface can be inconvenient for some purposes. As you
+can't use `RET' to insert a newline (use `C-j' for that), writing a
+longer message can be painful. Also, it is not possible to include a
+subject in the message, or send the message to multiple recipients.
+
+ These features are implemented by the message composing tool. Type
+`M-x jabber-compose' to start it. In the buffer that comes up, you can
+specify recipients, enter a subject, and type your message.
+
+
+File: jabber.info, Node: File transfer, Next: Services, Prev: Composing messages, Up: Top
+
+5 File transfer
+***************
+
+jabber.el has limited support for file transfer. The most important
+limit is that files sent and received are kept in buffers, so Emacs must
+be able to allocate enough memory for the entire file, and the file size
+must be smaller than the maximum buffer size.(1)
+
+ jabber.el is able to exchange files with most Jabber clients (and
+also some MSN transports), but notably not with the official Google Talk
+client. The Google Talk client uses a different file transfer protocol
+that, at the time of this release, has not been published.
+
+* Menu:
+
+* Receiving files::
+* Sending files::
+
+ ---------- Footnotes ----------
+
+ (1) The maximum buffer size is kept in the variable
+`most-positive-fixnum'. On most 32-bit systems, this is 128 or 256
+megabytes, depending on your Emacs version.
+
+
+File: jabber.info, Node: Receiving files, Next: Sending files, Prev: File transfer, Up: File transfer
+
+5.1 Receiving files
+===================
+
+Receiving files requires no configuration. When someone wants to send a
+file to you, you are asked (through `yes-or-no-p') whether you want to
+accept the file. If you answer yes, you get to choose where to save
+the file.
+
+ If the sender's client is correctly configured (this is often not the
+case; see below), the file transfer will start. Currently, the only way
+to watch the progress is to inspect the buffer of the file being
+transfered; `C-x C-b' is one way of doing that. *Note Listing Existing
+Buffers: (emacs)List Buffers. When the transfer is done, the message
+"FILE downloaded" appears in the echo area, and the buffer is killed.
+
+ If this doesn't happen, it is most likely the sender's fault. The
+sender needs to have a public IP address, either directly, through port
+forwarding (in which case the client needs to be configured with the
+real public IP address), or through an XEP-0065 proxy. If you have
+activated XML logging (*note Debug options::), you can see the IP
+address that the other client is asking you to connect to there. Often
+you will find that this is an internal IP address (often starts with
+`192.168'). See the documentation of the sender's client for setting
+this up.
+
+
+File: jabber.info, Node: Sending files, Prev: Receiving files, Up: File transfer
+
+5.2 Sending files
+=================
+
+To send a file to someone, you need an XEP-0065 proxy.(1) If your
+Jabber server hosts such a proxy, it will be found automatically,
+otherwise it needs to be manually configured.
+
+ You can check whether your Jabber server has a proxy with `M-x
+jabber-get-disco-items'; see *Note Service discovery and browsing::.
+
+ To configure a proxy manually, customize the variable
+`jabber-socks5-proxies'. Putting `proxy.jabber.se' there should work.
+Type `M-x jabber-socks5-query-all-proxies' to see if the proxies answer.
+
+ Now, you can type `M-x jabber-ft-send' to send a file to someone.
+You need to enter the correct full JID, including resource, to get this
+right. If the contact is logged in with only one client, and you can
+see it online, just typing the JID or roster name is enough. If you run
+the command from a chat buffer, the JID of the contact is given as the
+default value.
+
+ If the contact has several clients online, you probably want to send
+the file to a particular one. If you run this command from within a
+chat buffer, the default target will be the one that last sent a
+message to you. If you just type a bare JID or a roster name, the
+client with the highest priority will get the file.
+
+ If the contact accepts the file, and the contact's client succeeds in
+connecting to the proxy, jabber.el will send the file through the
+proxy. During this time, your Emacs will be blocked, so you might want
+to avoid sending large files over slow connections.
+
+ ---------- Footnotes ----------
+
+ (1) This requirement is not inherent in the protocol, only in the
+current file transfer implementation of jabber.el, and in Emacs
+versions earlier than 22.
+
+
+File: jabber.info, Node: Services, Next: Personal information, Prev: File transfer, Up: Top
+
+6 Services
+**********
+
+Not every Jabber entity is a physical person. There are many automatic
+entities, called servers, services, components, agents, transports and
+other names. The use of these is described here.
+
+ The functions described in this chapter use "browse buffers".
+Browse buffers are named `*-jabber-browse-:-SERVICE-*', sometimes with
+a numerical suffix. The different menus have the same keybindings as
+in the roster buffer, and if you call a function operating on a JID
+while point is over a JID, that JID will be the default value, so you
+don't have to type it or copy it yourself.
+
+* Menu:
+
+* Service discovery and browsing::
+* Registering::
+* Searching::
+* Ad-Hoc Commands::
+
+
+File: jabber.info, Node: Service discovery and browsing, Next: Registering, Prev: Services, Up: Services
+
+6.1 Service discovery and browsing
+==================================
+
+To find services you want to use, you need to discover them first.
+This can be done with either service discovery or browsing. Service
+discovery is the newer and preferred protocol, while browsing is still
+used by much software. The use of both is very similar.
+
+ The most common use of service discovery is to browse your home
+server, to see what services are provided locally. Note, however, that
+this is no restriction; you can use services from all over the network.
+
+ For service discovery there are two commands,
+`jabber-get-disco-items' and `jabber-get-disco-info', depending on
+whether you want information about that specific JID or about services
+related to it, respectively. To start browsing, type `M-x
+jabber-get-browse' and enter the JID you want to browse.
+
+ These commands can be accessed from the Info menu, which is opened by
+typing `C-c C-i'.
+
+ If you think that the interface to service discovery is awkward and
+should be replaced with something better, you are completely right.
+
+
+File: jabber.info, Node: Registering, Next: Searching, Prev: Service discovery and browsing, Up: Services
+
+6.2 Registering
+===============
+
+Some services, in particular user directories and gateways to legacy IM
+systems, require registration. To register with such a service, either
+type `M-x jabber-get-register' or select it from the Service menu,
+which is opened by typing `C-c C-s'. You have to know the service's
+JID, possibly from service discovery. (*note Service discovery and
+browsing::)
+
+ This is also the way to change your registration details, e.g. your
+password -- just ask to register with that service again. To change
+the password of your Jabber account, ask to register with your Jabber
+server.
+
+ Please note that any passwords sent in this way will be sent in
+cleartext to your Jabber server, unless you have enabled SSL encryption
+(*note Connection settings::), and possibly sent in cleartext from your
+server to the server hosting the service.
+
+ jabber.el will then request a registration form from that service.
+If for some reason the service does not answer (maybe network problems,
+or some services neither support registration nor report errors about
+that) that will be the last thing you saw about it. jabber.el will not
+report timeout errors, but rather simply wait until you shut it down.
+
+ Once the response arrives, the form will be rendered in a browse
+buffer. Just fill out the fields, and hit Submit. You will receive
+confirmation of your registration in the echo area.
+
+ To cancel an existing registration (and also for cancelling your
+Jabber account, if you sent a registration request to your server), hit
+Cancel. The unregistration will be confirmed in the echo area.
+
+
+File: jabber.info, Node: Searching, Next: Ad-Hoc Commands, Prev: Registering, Up: Services
+
+6.3 Searching
+=============
+
+Some services, notably user directories and gateways to legacy IM
+systems, allow searching. Searching in Jabber generally means
+searching for someone's JID, but the protocol is general enough to
+support most databases.
+
+ To search a service, either type `M-x jabber-get-search' or select
+it from the Service menu, which is opened by typing `C-c C-s'.
+
+ Just like with registration, this command sends a request for a
+search form, and displays it if and when the response arrives. Enter
+your search and submit it. Search results will be displayed in a
+different browse buffer.
+
+
+File: jabber.info, Node: Ad-Hoc Commands, Prev: Searching, Up: Services
+
+6.4 Ad-Hoc Commands
+===================
+
+jabber.el supports a subset of XEP-0050, the standard for Ad-Hoc
+Commands. As the name implies, this can be used for just about
+anything. It has been used for remote-controlling clients (e.g. Psi),
+and administering services (e.g. PyMSNt).
+
+ Currently, jabber.el uses ad-hoc commands for setting presence
+remotely. If you realize that you forgot to set your client to "away"
+with a low priority, you can do it remotely.(1)
+
+ The commands for executing ad-hoc commands are available under the
+Service menu, which is opened by typing `C-c C-s'.
+
+ To find which commands are available, run "Request command-list"
+(`jabber-ahc-get-list').(2)
+
+ To run a command from the list, put point over it and run "Execute
+command" (`jabber-ahc-execute-command'), accepting the defaults for JID
+and node. (If you already know those, you could of course enter them
+yourself) The form you get should hopefully be self-explanatory.
+
+ ---------- Footnotes ----------
+
+ (1) Most Jabber servers also support kicking a client off the net by
+logging in with another client with exactly the same resource.
+
+ (2) This is the same thing as a disco items request to the node
+`http://jabber.org/protocol/commands'.
+
+
+File: jabber.info, Node: Personal information, Next: Avatars, Prev: Services, Up: Top
+
+7 Personal information
+**********************
+
+The Jabber way of handling personal information (name, addresses, phone
+numbers, etc) is "vCards" encoded in XML. You can get information
+about a user by running `M-x jabber-vcard-get', and you can edit your
+own information by running `M-x jabber-vcard-edit'.
+
+ The form for editing your information can be slightly confusing --
+you are allowed to enter any number of addresses, phone numbers and
+e-mail addresses, each of which has a set of orthogonal properties.
+You can add and remove items with the [INS] and [DEL] buttons,
+respectively.
+
+ This is also where you set your avatar (*note Avatars::). The size
+of your avatar file is limited to 8 kilobytes.
+
+
+File: jabber.info, Node: Avatars, Next: Time queries, Prev: Personal information, Up: Top
+
+8 Avatars
+*********
+
+jabber.el supports viewing and publishing avatars according to XEP-0153,
+vCard-Based Avatars. By default, if you have an avatar in your vCard
+(*note Personal information::), it will be published for others to see,
+and if other people publish their avatars, they will be displayed in the
+roster buffer and in the header line of chat buffers, assuming that your
+Emacs can display images.
+
+ To disable retrieval of other people's avatars, set
+`jabber-vcard-avatars-retrieve' to nil. To disable publishing of your
+own avatar, set `jabber-vcard-avatars-publish' to nil.
+
+ Avatars are cached in the directory specified by
+`jabber-avatar-cache-directory', by default `~/.jabber-avatars/'. The
+cache is never cleaned, so you might want to do that yourself from time
+to time.
+
+
+File: jabber.info, Node: Time queries, Next: Useful features, Prev: Avatars, Up: Top
+
+9 Time queries
+**************
+
+With `M-x jabber-get-time', you can ask what time an entity (client,
+server or component) thinks it is, and what time zone it thinks it is
+in.
+
+ You can query a server about when a certain user was last seen
+online. Use `M-x jabber-get-last-online' for that.
+
+ You can also ask a client about how long a user has been idle with
+`M-x jabber-get-idle-time'. Not all clients support this, e.g.
+jabber.el doesn't. This command can also tell the uptime of a server
+or component.
+
+
+File: jabber.info, Node: Useful features, Next: Message history, Prev: Time queries, Up: Top
+
+10 Useful features
+******************
+
+jabber.el includes a number of features meant to improve the user
+interface and do other useful things.
+
+* Menu:
+
+* Autoaway::
+* Modeline status::
+* Keepalive::
+* Tracking activity::
+* Watch buddies::
+* Spell checking::
+
+
+File: jabber.info, Node: Autoaway, Next: Modeline status, Prev: Useful features, Up: Useful features
+
+10.1 Autoaway
+=============
+
+It is possible to automatically set your status to "away" when you
+haven't used your computer for a while. This lets your contacts know
+that you might not answer immediately.
+
+ To activate this feature, add `jabber-autoaway-start' to
+`jabber-post-connect-hook', e.g:
+ (add-hook 'jabber-post-connect-hook 'jabber-autoaway-start)
+
+ There are different methods to find how long you have been "idle".
+The method to use is specified by `jabber-autoaway-method'. The value
+of this variable should be a function that returns the number of
+seconds you have been idle. Three functions are provided.
+
+ If you are running Emacs 22 and thus have the `current-idle-time'
+function, it is used by default. Note that this method only measures
+the time since you last interacted with Emacs, and thus disregards
+activity in other programs.
+
+ If you are using the X Window System, you can use the xprintidle
+(http://www.dtek.chalmers.se/~henoch/text/xprintidle.html) program.
+Make sure that `jabber-xprintidle-program' is set to the correct file
+name. This uses the same method as XScreensaver to find your idle time.
+
+ If you are using Emacs on a GNU/Linux terminal, the function
+`jabber-termatime-get-idle-time' is used by default.
+
+
+File: jabber.info, Node: Modeline status, Next: Keepalive, Prev: Autoaway, Up: Useful features
+
+10.2 Modeline status
+====================
+
+By typing `M-x jabber-mode-line-mode' you toggle display of some status
+in mode lines. The information is your own presence status, and some
+numbers showing the status of your roster contacts. By default, there
+are three numbers, for "online" (chatty and online), "away" (away,
+extended away and do not disturb) and offline contacts.
+
+ If you set `jabber-mode-line-compact' to nil, you get a complete
+breakdown of presence status. That gives you six numbers indicating
+the number of chatty, online, away, extended away, dnd, and offline
+contacts, respectively.
+
+
+File: jabber.info, Node: Keepalive, Next: Tracking activity, Prev: Modeline status, Up: Useful features
+
+10.3 Keepalive
+==============
+
+Sometimes network connections are lost without you noticing. This is
+especially true with Jabber, as it is quite reasonable to keep the
+connection open for a long time without either sending or receiving any
+data.
+
+ If you want to detect a lost connection earlier, you can use the
+keepalive functions. Type `M-x jabber-keepalive-start' to start it,
+and `M-x jabber-keepalive-stop' to stop it.
+
+ These functions work by asking your server for the time once in a
+while (by default every ten minutes), and considering the connection
+lost if the server doesn't answer within reasonable time (by default 20
+seconds).
+
+ You can customize the interval and the timeout with the variables
+`jabber-keepalive-interval' and `jabber-keepalive-timeout',
+respectively.
+
+
+File: jabber.info, Node: Tracking activity, Next: Watch buddies, Prev: Keepalive, Up: Useful features
+
+10.4 Tracking activity
+======================
+
+When you're working on something important you might want to delay
+responding to incoming messages. However, when you're done working,
+will you remember them? If you're anything like me, you'll have a lot
+of buffers in your Emacs session, and a jabber chat buffer can easily
+get lost.
+
+ When you type `M-x jabber-activity-mode' Emacs starts keeping track
+of the buddies which have messaged you since last you visited their
+buffer, and will display them in mode line. As soon as you visit their
+buffer they disappear from the mode line, indicating that you've read
+their message.
+
+ If your mode line fills over because of these notifications, you can
+customize `jabber-activity-make-strings' to shorten them to the
+shortest possibly unambiguous form.
+
+ If you try to exit Emacs while you still have unread messages, you
+will be notified and asked about this. If you don't like that, set
+`jabber-activity-query-unread' to nil.
+
+ If you want to display the number of unread buffers in the frame
+title, set `jabber-activity-count-in-title' to t. The format of the
+number can be changed through `jabber-activity-count-in-title-format'.
+
+ For complete customizability, write a hook function for
+`jabber-activity-update-hook'. From that function, you can take action
+based on `jabber-activity-jids', `jabber-activity-mode-string', and
+`jabber-activity-count-string'.
+
+
+File: jabber.info, Node: Watch buddies, Next: Spell checking, Prev: Tracking activity, Up: Useful features
+
+10.5 Watch buddies
+==================
+
+Sometimes you might be waiting for a certain person to come online, and
+you don't want that occasion to get lost in the noise. To get an
+obtrusive message when that happens, type `M-x jabber-watch-add' and
+select the person in question. You can enter a comment, to remember
+why you added the watch.
+
+ You will get a message whenever that person goes from offline to
+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 of
+it, type `M-x jabber-watch-remove'.
+
+
+File: jabber.info, Node: Spell checking, Prev: Watch buddies, Up: Useful features
+
+10.6 Spell checking
+===================
+
+You can activate spell checking in a chat buffer with `M-x
+flyspell-mode'. It will check only what you are currently writing, not
+what you receive or what you have already sent. You may want to add
+`flyspell-mode' to `jabber-chat-mode-hook'.
+
+ For more information about Emacs spell checking, *Note Checking and
+Correcting Spelling: (emacs)Spelling.
+
+
+File: jabber.info, Node: Message history, Next: Message events, Prev: Useful features, Up: Top
+
+11 Message history
+******************
+
+If you want a record of messages sent and received, set
+`jabber-history-enabled' to t. By default all messages to will be
+saved to a global history file specified by
+`jabber-global-history-filename' (`~/.jabber_global_message_log' by
+default). If you prefer to store your chats' history in per-contact
+files, you can set the `jabber-use-global-history' variable to `nil'.
+When using per-contact history, files are named by the contact JID and
+saved under the directory specified by the variable
+`jabber-history-dir' (default is `~/.emacs-jabber').
+
+ There is no facility for reading old messages yet, but just reading
+the file as text should be enough for many purposes.
+
+ When you open a new chat buffer and have entries in your history
+file, the last few messages you recently exchanged with the contact in
+question will be inserted. You can control how many messages with
+`jabber-backlog-number' (by default 10), and how old messages with
+`jabber-backlog-days' (by default 3 days).
+
+ If you worry about your history file(s) size, you can enable history
+rotation feature by setting the variable
+`jabber-history-enable-rotation' to `t' (default is `nil'). This
+feature "rotates" your history files according to the following rule:
+When `jabber-history-size-limit' (in kilobytes) is reached, the history
+file is renamed to <history-file>-<number>, where <number> is 1 or the
+smallest number after the last rotation. For example, suppose you set
+the `jabber-history-size-limit' variable to 512 and you chat with your
+buddy foo@jabber.server using the per-contact strategy to store history
+files. So, when the history file (`foo@jabber-server') reaches 512K
+bytes, it will be renamed to `foo@jabber-server-1' and
+`foo@jabber-server' will be set empty. Next time `foo@jabber-server'
+grows to 512K bytes, it will be saved as `foo@jabber-server-2' and so
+on. Although the example was presented with the per-contact history
+file strategy, history rotation works for both per-contact and global
+history logging strategies.
+
+
+File: jabber.info, Node: Message events, Next: Roster import and export, Prev: Message history, Up: Top
+
+12 Message events
+*****************
+
+In the status line of the chat buffer, you can sometimes see
+notifications about the progress of the message you just sent. These
+states are possible:
+
+ * Delivered to offline storage (the user will receive it on next
+ logon)
+
+ * Delivered to user's client (but not necessarily displayed)
+
+ * Displayed to user
+
+ * User is composing a reply
+
+
+ The first state is only reported by servers; the other three are
+reported by clients. jabber.el can report all three of them, and can
+display all four; not all clients support all states, though.
+
+ If you don't want jabber.el to send out this information about you,
+set the variables `jabber-events-confirm-delivered',
+`jabber-events-confirm-displayed', and/or
+`jabber-events-confirm-composing' to nil. You can make jabber.el not
+to request such information by customizing
+`jabber-events-request-these'.
+
+
+File: jabber.info, Node: Roster import and export, Next: XMPP URIs, Prev: Message events, Up: Top
+
+13 Roster import and export
+***************************
+
+Your roster is saved on the Jabber server, and usually not in the
+client. However, you might want to save the roster to a file anyway.
+The most common reason for this is probably to copy it to another
+account.
+
+ To export your roster to a file, type `M-x jabber-export-roster'. A
+buffer will appear in which you can edit the data to be exported.
+Changes done in that buffer will not affect your real roster.
+
+ To import your roster from a file, type `M-x jabber-import-roster'.
+You will be able to edit the data before importing it. Items not in the
+roster will be added; items in the roster will be modified to match
+imported data. Subscriptions will be updated.
+
+ The format of the roster files is the XML used by roster pushes in
+the XMPP protocol, in UTF-8 encoding.
+
+
+File: jabber.info, Node: XMPP URIs, Next: Customization, Prev: Roster import and export, Up: Top
+
+14 XMPP URIs
+************
+
+Many web page authors use links starting with `xmpp:' for JIDs. Your
+web browser could be made to pass such links to jabber.el, so that such
+links are actually useful and not just decoration. How to do that
+depends on your operating system and web browser.
+
+14.1 Mozilla and Unix
+=====================
+
+If you use a Mozilla-based web browser on a Unix-like operating system,
+follow these steps.
+
+ 1. Make sure you are running the Emacs server. *Note Using Emacs as
+ a Server: (emacs)Emacs Server.
+
+ 2. Note the path of the `xmppuri.sh' file in the jabber.el
+ distribution, and make sure it is executable.
+
+ 3. Set the Mozilla preference `network.protocol-handler.app.xmpp' to
+ the path of `xmppuri.sh'. There are two ways to do this:
+
+ * Go to the URL `about:config', right-click in the list, choose
+ "New string", and enter `network.protocol-handler.app.xmpp'
+ and the path in the following dialogs.
+
+ * Open or create the file `user.js' in your Mozilla profile
+ directory (in the same directory as `prefs.js'), and add the
+ following line:
+
+ user_pref("network.protocol-handler.app.xmpp", "/PATH/TO/xmppuri.sh");
+
+ Restart Mozilla for this change to take effect.
+
+14.2 Other systems
+==================
+
+If you know how to pass an XMPP URI from your browser to the function
+`jabber-handle-uri', your contribution for this section would be
+appreciated.
+
+
+File: jabber.info, Node: Customization, Next: Hacking and extending, Prev: XMPP URIs, Up: Top
+
+15 Customization
+****************
+
+jabber.el is intended to be customizable for many tastes. After all,
+this is Emacs. To open a customization buffer for jabber.el, type `M-x
+jabber-customize'.
+
+* Menu:
+
+* Account settings::
+* Connection settings::
+* Miscellaneous settings::
+* Customizing the roster buffer::
+* Customizing the chat buffer::
+* Customizing alerts::
+* Hooks::
+* Debug options::
+
+
+File: jabber.info, Node: Account settings, Next: Connection settings, Prev: Customization, Up: Customization
+
+15.1 Account settings
+=====================
+
+`jabber-username' is the username part of your JID.
+
+ `jabber-server' is the JID of your server, i.e. the hostname part of
+your JID. This is usually, but not necessarily, the same as the
+hostname of the server.
+
+ `jabber-password' is your password. You have the option to set it
+here, in which case it will be stored in cleartext in your `.emacs'
+file. If this is set to `nil', you will be prompted for your password
+every time you connect.
+
+ `jabber-resource' is the resource you want to log in under. This
+only matters if you are connected to the same account from different
+clients or different computers, since each connection must have a
+unique resource. You might want to set this to your hostname.
+
+ `jabber-default-priority' is the default priority sent with your
+presence. Regardless of what you have here, you can change your
+priority during a session with `jabber-send-presence'. *Note
+Presence::, for more information on priority.
+
+ `jabber-nickname' is your default nickname for groupchats.
+
+
+File: jabber.info, Node: Connection settings, Next: Miscellaneous settings, Prev: Account settings, Up: Customization
+
+15.2 Connection settings
+========================
+
+`jabber-network-server' is the hostname or IP address of your server.
+If it is set to `nil', jabber.el will use the name in `jabber-server'.
+
+ `jabber-port' is the TCP port of the server to connect to. If
+`nil', the default port is selected based on the chosen connection
+method.
+
+ If both `jabber-network-server' and `jabber-port' are nil, and a
+sufficiently modern `dns.el' is available, jabber.el will use SRV
+records to find the right hostname and port.
+
+ `jabber-connection-type' specifies what kind of connection to use.
+`network' means normal unencrypted network connection (usually on port
+5222), and `ssl' means encrypted connection through GnuTLS or OpenSSL
+(port 5223), while `starttls' will initiate an unencrypted connection
+and switch to encrypted if offered by the server. You can change the
+settings of the encryption program through `M-x customize-group RET
+tls', `M-x customize-group RET starttls' or `M-x customize-group RET
+ssl', respectively.
+
+ By default, GnuTLS will be used if the `tls' library is available,
+and if that fails, OpenSSL will be used if the `ssl' library is
+available. You can force the use of either program by setting
+`jabber-connection-ssl-program' to `gnutls' or `openssl', respectively.
+If you use `starttls' the library with the same name is required, and
+it depends on the GnuTLS command line client.
+
+
+File: jabber.info, Node: Miscellaneous settings, Next: Customizing the roster buffer, Prev: Connection settings, Up: Customization
+
+15.3 Miscellaneous settings
+===========================
+
+If you want a Jabber menu on the menu bar with some common commands,
+type `M-x jabber-menu'. You can remove it again with `C-u M-x
+jabber-menu'. Unfortunately, this cannot be changed through Customize
+settings, so you need to add `(jabber-menu)' to your `.emacs' to enable
+it permanently.
+
+
+File: jabber.info, Node: Customizing the roster buffer, Next: Customizing the chat buffer, Prev: Miscellaneous settings, Up: Customization
+
+15.4 Customizing the roster buffer
+==================================
+
+`jabber-roster-sort-functions' controls how roster items are sorted.
+By default, contacts are sorted first by presence, and then
+alphabetically by displayed name.
+
+ `jabber-sort-order' controls how roster items are sorted by
+presence. It is a list containing strings corresponding to show status
+(*note Presence::) or `nil', which represents offline.
+
+ `jabber-show-resources' controls when your contacts' resources are
+shown in the roster buffer. The default is to show resources when a
+contact has more than one connected resource.
+
+ `jabber-roster-line-format' specifies how the entry for each contact
+looks. It is a string where some characters are special if preceded by
+a percent sign:
+
+`%a'
+ Avatar of contact, if any
+
+`%c'
+ "*" if the contact is connected, or " " if not
+
+`%u'
+ Subscription state - see below
+
+`%n'
+ Nickname of contact, or JID if no nickname
+
+`%j'
+ Bare JID of contact (without resource)
+
+`%r'
+ Highest-priority resource of contact
+
+`%s'
+ Availability of contact as string ("Online", "Away" etc)
+
+`%S'
+ Status string specified by contact
+
+ `jabber-resource-line-format' is nearly identical, except that the
+values correspond to the values of the resource in question, and that
+the `%p' escape is available, which inserts the priority of the
+resource.
+
+ `jabber-roster-buffer' specifies the name of the roster buffer. If
+you change this, the new name will be used the next time you connect.
+
+ `jabber-roster-show-bindings' controls whether to show a list of
+keybindings at the top of the roster buffer. You need to run `M-x
+jabber-display-roster' after changing this variable to update the
+display.
+
+ `%u' is replaced by one of the strings given by
+`jabber-roster-subscription-display'.
+
+
+File: jabber.info, Node: Customizing the chat buffer, Next: Customizing alerts, Prev: Customizing the roster buffer, Up: Customization
+
+15.5 Customizing the chat buffer
+================================
+
+You can customize the look of the prompts in the chat buffer. There
+are separate settings for local (i.e. your own messages) and foreign
+prompts.
+
+ `jabber-chat-text-local' and `jabber-chat-text-foreign' determine
+the faces used for chat messages.
+
+ `jabber-chat-prompt-local' and `jabber-chat-prompt-foreign'
+determine the faces used for the prompts.
+
+ `jabber-chat-local-prompt-format' and
+`jabber-chat-foreign-prompt-format' determine what text is displayed in
+the prompts. They are format strings, with the following special
+sequences defined:
+
+`%t'
+ The time when the message was sent or received
+
+`%n'
+ The nickname of the user. For the foreign prompt, this is the
+ name of the contact in the roster, or the JID if no name set. For
+ the local prompt, this is the username part of your JID.
+
+`%u'
+ The username of the user.
+
+`%r'
+ The resource.
+
+`%j'
+ The bare JID of the user
+
+ `jabber-chat-time-format' defines how `%t' shows time. Its format
+is identical to that passed to `format-time-string'. *Note Time
+Conversion: (elisp)Time Conversion.
+
+ `jabber-chat-delayed-time-format' is used instead of
+`jabber-chat-time-format' for delayed messages (messages sent while you
+were offline, or fetched from history). This way you can have short
+timestamps everywhere except where you need long ones. You can always
+see the complete timestamp in a tooltip by hovering over the prompt with
+the mouse.
+
+ "rare" times). This can be toggled with `jabber-print-rare-time'.
+You can customize the displayed time by setting
+`jabber-rare-time-format'. Rare timestamps will be printed whenever
+time formatted by that format string would change.
+
+ You can also customize the header line of chat buffers, by modifying
+the variable `jabber-chat-header-line-format'. The format of that
+variable is the same as that of `mode-line-format' and
+`header-line-format'. *Note Mode-Line Format: (elisp)Mode Line Format.
+For MUC buffers, `jabber-muc-header-line-format' is used instead.
+
+ The variable `jabber-chat-fill-long-lines' controls whether long
+lines in the chat buffer are filled.
+
+
+File: jabber.info, Node: Customizing alerts, Next: Hooks, Prev: Customizing the chat buffer, Up: Customization
+
+15.6 Customizing alerts
+=======================
+
+When an event happens (currently including presence changes, incoming
+messages, and completed queries) you will usually want to be notified.
+Since tastes in this area vary wildly, these alerts are implemented as
+hooks, so you can choose which ones you want, or write your own if none
+fit.
+
+ Actually, if you don't want to write your own, stop reading this
+section and just read *Note Standard alerts::.
+
+ Many kinds of alerts consist in displaying a text message through a
+certain mechanism. This text message is provided by a function which
+you can rewrite or replace. If this function returns `nil', no message
+is displayed, and non-textual alerts refrain from action.
+
+ If you want to write alert hooks that do nothing except displaying
+the supplied message in some way, use the macro `define-jabber-alert'.
+For example, if FOO is a function that takes a string as an argument,
+write
+ (define-jabber-alert foo
+ "Display a message in a fooish way"
+ 'foo)
+ and all details will be taken care of for you.
+
+ The hooks take different arguments depending on category. However,
+they all have in common that the last argument is the result of the
+message function. The message function for each category takes the
+same arguments as the corresponding hooks, except for that last
+argument.
+
+ Alert hook contributions are very welcome. You can send them to the
+mailing list, or to the Sourceforge patch tracker.
+
+ Alert hooks are meant for optional UI things, that are subject to
+varying user tastes, and that can be toggled by simply adding or
+removing the function to and from the hook. For other things, there
+are corresponding general hooks, that are defvars instead of
+defcustoms, and that are to be managed by Lisp code. They have the
+same name as the alert hooks minus the `-alert' part, i.e.
+`jabber-message-hooks' vs `jabber-alert-message-hooks', etc.
+
+* Menu:
+
+* Standard alerts::
+* Presence alerts::
+* Message alerts::
+* MUC alerts::
+* Info alerts::
+
+
+File: jabber.info, Node: Standard alerts, Next: Presence alerts, Prev: Customizing alerts, Up: Customizing alerts
+
+15.6.1 Standard alerts
+----------------------
+
+Eight alerts are already written for all four alert categories. These
+all obey the result from the corresponding message function.
+
+ The `beep' alerts simply sound the terminal bell by calling `ding'.
+They are disabled by default.
+
+ The `echo' alerts display a message in the echo area by calling
+`message'. They are enabled by default.
+
+ The `switch' alerts switch to the buffer where the event occurred
+(chat buffer for incoming messages, roster buffer for presence changes,
+browse buffer for completed queries). They are disabled by default.
+Take care when using them, as they may interrupt your editing.
+
+ The `display' alerts display but do not select the buffer in
+question, using the function `display-buffer'. *Note Choosing a Window
+for Display: (elisp)Choosing Window, for information about customizing
+its behaviour. This is enabled by default for info requests.
+
+ The `wave' alerts play a sound file by calling `play-sound-file'.
+No sound files are provided. To use this, enter the names of the sound
+files in `jabber-alert-message-wave', `jabber-alert-presence-wave' and
+`jabber-alert-info-wave', respectively. You can specify specific sound
+files for contacts matching a regexp in the variables
+`jabber-alert-message-wave-alist' and
+`jabber-alert-presence-wave-alist'.
+
+ The `screen' alerts send a message through the Screen terminal
+manager (see `http://www.gnu.org/software/screen/'). They do no harm
+if called when you don't use Screen.
+
+ The `ratpoison' alerts send a message through the Ratpoison window
+manager (see `http://ratpoison.sourceforge.net/'). They do no harm if
+used when you're not running X, but if you are running X with another
+window manager, the ratpoison processes will never exit. You can look
+at them with `list-processes'.
+
+ The `sawfish' alerts send a message through the Sawfish window
+manager.
+
+ The `festival' alerts speak the message using the Emacs interface of
+the Festival speech synthesis system (see
+`http://www.cstr.ed.ac.uk/projects/festival/').
+
+ Additionally, for one-to-one and MUC messages, there are `scroll'
+alerts (enabled by default), that aim to do the right thing with chat
+buffers that are visible but not active. Sometimes you want point to
+scroll down, and sometimes not. These functions should do what you
+mean; if they don't, it's a bug.
+
+ Some of these functions are in the `jabber-alert.el' file, and the
+others are in their own files. You can use them as templates or
+inspiration for your own alerts.
+
+
+File: jabber.info, Node: Presence alerts, Next: Message alerts, Prev: Standard alerts, Up: Customizing alerts
+
+15.6.2 Presence alerts
+----------------------
+
+Set `jabber-alert-presence-message-function' to your desired function.
+This function should look like:
+
+ (defun FUNCTION (WHO OLDSTATUS NEWSTATUS STATUSTEXT)
+ ...
+ )
+
+ WHO is the JID symbol (*note Roster structure::), OLDSTATUS and
+NEWSTATUS are the previous and current stati, respectively, and
+STATUSTEXT is the status message if provided, otherwise nil.
+
+ NEWSTATUS can also be one of `"subscribe"', `"subscribed"',
+`"unsubscribe"' and `"unsubscribed"'.
+
+ The default function, `jabber-presence-default-message', returns
+`nil' if OLDSTATUS and NEWSTATUS are the same, and in other cases
+constructs a message from the given data.
+
+ All presence alert hooks take the same arguments plus the additional
+PROPOSED-ALERT, which is the result of the specified message function.
+This last argument is usually the only one they use.
+
+
+File: jabber.info, Node: Message alerts, Next: MUC alerts, Prev: Presence alerts, Up: Customizing alerts
+
+15.6.3 Message alerts
+---------------------
+
+If you don't want message alerts when the chat buffer in question is
+already the current buffer, set `jabber-message-alert-same-buffer' to
+nil. This affects the behaviour of the default message function, so
+you'll have to reimplement this functionality if you write your own
+message function.
+
+ Set `jabber-alert-message-function' to your desired function.(1)
+This function should look like:
+
+ (defun FUNCTION (FROM BUFFER TEXT)
+ ...
+ )
+
+ FROM is the JID symbol (*note Roster structure::), BUFFER is the
+buffer where the message is displayed, and TEXT is the text of the
+message.
+
+ The default function, `jabber-message-default-message', returns
+"Message from PERSON", where PERSON is the name of the person if
+specified in the roster, otherwise the JID.
+
+ All message alert hooks take the same arguments plus the additional
+PROPOSED-ALERT, which is the result of the specified message function.
+
+ ---------- Footnotes ----------
+
+ (1) Logically it should be `jabber-alert-message-message-function',
+but that would be really ugly.
+
+
+File: jabber.info, Node: MUC alerts, Next: Info alerts, Prev: Message alerts, Up: Customizing alerts
+
+15.6.4 MUC alerts
+-----------------
+
+Set `jabber-alert-muc-function' to your desired function. This
+function should look like:
+
+ (defun FUNCTION (NICK GROUP BUFFER TEXT)
+ ...
+ )
+
+ NICK is the nickname, GROUP is the JID of the group, BUFFER is the
+buffer where the message is displayed, and TEXT is the text of the
+message.
+
+ The default function, `jabber-muc-default-message', returns "Message
+from NICK in GROUP" or "Message in GROUP", the latter for messages from
+the room itself.
+
+ All MUC alert hooks take the same arguments plus the additional
+PROPOSED-ALERT, which is the result of the specified message function.
+
+ By default, no alert is made for messages from yourself. To change
+that, customize the variable `jabber-muc-alert-self'.
+
+
+File: jabber.info, Node: Info alerts, Prev: MUC alerts, Up: Customizing alerts
+
+15.6.5 Info alerts
+------------------
+
+Info alerts are sadly underdeveloped. The message function,
+`jabber-alert-info-message-function', takes two arguments, INFOTYPE and
+BUFFER. BUFFER is the buffer where something happened, and INFOTYPE is
+either `'roster' for roster updates, or `'browse' for anything that
+uses the browse buffer (basically anything except chatting).
+
+ The info alert hooks take an extra argument, as could be expected.
+
+
+File: jabber.info, Node: Hooks, Next: Debug options, Prev: Customizing alerts, Up: Customization
+
+15.7 Hooks
+==========
+
+jabber.el provides various hooks that you can use for whatever purpose.
+
+`jabber-post-connect-hook'
+ This hook is called after successful connection and authentication.
+ By default it contains `jabber-send-default-presence' (*note
+ Presence::).
+
+`jabber-lost-connection-hook'
+ This hook is called when you have been disconnected for unknown
+ reasons. Usually this isn't noticed for quite a long time.
+
+`jabber-pre-disconnect-hook'
+ This hook is called just before voluntary disconnection. This
+ might be due to failed authentication, so check
+ `*jabber-authenticated*' if you want to send a stanza.
+
+`jabber-post-disconnect-hook'
+ This hook is called after disconnection of any kind, possibly just
+ after `jabber-lost-connection-hook'.
+
+`jabber-chat-mode-hook'
+ This hook is called when a new chat buffer is created.
+
+
+
+File: jabber.info, Node: Debug options, Prev: Hooks, Up: Customization
+
+15.8 Debug options
+==================
+
+These settings provide a lot of information which is usually not very
+interesting, but can be useful for debugging various things.
+
+ `jabber-debug-log-xml' activates XML logging. All XML stanzas sent
+and received are logged in the buffer `*-jabber-xml-log-*' in list
+format. *Note XML representation::.
+
+
+File: jabber.info, Node: Hacking and extending, Next: Protocol support, Prev: Customization, Up: Top
+
+16 Hacking and extending
+************************
+
+This part of the manual is an attempt to explain parts of the source
+code. It is not meant to discourage you from reading the code yourself
+and trying to figure it out, but as a guide on where to look.
+Knowledge of Jabber protocols is assumed.
+
+* Menu:
+
+* XML representation::
+* Roster structure::
+* Listening for new requests::
+* Sending new requests::
+* Extending service discovery::
+* Chat printers::
+* Stanza chains::
+
+
+File: jabber.info, Node: XML representation, Next: Roster structure, Prev: Hacking and extending, Up: Hacking and extending
+
+16.1 XML representation
+=======================
+
+The XML representation is the one generated by `xml.el' in Emacs,
+namely the following. Each tag is a list. The first element of the
+list is a symbol, the name of which is the name of the tag. The second
+element is an alist of attributes, where the keys are the attribute
+names in symbol form, and the values are strings. The remaining
+elements are the tags and data contained within the tag.
+
+ For example,
+ <foo bar='baz'>
+ <frobozz/>Fnord
+ </foo>
+ is represented as
+ (foo ((bar . "baz")) (frobozz nil "") "Fnord
+ ")
+
+ Note the empty string as the third element of the `frobozz' list.
+It is not present in newer (post-21.3) versions of `xml.el', but it's
+probably best to assume it might be there.
+
+ If you want to see what an XML tag would look like, use
+`jabber-sexp2xml', which takes a tag and returns a string. You will
+usually not need it in your code, as you can use `jabber-send-sexp' to
+send away your tags to the server.
+
+
+File: jabber.info, Node: Roster structure, Next: Listening for new requests, Prev: XML representation, Up: Hacking and extending
+
+16.2 Roster structure
+=====================
+
+Roster entries are contained in the list `*jabber-roster*'.
+
+ A roster entry is a symbol. Its name is the JID, and it is interned
+in `jabber-jid-obarray'. A roster entry can have the following
+properties:
+
+`xml'
+ The XML tag received from the server on roster update
+
+`name'
+ The name of the roster item (just like the XML attribute)
+
+`subscription'
+ The subscription state (also copied)
+
+`ask'
+ The ask state (copied)
+
+`groups'
+ A list of strings (possibly empty) containing all the groups the
+ contact is in
+
+`connected'
+ Boolean, true if any resource is connected
+
+`show'
+ Presence show status for highest-priority connected resource
+
+`status'
+ Presence status message for highest-priority connected resource
+
+`resources'
+ Alist. Keys are strings (resource names), values are plists with
+ properties `connected', `show', `status' and `priority'.
+
+
+ Incoming presence information is inserted in `resources', and the
+information from the resource with the highest priority is inserted in
+`show' and `status' by the function `jabber-prioritize-resources'.
+
+
+File: jabber.info, Node: Listening for new requests, Next: Sending new requests, Prev: Roster structure, Up: Hacking and extending
+
+16.3 Listening for new requests
+===============================
+
+To listen for new IQ requests, add the appropriate entry in
+`jabber-iq-get-xmlns-alist' or `jabber-iq-set-xmlns-alist'. The key is
+the namespace of the request, and the value is a function that takes
+one argument, the entire IQ stanza in list format. `jabber-process-iq'
+reads these alists to determine which function to call on incoming
+packets.
+
+ For example, the Ad-Hoc Commands module contains the following:
+
+ (add-to-list 'jabber-iq-set-xmlns-alist
+ (cons "http://jabber.org/protocol/commands" 'jabber-ahc-process))
+
+ To send a response to an IQ request, use `(jabber-send-iq SENDER
+"result" QUERY nil nil nil nil ID)', where QUERY is the query in list
+format. `jabber-send-iq' will encapsulate the query in an IQ packet
+with the specified id.
+
+ To return an error to the Jabber entity that sent the query, use
+`jabber-signal-error'. The signal is caught by `jabber-process-iq',
+which takes care of sending the error.
+
+
+File: jabber.info, Node: Sending new requests, Next: Extending service discovery, Prev: Listening for new requests, Up: Hacking and extending
+
+16.4 Sending new requests
+=========================
+
+To send an IQ request, use `jabber-send-iq'. It will generate an id,
+and create a mapping for it for use when the response comes. The
+syntax is:
+
+ (jabber-send-iq TO TYPE QUERY
+ SUCCESS-CALLBACK SUCCESS-CLOSURE
+ FAILURE-CALLBACK FAILURE-CLOSURE)
+
+ Both callbacks take two arguments, the IQ stanza returned and the
+closure item mentioned here.
+
+ Two standard callbacks are provided. `jabber-report-success' takes
+a string as closure item, and reports success or failure in the echo
+area. `jabber-process-data' prepares a browse buffer. If its closure
+argument is a function, it calls that function with point in this
+browse buffer. If it's a string, it prints that string along with the
+error message in the IQ response. If it's anything else (e.g. `nil'),
+it just dumps the XML in the browse buffer.
+
+ Examples follow. This is the hypothetical Jabber protocol "frob",
+for which only success report is needed:
+ (jabber-send-iq "someone@somewhere.org" "set"
+ '(query ((xmlns . "frob")))
+ 'jabber-report-success "Frobbing"
+ 'jabber-report-success "Frobbing")
+ This will print "Frobbing succeeded" or "Frobbing failed: reason",
+respectively, in the echo area.
+
+ The protocol "investigate" needs to parse results and show them in a
+browse buffer:
+ (jabber-send-iq "someone@somewhere.org" "get"
+ '(query ((xmlns . "investigate")))
+ 'jabber-process-data 'jabber-process-investigate
+ 'jabber-process-data "Investigation failed")
+ Of course, the previous example could have used
+`jabber-report-success' for the error message. It's a matter of UI
+taste.
+
+
+File: jabber.info, Node: Extending service discovery, Next: Chat printers, Prev: Sending new requests, Up: Hacking and extending
+
+16.5 Service discovery
+======================
+
+Your new handlers will likely want to advertise their existence through
+service discovery.
+
+ To have an additional feature reported in response to disco info
+requests, add a string to `jabber-advertised-features'.
+
+ By default, the service discovery functions reject all requests
+containing a node identifier with an "Item not found" error. To make
+them respond, add the appropriate entries to `jabber-disco-items-nodes'
+and `jabber-disco-info-nodes'. Both variables work in the same way.
+They are alists, where the keys are the node names, and the values are
+lists of two items.
+
+ The first item is the data to return -- either a list or a function
+taking the entire IQ stanza and returning a list, this list containing
+the XML nodes to include in the `<query/>' node in the response.
+
+ The second item is the access control function. An access control
+function receives the JID as its only argument, and returns non-nil if
+access is to be granted. If nil is specified instead of a function,
+access is always granted. One such function is provided,
+`jabber-my-jid-p', which grants access for JIDs where the username and
+server (not necessarily resource) are equal to those of the user.
+
+
+File: jabber.info, Node: Chat printers, Next: Stanza chains, Prev: Extending service discovery, Up: Hacking and extending
+
+16.6 Chat printers
+==================
+
+Chat printers are functions that print a certain aspect of an incoming
+message in a chat buffer. Included are functions for printing subjects
+(`jabber-chat-print-subject'), bodies (`jabber-chat-print-body', and
+`jabber:x:oob'-style URLs (`jabber-chat-print-url'). The functions in
+`jabber-chat-printers' are called in order, with the entire
+`<message/>' stanza as argument, and are expected to call `insert' if
+they have anything to add.
+
+ For MUC, the functions in `jabber-muc-printers' are prepended to
+those in `jabber-chat-printers'.
+
+ Body printers are a subgroup of chat printers. They are exclusive;
+only one of them applies to any given message. The idea is that
+"higher-quality" parts of the message override pieces included for
+backwards compatibility. Included are `jabber-muc-print-invite' and
+`jabber-chat-normal-body'; functions for XHTML-IM and PGP encrypted
+messages may be written in the future. The functions in
+`jabber-body-printers' are called in order until one of them returns
+non-nil.
+
+
+File: jabber.info, Node: Stanza chains, Prev: Chat printers, Up: Hacking and extending
+
+16.7 Stanza chains
+==================
+
+If you really need to get under the skin of jabber.el, you can add
+functions to the lists `jabber-message-chain', `jabber-iq-chain' and
+`jabber-presence-chain'. The functions in these lists will be called
+in order when an XML stanza of the corresponding type arrives, with the
+entire XML stanza passed as the only argument. Earlier functions can
+modify the stanza to change the behaviour of downstream functions.
+
+
+File: jabber.info, Node: Protocol support, Next: Concept index, Prev: Hacking and extending, Up: Top
+
+Appendix A Protocol support
+***************************
+
+These are the protocols currently supported (in full or partially) by
+jabber.el.
+
+* Menu:
+
+* RFC 3920:: XMPP-CORE
+* RFC 3921:: XMPP-IM
+* XEP-0004:: Data Forms
+* XEP-0012:: Last Activity
+* XEP-0020:: Feature Negotiation
+* XEP-0022:: Message Events
+* XEP-0030:: Service Discovery
+* XEP-0045:: Multi-User Chat
+* XEP-0049:: Private XML Storage
+* XEP-0050:: Ad-Hoc Commands
+* XEP-0054:: vcard-temp
+* XEP-0055:: Jabber Search
+* XEP-0065:: SOCKS5 Bytestreams
+* XEP-0066:: Out of Band Data
+* XEP-0068:: Field Standardization for Data Forms
+* XEP-0077:: In-Band Registration
+* XEP-0078:: Non-SASL Authentication
+* XEP-0082:: Jabber Date and Time Profiles
+* XEP-0086:: Error Condition Mappings
+* XEP-0090:: Entity Time
+* XEP-0091:: Delayed Delivery
+* XEP-0092:: Software Version
+* XEP-0095:: Stream Initiation
+* XEP-0096:: File Transfer
+* XEP-0146:: Remote Controlling Clients
+* XEP-0153:: vCard-Based Avatars
+
+
+File: jabber.info, Node: RFC 3920, Next: RFC 3921, Prev: Protocol support, Up: Protocol support
+
+A.1 RFC 3920 (XMPP-CORE)
+========================
+
+Most of RFC 3920 is supported, with the following exceptions.
+
+ SASL is supported only when an external SASL library from FLIM or
+Gnus is present. As SASL is an essential part to XMPP, jabber.el will
+send pre-XMPP stream headers if it is not available.
+
+ None of the stringprep profiles are implemented. jabber.el changes
+JIDs to lowercase internally; that's all.
+
+ jabber.el doesn't interpret namespace prefixes.
+
+ The `xml:lang' attribute is neither interpreted nor generated.
+
+ SRV records are used if a modern version of `dns.el' is installed.
+
+
+File: jabber.info, Node: RFC 3921, Next: XEP-0004, Prev: RFC 3920, Up: Protocol support
+
+A.2 RFC 3921 (XMPP-IM)
+======================
+
+Most of RFC 3921 is supported, with the following exceptions.
+
+ Messages of type "headline" are not treated in any special way.
+
+ The `<thread/>' element is not used or generated.
+
+ Sending "directed presence" is supported; however, presence stanzas
+received from contacts not in roster are ignored.
+
+ Privacy lists are not supported at all.
+
+ jabber.el doesn't support XMPP-E2E or "im:" CPIM URIs.
+
+
+File: jabber.info, Node: XEP-0004, Next: XEP-0012, Prev: RFC 3921, Up: Protocol support
+
+A.3 XEP-0004 (Data Forms)
+=========================
+
+XEP-0004 support is good enough for many purposes. Limitations are the
+following.
+
+ Forms in incoming messages are not interpreted. See each specific
+protocol for whether forms are accepted in that context.
+
+ "Cancel" messages are probably not consistently generated when they
+should be. This is partly a paradigm clash, as jabber.el doesn't use
+modal dialog boxes but buffers which can easily be buried.
+
+ `<required/>' elements are not enforced.
+
+ The field types "jid-single", "jid-multi" and "list-multi" are not
+implemented, due to programmer laziness. Let us know if you need them.
+
+
+File: jabber.info, Node: XEP-0012, Next: XEP-0020, Prev: XEP-0004, Up: Protocol support
+
+A.4 XEP-0012 (Last Activity)
+============================
+
+jabber.el can generate all three query types described in the protocol.
+However, it does not answer to such requests.
+
+
+File: jabber.info, Node: XEP-0020, Next: XEP-0022, Prev: XEP-0012, Up: Protocol support
+
+A.5 XEP-0020 (Feature Negotiation)
+==================================
+
+There are no known limitations or bugs in XEP-0020 support.
+
+
+File: jabber.info, Node: XEP-0022, Next: XEP-0030, Prev: XEP-0020, Up: Protocol support
+
+A.6 XEP-0022 (Message Events)
+=============================
+
+jabber.el understands all four specified kinds of message events
+(offline, delivered, displayed, and composing) and by default requests
+all of them. It also reports those three events that make sense for
+clients.
+
+
+File: jabber.info, Node: XEP-0030, Next: XEP-0045, Prev: XEP-0022, Up: Protocol support
+
+A.7 XEP-0030 (Service Discovery)
+================================
+
+Service discovery is supported, both as client and server. When used in
+the code, service discovery results are cached indefinitely.
+
+
+File: jabber.info, Node: XEP-0045, Next: XEP-0049, Prev: XEP-0030, Up: Protocol support
+
+A.8 XEP-0045 (Multi-User Chat)
+==============================
+
+jabber.el supports parts of XEP-0045. Entering, leaving and chatting
+work. So do invitations and private messages. Room configuration is
+supported. Changing roles of participants (basic moderation) is
+implemented, as is changing affiliations, but requesting affiliation
+lists is not yet supported.
+
+
+File: jabber.info, Node: XEP-0049, Next: XEP-0050, Prev: XEP-0045, Up: Protocol support
+
+A.9 XEP-0049 (Private XML Storage)
+==================================
+
+jabber.el contains an implementation of XEP-0049; however it is not used
+for anything right now.
+
+
+File: jabber.info, Node: XEP-0050, Next: XEP-0054, Prev: XEP-0049, Up: Protocol support
+
+A.10 XEP-0050 (Ad-Hoc Commands)
+===============================
+
+jabber.el is probably the first implementation of XEP-0050 (see post on
+jdev from 2004-03-10
+(http://article.gmane.org/gmane.network.jabber.devel/21413)). Both the
+client and server parts are supported.
+
+
+File: jabber.info, Node: XEP-0054, Next: XEP-0055, Prev: XEP-0050, Up: Protocol support
+
+A.11 XEP-0054 (vcard-temp)
+==========================
+
+Both displaying other users' vCards and editing your own vCard are
+supported. The implementation tries to follow the schema in the XEP
+accurately.
+
+
+File: jabber.info, Node: XEP-0055, Next: XEP-0065, Prev: XEP-0054, Up: Protocol support
+
+A.12 XEP-0055 (Jabber Search)
+=============================
+
+XEP-0055 is supported, both with traditional fields and with Data Forms
+(*note XEP-0004::). As the traditional fields specified by the XEP is a
+subset of those allowed in XEP-0077, handling of those two form types
+are merged. *Note XEP-0077::.
+
+
+File: jabber.info, Node: XEP-0065, Next: XEP-0066, Prev: XEP-0055, Up: Protocol support
+
+A.13 XEP-0065 (SOCKS5 Bytestreams)
+==================================
+
+XEP-0065 is supported. Currently jabber.el cannot act as a server, not
+even on on Emacsen that support server sockets (GNU Emacs 22 and up).
+Therefore it relies on proxies. Proxies have to be entered and queried
+manually.
+
+ Psi's "fast mode" (`http://delta.affinix.com/specs/stream.html'),
+which gives greater flexibility with regards to NAT, is not implemented.
+
+
+File: jabber.info, Node: XEP-0066, Next: XEP-0068, Prev: XEP-0065, Up: Protocol support
+
+A.14 XEP-0066 (Out of Band Data)
+================================
+
+jabber.el will display URLs sent in message stanzas qualified by the
+`jabber:x:oob' namespace, as described in this XEP. Sending such URLs
+or doing anything with iq stanzas (using the `jabber:iq:oob' namespace)
+is not supported.
+
+
+File: jabber.info, Node: XEP-0068, Next: XEP-0077, Prev: XEP-0066, Up: Protocol support
+
+A.15 XEP-0068 (Field Standardization for Data Forms)
+====================================================
+
+XEP-0068 is only used in the context of creating a new Jabber account,
+to prefill the username field of the registration form.
+
+
+File: jabber.info, Node: XEP-0077, Next: XEP-0078, Prev: XEP-0068, Up: Protocol support
+
+A.16 XEP-0077 (In-Band Registration)
+====================================
+
+In-band registration is supported for all purposes. That means
+registering a new Jabber account, changing Jabber password, removing a
+Jabber account, registering with a service, and cancelling registration
+to a service. Data forms are supported as well. URL redirections are
+not.
+
+ jabber.el will not prevent or alert a user trying to change a
+password over an unencrypted connection.
+
+
+File: jabber.info, Node: XEP-0078, Next: XEP-0082, Prev: XEP-0077, Up: Protocol support
+
+A.17 XEP-0078 (Non-SASL Authentication)
+=======================================
+
+Non-SASL authentication is supported, both plaintext and digest.
+Digest is preferred, and a warning is displayed to the user if only
+plaintext is available.
+
+
+File: jabber.info, Node: XEP-0082, Next: XEP-0086, Prev: XEP-0078, Up: Protocol support
+
+A.18 XEP-0082 (Jabber Date and Time Profiles)
+=============================================
+
+The DateTime profile of XEP-0082 is supported. Currently this is only
+used for file transfer.
+
+
+File: jabber.info, Node: XEP-0086, Next: XEP-0090, Prev: XEP-0082, Up: Protocol support
+
+A.19 XEP-0086 (Error Condition Mappings)
+========================================
+
+Legacy errors are interpreted, but never generated. XMPP style error
+messages take precedence when errors are reported to the user.
+
+
+File: jabber.info, Node: XEP-0090, Next: XEP-0091, Prev: XEP-0086, Up: Protocol support
+
+A.20 XEP-0090 (Entity Time)
+===========================
+
+jabber.el can query other entities for their time, and return the
+current time to those who ask.
+
+
+File: jabber.info, Node: XEP-0091, Next: XEP-0092, Prev: XEP-0090, Up: Protocol support
+
+A.21 XEP-0091 (Delayed Delivery)
+================================
+
+The time specified on delayed incoming messages is interpreted, and
+displayed in chat buffers instead of the current time.
+
+
+File: jabber.info, Node: XEP-0092, Next: XEP-0095, Prev: XEP-0091, Up: Protocol support
+
+A.22 XEP-0092 (Software Version)
+================================
+
+The user can request the version of any entity. jabber.el answers
+version requests to anyone, giving "jabber.el" as name, and the Emacs
+version as OS.
+
+
+File: jabber.info, Node: XEP-0095, Next: XEP-0096, Prev: XEP-0092, Up: Protocol support
+
+A.23 XEP-0095 (Stream Initiation)
+=================================
+
+XEP-0095 is supported, both incoming and outgoing, except that jabber.el
+doesn't check service discovery results before sending a stream
+initiation request.
+
+
+File: jabber.info, Node: XEP-0096, Next: XEP-0146, Prev: XEP-0095, Up: Protocol support
+
+A.24 XEP-0096 (File Transfer)
+=============================
+
+Both sending and receiving files is supported. If a suitable program is
+found, MD5 hashes of outgoing files are calculated and sent. However,
+hashes of received files are not checked. Ranged transfers are not
+supported. In-band bytestreams are not yet supported, even though
+XEP-0096 requires them.
+
+
+File: jabber.info, Node: XEP-0146, Next: XEP-0153, Prev: XEP-0096, Up: Protocol support
+
+A.25 XEP-0146 (Remote Controlling Clients)
+==========================================
+
+The "set-status" command in XEP-0146 is supported.
+
+
+File: jabber.info, Node: XEP-0153, Prev: XEP-0146, Up: Protocol support
+
+A.26 XEP-0153 (vCard-Based Avatars)
+===================================
+
+vCard-based avatars are supported, both publishing and displaying. The
+pixel size limits on avatars are not enforced.
+
+
+File: jabber.info, Node: Concept index, Next: Function index, Prev: Protocol support, Up: Top
+
+Concept index
+*************
+
+
+* Menu:
+
+* Account removal: Registering. (line 6)
+* Activity: Tracking activity. (line 6)
+* Ad-Hoc Commands: Ad-Hoc Commands. (line 6)
+* Affiliations, MUC: MUC Administration. (line 37)
+* Alert hooks: Customizing alerts. (line 6)
+* Alerts: Standard alerts. (line 6)
+* autoaway: Autoaway. (line 6)
+* Autojoin chat rooms: Automation. (line 6)
+* avatars: Avatars. (line 6)
+* Backlog: Message history. (line 6)
+* Banning, MUC: MUC Administration. (line 37)
+* Body printers: Chat printers. (line 6)
+* Browse buffers: Services. (line 6)
+* browser integration: XMPP URIs. (line 6)
+* Browsing: Service discovery and browsing.
+ (line 6)
+* Cancelling registration: Registering. (line 6)
+* Changing nickname: Groupchat. (line 9)
+* Changing password: Registering. (line 6)
+* Chat buffer: Customizing the chat buffer.
+ (line 6)
+* Chat printers: Chat printers. (line 6)
+* Chatrooms: Groupchat. (line 6)
+* Chatting: Chatting. (line 6)
+* Composing: Message events. (line 6)
+* composing messages: Composing messages. (line 6)
+* Connecting: Connecting. (line 6)
+* Connection settings: Connection settings. (line 6)
+* Customization: Customization. (line 6)
+* Default MUC nickname: Automation. (line 6)
+* Delivered: Message events. (line 6)
+* Detecting lost connections: Keepalive. (line 6)
+* directed presence: Presence. (line 43)
+* Displayed: Message events. (line 6)
+* Export roster: Roster import and export.
+ (line 6)
+* Faces, chat buffer: Customizing the chat buffer.
+ (line 6)
+* File transfer: File transfer. (line 6)
+* file transfer proxy: Sending files. (line 6)
+* Filling long lines in chat buffer: Customizing the chat buffer.
+ (line 60)
+* flyspell: Spell checking. (line 6)
+* Gateway registration: Registering. (line 6)
+* GnuTLS: Connection settings. (line 26)
+* Groupchat: Groupchat. (line 6)
+* History: Message history. (line 6)
+* idle: Autoaway. (line 6)
+* idle time, query: Time queries. (line 13)
+* Import roster: Roster import and export.
+ (line 6)
+* Invitations: Invitations. (line 6)
+* Joining a groupchat: Groupchat. (line 9)
+* Keepalive: Keepalive. (line 6)
+* Key bindings: Roster buffer. (line 6)
+* Kicking, MUC: MUC Administration. (line 13)
+* last online: Time queries. (line 10)
+* links: XMPP URIs. (line 6)
+* Menus <1>: Roster buffer. (line 6)
+* Menus: Miscellaneous settings.
+ (line 6)
+* message composition: Composing messages. (line 6)
+* Modeline: Modeline status. (line 6)
+* Moderator, MUC: MUC Administration. (line 13)
+* Mozilla integration: XMPP URIs. (line 6)
+* MUC: Groupchat. (line 6)
+* Network settings: Connection settings. (line 6)
+* Nickname, changing: Groupchat. (line 9)
+* Online notifications: Watch buddies. (line 6)
+* OpenSSL: Connection settings. (line 26)
+* Password change: Registering. (line 6)
+* Personal information: Personal information. (line 6)
+* Presence: Presence. (line 6)
+* Presence subscription: Presence subscription.
+ (line 6)
+* Private MUC messages: Private messages. (line 6)
+* proxy, file transfer: Sending files. (line 6)
+* query groupchat: Groupchat. (line 16)
+* Registering an account: Connecting. (line 6)
+* Registration: Registering. (line 6)
+* Removing an account: Registering. (line 6)
+* Resource: Account settings. (line 6)
+* Roles, MUC: MUC Administration. (line 13)
+* Roster buffer, basics: Roster buffer. (line 6)
+* Roster buffer, customizing: Customizing the roster buffer.
+ (line 6)
+* Rotation: Message history. (line 6)
+* Scroll: Standard alerts. (line 6)
+* Searching: Searching. (line 6)
+* send directed presence: Presence. (line 43)
+* Sending files: File transfer. (line 6)
+* Sending presence: Presence. (line 6)
+* Service discovery: Service discovery and browsing.
+ (line 6)
+* Sorting the roster: Customizing the roster buffer.
+ (line 6)
+* Spell checking: Spell checking. (line 6)
+* SRV records: Connection settings. (line 6)
+* SSL: Connection settings. (line 6)
+* STARTTLS: Connection settings. (line 6)
+* Subscribing to someone's presence: Presence subscription.
+ (line 6)
+* Supported protocols: Protocol support. (line 6)
+* time query: Time queries. (line 6)
+* Timestamps: Customizing the chat buffer.
+ (line 6)
+* TLS: Connection settings. (line 6)
+* Topic, MUC: Groupchat. (line 28)
+* uptime, query: Time queries. (line 13)
+* URIs: XMPP URIs. (line 6)
+* URLs: XMPP URIs. (line 6)
+* Username: Account settings. (line 6)
+* vCard: Personal information. (line 6)
+* Voice, MUC: MUC Administration. (line 13)
+* Watch: Watch buddies. (line 6)
+* web browser integration: XMPP URIs. (line 6)
+* XEP-0065 proxy: Sending files. (line 6)
+* XML log: Debug options. (line 6)
+* XML representation: XML representation. (line 6)
+* xmpp: links: XMPP URIs. (line 6)
+* xprintidle: Autoaway. (line 6)
+
+
+File: jabber.info, Node: Function index, Next: Variable index, Prev: Concept index, Up: Top
+
+Function index
+**************
+
+
+* Menu:
+
+* define-jabber-alert: Customizing alerts. (line 6)
+* jabber-activity-mode: Tracking activity. (line 6)
+* jabber-ahc-execute-command: Ad-Hoc Commands. (line 6)
+* jabber-ahc-get-list: Ad-Hoc Commands. (line 6)
+* jabber-chat-with: Chatting. (line 6)
+* jabber-compose: Composing messages. (line 6)
+* jabber-connect: Connecting. (line 6)
+* jabber-customize: Customization. (line 6)
+* jabber-disconnect: Connecting. (line 6)
+* jabber-display-roster: Roster buffer. (line 6)
+* jabber-export-roster: Roster import and export.
+ (line 6)
+* jabber-ft-send: Sending files. (line 17)
+* jabber-get-browse: Service discovery and browsing.
+ (line 6)
+* jabber-get-disco-info: Service discovery and browsing.
+ (line 6)
+* jabber-get-disco-items: Service discovery and browsing.
+ (line 6)
+* jabber-get-idle-time: Time queries. (line 13)
+* jabber-get-last-online: Time queries. (line 10)
+* jabber-get-register: Registering. (line 6)
+* jabber-get-search: Searching. (line 6)
+* jabber-get-time: Time queries. (line 6)
+* jabber-groupchat-get-config: Groupchat. (line 33)
+* jabber-groupchat-join: Groupchat. (line 9)
+* jabber-groupchat-leave: Groupchat. (line 31)
+* jabber-handle-uri: XMPP URIs. (line 6)
+* jabber-import-roster: Roster import and export.
+ (line 6)
+* jabber-info-default-message: Info alerts. (line 6)
+* jabber-keepalive-start: Keepalive. (line 6)
+* jabber-keepalive-stop: Keepalive. (line 6)
+* jabber-menu: Miscellaneous settings.
+ (line 6)
+* jabber-message-default-message: Message alerts. (line 6)
+* jabber-mode-line-mode: Modeline status. (line 6)
+* jabber-muc-autojoin: Automation. (line 6)
+* jabber-muc-default-message: MUC alerts. (line 6)
+* jabber-muc-invite: Invitations. (line 6)
+* jabber-muc-names: Groupchat. (line 37)
+* jabber-muc-private: Private messages. (line 6)
+* jabber-muc-set-affiliation: MUC Administration. (line 37)
+* jabber-muc-set-role: MUC Administration. (line 13)
+* jabber-muc-set-topic: Groupchat. (line 28)
+* jabber-my-jid-p: Extending service discovery.
+ (line 6)
+* jabber-presence-default-message: Presence alerts. (line 6)
+* jabber-process-data: Sending new requests. (line 6)
+* jabber-process-iq <1>: Listening for new requests.
+ (line 6)
+* jabber-process-iq: Sending new requests. (line 6)
+* jabber-report-success: Sending new requests. (line 6)
+* jabber-send-default-presence: Presence. (line 6)
+* jabber-send-directed-presence: Presence. (line 43)
+* jabber-send-iq <1>: Sending new requests. (line 6)
+* jabber-send-iq: Listening for new requests.
+ (line 6)
+* jabber-send-presence: Presence. (line 6)
+* jabber-send-subscription-request: Presence subscription.
+ (line 6)
+* jabber-signal-error: Listening for new requests.
+ (line 6)
+* jabber-socks5-query-all-proxies: Sending files. (line 13)
+* jabber-vcard-edit: Personal information. (line 6)
+* jabber-vcard-get: Personal information. (line 6)
+* jabber-watch-add: Watch buddies. (line 6)
+* jabber-watch-remove: Watch buddies. (line 6)
+
+
+File: jabber.info, Node: Variable index, Prev: Function index, Up: Top
+
+Variable index
+**************
+
+
+* Menu:
+
+* *jabber-roster*: Roster structure. (line 6)
+* jabber-activity-count-in-title: Tracking activity. (line 6)
+* jabber-activity-count-in-title-format: Tracking activity. (line 6)
+* jabber-activity-make-strings: Tracking activity. (line 6)
+* jabber-activity-query-unread: Tracking activity. (line 6)
+* jabber-advertised-features: Extending service discovery.
+ (line 6)
+* jabber-alert-info-message-function: Info alerts. (line 6)
+* jabber-alert-message-function: Message alerts. (line 6)
+* jabber-alert-muc-function: MUC alerts. (line 6)
+* jabber-alert-presence-message-function: Presence alerts. (line 6)
+* jabber-autoaway-method: Autoaway. (line 6)
+* jabber-avatar-cache-directory: Avatars. (line 6)
+* jabber-backlog-days: Message history. (line 6)
+* jabber-backlog-number: Message history. (line 6)
+* jabber-body-printers: Chat printers. (line 6)
+* jabber-chat-delayed-time-format: Customizing the chat buffer.
+ (line 42)
+* jabber-chat-fill-long-lines: Customizing the chat buffer.
+ (line 60)
+* jabber-chat-foreign-prompt-format: Customizing the chat buffer.
+ (line 16)
+* jabber-chat-header-line-format: Customizing the chat buffer.
+ (line 54)
+* jabber-chat-local-prompt-format: Customizing the chat buffer.
+ (line 16)
+* jabber-chat-mode-hook: Hooks. (line 26)
+* jabber-chat-printers: Chat printers. (line 6)
+* jabber-chat-prompt-foreign: Customizing the chat buffer.
+ (line 13)
+* jabber-chat-prompt-local: Customizing the chat buffer.
+ (line 13)
+* jabber-chat-text-foreign: Customizing the chat buffer.
+ (line 10)
+* jabber-chat-text-local: Customizing the chat buffer.
+ (line 10)
+* jabber-chat-text-localBy default, timestamps are printed in the chat buffer every hour (at: Customizing the chat buffer.
+ (line 49)
+* jabber-chat-time-format: Customizing the chat buffer.
+ (line 38)
+* jabber-connection-ssl-program: Connection settings. (line 6)
+* jabber-connection-type: Connection settings. (line 6)
+* jabber-debug-log-xml: Debug options. (line 6)
+* jabber-default-priority <1>: Account settings. (line 6)
+* jabber-default-priority: Presence. (line 6)
+* jabber-default-show: Presence. (line 6)
+* jabber-default-status: Presence. (line 6)
+* jabber-disco-info-nodes: Extending service discovery.
+ (line 6)
+* jabber-disco-items-nodes: Extending service discovery.
+ (line 6)
+* jabber-events-confirm-composing: Message events. (line 6)
+* jabber-events-confirm-delivered: Message events. (line 6)
+* jabber-events-confirm-displayed: Message events. (line 6)
+* jabber-events-request-these: Message events. (line 6)
+* jabber-global-history-filename: Message history. (line 6)
+* jabber-history-dir: Message history. (line 6)
+* jabber-history-enable-rotation: Message history. (line 6)
+* jabber-history-enabled: Message history. (line 6)
+* jabber-history-size-limit: Message history. (line 6)
+* jabber-iq-chain: Stanza chains. (line 6)
+* jabber-iq-get-xmlns-alist: Listening for new requests.
+ (line 6)
+* jabber-iq-set-xmlns-alist: Listening for new requests.
+ (line 6)
+* jabber-jid-obarray: Roster structure. (line 6)
+* jabber-keepalive-interval: Keepalive. (line 6)
+* jabber-keepalive-timeout: Keepalive. (line 6)
+* jabber-lost-connection-hook: Hooks. (line 13)
+* jabber-message-alert-same-buffer: Message alerts. (line 6)
+* jabber-message-chain: Stanza chains. (line 6)
+* jabber-mode-line-compact: Modeline status. (line 6)
+* jabber-mode-line-mode: Modeline status. (line 6)
+* jabber-muc-alert-self: MUC alerts. (line 6)
+* jabber-muc-autojoin: Automation. (line 6)
+* jabber-muc-default-nicknames: Automation. (line 6)
+* jabber-muc-disable-disco-check: Groupchat. (line 16)
+* jabber-muc-header-line-format: Customizing the chat buffer.
+ (line 54)
+* jabber-muc-printers: Chat printers. (line 6)
+* jabber-network-server: Connection settings. (line 6)
+* jabber-nickname: Account settings. (line 6)
+* jabber-password: Account settings. (line 6)
+* jabber-port: Connection settings. (line 6)
+* jabber-post-connect-hook: Hooks. (line 8)
+* jabber-post-disconnect-hook: Hooks. (line 22)
+* jabber-pre-disconnect-hook: Hooks. (line 17)
+* jabber-presence-chain: Stanza chains. (line 6)
+* jabber-print-rare-time: Customizing the chat buffer.
+ (line 49)
+* jabber-rare-time-format: Customizing the chat buffer.
+ (line 49)
+* jabber-resource: Account settings. (line 6)
+* jabber-resource-line-format: Customizing the roster buffer.
+ (line 6)
+* jabber-roster-buffer: Customizing the roster buffer.
+ (line 6)
+* jabber-roster-line-format: Customizing the roster buffer.
+ (line 6)
+* jabber-roster-show-bindings: Customizing the roster buffer.
+ (line 6)
+* jabber-roster-sort-functions: Customizing the roster buffer.
+ (line 6)
+* jabber-server: Account settings. (line 6)
+* jabber-show-resources: Customizing the roster buffer.
+ (line 6)
+* jabber-socks5-proxies: Sending files. (line 13)
+* jabber-sort-order: Customizing the roster buffer.
+ (line 6)
+* jabber-use-global-history: Message history. (line 6)
+* jabber-username: Account settings. (line 6)
+* jabber-vcard-avatars-publish: Avatars. (line 6)
+* jabber-vcard-avatars-retrieve: Avatars. (line 6)
+
+
+
+Tag Table:
+Node: Top509
+Node: Introduction1330
+Node: Contact2212
+Node: Basic operation2654
+Node: Connecting3288
+Ref: Connecting-Footnote-14684
+Node: Chatting4764
+Node: Presence5831
+Node: Presence subscription8144
+Node: Roster buffer9123
+Ref: Roster buffer-Footnote-110549
+Node: Groupchat10626
+Node: Automation12575
+Node: Invitations13203
+Node: Private messages13880
+Node: MUC Administration14503
+Node: Composing messages16105
+Node: File transfer16730
+Ref: File transfer-Footnote-117483
+Node: Receiving files17651
+Node: Sending files19015
+Ref: Sending files-Footnote-120654
+Node: Services20814
+Node: Service discovery and browsing21613
+Node: Registering22809
+Node: Searching24539
+Node: Ad-Hoc Commands25250
+Ref: Ad-Hoc Commands-Footnote-126332
+Ref: Ad-Hoc Commands-Footnote-226468
+Node: Personal information26575
+Node: Avatars27380
+Node: Time queries28273
+Node: Useful features28878
+Node: Autoaway29238
+Node: Modeline status30610
+Node: Keepalive31322
+Node: Tracking activity32227
+Node: Watch buddies33760
+Node: Spell checking34457
+Node: Message history34941
+Node: Message events37112
+Node: Roster import and export38128
+Node: XMPP URIs39072
+Node: Customization40649
+Node: Account settings41146
+Node: Connection settings42329
+Node: Miscellaneous settings43864
+Node: Customizing the roster buffer44351
+Node: Customizing the chat buffer46331
+Node: Customizing alerts48664
+Node: Standard alerts50822
+Node: Presence alerts53498
+Node: Message alerts54516
+Ref: Message alerts-Footnote-155633
+Node: MUC alerts55736
+Node: Info alerts56616
+Node: Hooks57146
+Node: Debug options58138
+Node: Hacking and extending58562
+Node: XML representation59145
+Node: Roster structure60291
+Node: Listening for new requests61580
+Node: Sending new requests62732
+Node: Extending service discovery64672
+Node: Chat printers66056
+Node: Stanza chains67243
+Node: Protocol support67791
+Node: RFC 392069351
+Node: RFC 392170066
+Node: XEP-000470618
+Node: XEP-001271367
+Node: XEP-002071640
+Node: XEP-002271867
+Node: XEP-003072238
+Node: XEP-004572535
+Node: XEP-004972996
+Node: XEP-005073260
+Node: XEP-005473625
+Node: XEP-005573924
+Node: XEP-006574327
+Node: XEP-006674861
+Node: XEP-006875254
+Node: XEP-007775584
+Node: XEP-007876145
+Node: XEP-008276479
+Node: XEP-008676763
+Node: XEP-009077075
+Node: XEP-009177325
+Node: XEP-009277611
+Node: XEP-009577926
+Node: XEP-009678248
+Node: XEP-014678708
+Node: XEP-015378942
+Node: Concept index79213
+Node: Function index88146
+Node: Variable index93218
+
+End Tag Table
diff --git a/jabber.texi b/jabber.texi
index 77dde78..4109d8d 100644
--- a/jabber.texi
+++ b/jabber.texi
@@ -1,7 +1,7 @@
\input texinfo @c -*-texinfo-*-
@c %**start of header
@setfilename jabber.info
-@settitle jabber.el manual 0.7
+@settitle jabber.el manual 0.7.1
@c %**end of header
@dircategory Emacs
@@ -10,9 +10,9 @@
@end direntry
@copying
-This manual is for jabber.el, version 0.7.
+This manual is for jabber.el, version 0.7.1.
-Copyright @copyright{} 2004, 2005 Magnus Henoch, Tom Berger.
+Copyright @copyright{} 2004, 2005, 2006, 2007 Magnus Henoch, Tom Berger.
@quotation
Permission is granted to make and distribute verbatim copies or
@@ -45,12 +45,17 @@ this permission notice are preserved on all copies.
* Introduction::
* Basic operation::
* Groupchat::
+* Composing messages::
+* File transfer::
* Services::
* Personal information::
+* Avatars::
+* Time queries::
* Useful features::
* Message history::
* Message events::
* Roster import and export::
+* XMPP URIs::
* Customization::
* Hacking and extending::
* Protocol support::
@@ -75,7 +80,7 @@ interaction with servers and services. Then again, jabber.el delivers
excellent console performance and customizable hooks (if you have
speech synthesizer software, hook it up to your presence alerts).
-jabber.el does not yet support STARTTLS, GPG, sending and receiving
+jabber.el does not yet support GPG, sending and receiving
roster items, and various other things.
@menu
@@ -144,8 +149,8 @@ If you successfully connect, jabber.el will download your roster and
display it in a buffer called @code{*-jabber-*}.
By default, you will appear as ``online'' to your contacts. To change
-this to e.g. ``away'', type @kbd{M-x jabber-send-presence}.
-@xref{Presence}, for more information.
+this to e.g. ``away'', type @kbd{M-x jabber-send-presence} or @kbd{C-x
+C-j C-p}. @xref{Presence}, for more information.
To disconnect, type @kbd{M-x jabber-disconnect} or @kbd{C-x C-j C-d}.
@@ -223,10 +228,22 @@ presence that is sent, change the variables
With jabber.el, you can set your presence remotely. @xref{Ad-Hoc Commands}.
+@cindex directed presence
+@cindex send directed presence
+@findex jabber-send-directed-presence
+You can send ``directed presence'' with @kbd{M-x
+jabber-send-directed-presence}. This is mostly useful to manage
+transports---sending directed presence is a way to turn them on and
+off. You can also send directed presence to an annoying contact to
+appear as away or offline to that contact. Note, however, that in both
+of these cases, all subscribed entities will get your next global
+presence update.
+
@node Presence subscription, Roster buffer, Presence, Basic operation
@section Presence subscription
@cindex Presence subscription
+@cindex Subscribing to someone's presence
@findex jabber-send-subscription-request
Having permission to view the presence status of a person is called
@@ -242,13 +259,14 @@ jabber-send-subscription-request}. You will be prompted for the JID
to send it to. This command can also be accessed through the Roster
menu, by typing @kbd{C-c C-r} in the roster buffer. After that, you
will probably want to give the contact a more readable name. The
-command for that is @code{jabber-roster-change}, which is also available
-in the Roster menu.
+command for that is @code{jabber-roster-change}, which is also
+available in the Roster menu or by typing @kbd{e} on a person in the
+roster buffer.
@node Roster buffer, , Presence subscription, Basic operation
@section The roster buffer
-@cindex Roster buffer
+@cindex Roster buffer, basics
@cindex Menus
@cindex Key bindings
@findex jabber-display-roster
@@ -281,42 +299,58 @@ You can choose not to have the roster updated automatically on
presence changes (@pxref{Presence alerts}). In that case, you need to
call @code{jabber-display-roster} manually.
-@node Groupchat, Services, Basic operation, Top
+@node Groupchat, Composing messages, Basic operation, Top
@chapter Groupchat
@cindex Groupchat
@cindex MUC
-@findex jabber-groupchat-join
-@findex jabber-groupchat-leave
-@findex jabber-groupchat-get-config
-@findex jabber-muc-names
-@findex jabber-muc-set-role
-@findex jabber-muc-set-topic
+@cindex Chatrooms
The groupchat menu can be accessed by typing @kbd{C-c C-m} in the
roster buffer. You can also type the commands directly, as will be
shown here.
+@findex jabber-groupchat-join
+@cindex Joining a groupchat
+@cindex Changing nickname
+@cindex Nickname, changing
To join a groupchat, type @kbd{M-x jabber-groupchat-join}. You will
be prompted for the groupchat to join, and your nickname in the
groupchat. This nickname doesn't need to have any correlation to your
JID; in fact, groupchats are usually (but not always) configured such
that only moderators can see your JID. You can change your nickname
-with @kbd{M-x jabber-muc-nick}.
+with @kbd{M-x jabber-muc-nick}. @xref{Automation}, for setting default
+nicknames.
+
+@cindex query groupchat
+@vindex jabber-muc-disable-disco-check
+When trying to join a room, jabber.el first sends a service discovery
+info request to the room, to find out whether it exists and what
+features are enabled (in particular whether the room is
+password-protected). However, this can cause problems with some buggy
+MUC services (or services that respond in a way that jabber.el doesn't
+expect). A workaround for that is to set
+@code{jabber-muc-disable-disco-check} to t; however, the bug should be
+unearthed and fixed.
Groupchat messages will be displayed in a buffer called
@code{*-jabber-groupchat-:-@var{groupchat}-*}. It works much like the
chat buffer.
-To change the topic of a groupchat, type @kbd{M-x
-jabber-muc-set-topic}.
+@cindex Topic, MUC
+@findex jabber-muc-set-topic
+To change the topic of a groupchat, type @kbd{M-x jabber-muc-set-topic}.
+The current topic is shown in the header line.
+@findex jabber-groupchat-leave
To leave a groupchat, type @kbd{M-x jabber-groupchat-leave}.
+@findex jabber-groupchat-get-config
If you are the owner of a groupchat, you can change its configuration
by typing @kbd{M-x jabber-groupchat-get-config}. A configuration form
will be rendered in new buffer.
+@findex jabber-muc-names
To see which people are in a groupchat, type @kbd{M-x
jabber-muc-names}. This gives a list of nicknames, ``roles'',
``affiliations'', and possibly JIDs. @xref{MUC Administration}, for
@@ -386,6 +420,23 @@ Private MUC messages use the same alerts as normal chat messages.
@node MUC Administration, , Private messages, Groupchat
@section Administration
+Administration of a MUC room mostly consists of managing roles and
+affiliations. Roles are temporary, and apply until the user leaves the
+room. Affiliations are permanent, and based on JIDs.
+
+@subsection Roles
+
+@findex jabber-muc-set-role
+@cindex Kicking, MUC
+@cindex Voice, MUC
+@cindex Moderator, MUC
+@cindex Roles, MUC
+If you have moderator privileges, you can change the role of a
+participant with @kbd{M-x jabber-muc-set-role}. Kicking means setting
+the role to ``none''. Granting and revoking voice are ``participant''
+and ``visitor'', respectively. ``moderator'' gives moderator
+privileges, obviously.
+
The possible roles are:
@table @samp
@@ -403,6 +454,17 @@ private messages)
Not in room.
@end table
+@subsection Affiliations
+
+@findex jabber-muc-set-affiliation
+@cindex Affiliations, MUC
+@cindex Banning, MUC
+If you have admin or owner privileges, you can change the affiliation of
+a user with @kbd{M-x jabber-muc-set-affiliation}. Affiliation is
+persistent, and based on JIDs. Depending of your affiliation and the
+MUC implementation, you might not be allowed to perform all kinds of
+changes, and maybe not in one step.
+
Affiliations are:
@table @samp
@@ -413,30 +475,127 @@ Can destroy room, appoint admins, make people members, ban people.
Can make people members or ban people.
@item member
-Different privileges depending on room configuration (room may be
-members-only, or grant voice only to members)
+Can enter the room, and has voice by default.
@item none
-Rights depend on room configuration.
+Rights depend on room configuration. The room might be members-only, or
+grant voice only to members.
@item outcast
Banned from the room
@end table
-If you have moderator privileges, you can change the role of a
-participant with @kbd{M-x jabber-muc-set-role}. Kicking means setting
-the role to ``none''. Granting and revoking voice are ``participant''
-and ``visitor'', respectively. ``moderator'' gives moderator
-privileges, obviously. The role of a participant is ephemeral, and
-disappears when leaving the room.
-If you have admin or owner privileges, you can change the affiliation of
-a user. Affiliation is persistent, and based on JIDs. Depending of
-your affiliation and the MUC implementation, you might not be allowed to
-perform all kinds of changes, and maybe not in one step.
+@node Composing messages, File transfer, Groupchat, Top
+@chapter Composing messages
+
+@findex jabber-compose
+@cindex composing messages
+@cindex message composition
+
+The chat buffer interface can be inconvenient for some purposes. As you
+can't use @kbd{RET} to insert a newline (use @kbd{C-j} for that),
+writing a longer message can be painful. Also, it is not possible to
+include a subject in the message, or send the message to multiple
+recipients.
+These features are implemented by the message composing tool. Type
+@kbd{M-x jabber-compose} to start it. In the buffer that comes up, you
+can specify recipients, enter a subject, and type your message.
-@node Services, Personal information, Groupchat, Top
+@node File transfer, Services, Composing messages, Top
+@chapter File transfer
+
+@cindex File transfer
+@cindex Sending files
+
+jabber.el has limited support for file transfer. The most important
+limit is that files sent and received are kept in buffers, so Emacs must
+be able to allocate enough memory for the entire file, and the file size
+must be smaller than the maximum buffer size.@footnote{The maximum
+buffer size is kept in the variable @code{most-positive-fixnum}. On
+most 32-bit systems, this is 128 or 256 megabytes, depending on your
+Emacs version.}
+
+jabber.el is able to exchange files with most Jabber clients (and also
+some MSN transports), but notably not with the official Google Talk
+client. The Google Talk client uses a different file transfer protocol
+that, at the time of this release, has not been published.
+
+@menu
+* Receiving files::
+* Sending files::
+@end menu
+
+@node Receiving files, Sending files, File transfer, File transfer
+@section Receiving files
+
+Receiving files requires no configuration. When someone wants to send a
+file to you, you are asked (through @code{yes-or-no-p}) whether you want
+to accept the file. If you answer yes, you get to choose where to save
+the file.
+
+If the sender's client is correctly configured (this is often not the
+case; see below), the file transfer will start. Currently, the only way
+to watch the progress is to inspect the buffer of the file being
+transfered; @kbd{C-x C-b} is one way of doing that. @xref{List Buffers,
+, Listing Existing Buffers, emacs, GNU Emacs Manual}. When the transfer
+is done, the message ``@var{file} downloaded'' appears in the echo area,
+and the buffer is killed.
+
+If this doesn't happen, it is most likely the sender's fault. The
+sender needs to have a public IP address, either directly, through port
+forwarding (in which case the client needs to be configured with the
+real public IP address), or through an XEP-0065 proxy. If you have
+activated XML logging (@pxref{Debug options}), you can see the IP
+address that the other client is asking you to connect to there. Often
+you will find that this is an internal IP address (often starts with
+@code{192.168}). See the documentation of the sender's client for
+setting this up.
+
+@node Sending files, , Receiving files, File transfer
+@section Sending files
+
+@cindex proxy, file transfer
+@cindex file transfer proxy
+@cindex XEP-0065 proxy
+
+To send a file to someone, you need an XEP-0065 proxy.@footnote{This
+requirement is not inherent in the protocol, only in the current file
+transfer implementation of jabber.el, and in Emacs versions earlier than
+22.} If your Jabber server hosts such a proxy, it will be found
+automatically, otherwise it needs to be manually configured.
+
+You can check whether your Jabber server has a proxy with @kbd{M-x
+jabber-get-disco-items}; see @ref{Service discovery and browsing}.
+
+@vindex jabber-socks5-proxies
+@findex jabber-socks5-query-all-proxies
+To configure a proxy manually, customize the variable
+@code{jabber-socks5-proxies}. Putting @code{proxy.jabber.se} there
+should work. Type @kbd{M-x jabber-socks5-query-all-proxies} to see if
+the proxies answer.
+
+@findex jabber-ft-send
+Now, you can type @kbd{M-x jabber-ft-send} to send a file to someone.
+You need to enter the correct full JID, including resource, to get this
+right. If the contact is logged in with only one client, and you can
+see it online, just typing the JID or roster name is enough. If you run
+the command from a chat buffer, the JID of the contact is given as
+the default value.
+
+If the contact has several clients online, you probably want to send the
+file to a particular one. If you run this command from within a chat
+buffer, the default target will be the one that last sent a message to
+you. If you just type a bare JID or a roster name, the client with the
+highest priority will get the file.
+
+If the contact accepts the file, and the contact's client succeeds in
+connecting to the proxy, jabber.el will send the file through the
+proxy. During this time, your Emacs will be blocked, so you might want
+to avoid sending large files over slow connections.
+
+@node Services, Personal information, File transfer, Top
@chapter Services
@cindex Browse buffers
@@ -498,6 +657,8 @@ should be replaced with something better, you are completely right.
@cindex Changing password
@cindex Gateway registration
@cindex Password change
+@cindex Account removal
+@cindex Removing an account
@findex jabber-get-register
Some services, in particular user directories and gateways to legacy
@@ -558,7 +719,7 @@ browse buffer.
@findex jabber-ahc-get-list
@findex jabber-ahc-execute-command
-jabber.el supports a subset of JEP-0050, the standard for Ad-Hoc
+jabber.el supports a subset of XEP-0050, the standard for Ad-Hoc
Commands. As the name implies, this can be used for just about
anything. It has been used for remote-controlling clients (e.g. Psi),
and administering services (e.g. PyMSNt).
@@ -583,10 +744,11 @@ for JID and node. (If you already know those, you could of course
enter them yourself) The form you get should hopefully be
self-explanatory.
-@node Personal information, Useful features, Services, Top
+@node Personal information, Avatars, Services, Top
@chapter Personal information
@cindex vCard
+@cindex Personal information
@findex jabber-vcard-get
@findex jabber-vcard-edit
@@ -602,13 +764,63 @@ e-mail addresses, each of which has a set of orthogonal properties.
You can add and remove items with the [INS] and [DEL] buttons,
respectively.
-@node Useful features, Message history, Personal information, Top
+This is also where you set your avatar (@pxref{Avatars}). The size of
+your avatar file is limited to 8 kilobytes.
+
+@node Avatars, Time queries, Personal information, Top
+@chapter Avatars
+
+@cindex avatars
+@vindex jabber-vcard-avatars-retrieve
+@vindex jabber-vcard-avatars-publish
+@vindex jabber-avatar-cache-directory
+
+jabber.el supports viewing and publishing avatars according to XEP-0153,
+vCard-Based Avatars. By default, if you have an avatar in your vCard
+(@pxref{Personal information}), it will be published for others to see,
+and if other people publish their avatars, they will be displayed in the
+roster buffer and in the header line of chat buffers, assuming that your
+Emacs can display images.
+
+To disable retrieval of other people's avatars, set
+@code{jabber-vcard-avatars-retrieve} to nil. To disable publishing of
+your own avatar, set @code{jabber-vcard-avatars-publish} to nil.
+
+Avatars are cached in the directory specified by
+@code{jabber-avatar-cache-directory}, by default
+@file{~/.jabber-avatars/}. The cache is never cleaned, so you might
+want to do that yourself from time to time.
+
+@node Time queries, Useful features, Avatars, Top
+@chapter Time queries
+
+@cindex time query
+@findex jabber-get-time
+With @kbd{M-x jabber-get-time}, you can ask what time an entity (client,
+server or component) thinks it is, and what time zone it thinks it is
+in.
+
+@cindex last online
+@findex jabber-get-last-online
+You can query a server about when a certain user was last seen online.
+Use @kbd{M-x jabber-get-last-online} for that.
+
+@cindex uptime, query
+@cindex idle time, query
+@findex jabber-get-idle-time
+You can also ask a client about how long a user has been idle with
+@kbd{M-x jabber-get-idle-time}. Not all clients support this,
+e.g. jabber.el doesn't. This command can also tell the uptime of a
+server or component.
+
+@node Useful features, Message history, Time queries, Top
@chapter Useful features
jabber.el includes a number of features meant to improve the user
interface and do other useful things.
@menu
+* Autoaway::
* Modeline status::
* Keepalive::
* Tracking activity::
@@ -616,10 +828,47 @@ interface and do other useful things.
* Spell checking::
@end menu
-@node Modeline status, Keepalive, Useful features, Useful features
+@node Autoaway, Modeline status, Useful features, Useful features
+@section Autoaway
+
+@cindex autoaway
+@cindex idle
+@cindex xprintidle
+@vindex jabber-autoaway-method
+
+It is possible to automatically set your status to ``away'' when you
+haven't used your computer for a while. This lets your contacts know
+that you might not answer immediately.
+
+To activate this feature, add @code{jabber-autoaway-start} to
+@code{jabber-post-connect-hook}, e.g:
+@example
+(add-hook 'jabber-post-connect-hook 'jabber-autoaway-start)
+@end example
+
+There are different methods to find how long you have been ``idle''.
+The method to use is specified by @code{jabber-autoaway-method}. The
+value of this variable should be a function that returns the number of
+seconds you have been idle. Three functions are provided.
+
+If you are running Emacs 22 and thus have the @code{current-idle-time}
+function, it is used by default. Note that this method only measures
+the time since you last interacted with Emacs, and thus disregards
+activity in other programs.
+
+If you are using the X Window System, you can use the
+@uref{http://www.dtek.chalmers.se/~henoch/text/xprintidle.html,
+xprintidle} program. Make sure that @code{jabber-xprintidle-program} is
+set to the correct file name. This uses the same method as XScreensaver
+to find your idle time.
+
+If you are using Emacs on a GNU/Linux terminal, the function
+@code{jabber-termatime-get-idle-time} is used by default.
+
+@node Modeline status, Keepalive, Autoaway, Useful features
@section Modeline status
-@cindex modeline
+@cindex Modeline
@findex jabber-mode-line-mode
@vindex jabber-mode-line-mode
@vindex jabber-mode-line-compact
@@ -639,7 +888,8 @@ contacts, respectively.
@node Keepalive, Tracking activity, Modeline status, Useful features
@section Keepalive
-@cindex keepalive
+@cindex Keepalive
+@cindex Detecting lost connections
@findex jabber-keepalive-start
@findex jabber-keepalive-stop
@vindex jabber-keepalive-interval
@@ -707,7 +957,8 @@ action based on @code{jabber-activity-jids},
@node Watch buddies, Spell checking, Tracking activity, Useful features
@section Watch buddies
-@cindex watch
+@cindex Watch
+@cindex Online notifications
@findex jabber-watch-add
@findex jabber-watch-remove
@@ -725,6 +976,9 @@ of it, type @kbd{M-x jabber-watch-remove}.
@node Spell checking, , Watch buddies, Useful features
@section Spell checking
+@cindex flyspell
+@cindex Spell checking
+
You can activate spell checking in a chat buffer with @kbd{M-x
flyspell-mode}. It will check only what you are currently writing, not
what you receive or what you have already sent. You may want to add
@@ -736,9 +990,9 @@ Checking and Correcting Spelling, emacs, GNU Emacs Manual}.
@node Message history, Message events, Useful features, Top
@chapter Message history
-@cindex history
-@cindex backlog
-@cindex rotation
+@cindex History
+@cindex Backlog
+@cindex Rotation
@vindex jabber-history-enabled
@vindex jabber-global-history-filename
@vindex jabber-use-global-history
@@ -790,9 +1044,9 @@ works for both per-contact and global history logging strategies.
@node Message events, Roster import and export, Message history, Top
@chapter Message events
-@cindex composing
-@cindex delivered
-@cindex displayed
+@cindex Composing
+@cindex Delivered
+@cindex Displayed
@vindex jabber-events-request-these
@vindex jabber-events-confirm-delivered
@vindex jabber-events-confirm-displayed
@@ -828,13 +1082,13 @@ the variables @code{jabber-events-confirm-delivered},
not to request such information by customizing
@code{jabber-events-request-these}.
-@node Roster import and export, Customization, Message events, Top
+@node Roster import and export, XMPP URIs, Message events, Top
@chapter Roster import and export
@findex jabber-export-roster
@findex jabber-import-roster
-@cindex export roster
-@cindex import roster
+@cindex Export roster
+@cindex Import roster
Your roster is saved on the Jabber server, and usually not in the
client. However, you might want to save the roster to a file anyway.
@@ -853,7 +1107,66 @@ imported data. Subscriptions will be updated.
The format of the roster files is the XML used by roster pushes in the
XMPP protocol, in UTF-8 encoding.
-@node Customization, Hacking and extending, Roster import and export, Top
+@node XMPP URIs, Customization, Roster import and export, Top
+@chapter XMPP URIs
+
+@cindex URIs
+@cindex URLs
+@cindex links
+@cindex xmpp: links
+@cindex Mozilla integration
+@cindex web browser integration
+@cindex browser integration
+@findex jabber-handle-uri
+
+Many web page authors use links starting with @samp{xmpp:} for JIDs.
+Your web browser could be made to pass such links to jabber.el, so that
+such links are actually useful and not just decoration. How to do that
+depends on your operating system and web browser.
+
+@section Mozilla and Unix
+
+If you use a Mozilla-based web browser on a Unix-like operating system,
+follow these steps.
+
+@enumerate
+@item
+Make sure you are running the Emacs server. @xref{Emacs Server, , Using
+Emacs as a Server, emacs, GNU Emacs Manual}.
+
+@item
+Note the path of the @file{xmppuri.sh} file in the jabber.el
+distribution, and make sure it is executable.
+
+@item
+Set the Mozilla preference @samp{network.protocol-handler.app.xmpp} to
+the path of @file{xmppuri.sh}. There are two ways to do this:
+
+@itemize
+@item
+Go to the URL @samp{about:config}, right-click in the list, choose ``New
+string'', and enter @samp{network.protocol-handler.app.xmpp} and the
+path in the following dialogs.
+
+@item
+Open or create the file @file{user.js} in your Mozilla profile directory
+(in the same directory as @file{prefs.js}), and add the following line:
+
+@example
+user_pref("network.protocol-handler.app.xmpp", "@var{/path/to}/xmppuri.sh");
+@end example
+
+Restart Mozilla for this change to take effect.
+@end itemize
+@end enumerate
+
+@section Other systems
+
+If you know how to pass an XMPP URI from your browser to the function
+@code{jabber-handle-uri}, your contribution for this section would be
+appreciated.
+
+@node Customization, Hacking and extending, XMPP URIs, Top
@chapter Customization
@findex jabber-customize
@@ -883,6 +1196,8 @@ this is Emacs. To open a customization buffer for jabber.el, type
@vindex jabber-resource
@vindex jabber-default-priority
@vindex jabber-nickname
+@cindex Username
+@cindex Resource
@code{jabber-username} is the username part of your JID.
@@ -914,8 +1229,12 @@ priority during a session with @code{jabber-send-presence}.
@vindex jabber-port
@vindex jabber-connection-type
@vindex jabber-connection-ssl-program
+@cindex Connection settings
+@cindex Network settings
@cindex SSL
@cindex TLS
+@cindex STARTTLS
+@cindex SRV records
@code{jabber-network-server} is the hostname or IP address of your
server. If it is set to @code{nil}, jabber.el will use the name in
@@ -925,18 +1244,27 @@ server. If it is set to @code{nil}, jabber.el will use the name in
@code{nil}, the default port is selected based on the chosen
connection method.
+If both @code{jabber-network-server} and @code{jabber-port} are nil, and
+a sufficiently modern @code{dns.el} is available, jabber.el will use SRV
+records to find the right hostname and port.
+
@code{jabber-connection-type} specifies what kind of connection to
use. @code{network} means normal unencrypted network connection
(usually on port 5222), and @code{ssl} means encrypted connection
-through GnuTLS or OpenSSL (port 5223). You can change the settings of
-the encryption program through @kbd{M-x customize-group RET tls} or
-@kbd{M-x customize-group RET ssl}, respectively.
-
+through GnuTLS or OpenSSL (port 5223), while @code{starttls} will
+initiate an unencrypted connection and switch to encrypted if offered
+by the server. You can change the settings of the encryption program
+through @kbd{M-x customize-group RET tls}, @kbd{M-x customize-group RET starttls}
+or @kbd{M-x customize-group RET ssl}, respectively.
+
+@cindex GnuTLS
+@cindex OpenSSL
By default, GnuTLS will be used if the @code{tls} library is available,
and if that fails, OpenSSL will be used if the @code{ssl} library is
available. You can force the use of either program by setting
@code{jabber-connection-ssl-program} to @code{gnutls} or @code{openssl},
-respectively.
+respectively. If you use @code{starttls} the library with the same name is
+required, and it depends on the GnuTLS command line client.
@node Miscellaneous settings, Customizing the roster buffer, Connection settings, Customization
@section Miscellaneous settings
@@ -960,7 +1288,9 @@ to enable it permanently.
@vindex jabber-resource-line-format
@vindex jabber-roster-buffer
@vindex jabber-roster-show-bindings
+@cindex Roster buffer, customizing
+@cindex Sorting the roster
@code{jabber-roster-sort-functions} controls how roster items are
sorted. By default, contacts are sorted first by presence, and then
alphabetically by displayed name.
@@ -978,8 +1308,12 @@ contact looks. It is a string where some characters are special if
preceded by a percent sign:
@table @code
+@item %a
+Avatar of contact, if any
@item %c
"*" if the contact is connected, or " " if not
+@item %u
+Subscription state - see below
@item %n
Nickname of contact, or JID if no nickname
@item %j
@@ -1005,30 +1339,32 @@ connect.
keybindings at the top of the roster buffer. You need to run @kbd{M-x
jabber-display-roster} after changing this variable to update the display.
+@code{%u} is replaced by one of the strings given by
+`jabber-roster-subscription-display'.
+
@node Customizing the chat buffer, Customizing alerts, Customizing the roster buffer, Customization
@section Customizing the chat buffer
-@vindex jabber-chat-time-format
-@vindex jabber-chat-delayed-time-format
-@vindex jabber-print-rare-time
-@vindex jabber-rare-time-format
-@vindex jabber-chat-local-prompt-format
-@vindex jabber-chat-foreign-prompt-format
-@vindex jabber-chat-prompt-local
-@vindex jabber-chat-prompt-foreign
-@vindex jabber-chat-header-line-format
-@vindex jabber-muc-header-line-format
-@vindex jabber-chat-fill-long-lines
@cindex Chat buffer
@cindex Timestamps
+@cindex Faces, chat buffer
You can customize the look of the prompts in the chat buffer. There
are separate settings for local (i.e. your own messages) and foreign
prompts.
+@vindex jabber-chat-text-local
+@vindex jabber-chat-text-foreign
+@code{jabber-chat-text-local} and @code{jabber-chat-text-foreign}
+determine the faces used for chat messages.
+
+@vindex jabber-chat-prompt-local
+@vindex jabber-chat-prompt-foreign
@code{jabber-chat-prompt-local} and @code{jabber-chat-prompt-foreign}
determine the faces used for the prompts.
+@vindex jabber-chat-local-prompt-format
+@vindex jabber-chat-foreign-prompt-format
@code{jabber-chat-local-prompt-format} and
@code{jabber-chat-foreign-prompt-format} determine what text is
displayed in the prompts. They are format strings, with the following
@@ -1041,15 +1377,21 @@ The time when the message was sent or received
The nickname of the user. For the foreign prompt, this is the name of
the contact in the roster, or the JID if no name set. For the local
prompt, this is the username part of your JID.
+@item %u
+The username of the user.
+@item %r
+The resource.
@item %j
The bare JID of the user
@end table
+@vindex jabber-chat-time-format
@code{jabber-chat-time-format} defines how @code{%t} shows time. Its
format is identical to that passed to @code{format-time-string}.
@xref{Time Conversion, , Time Conversion, elisp, GNU Emacs Lisp
Reference Manual}.
+@vindex jabber-chat-delayed-time-format
@code{jabber-chat-delayed-time-format} is used instead of
@code{jabber-chat-time-format} for delayed messages (messages sent while
you were offline, or fetched from history). This way you can have short
@@ -1057,12 +1399,16 @@ timestamps everywhere except where you need long ones. You can always
see the complete timestamp in a tooltip by hovering over the prompt with
the mouse.
-By default, timestamps are printed in the chat buffer every hour (at
+@vindex jabber-print-rare-time
+@vindex jabber-rare-time-format
+@vindex jabber-chat-text-localBy default, timestamps are printed in the chat buffer every hour (at
``rare'' times). This can be toggled with
@code{jabber-print-rare-time}. You can customize the displayed time by
setting @code{jabber-rare-time-format}. Rare timestamps will be printed
whenever time formatted by that format string would change.
+@vindex jabber-chat-header-line-format
+@vindex jabber-muc-header-line-format
You can also customize the header line of chat buffers, by modifying
the variable @code{jabber-chat-header-line-format}. The format of
that variable is the same as that of @code{mode-line-format} and
@@ -1070,6 +1416,8 @@ that variable is the same as that of @code{mode-line-format} and
Format, elisp, GNU Emacs Lisp Reference Manual}. For MUC buffers,
@code{jabber-muc-header-line-format} is used instead.
+@vindex jabber-chat-fill-long-lines
+@cindex Filling long lines in chat buffer
The variable @code{jabber-chat-fill-long-lines} controls whether long
lines in the chat buffer are filled.
@@ -1115,10 +1463,10 @@ mailing list, or to the Sourceforge patch tracker.
Alert hooks are meant for optional UI things, that are subject to
varying user tastes, and that can be toggled by simply adding or
-removing the function from/to the hook. For other things, there are
-corresponding general hooks, that are defvars instead of defcustoms, and
-that are to be managed by Lisp code. They have the same name as the
-alert hooks minus the @code{-alert} part,
+removing the function to and from the hook. For other things, there
+are corresponding general hooks, that are defvars instead of
+defcustoms, and that are to be managed by Lisp code. They have the
+same name as the alert hooks minus the @code{-alert} part,
i.e. @code{jabber-message-hooks} vs @code{jabber-alert-message-hooks},
etc.
@@ -1133,8 +1481,8 @@ etc.
@node Standard alerts, Presence alerts, Customizing alerts, Customizing alerts
@subsection Standard alerts
-@cindex alerts
-@cindex scroll
+@cindex Alerts
+@cindex Scroll
Eight alerts are already written for all four alert categories. These
all obey the result from the corresponding message function.
@@ -1161,7 +1509,10 @@ The @code{wave} alerts play a sound file by calling
@code{play-sound-file}. No sound files are provided. To use this,
enter the names of the sound files in
@code{jabber-alert-message-wave}, @code{jabber-alert-presence-wave}
-and @code{jabber-alert-info-wave}, respectively.
+and @code{jabber-alert-info-wave}, respectively. You can specify
+specific sound files for contacts matching a regexp in the variables
+@code{jabber-alert-message-wave-alist} and
+@code{jabber-alert-presence-wave-alist}.
The @code{screen} alerts send a message through the Screen terminal
manager (see @uref{http://www.gnu.org/software/screen/}). They do no
@@ -1261,6 +1612,7 @@ function.
@subsection MUC alerts
@vindex jabber-alert-muc-function
+@vindex jabber-muc-alert-self
@findex jabber-muc-default-message
Set @code{jabber-alert-muc-function} to your desired
@@ -1284,6 +1636,9 @@ All MUC alert hooks take the same arguments plus the additional
@var{proposed-alert}, which is the result of the specified message
function.
+By default, no alert is made for messages from yourself. To change
+that, customize the variable @code{jabber-muc-alert-self}.
+
@node Info alerts, , MUC alerts, Customizing alerts
@subsection Info alerts
@@ -1302,39 +1657,43 @@ The info alert hooks take an extra argument, as could be expected.
@node Hooks, Debug options, Customizing alerts, Customization
@section Hooks
-@vindex jabber-post-connect-hook
-@vindex jabber-pre-disconnect-hook
-@vindex jabber-post-disconnect-hook
-@vindex jabber-lost-connection-hook
-
jabber.el provides various hooks that you can use for whatever
purpose.
@table @code
+@vindex jabber-post-connect-hook
@item jabber-post-connect-hook
This hook is called after successful connection and authentication.
By default it contains @code{jabber-send-default-presence}
(@pxref{Presence}).
+@vindex jabber-lost-connection-hook
@item jabber-lost-connection-hook
This hook is called when you have been disconnected for unknown
reasons. Usually this isn't noticed for quite a long time.
+@vindex jabber-pre-disconnect-hook
@item jabber-pre-disconnect-hook
This hook is called just before voluntary disconnection. This might
be due to failed authentication, so check
@code{*jabber-authenticated*} if you want to send a stanza.
+@vindex jabber-post-disconnect-hook
@item jabber-post-disconnect-hook
This hook is called after disconnection of any kind, possibly just
after @code{jabber-lost-connection-hook}.
+@vindex jabber-chat-mode-hook
+@item jabber-chat-mode-hook
+This hook is called when a new chat buffer is created.
+
@end table
@node Debug options, , Hooks, Customization
@section Debug options
@vindex jabber-debug-log-xml
+@cindex XML log
These settings provide a lot of information which is usually not very
interesting, but can be useful for debugging various things.
@@ -1609,40 +1968,45 @@ behaviour of downstream functions.
@node Protocol support, Concept index, Hacking and extending, Top
@appendix Protocol support
+@cindex Supported protocols
+
These are the protocols currently supported (in full or partially) by
jabber.el.
@menu
-* RFC 3920 (XMPP-CORE)::
-* RFC 3921 (XMPP-IM)::
-* JEP-0004 (Data Forms)::
-* JEP-0020 (Feature Negotiation)::
-* JEP-0022 (Message Events)::
-* JEP-0030 (Service Discovery)::
-* JEP-0045 (Multi-User Chat)::
-* JEP-0050 (Ad-Hoc Commands)::
-* JEP-0054 (vcard-temp)::
-* JEP-0055 (Jabber Search)::
-* JEP-0065 (SOCKS5 Bytestreams)::
-* JEP-0066 (Out of Band Data)::
-* JEP-0068 (Field Standardization for Data Forms)::
-* JEP-0077 (In-Band Registration)::
-* JEP-0078 (Non-SASL Authentication)::
-* JEP-0082 (Jabber Date and Time Profiles)::
-* JEP-0086 (Error Condition Mappings)::
-* JEP-0091 (Delayed Delivery)::
-* JEP-0092 (Software Version)::
-* JEP-0095 (Stream Initiation)::
-* JEP-0096 (File Transfer)::
+* RFC 3920:: XMPP-CORE
+* RFC 3921:: XMPP-IM
+* XEP-0004:: Data Forms
+* XEP-0012:: Last Activity
+* XEP-0020:: Feature Negotiation
+* XEP-0022:: Message Events
+* XEP-0030:: Service Discovery
+* XEP-0045:: Multi-User Chat
+* XEP-0049:: Private XML Storage
+* XEP-0050:: Ad-Hoc Commands
+* XEP-0054:: vcard-temp
+* XEP-0055:: Jabber Search
+* XEP-0065:: SOCKS5 Bytestreams
+* XEP-0066:: Out of Band Data
+* XEP-0068:: Field Standardization for Data Forms
+* XEP-0077:: In-Band Registration
+* XEP-0078:: Non-SASL Authentication
+* XEP-0082:: Jabber Date and Time Profiles
+* XEP-0086:: Error Condition Mappings
+* XEP-0090:: Entity Time
+* XEP-0091:: Delayed Delivery
+* XEP-0092:: Software Version
+* XEP-0095:: Stream Initiation
+* XEP-0096:: File Transfer
+* XEP-0146:: Remote Controlling Clients
+* XEP-0153:: vCard-Based Avatars
@end menu
-@node RFC 3920 (XMPP-CORE), RFC 3921 (XMPP-IM), Protocol support, Protocol support
+@node RFC 3920, RFC 3921, Protocol support, Protocol support
@section RFC 3920 (XMPP-CORE)
Most of RFC 3920 is supported, with the following exceptions.
-The STARTTLS feature is not supported.
-
SASL is supported only when an external SASL library from FLIM or Gnus
is present. As SASL is an essential part to XMPP, jabber.el will send
pre-XMPP stream headers if it is not available.
@@ -1654,9 +2018,9 @@ jabber.el doesn't interpret namespace prefixes.
The @code{xml:lang} attribute is neither interpreted nor generated.
-SRV records are not used.
+SRV records are used if a modern version of @code{dns.el} is installed.
-@node RFC 3921 (XMPP-IM), JEP-0004 (Data Forms), RFC 3920 (XMPP-CORE), Protocol support
+@node RFC 3921, XEP-0004, RFC 3920, Protocol support
@section RFC 3921 (XMPP-IM)
Most of RFC 3921 is supported, with the following exceptions.
@@ -1665,16 +2029,17 @@ Messages of type ``headline'' are not treated in any special way.
The @code{<thread/>} element is not used or generated.
-Neither sending nor receiving ``directed presence'' is supported.
+Sending ``directed presence'' is supported; however, presence stanzas
+received from contacts not in roster are ignored.
Privacy lists are not supported at all.
jabber.el doesn't support XMPP-E2E or ``im:'' CPIM URIs.
-@node JEP-0004 (Data Forms), JEP-0020 (Feature Negotiation), RFC 3921 (XMPP-IM), Protocol support
-@section JEP-0004 (Data Forms)
+@node XEP-0004, XEP-0012, RFC 3921, Protocol support
+@section XEP-0004 (Data Forms)
-JEP-0004 support is good enough for many purposes. Limitations are
+XEP-0004 support is good enough for many purposes. Limitations are
the following.
Forms in incoming messages are not interpreted. See each specific
@@ -1690,91 +2055,97 @@ The field types ``jid-single'', ``jid-multi'' and ``list-multi'' are
not implemented, due to programmer laziness. Let us know if you need
them.
-@node JEP-0020 (Feature Negotiation), JEP-0022 (Message Events), JEP-0004 (Data Forms), Protocol support
-@section JEP-0020 (Feature Negotiation)
+@node XEP-0012, XEP-0020, XEP-0004, Protocol support
+@section XEP-0012 (Last Activity)
+
+jabber.el can generate all three query types described in the protocol.
+However, it does not answer to such requests.
-There are no known limitations or bugs in JEP-0020 support.
+@node XEP-0020, XEP-0022, XEP-0012, Protocol support
+@section XEP-0020 (Feature Negotiation)
-@node JEP-0022 (Message Events), JEP-0030 (Service Discovery), JEP-0020 (Feature Negotiation), Protocol support
-@section JEP-0022 (Message Events)
+There are no known limitations or bugs in XEP-0020 support.
+
+@node XEP-0022, XEP-0030, XEP-0020, Protocol support
+@section XEP-0022 (Message Events)
jabber.el understands all four specified kinds of message events
(offline, delivered, displayed, and composing) and by default requests
all of them. It also reports those three events that make sense for
clients.
-@node JEP-0030 (Service Discovery), JEP-0045 (Multi-User Chat), JEP-0022 (Message Events), Protocol support
-@section JEP-0030 (Service Discovery)
-
-Service discovery is supported, both as client and server, with the
-following limitations. Currently, the client part is not used by any
-code, but is provided only as a user tool. The user interface is not
-appealing.
+@node XEP-0030, XEP-0045, XEP-0022, Protocol support
+@section XEP-0030 (Service Discovery)
-Publishing items is not supported.
+Service discovery is supported, both as client and server. When used in
+the code, service discovery results are cached indefinitely.
-@node JEP-0045 (Multi-User Chat), JEP-0050 (Ad-Hoc Commands), JEP-0030 (Service Discovery), Protocol support
-@section JEP-0045 (Multi-User Chat)
+@node XEP-0045, XEP-0049, XEP-0030, Protocol support
+@section XEP-0045 (Multi-User Chat)
-jabber.el supports parts of JEP-0045. Entering, leaving and chatting
+jabber.el supports parts of XEP-0045. Entering, leaving and chatting
work. So do invitations and private messages. Room configuration is
supported. Changing roles of participants (basic moderation) is
implemented, as is changing affiliations, but requesting affiliation
lists is not yet supported.
-@node JEP-0050 (Ad-Hoc Commands), JEP-0054 (vcard-temp), JEP-0045 (Multi-User Chat), Protocol support
-@section JEP-0050 (Ad-Hoc Commands)
+@node XEP-0049, XEP-0050, XEP-0045, Protocol support
+@section XEP-0049 (Private XML Storage)
+
+jabber.el contains an implementation of XEP-0049; however it is not used
+for anything right now.
+
+@node XEP-0050, XEP-0054, XEP-0049, Protocol support
+@section XEP-0050 (Ad-Hoc Commands)
-jabber.el is probably the first implementation of JEP-0050 (see
+jabber.el is probably the first implementation of XEP-0050 (see
@uref{http://article.gmane.org/gmane.network.jabber.devel/21413, post
on jdev from 2004-03-10}). Both the client and server parts are
supported.
-@node JEP-0054 (vcard-temp), JEP-0055 (Jabber Search), JEP-0050 (Ad-Hoc Commands), Protocol support
-@section JEP-0054 (vcard-temp)
+@node XEP-0054, XEP-0055, XEP-0050, Protocol support
+@section XEP-0054 (vcard-temp)
Both displaying other users' vCards and editing your own vCard are
-supported. The implementation tries to follow the schema in the JEP
+supported. The implementation tries to follow the schema in the XEP
accurately.
-@node JEP-0055 (Jabber Search), JEP-0065 (SOCKS5 Bytestreams), JEP-0054 (vcard-temp), Protocol support
-@section JEP-0055 (Jabber Search)
+@node XEP-0055, XEP-0065, XEP-0054, Protocol support
+@section XEP-0055 (Jabber Search)
-JEP-0055 is supported, both with traditional fields and with Data
-Forms (@pxref{JEP-0004 (Data Forms)}). As the traditional fields
-specified by the JEP is a subset of those allowed in JEP-0077,
-handling of those two form types are merged. @ref{JEP-0077 (In-Band
-Registration)}.
+XEP-0055 is supported, both with traditional fields and with Data Forms
+(@pxref{XEP-0004}). As the traditional fields specified by the XEP is a
+subset of those allowed in XEP-0077, handling of those two form types
+are merged. @xref{XEP-0077}.
-@node JEP-0065 (SOCKS5 Bytestreams), JEP-0066 (Out of Band Data), JEP-0055 (Jabber Search), Protocol support
-@section JEP-0065 (SOCKS5 Bytestreams)
+@node XEP-0065, XEP-0066, XEP-0055, Protocol support
+@section XEP-0065 (SOCKS5 Bytestreams)
-JEP-0065 support seems to work, but it is not yet enabled by default.
-
-Currently jabber.el cannot act as a server, not even on on Emacsen
-that support server sockets (GNU Emacs 22 and up). Therefore it
-relies on proxies. Proxies have to be entered and queried manually.
+XEP-0065 is supported. Currently jabber.el cannot act as a server, not
+even on on Emacsen that support server sockets (GNU Emacs 22 and up).
+Therefore it relies on proxies. Proxies have to be entered and queried
+manually.
Psi's ``fast mode''
(@uref{http://delta.affinix.com/specs/stream.html}), which gives
greater flexibility with regards to NAT, is not implemented.
-@node JEP-0066 (Out of Band Data), JEP-0068 (Field Standardization for Data Forms), JEP-0065 (SOCKS5 Bytestreams), Protocol support
-@section JEP-0066 (Out of Band Data)
+@node XEP-0066, XEP-0068, XEP-0065, Protocol support
+@section XEP-0066 (Out of Band Data)
jabber.el will display URLs sent in message stanzas qualified by
-the @code{jabber:x:oob} namespace, as described in this JEP. Sending
+the @code{jabber:x:oob} namespace, as described in this XEP. Sending
such URLs or doing anything with iq stanzas (using the
@code{jabber:iq:oob} namespace) is not supported.
-@node JEP-0068 (Field Standardization for Data Forms), JEP-0077 (In-Band Registration), JEP-0066 (Out of Band Data), Protocol support
-@section JEP-0068 (Field Standardization for Data Forms)
+@node XEP-0068, XEP-0077, XEP-0066, Protocol support
+@section XEP-0068 (Field Standardization for Data Forms)
-JEP-0068 is only used in the context of creating a new Jabber account,
+XEP-0068 is only used in the context of creating a new Jabber account,
to prefill the username field of the registration form.
-@node JEP-0077 (In-Band Registration), JEP-0078 (Non-SASL Authentication), JEP-0068 (Field Standardization for Data Forms), Protocol support
-@section JEP-0077 (In-Band Registration)
+@node XEP-0077, XEP-0078, XEP-0068, Protocol support
+@section XEP-0077 (In-Band Registration)
In-band registration is supported for all purposes. That means
registering a new Jabber account, changing Jabber password, removing a
@@ -1785,61 +2156,70 @@ redirections are not.
jabber.el will not prevent or alert a user trying to change a password
over an unencrypted connection.
-@node JEP-0078 (Non-SASL Authentication), JEP-0082 (Jabber Date and Time Profiles), JEP-0077 (In-Band Registration), Protocol support
-@section JEP-0078 (Non-SASL Authentication)
+@node XEP-0078, XEP-0082, XEP-0077, Protocol support
+@section XEP-0078 (Non-SASL Authentication)
Non-SASL authentication is supported, both plaintext and digest.
Digest is preferred, and a warning is displayed to the user if only
plaintext is available.
-@node JEP-0082 (Jabber Date and Time Profiles), JEP-0086 (Error Condition Mappings), JEP-0078 (Non-SASL Authentication), Protocol support
-@section JEP-0082 (Jabber Date and Time Profiles)
+@node XEP-0082, XEP-0086, XEP-0078, Protocol support
+@section XEP-0082 (Jabber Date and Time Profiles)
-The DateTime profile of JEP-0082 is supported. Currently this is only
+The DateTime profile of XEP-0082 is supported. Currently this is only
used for file transfer.
-@node JEP-0086 (Error Condition Mappings), JEP-0091 (Delayed Delivery), JEP-0082 (Jabber Date and Time Profiles), Protocol support
-@section JEP-0086 (Error Condition Mappings)
+@node XEP-0086, XEP-0090, XEP-0082, Protocol support
+@section XEP-0086 (Error Condition Mappings)
Legacy errors are interpreted, but never generated. XMPP style error
messages take precedence when errors are reported to the user.
-@node JEP-0091 (Delayed Delivery), JEP-0092 (Software Version), JEP-0086 (Error Condition Mappings), Protocol support
-@section JEP-0091 (Delayed Delivery)
+@node XEP-0090, XEP-0091, XEP-0086, Protocol support
+@section XEP-0090 (Entity Time)
+
+jabber.el can query other entities for their time, and return the
+current time to those who ask.
+
+@node XEP-0091, XEP-0092, XEP-0090, Protocol support
+@section XEP-0091 (Delayed Delivery)
The time specified on delayed incoming messages is interpreted, and
displayed in chat buffers instead of the current time.
-@node JEP-0092 (Software Version), JEP-0095 (Stream Initiation), JEP-0091 (Delayed Delivery), Protocol support
-@section JEP-0092 (Software Version)
+@node XEP-0092, XEP-0095, XEP-0091, Protocol support
+@section XEP-0092 (Software Version)
The user can request the version of any entity. jabber.el answers
version requests to anyone, giving ``jabber.el'' as name, and the
Emacs version as OS.
-@node JEP-0095 (Stream Initiation), JEP-0096 (File Transfer), JEP-0092 (Software Version), Protocol support
-@section JEP-0095 (Stream Initiation)
+@node XEP-0095, XEP-0096, XEP-0092, Protocol support
+@section XEP-0095 (Stream Initiation)
-JEP-0095 is supported, both incoming and outgoing, with the following
-exceptions. It is not enabled by default, as it hasn't received much
-testing.
+XEP-0095 is supported, both incoming and outgoing, except that jabber.el
+doesn't check service discovery results before sending a stream
+initiation request.
-jabber.el doesn't check service discovery results before sending a
-stream initiation request.
+@node XEP-0096, XEP-0146, XEP-0095, Protocol support
+@section XEP-0096 (File Transfer)
-@node JEP-0096 (File Transfer), , JEP-0095 (Stream Initiation), Protocol support
-@section JEP-0096 (File Transfer)
+Both sending and receiving files is supported. If a suitable program is
+found, MD5 hashes of outgoing files are calculated and sent. However,
+hashes of received files are not checked. Ranged transfers are not
+supported. In-band bytestreams are not yet supported, even though
+XEP-0096 requires them.
-Both sending and receiving files is supported, though not enabled by
-default. The following limitations apply.
+@node XEP-0146, XEP-0153, XEP-0096, Protocol support
+@section XEP-0146 (Remote Controlling Clients)
-The hash of a file being sent is not calculated and sent in the
-request.
+The ``set-status'' command in XEP-0146 is supported.
-Ranged transfers are not supported.
+@node XEP-0153, , XEP-0146, Protocol support
+@section XEP-0153 (vCard-Based Avatars)
-In-band bytestreams are not yet supported, even though JEP-0096
-requires them.
+vCard-based avatars are supported, both publishing and displaying. The
+pixel size limits on avatars are not enforced.
@node Concept index, Function index, Protocol support, Top
@unnumbered Concept index
diff --git a/sha1.el b/sha1.el
deleted file mode 100644
index 99b9aa4..0000000
--- a/sha1.el
+++ /dev/null
@@ -1,443 +0,0 @@
-;;; sha1.el --- SHA1 Secure Hash Algorithm in Emacs-Lisp
-
-;; Copyright (C) 1999, 2001, 2002, 2003, 2004,
-;; 2005 Free Software Foundation, Inc.
-
-;; Author: Shuhei KOBAYASHI <shuhei@aqua.ocn.ne.jp>
-;; Keywords: SHA1, FIPS 180-1
-
-;; This file is part of FLIM (Faithful Library about Internet Message).
-
-;; 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, 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; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; This program is implemented from the definition of SHA-1 in FIPS PUB
-;; 180-1 (Federal Information Processing Standards Publication 180-1),
-;; "Announcing the Standard for SECURE HASH STANDARD".
-;; <URL:http://www.itl.nist.gov/div897/pubs/fip180-1.htm>
-;; (EXCEPTION; two optimizations taken from GnuPG/cipher/sha1.c)
-;;
-;; Test cases from FIPS PUB 180-1.
-;;
-;; (sha1 "abc")
-;; => a9993e364706816aba3e25717850c26c9cd0d89d
-;;
-;; (sha1 "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
-;; => 84983e441c3bd26ebaae4aa1f95129e5e54670f1
-;;
-;; (sha1 (make-string 1000000 ?a))
-;; => 34aa973cd4c4daa4f61eeb2bdbad27316534016f
-;;
-;; BUGS:
-;; * It is assumed that length of input string is less than 2^29 bytes.
-;; * It is caller's responsibility to make string (or region) unibyte.
-;;
-;; TODO:
-;; * Rewrite from scratch!
-;; This version is much faster than Keiichi Suzuki's another sha1.el,
-;; but it is too dirty.
-
-;;; Code:
-
-(require 'hex-util)
-
-;;;
-;;; external SHA1 function.
-;;;
-
-(defgroup sha1 nil
- "Elisp interface for SHA1 hash computation."
- :version "22.1"
- :group 'extensions)
-
-(defcustom sha1-maximum-internal-length 500
- "*Maximum length of message to use Lisp version of SHA1 function.
-If message is longer than this, `sha1-program' is used instead.
-
-If this variable is set to 0, use external program only.
-If this variable is set to nil, use internal function only."
- :type 'integer
- :group 'sha1)
-
-(defcustom sha1-program '("sha1sum")
- "*Name of program to compute SHA1.
-It must be a string \(program name\) or list of strings \(name and its args\)."
- :type '(repeat string)
- :group 'sha1)
-
-(defcustom sha1-use-external (condition-case ()
- (executable-find (car sha1-program))
- (error))
- "*Use external SHA1 program.
-If this variable is set to nil, use internal function only."
- :type 'boolean
- :group 'sha1)
-
-(defun sha1-string-external (string &optional binary)
- (let (prog args digest default-enable-multibyte-characters)
- (if (consp sha1-program)
- (setq prog (car sha1-program)
- args (cdr sha1-program))
- (setq prog sha1-program
- args nil))
- (with-temp-buffer
- (insert string)
- (apply (function call-process-region)
- (point-min)(point-max)
- prog t t nil args)
- ;; SHA1 is 40 bytes long in hexadecimal form.
- (setq digest (buffer-substring (point-min)(+ (point-min) 40))))
- (if binary
- (decode-hex-string digest)
- digest)))
-
-(defun sha1-region-external (beg end &optional binary)
- (sha1-string-external (buffer-substring-no-properties beg end) binary))
-
-;;;
-;;; internal SHA1 function.
-;;;
-
-(eval-when-compile
- ;; optional second arg of string-to-number is new in v20.
- (defconst sha1-K0-high 23170) ; (string-to-number "5A82" 16)
- (defconst sha1-K0-low 31129) ; (string-to-number "7999" 16)
- (defconst sha1-K1-high 28377) ; (string-to-number "6ED9" 16)
- (defconst sha1-K1-low 60321) ; (string-to-number "EBA1" 16)
- (defconst sha1-K2-high 36635) ; (string-to-number "8F1B" 16)
- (defconst sha1-K2-low 48348) ; (string-to-number "BCDC" 16)
- (defconst sha1-K3-high 51810) ; (string-to-number "CA62" 16)
- (defconst sha1-K3-low 49622) ; (string-to-number "C1D6" 16)
-
-;;; original definition of sha1-F0.
-;;; (defmacro sha1-F0 (B C D)
-;;; (` (logior (logand (, B) (, C))
-;;; (logand (lognot (, B)) (, D)))))
-;;; a little optimization from GnuPG/cipher/sha1.c.
- (defmacro sha1-F0 (B C D)
- (` (logxor (, D) (logand (, B) (logxor (, C) (, D))))))
- (defmacro sha1-F1 (B C D)
- (` (logxor (, B) (, C) (, D))))
-;;; original definition of sha1-F2.
-;;; (defmacro sha1-F2 (B C D)
-;;; (` (logior (logand (, B) (, C))
-;;; (logand (, B) (, D))
-;;; (logand (, C) (, D)))))
-;;; a little optimization from GnuPG/cipher/sha1.c.
- (defmacro sha1-F2 (B C D)
- (` (logior (logand (, B) (, C))
- (logand (, D) (logior (, B) (, C))))))
- (defmacro sha1-F3 (B C D)
- (` (logxor (, B) (, C) (, D))))
-
- (defmacro sha1-S1 (W-high W-low)
- (` (let ((W-high (, W-high))
- (W-low (, W-low)))
- (setq S1W-high (+ (% (* W-high 2) 65536)
- (/ W-low (, (/ 65536 2)))))
- (setq S1W-low (+ (/ W-high (, (/ 65536 2)))
- (% (* W-low 2) 65536))))))
- (defmacro sha1-S5 (A-high A-low)
- (` (progn
- (setq S5A-high (+ (% (* (, A-high) 32) 65536)
- (/ (, A-low) (, (/ 65536 32)))))
- (setq S5A-low (+ (/ (, A-high) (, (/ 65536 32)))
- (% (* (, A-low) 32) 65536))))))
- (defmacro sha1-S30 (B-high B-low)
- (` (progn
- (setq S30B-high (+ (/ (, B-high) 4)
- (* (% (, B-low) 4) (, (/ 65536 4)))))
- (setq S30B-low (+ (/ (, B-low) 4)
- (* (% (, B-high) 4) (, (/ 65536 4))))))))
-
- (defmacro sha1-OP (round)
- (` (progn
- (sha1-S5 sha1-A-high sha1-A-low)
- (sha1-S30 sha1-B-high sha1-B-low)
- (setq sha1-A-low (+ ((, (intern (format "sha1-F%d" round)))
- sha1-B-low sha1-C-low sha1-D-low)
- sha1-E-low
- (, (symbol-value
- (intern (format "sha1-K%d-low" round))))
- (aref block-low idx)
- (progn
- (setq sha1-E-low sha1-D-low)
- (setq sha1-D-low sha1-C-low)
- (setq sha1-C-low S30B-low)
- (setq sha1-B-low sha1-A-low)
- S5A-low)))
- (setq carry (/ sha1-A-low 65536))
- (setq sha1-A-low (% sha1-A-low 65536))
- (setq sha1-A-high (% (+ ((, (intern (format "sha1-F%d" round)))
- sha1-B-high sha1-C-high sha1-D-high)
- sha1-E-high
- (, (symbol-value
- (intern (format "sha1-K%d-high" round))))
- (aref block-high idx)
- (progn
- (setq sha1-E-high sha1-D-high)
- (setq sha1-D-high sha1-C-high)
- (setq sha1-C-high S30B-high)
- (setq sha1-B-high sha1-A-high)
- S5A-high)
- carry)
- 65536)))))
-
- (defmacro sha1-add-to-H (H X)
- (` (progn
- (setq (, (intern (format "sha1-%s-low" H)))
- (+ (, (intern (format "sha1-%s-low" H)))
- (, (intern (format "sha1-%s-low" X)))))
- (setq carry (/ (, (intern (format "sha1-%s-low" H))) 65536))
- (setq (, (intern (format "sha1-%s-low" H)))
- (% (, (intern (format "sha1-%s-low" H))) 65536))
- (setq (, (intern (format "sha1-%s-high" H)))
- (% (+ (, (intern (format "sha1-%s-high" H)))
- (, (intern (format "sha1-%s-high" X)))
- carry)
- 65536)))))
- )
-
-;;; buffers (H0 H1 H2 H3 H4).
-(defvar sha1-H0-high)
-(defvar sha1-H0-low)
-(defvar sha1-H1-high)
-(defvar sha1-H1-low)
-(defvar sha1-H2-high)
-(defvar sha1-H2-low)
-(defvar sha1-H3-high)
-(defvar sha1-H3-low)
-(defvar sha1-H4-high)
-(defvar sha1-H4-low)
-
-(defun sha1-block (block-high block-low)
- (let (;; step (c) --- initialize buffers (A B C D E).
- (sha1-A-high sha1-H0-high) (sha1-A-low sha1-H0-low)
- (sha1-B-high sha1-H1-high) (sha1-B-low sha1-H1-low)
- (sha1-C-high sha1-H2-high) (sha1-C-low sha1-H2-low)
- (sha1-D-high sha1-H3-high) (sha1-D-low sha1-H3-low)
- (sha1-E-high sha1-H4-high) (sha1-E-low sha1-H4-low)
- (idx 16))
- ;; step (b).
- (let (;; temporary variables used in sha1-S1 macro.
- S1W-high S1W-low)
- (while (< idx 80)
- (sha1-S1 (logxor (aref block-high (- idx 3))
- (aref block-high (- idx 8))
- (aref block-high (- idx 14))
- (aref block-high (- idx 16)))
- (logxor (aref block-low (- idx 3))
- (aref block-low (- idx 8))
- (aref block-low (- idx 14))
- (aref block-low (- idx 16))))
- (aset block-high idx S1W-high)
- (aset block-low idx S1W-low)
- (setq idx (1+ idx))))
- ;; step (d).
- (setq idx 0)
- (let (;; temporary variables used in sha1-OP macro.
- S5A-high S5A-low S30B-high S30B-low carry)
- (while (< idx 20) (sha1-OP 0) (setq idx (1+ idx)))
- (while (< idx 40) (sha1-OP 1) (setq idx (1+ idx)))
- (while (< idx 60) (sha1-OP 2) (setq idx (1+ idx)))
- (while (< idx 80) (sha1-OP 3) (setq idx (1+ idx))))
- ;; step (e).
- (let (;; temporary variables used in sha1-add-to-H macro.
- carry)
- (sha1-add-to-H H0 A)
- (sha1-add-to-H H1 B)
- (sha1-add-to-H H2 C)
- (sha1-add-to-H H3 D)
- (sha1-add-to-H H4 E))))
-
-(defun sha1-binary (string)
- "Return the SHA1 of STRING in binary form."
- (let (;; prepare buffers for a block. byte-length of block is 64.
- ;; input block is split into two vectors.
- ;;
- ;; input block: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F ...
- ;; block-high: +-0-+ +-1-+ +-2-+ +-3-+
- ;; block-low: +-0-+ +-1-+ +-2-+ +-3-+
- ;;
- ;; length of each vector is 80, and elements of each vector are
- ;; 16bit integers. elements 0x10-0x4F of each vector are
- ;; assigned later in `sha1-block'.
- (block-high (eval-when-compile (make-vector 80 nil)))
- (block-low (eval-when-compile (make-vector 80 nil))))
- (unwind-protect
- (let* (;; byte-length of input string.
- (len (length string))
- (lim (* (/ len 64) 64))
- (rem (% len 4))
- (idx 0)(pos 0))
- ;; initialize buffers (H0 H1 H2 H3 H4).
- (setq sha1-H0-high 26437 ; (string-to-number "6745" 16)
- sha1-H0-low 8961 ; (string-to-number "2301" 16)
- sha1-H1-high 61389 ; (string-to-number "EFCD" 16)
- sha1-H1-low 43913 ; (string-to-number "AB89" 16)
- sha1-H2-high 39098 ; (string-to-number "98BA" 16)
- sha1-H2-low 56574 ; (string-to-number "DCFE" 16)
- sha1-H3-high 4146 ; (string-to-number "1032" 16)
- sha1-H3-low 21622 ; (string-to-number "5476" 16)
- sha1-H4-high 50130 ; (string-to-number "C3D2" 16)
- sha1-H4-low 57840) ; (string-to-number "E1F0" 16)
- ;; loop for each 64 bytes block.
- (while (< pos lim)
- ;; step (a).
- (setq idx 0)
- (while (< idx 16)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (aset block-low idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (setq idx (1+ idx)))
- (sha1-block block-high block-low))
- ;; last block.
- (if (prog1
- (< (- len lim) 56)
- (setq lim (- len rem))
- (setq idx 0)
- (while (< pos lim)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (aset block-low idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (setq idx (1+ idx)))
- ;; this is the last (at most) 32bit word.
- (cond
- ((= rem 3)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (setq pos (+ pos 2))
- (aset block-low idx (+ (* (aref string pos) 256)
- 128)))
- ((= rem 2)
- (aset block-high idx (+ (* (aref string pos) 256)
- (aref string (1+ pos))))
- (aset block-low idx 32768))
- ((= rem 1)
- (aset block-high idx (+ (* (aref string pos) 256)
- 128))
- (aset block-low idx 0))
- (t ;; (= rem 0)
- (aset block-high idx 32768)
- (aset block-low idx 0)))
- (setq idx (1+ idx))
- (while (< idx 16)
- (aset block-high idx 0)
- (aset block-low idx 0)
- (setq idx (1+ idx))))
- ;; last block has enough room to write the length of string.
- (progn
- ;; write bit length of string to last 4 bytes of the block.
- (aset block-low 15 (* (% len 8192) 8))
- (setq len (/ len 8192))
- (aset block-high 15 (% len 65536))
- ;; XXX: It is not practical to compute SHA1 of
- ;; such a huge message on emacs.
- ;; (setq len (/ len 65536)) ; for 64bit emacs.
- ;; (aset block-low 14 (% len 65536))
- ;; (aset block-high 14 (/ len 65536))
- (sha1-block block-high block-low))
- ;; need one more block.
- (sha1-block block-high block-low)
- (fillarray block-high 0)
- (fillarray block-low 0)
- ;; write bit length of string to last 4 bytes of the block.
- (aset block-low 15 (* (% len 8192) 8))
- (setq len (/ len 8192))
- (aset block-high 15 (% len 65536))
- ;; XXX: It is not practical to compute SHA1 of
- ;; such a huge message on emacs.
- ;; (setq len (/ len 65536)) ; for 64bit emacs.
- ;; (aset block-low 14 (% len 65536))
- ;; (aset block-high 14 (/ len 65536))
- (sha1-block block-high block-low))
- ;; make output string (in binary form).
- (let ((result (make-string 20 0)))
- (aset result 0 (/ sha1-H0-high 256))
- (aset result 1 (% sha1-H0-high 256))
- (aset result 2 (/ sha1-H0-low 256))
- (aset result 3 (% sha1-H0-low 256))
- (aset result 4 (/ sha1-H1-high 256))
- (aset result 5 (% sha1-H1-high 256))
- (aset result 6 (/ sha1-H1-low 256))
- (aset result 7 (% sha1-H1-low 256))
- (aset result 8 (/ sha1-H2-high 256))
- (aset result 9 (% sha1-H2-high 256))
- (aset result 10 (/ sha1-H2-low 256))
- (aset result 11 (% sha1-H2-low 256))
- (aset result 12 (/ sha1-H3-high 256))
- (aset result 13 (% sha1-H3-high 256))
- (aset result 14 (/ sha1-H3-low 256))
- (aset result 15 (% sha1-H3-low 256))
- (aset result 16 (/ sha1-H4-high 256))
- (aset result 17 (% sha1-H4-high 256))
- (aset result 18 (/ sha1-H4-low 256))
- (aset result 19 (% sha1-H4-low 256))
- result))
- ;; do not leave a copy of input string.
- (fillarray block-high nil)
- (fillarray block-low nil))))
-
-(defun sha1-string-internal (string &optional binary)
- (if binary
- (sha1-binary string)
- (encode-hex-string (sha1-binary string))))
-
-(defun sha1-region-internal (beg end &optional binary)
- (sha1-string-internal (buffer-substring-no-properties beg end) binary))
-
-;;;
-;;; application interface.
-;;;
-
-(defun sha1-region (beg end &optional binary)
- (if (and sha1-use-external
- sha1-maximum-internal-length
- (> (abs (- end beg)) sha1-maximum-internal-length))
- (sha1-region-external beg end binary)
- (sha1-region-internal beg end binary)))
-
-(defun sha1-string (string &optional binary)
- (if (and sha1-use-external
- sha1-maximum-internal-length
- (> (length string) sha1-maximum-internal-length))
- (sha1-string-external string binary)
- (sha1-string-internal string binary)))
-
-;;;###autoload
-(defun sha1 (object &optional beg end binary)
- "Return the SHA1 (Secure Hash Algorithm) of an object.
-OBJECT is either a string or a buffer.
-Optional arguments BEG and END denote buffer positions for computing the
-hash of a portion of OBJECT.
-If BINARY is non-nil, return a string in binary form."
- (if (stringp object)
- (sha1-string object binary)
- (save-excursion
- (set-buffer object)
- (sha1-region (or beg (point-min)) (or end (point-max)) binary))))
-
-(provide 'sha1)
-
-;;; arch-tag: c0f9abd0-ffc1-4557-aac6-ece7f2d4c901
-;;; sha1.el ends here
diff --git a/srv.el b/srv.el
new file mode 100644
index 0000000..ccd5aaf
--- /dev/null
+++ b/srv.el
@@ -0,0 +1,95 @@
+;;; srv.el --- perform SRV DNS requests
+
+;; Copyright (C) 2005 Magnus Henoch
+
+;; Author: Magnus Henoch <mange@freemail.hu>
+;; Keywords: comm
+;; Version: 0.1
+
+;; This file 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, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+
+;; This code implements RFC 2782 (SRV records). It requires a version
+;; of dns.el that supports SRV records; look in Gnus CVS if you don't
+;; have one.
+
+;;; Code:
+
+(require 'dns)
+(eval-when-compile (require 'cl))
+
+(defun srv-lookup (target)
+ "Perform SRV lookup of TARGET and return list of connection candidiates.
+TARGET is a string of the form \"_Service._Proto.Name\".
+
+Returns a list with elements of the form (HOST . PORT), where HOST is
+a hostname and PORT is a numeric port. The caller is supposed to
+make connection attempts in the order given, starting from the beginning
+of the list. The list is empty if no SRV records were found."
+ (unless (assq 'SRV dns-query-types)
+ (error "dns.el doesn't support SRV lookups"))
+ (let* ((result (query-dns target 'SRV t))
+ (answers (mapcar #'(lambda (a)
+ (cadr (assq 'data a)))
+ (cadr (assq 'answers result))))
+ answers-by-priority weighted-result)
+ (if (or (null answers)
+ ;; Special case for "service decidedly not available"
+ (and (eq (length answers) 1)
+ (string= (cadr (assq 'target (car answers))) ".")))
+ nil
+ ;; Sort answers into groups of same priority.
+ (dolist (a answers)
+ (let* ((priority (cadr (assq 'priority a)))
+ (entry (assq priority answers-by-priority)))
+ (if entry
+ (push a (cdr entry))
+ (push (cons priority (list a)) answers-by-priority))))
+ ;; Sort by priority.
+ (setq answers-by-priority
+ (sort answers-by-priority
+ #'(lambda (a b) (< (car a) (car b)))))
+ ;; Randomize by weight within priority groups. See
+ ;; algorithm in RFC 2782.
+ (dolist (p answers-by-priority)
+ (let ((weight-acc 0)
+ weight-order)
+ ;; Assign running sum of weight to each entry.
+ (dolist (a (cdr p))
+ (incf weight-acc (cadr (assq 'weight a)))
+ (push (cons weight-acc a) weight-order))
+ (setq weight-order (nreverse weight-order))
+
+ ;; While elements remain, pick a random number between 0 and
+ ;; weight-acc inclusive, and select the first entry whose
+ ;; running sum is greater than or equal to this number.
+ (while weight-order
+ (let* ((r (random (1+ weight-acc)))
+ (next-entry (dolist (a weight-order)
+ (if (>= (car a) r)
+ (return a)))))
+ (push (cdr next-entry) weighted-result)
+ (setq weight-order
+ (delq next-entry weight-order))))))
+ ;; Extract hostnames and ports
+ (mapcar #'(lambda (a) (cons (cadr (assq 'target a))
+ (cadr (assq 'port a))))
+ (nreverse weighted-result)))))
+
+(provide 'srv)
+;; arch-tag: b43358f2-d241-11da-836e-000a95c2fcd0
+;;; srv.el ends here
diff --git a/xmppuri.sh b/xmppuri.sh
new file mode 100755
index 0000000..e60673d
--- /dev/null
+++ b/xmppuri.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# Pass XMPP URIs to jabber.el. See `(jabber)XMPP URIs'.
+
+emacsclient -e "(jabber-handle-uri \"$1\")"
+
+# arch-tag: 3b655d90-0247-11db-86ba-000a95c2fcd0