aboutsummaryrefslogtreecommitdiffstats
path: root/doc/user-guide/quickstart.xml
blob: 0539a7c79e32dd4a4b96485bbd21e82de3aba0fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<chapter id="quickstart">
<title>Quickstart</title>

<para>
Welcome to BitlBee, your IRC gateway to ICQ, MSN, AOL, Jabber and Yahoo Instant Messaging Systems.
</para>

<para>
The center of BitlBee is the control channel, <emphasis>&amp;bitlbee</emphasis>. Two users will always be there, <emphasis>you</emphasis> (where "you" is the nickname you are using) and the system user, <emphasis>root</emphasis>.
</para>

<para>
You need register so that all your IM settings (passwords, contacts, etc) can be saved on the BitlBee server. It's important that you pick a good password so no one else can access your account. Register with this password using the <emphasis>register</emphasis> command: <emphasis>register &lt;password&gt;</emphasis> (without the brackets!).
</para>

<para>
Be sure to remember your password. The next time you connect to the BitlBee server you will need to <emphasis>identify &lt;password&gt;</emphasis> so that you will be recognised and logged in to all the IM services automatically.
</para>

<para>
When finished, type <emphasis>help quickstart2</emphasis> to continue.
</para>

<sect1 id="quickstart2">
<title>Add and Connect To your IM Account(s)</title>
<!-- quickstart2 -->
<para>
<emphasis>Step Two: Add and Connect To your IM Account(s).</emphasis>
</para>

<para>
To add an account to the account list you will need to use the <emphasis>account add</emphasis> command: <emphasis>account add &lt;protocol&gt; &lt;username&gt; &lt;password&gt; [&lt;server&gt;]</emphasis>.
</para>

<para>
For instance, suppose you have a Jabber account at jabber.org with handle <emphasis>bitlbee@jabber.org</emphasis> with password <emphasis>QuickStart</emphasis>, you would:
</para>

<ircexample>
	<ircline nick="you">account add jabber bitlbee@jabber.org QuickStart</ircline>
	<ircline nick="root">Account successfully added</ircline>
</ircexample>

<para>
Other available IM protocols are msn, oscar, and yahoo. OSCAR is the protocol used by ICQ and AOL. For more information about the <emphasis>account add</emphasis> command, see <emphasis>help account add</emphasis>.
</para>

<para>
When you are finished adding your account(s) use the <emphasis>account on</emphasis> command to enable all your accounts, type <emphasis>help quickstart3</emphasis> to continue.
</para>

</sect1>

<sect1 id="quickstart3">
<title>Managing Contact Lists: Rename</title>

<!--quickstart3-->
<para>
<emphasis>Step Three: Managing Contact Lists: Rename</emphasis>
</para>

<para>
Now BitlBee logs in and downloads the contact list from the IM server. In a few seconds, all your on-line buddies should show up in the control channel.
</para>

<para>
BitlBee will convert names into IRC-friendly form (for instance: tux@example.com will be given the nickname tux). If you have more than one person who would have the same name by this logic (for instance: tux@example.com and tux@bitlbee.org) the second one to log on will be tux_. The same is true if you have a tux log on to AOL and a tux log on from Yahoo.
</para>

<para>
It would be easy to get these two mixed up, so BitlBee has a <emphasis>rename</emphasis> command to change the nickname into something more suitable: <emphasis>rename &lt;oldnick&gt; &lt;newnick&gt;</emphasis>
</para>

<ircexample>
	<ircline nick="you">rename tux_ bitlbeetux</ircline>
	<ircaction nick="tux_">is now known as <emphasis>bitlbeetux</emphasis></ircaction>
	<ircline nick="root">Nick successfully changed</ircline>
</ircexample>

<para>
When finished, type <emphasis>help quickstart4</emphasis> to continue.
</para>

</sect1>

<sect1 id="quickstart4">
<title>Step Four: Managing Contact Lists: Add and Remove.</title>

<para>
<emphasis>Step Four: Managing Contact Lists: Add and Remove.</emphasis>
</para>

<para>
Now you might want to add some contacts, to do this we will use the <emphasis>add</emphasis> command. It needs two arguments: a connection ID (which can be a number (try <emphasis>account list</emphasis>), protocol name or (part of) the screenname) and the user's handle. It is used in the following way: <emphasis>add &lt;connection&gt; &lt;handle&gt;</emphasis>
</para>

<ircexample>
	<ircline nick="you">add 0 r2d2@example.com</ircline>
	<ircaction nick="r2d2"> has joined <emphasis>&amp;bitlbee</emphasis></ircaction>
</ircexample>

<para>
In this case r2d2 is online, since he/she joins the channel immediately. If the user is not online you will not see them join until they log on.
</para>

<para>
Lets say you accidentally added r2d3@example.com rather than r2d2@example.com, or maybe you just want to remove a user from your list because you never talk to them. To remove a name you will want to use the <emphasis>remove</emphasis> command: <emphasis>remove &lt;nick&gt;</emphasis>
</para>

<para>
When finished, type <emphasis>help quickstart5</emphasis> to continue.
</para>

</sect1>

<sect1 id="quickstart5">
<title>Chatting</title>

<para>
<emphasis>Step Five: Chatting.</emphasis>
</para>

<para>
First of all, a person must be on your contact list for you to chat with them (unless it's a group chat, <emphasis>help groupchats</emphasis> for more). If someone not on your contact list sends you a message, simply add them to the proper account with the <emphasis>add</emphasis> command. Once they are on your list and online, you can chat with them in &amp;bitlbee:
</para>

<ircexample>
	<ircline nick="you">tux: hey, how's the weather down there?</ircline>
	<ircline nick="tux">you: a bit chilly!</ircline>
</ircexample>

<para>
Note that, although all contacts are in the &amp;bitlbee channel, only tux will actually receive this message. The &amp;bitlbee channel shouldn't be confused with a real IRC channel.
</para>

<para>
If you prefer chatting in a separate window, use the <emphasis>/msg</emphasis> or <emphasis>/query</emphasis> command, just like on real IRC. BitlBee will remember how you talk to someone and show his/her responses the same way. If you want to change the default behaviour (for people you haven't talked to yet), see <emphasis>help set private</emphasis>.
</para>

<para>
You know the basics. If you want to get to know more about BitlBee, please type <emphasis>help quickstart6</emphasis>.
</para>

</sect1>

<sect1 id="quickstart6">
<title>Further Resources</title>

<para>
<emphasis>So you want more than just chatting? Or maybe you're just looking for a feature?</emphasis>
</para>

<para>
You can type <emphasis>help set</emphasis> to learn more about the possible BitlBee user settings. Among these user settings you will find options for common issues, such as changing the charset, HTML stripping and automatic connecting (simply type <emphasis>set</emphasis> to see current user settings).
</para>

<para>
For more subjects (like groupchats and away states), please type <emphasis>help index</emphasis>.
</para>

<para>
If you're still looking for something, please visit us in #bitlbee on the OFTC network (you can connect via irc.bitlbee.org), or mail us your problem/suggestion. Good luck and enjoy the Bee!
</para>

</sect1>

</chapter>
an class="o">= write(jd->fd, jd->txq, jd->tx_len); } if (st == jd->tx_len) { /* We wrote everything, clear the buffer. */ g_free(jd->txq); jd->txq = NULL; jd->tx_len = 0; return TRUE; } else if (st == 0 || (st < 0 && !ssl_sockerr_again(jd->ssl))) { /* Set fd to -1 to make sure we won't write to it anymore. */ closesocket(jd->fd); /* Shouldn't be necessary after errors? */ jd->fd = -1; imcb_error(ic, "Short write() to server"); imc_logout(ic, TRUE); return FALSE; } else if (st > 0) { char *s; s = g_memdup(jd->txq + st, jd->tx_len - st); jd->tx_len -= st; g_free(jd->txq); jd->txq = s; return TRUE; } else { /* Just in case we had EINPROGRESS/EAGAIN: */ return TRUE; } } static gboolean jabber_feed_input(struct im_connection *ic, char *buf, int size) { struct jabber_data *jd = ic->proto_data; /* Allow not passing a size for debugging purposes. * This never happens when reading from the socket */ if (size == -1) { size = strlen(buf); } /* Parse. */ if (xt_feed(jd->xt, buf, size) < 0) { imcb_error(ic, "XML stream error"); imc_logout(ic, TRUE); return FALSE; } /* Execute all handlers. */ if (!xt_handle(jd->xt, NULL, 1)) { /* Don't do anything, the handlers should have aborted the connection already. */ return FALSE; } if (jd->flags & JFLAG_STREAM_RESTART) { jd->flags &= ~JFLAG_STREAM_RESTART; jabber_start_stream(ic); } /* Garbage collection. */ xt_cleanup(jd->xt, NULL, 1); /* This is a bit hackish, unfortunately. Although xmltree has nifty event handler stuff, it only calls handlers when nodes are complete. Since the server should only send an opening <stream:stream> tag, we have to check this by hand. :-( */ if (!(jd->flags & JFLAG_STREAM_STARTED) && jd->xt && jd->xt->root) { if (g_strcasecmp(jd->xt->root->name, "stream:stream") == 0) { jd->flags |= JFLAG_STREAM_STARTED; /* If there's no version attribute, assume this is an old server that can't do SASL authentication. */ if (!set_getbool(&ic->acc->set, "sasl") || !sasl_supported(ic)) { /* If there's no version= tag, we suppose this server does NOT implement: XMPP 1.0, SASL and TLS. */ if (set_getbool(&ic->acc->set, "tls")) { imcb_error(ic, "TLS is turned on for this " "account, but is not supported by this server"); imc_logout(ic, FALSE); return FALSE; } else { if (!jabber_init_iq_auth(ic)) { return FALSE; } } } } else { imcb_error(ic, "XML stream error"); imc_logout(ic, TRUE); return FALSE; } } return TRUE; } static gboolean jabber_read_callback(gpointer data, gint fd, b_input_condition cond) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; char buf[512]; int st; if (jd->fd == -1) { return FALSE; } if (jd->ssl) { st = ssl_read(jd->ssl, buf, sizeof(buf)); } else { st = read(jd->fd, buf, sizeof(buf)); } if (st > 0) { if (!jabber_feed_input(ic, buf, st)) { return FALSE; } } else if (st == 0 || (st < 0 && !ssl_sockerr_again(jd->ssl))) { closesocket(jd->fd); jd->fd = -1; imcb_error(ic, "Error while reading from server"); imc_logout(ic, TRUE); return FALSE; } if (ssl_pending(jd->ssl)) { /* OpenSSL empties the TCP buffers completely but may keep some data in its internap buffers. select() won't see that, but ssl_pending() does. */ return jabber_read_callback(data, fd, cond); } else { return TRUE; } } gboolean jabber_connected_plain(gpointer data, gint source, b_input_condition cond) { struct im_connection *ic = data; if (g_slist_find(jabber_connections, ic) == NULL) { return FALSE; } if (source == -1) { imcb_error(ic, "Could not connect to server"); imc_logout(ic, TRUE); return FALSE; } imcb_log(ic, "Connected to server, logging in"); return jabber_start_stream(ic); } gboolean jabber_connected_ssl(gpointer data, int returncode, void *source, b_input_condition cond) { struct im_connection *ic = data; struct jabber_data *jd; if (g_slist_find(jabber_connections, ic) == NULL) { return FALSE; } jd = ic->proto_data; if (source == NULL) { /* The SSL connection will be cleaned up by the SSL lib already, set it to NULL here to prevent a double cleanup: */ jd->ssl = NULL; if (returncode != 0) { char *err = ssl_verify_strerror(returncode); imcb_error(ic, "Certificate verification problem 0x%x: %s", returncode, err ? err : "Unknown"); g_free(err); imc_logout(ic, FALSE); } else { imcb_error(ic, "Could not connect to server"); imc_logout(ic, TRUE); } return FALSE; } imcb_log(ic, "Connected to server, logging in"); return jabber_start_stream(ic); } static xt_status jabber_end_of_stream(struct xt_node *node, gpointer data) { imc_logout(data, TRUE); return XT_ABORT; } static xt_status jabber_pkt_features(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; struct xt_node *c, *reply; int trytls; trytls = g_strcasecmp(set_getstr(&ic->acc->set, "tls"), "try") == 0; c = xt_find_node(node->children, "starttls"); if (c && !jd->ssl) { /* If the server advertises the STARTTLS feature and if we're not in a secure connection already: */ c = xt_find_node(c->children, "required"); if (c && (!trytls && !set_getbool(&ic->acc->set, "tls"))) { imcb_error(ic, "Server requires TLS connections, but TLS is turned off for this account"); imc_logout(ic, FALSE); return XT_ABORT; } /* Only run this if the tls setting is set to true or try: */ if ((trytls || set_getbool(&ic->acc->set, "tls"))) { reply = xt_new_node("starttls", NULL, NULL); xt_add_attr(reply, "xmlns", XMLNS_TLS); if (!jabber_write_packet(ic, reply)) { xt_free_node(reply); return XT_ABORT; } xt_free_node(reply); return XT_HANDLED; } } else if (!c && !jd->ssl) { /* If the server does not advertise the STARTTLS feature and we're not in a secure connection already: (Servers have a habit of not advertising <starttls/> anymore when already using SSL/TLS. */ if (!trytls && set_getbool(&ic->acc->set, "tls")) { imcb_error(ic, "TLS is turned on for this account, but is not supported by this server"); imc_logout(ic, FALSE); return XT_ABORT; } } /* This one used to be in jabber_handlers[], but it has to be done from here to make sure the TLS session will be initialized properly before we attempt SASL authentication. */ if ((c = xt_find_node(node->children, "mechanisms"))) { if (sasl_pkt_mechanisms(c, data) == XT_ABORT) { return XT_ABORT; } } /* If the server *SEEMS* to support SASL authentication but doesn't support it after all, we should try to do authentication the other way. jabber.com doesn't seem to do SASL while it pretends to be XMPP 1.0 compliant! */ else if (!(jd->flags & JFLAG_AUTHENTICATED) && set_getbool(&ic->acc->set, "sasl") && sasl_supported(ic)) { if (!jabber_init_iq_auth(ic)) { return XT_ABORT; } } if ((c = xt_find_node(node->children, "bind"))) { jd->flags |= JFLAG_WANT_BIND; } if ((c = xt_find_node(node->children, "session"))) { jd->flags |= JFLAG_WANT_SESSION; } if (jd->flags & JFLAG_AUTHENTICATED) { return jabber_pkt_bind_sess(ic, NULL, NULL); } return XT_HANDLED; } static xt_status jabber_pkt_proceed_tls(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; char *xmlns, *tlsname; xmlns = xt_find_attr(node, "xmlns"); /* Just ignore it when it doesn't seem to be TLS-related (is that at all possible??). */ if (!xmlns || strcmp(xmlns, XMLNS_TLS) != 0) { return XT_HANDLED; } /* We don't want event handlers to touch our TLS session while it's still initializing! */ b_event_remove(jd->r_inpa); if (jd->tx_len > 0) { /* Actually the write queue should be empty here, but just to be sure... */ b_event_remove(jd->w_inpa); g_free(jd->txq); jd->txq = NULL; jd->tx_len = 0; } jd->w_inpa = jd->r_inpa = 0; imcb_log(ic, "Converting stream to TLS"); jd->flags |= JFLAG_STARTTLS_DONE; /* If the user specified a server for the account, use this server as the * hostname in the certificate verification. Else we use the domain from * the username. */ if (ic->acc->server && *ic->acc->server) { tlsname = ic->acc->server; } else { tlsname = jd->server; } jd->ssl = ssl_starttls(jd->fd, tlsname, set_getbool(&ic->acc->set, "tls_verify"), jabber_connected_ssl, ic); return XT_HANDLED; } static xt_status jabber_pkt_stream_error(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; int allow_reconnect = TRUE; struct jabber_error *err; struct xt_node *host; if (!(ic->flags & OPT_LOGGED_IN) && (host = xt_find_node(node->children, "see-other-host")) && host->text) { char *s; int port = set_getint(&ic->acc->set, "port"); /* Let's try to obey this request, if we're not logged in yet (i.e. not have too much state yet). */ if (jd->ssl) { ssl_disconnect(jd->ssl); } closesocket(jd->fd); b_event_remove(jd->r_inpa); b_event_remove(jd->w_inpa); jd->ssl = NULL; jd->r_inpa = jd->w_inpa = 0; jd->flags &= JFLAG_XMLCONSOLE; s = strchr(host->text, ':'); if (s != NULL) { sscanf(s + 1, "%d", &port); } imcb_log(ic, "Redirected to %s", host->text); jd->fd = proxy_connect(host->text, port, jabber_connected_plain, ic); return XT_ABORT; } err = jabber_error_parse(node, XMLNS_STREAM_ERROR); /* Tssk... */ if (err->code == NULL) { imcb_error(ic, "Unknown stream error reported by server"); imc_logout(ic, allow_reconnect); jabber_error_free(err); return XT_ABORT; } /* We know that this is a fatal error. If it's a "conflict" error, we should turn off auto-reconnect to make sure we won't get some nasty infinite loop! */ if (strcmp(err->code, "conflict") == 0) { imcb_error(ic, "Account and resource used from a different location"); allow_reconnect = FALSE; } else if (strcmp(err->code, "not-authorized") == 0) { imcb_error(ic, "Not authorized"); allow_reconnect = FALSE; } else { imcb_error(ic, "Stream error: %s%s%s", err->code, err->text ? ": " : "", err->text ? err->text : ""); } jabber_error_free(err); imc_logout(ic, allow_reconnect); return XT_ABORT; } static xt_status jabber_xmlconsole(struct xt_node *node, gpointer data) { struct im_connection *ic = data; struct jabber_data *jd = ic->proto_data; if (jd->flags & JFLAG_XMLCONSOLE) { char *msg, *pkt; pkt = xt_to_string(node); msg = g_strdup_printf("RX: %s", pkt); imcb_buddy_msg(ic, JABBER_XMLCONSOLE_HANDLE, msg, 0, 0); g_free(msg); g_free(pkt); } return XT_NEXT; } static const struct xt_handler_entry jabber_handlers[] = { { NULL, "stream:stream", jabber_xmlconsole }, { "stream:stream", "<root>", jabber_end_of_stream }, { "message", "stream:stream", jabber_pkt_message }, { "presence", "stream:stream", jabber_pkt_presence }, { "iq", "stream:stream", jabber_pkt_iq }, { "stream:features", "stream:stream", jabber_pkt_features }, { "stream:error", "stream:stream", jabber_pkt_stream_error }, { "proceed", "stream:stream", jabber_pkt_proceed_tls }, { "challenge", "stream:stream", sasl_pkt_challenge }, { "success", "stream:stream", sasl_pkt_result }, { "failure", "stream:stream", sasl_pkt_result }, { NULL, NULL, NULL } }; gboolean jabber_start_stream(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; int st; char *greet; /* We'll start our stream now, so prepare everything to receive one from the server too. */ xt_free(jd->xt); /* In case we're RE-starting. */ jd->xt = xt_new(jabber_handlers, ic); if (jd->r_inpa <= 0) { jd->r_inpa = b_input_add(jd->fd, B_EV_IO_READ, jabber_read_callback, ic); } greet = g_strdup_printf("%s<stream:stream to=\"%s\" xmlns=\"jabber:client\" " "xmlns:stream=\"http://etherx.jabber.org/streams\" version=\"1.0\">", (jd->flags & JFLAG_STARTTLS_DONE) ? "" : "<?xml version='1.0' ?>", jd->server); st = jabber_write(ic, greet, strlen(greet)); g_free(greet); return st; } void jabber_end_stream(struct im_connection *ic) { struct jabber_data *jd = ic->proto_data; /* Let's only do this if the queue is currently empty, otherwise it'd take too long anyway. */ if (jd->tx_len == 0) { char eos[] = "</stream:stream>"; struct xt_node *node; int st = 1; if (ic->flags & OPT_LOGGED_IN) { node = jabber_make_packet("presence", "unavailable", NULL, NULL); st = jabber_write_packet(ic, node); xt_free_node(node); } if (st) { jabber_write(ic, eos, strlen(eos)); } } }