1 /** 2 * @file jabber.h 3 * 4 * purple 5 * 6 * Purple is the legal property of its developers, whose names are too numerous 7 * to list here. Please refer to the COPYRIGHT file distributed with this 8 * source distribution. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA 23 */ 24 #ifndef PURPLE_JABBER_H_ 25 #define PURPLE_JABBER_H_ 26 27 typedef enum { 28 JABBER_CAP_NONE = 0, 29 /* JABBER_CAP_XHTML = 1 << 0, */ 30 /* JABBER_CAP_COMPOSING = 1 << 1, */ 31 JABBER_CAP_SI = 1 << 2, 32 JABBER_CAP_SI_FILE_XFER = 1 << 3, 33 JABBER_CAP_BYTESTREAMS = 1 << 4, 34 JABBER_CAP_IBB = 1 << 5, 35 JABBER_CAP_CHAT_STATES = 1 << 6, 36 JABBER_CAP_IQ_SEARCH = 1 << 7, 37 JABBER_CAP_IQ_REGISTER = 1 << 8, 38 39 /* Google Talk extensions: 40 * http://code.google.com/apis/talk/jep_extensions/extensions.html 41 */ 42 JABBER_CAP_GMAIL_NOTIFY = 1 << 9, 43 JABBER_CAP_GOOGLE_ROSTER = 1 << 10, 44 45 JABBER_CAP_PING = 1 << 11, 46 JABBER_CAP_ADHOC = 1 << 12, 47 JABBER_CAP_BLOCKING = 1 << 13, 48 49 JABBER_CAP_ITEMS = 1 << 14, 50 JABBER_CAP_ROSTER_VERSIONING = 1 << 15, 51 52 JABBER_CAP_STREAM_MANAGEMENT = 1 << 16, 53 54 JABBER_CAP_RETRIEVED = 1 << 31 55 } JabberCapabilities; 56 57 typedef struct _JabberStream JabberStream; 58 59 #include <libxml/parser.h> 60 #include <glib.h> 61 #include "circbuffer.h" 62 #include "connection.h" 63 #include "dnsquery.h" 64 #include "dnssrv.h" 65 #include "media.h" 66 #include "mediamanager.h" 67 #include "roomlist.h" 68 #include "sslconn.h" 69 70 #include "namespaces.h" 71 72 #include "auth.h" 73 #include "iq.h" 74 #include "jutil.h" 75 #include "xmlnode.h" 76 #include "buddy.h" 77 #include "bosh.h" 78 79 #ifdef HAVE_CYRUS_SASL 80 #include <sasl/sasl.h> 81 #endif 82 83 #define CAPS0115_NODE "http://pidgin.im/" 84 85 #define JABBER_DEFAULT_REQUIRE_TLS "require_starttls" 86 #define JABBER_DEFAULT_FT_PROXIES "" 87 88 /* Index into attention_types list */ 89 #define JABBER_BUZZ 0 90 91 typedef enum { 92 JABBER_STREAM_OFFLINE, 93 JABBER_STREAM_CONNECTING, 94 JABBER_STREAM_INITIALIZING, 95 JABBER_STREAM_INITIALIZING_ENCRYPTION, 96 JABBER_STREAM_AUTHENTICATING, 97 JABBER_STREAM_POST_AUTH, 98 JABBER_STREAM_CONNECTED 99 } JabberStreamState; 100 101 typedef enum { 102 SM_DISABLED, 103 SM_PLANNED, 104 SM_REQUESTED, 105 SM_ENABLED 106 } JabberStreamManagementState; 107 108 struct _JabberStream 109 { 110 int fd; 111 112 PurpleSrvTxtQueryData *srv_query_data; 113 114 xmlParserCtxt *context; 115 xmlnode *current; 116 117 struct { 118 guint8 major; 119 guint8 minor; 120 } protocol_version; 121 122 JabberSaslMech *auth_mech; 123 gpointer auth_mech_data; 124 125 /** 126 * The header from the opening <stream/> tag. This being NULL is treated 127 * as a special condition in the parsing code (signifying the next 128 * stanza started is an opening stream tag), and its being missing on 129 * the stream header is treated as a fatal error. 130 */ 131 char *stream_id; 132 JabberStreamState state; 133 134 GHashTable *buddies; 135 136 /* 137 * This boolean was added to eliminate a heinous bug where we would 138 * get into a loop with the server and move a buddy back and forth 139 * from one group to another. 140 * 141 * The sequence goes something like this: 142 * 1. Our resource and another resource both approve an authorization 143 * request at the exact same time. We put the buddy in group A and 144 * the other resource put the buddy in group B. 145 * 2. The server receives the roster add for group B and sends us a 146 * roster push. 147 * 3. We receive this roster push and modify our local blist. This 148 * triggers us to send a roster add for group B. 149 * 4. The server recieves our earlier roster add for group A and sends 150 * us a roster push. 151 * 5. We receive this roster push and modify our local blist. This 152 * triggers us to send a roster add for group A. 153 * 6. The server receives our earlier roster add for group B and sends 154 * us a roster push. 155 * (repeat steps 3 through 6 ad infinitum) 156 * 157 * This boolean is used to short-circuit the sending of a roster add 158 * when we receive a roster push. 159 * 160 * See these bug reports: 161 * http://trac.adiumx.com/ticket/8834 162 * http://developer.pidgin.im/ticket/5484 163 * http://developer.pidgin.im/ticket/6188 164 */ 165 gboolean currently_parsing_roster_push; 166 167 GHashTable *chats; 168 GList *chat_servers; 169 PurpleRoomlist *roomlist; 170 GList *user_directories; 171 172 GHashTable *iq_callbacks; 173 int next_id; 174 175 GList *bs_proxies; 176 GList *oob_file_transfers; 177 GList *file_transfers; 178 179 time_t idle; 180 time_t old_idle; 181 182 /** When we last pinged the server, so we don't ping more 183 * often than once every minute. 184 */ 185 time_t last_ping; 186 187 JabberID *user; 188 JabberBuddy *user_jb; 189 190 PurpleConnection *gc; 191 PurpleSslConnection *gsc; 192 193 gboolean registration; 194 195 char *initial_avatar_hash; 196 char *avatar_hash; 197 GSList *pending_avatar_requests; 198 199 GSList *pending_buddy_info_requests; 200 201 PurpleCircBuffer *write_buffer; 202 guint writeh; 203 204 gboolean reinit; 205 206 JabberCapabilities server_caps; 207 gboolean googletalk; 208 char *server_name; 209 210 char *gmail_last_time; 211 char *gmail_last_tid; 212 213 char *serverFQDN; 214 215 #ifdef HAVE_CYRUS_SASL 216 sasl_conn_t *sasl; 217 sasl_callback_t *sasl_cb; 218 sasl_secret_t *sasl_secret; 219 const char *current_mech; 220 int auth_fail_count; 221 222 int sasl_state; 223 int sasl_maxbuf; 224 GString *sasl_mechs; 225 #endif 226 227 gboolean unregistration; 228 PurpleAccountUnregistrationCb unregistration_cb; 229 void *unregistration_user_data; 230 231 gboolean vcard_fetched; 232 /* Timer at login to push updated avatar */ 233 guint vcard_timer; 234 235 /* Entity Capabilities hash */ 236 char *caps_hash; 237 238 /* does the local server support PEP? */ 239 gboolean pep; 240 241 /* Is Buzz enabled? */ 242 gboolean allowBuzz; 243 244 /* A list of JabberAdHocCommands supported by the server */ 245 GList *commands; 246 247 /* last presence update to check for differences */ 248 JabberBuddyState old_state; 249 char *old_msg; 250 int old_priority; 251 char *old_avatarhash; 252 253 /* same for user tune */ 254 char *old_artist; 255 char *old_title; 256 char *old_source; 257 char *old_uri; 258 int old_length; 259 char *old_track; 260 261 char *certificate_CN; 262 263 /* A purple timeout tag for the keepalive */ 264 guint keepalive_timeout; 265 guint max_inactivity; 266 guint inactivity_timer; 267 268 PurpleSrvResponse *srv_rec; 269 guint srv_rec_idx; 270 guint max_srv_rec_idx; 271 272 /* BOSH stuff */ 273 PurpleBOSHConnection *bosh; 274 275 /** 276 * This linked list contains PurpleUtilFetchUrlData structs 277 * for when we lookup buddy icons from a url 278 */ 279 GSList *url_datas; 280 281 /* keep a hash table of JingleSessions */ 282 GHashTable *sessions; 283 284 /* maybe this should only be present when USE_VV? */ 285 gchar *stun_ip; 286 int stun_port; 287 PurpleDnsQueryData *stun_query; 288 289 /* stuff for Google's relay handling */ 290 gchar *google_relay_token; 291 gchar *google_relay_host; 292 GList *google_relay_requests; /* the HTTP requests to get */ 293 /* relay info */ 294 295 /* XEP-0198 (stream management) state */ 296 guint32 sm_outbound_count; 297 guint32 sm_inbound_count; 298 guint32 sm_outbound_confirmed; 299 JabberStreamManagementState sm_state; 300 }; 301 302 typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace); 303 304 typedef struct _JabberFeature 305 { 306 gchar *namespace; 307 JabberFeatureEnabled *is_enabled; 308 } JabberFeature; 309 310 typedef struct _JabberIdentity 311 { 312 gchar *category; 313 gchar *type; 314 gchar *name; 315 gchar *lang; 316 } JabberIdentity; 317 318 typedef struct _JabberBytestreamsStreamhost { 319 char *jid; 320 char *host; 321 int port; 322 char *zeroconf; 323 } JabberBytestreamsStreamhost; 324 325 /* what kind of additional features as returned from disco#info are supported? */ 326 extern GList *jabber_features; 327 /* A sorted list of identities advertised. Use jabber_add_identity to add 328 * so it remains sorted. 329 */ 330 extern GList *jabber_identities; 331 332 gboolean jabber_is_stanza(xmlnode *packet); 333 334 void jabber_stream_features_parse(JabberStream *js, xmlnode *packet); 335 void jabber_process_packet(JabberStream *js, xmlnode **packet); 336 void jabber_send(JabberStream *js, xmlnode *data); 337 void jabber_send_raw(JabberStream *js, const char *data, int len); 338 void jabber_send_signal_cb(PurpleConnection *pc, xmlnode **packet, 339 gpointer unused); 340 341 void jabber_stream_set_state(JabberStream *js, JabberStreamState state); 342 343 void jabber_register_parse(JabberStream *js, const char *from, 344 JabberIqType type, const char *id, xmlnode *query); 345 void jabber_register_start(JabberStream *js); 346 347 char *jabber_get_next_id(JabberStream *js); 348 349 /** Parse an error into a human-readable string and optionally a disconnect 350 * reason. 351 * @param js the stream on which the error occurred. 352 * @param packet the error packet 353 * @param reason where to store the disconnection reason, or @c NULL if you 354 * don't care or you don't intend to close the connection. 355 */ 356 char *jabber_parse_error(JabberStream *js, xmlnode *packet, PurpleConnectionError *reason); 357 358 /** 359 * Add a feature to the list of features advertised via disco#info. If you 360 * call this while accounts are connected, Bad Things(TM) will happen because 361 * the Entity Caps hash will be out-of-date (which should be fixed :/) 362 * 363 * @param namespace The namespace of the feature 364 * @param cb A callback determining whether or not this feature 365 * will advertised; may be NULL. 366 */ 367 void jabber_add_feature(const gchar *namespace, JabberFeatureEnabled cb); 368 void jabber_remove_feature(const gchar *namespace); 369 370 /** Adds an identity to this jabber library instance. For list of valid values 371 * visit the website of the XMPP Registrar 372 * (http://www.xmpp.org/registrar/disco-categories.html#client). 373 * 374 * Like with jabber_add_feature, if you call this while accounts are connected, 375 * Bad Things will happen. 376 * 377 * @param category the category of the identity. 378 * @param type the type of the identity. 379 * @param language the language localization of the name. Can be NULL. 380 * @param name the name of the identity. 381 */ 382 void jabber_add_identity(const gchar *category, const gchar *type, const gchar *lang, const gchar *name); 383 384 /** 385 * GCompareFunc for JabberIdentity structs. 386 */ 387 gint jabber_identity_compare(gconstpointer a, gconstpointer b); 388 389 /** 390 * Returns true if this connection is over a secure (SSL) stream. Use this 391 * instead of checking js->gsc because BOSH stores its PurpleSslConnection 392 * members in its own data structure. 393 */ 394 gboolean jabber_stream_is_ssl(JabberStream *js); 395 396 /** 397 * Restart the "we haven't sent anything in a while and should send 398 * something or the server will kick us off" timer (obviously 399 * called when sending something. It's exposed for BOSH.) 400 */ 401 void jabber_stream_restart_inactivity_timer(JabberStream *js); 402 403 /** PRPL functions */ 404 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b); 405 const char* jabber_list_emblem(PurpleBuddy *b); 406 char *jabber_status_text(PurpleBuddy *b); 407 void jabber_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full); 408 GList *jabber_status_types(PurpleAccount *account); 409 void jabber_login(PurpleAccount *account); 410 void jabber_close(PurpleConnection *gc); 411 void jabber_idle_set(PurpleConnection *gc, int idle); 412 void jabber_blocklist_parse_push(JabberStream *js, const char *from, 413 JabberIqType type, const char *id, 414 xmlnode *child); 415 void jabber_request_block_list(JabberStream *js); 416 void jabber_add_deny(PurpleConnection *gc, const char *who); 417 void jabber_rem_deny(PurpleConnection *gc, const char *who); 418 void jabber_keepalive(PurpleConnection *gc); 419 void jabber_register_gateway(JabberStream *js, const char *gateway); 420 void jabber_register_account(PurpleAccount *account); 421 void jabber_unregister_account(PurpleAccount *account, PurpleAccountUnregistrationCb cb, void *user_data); 422 gboolean jabber_send_attention(PurpleConnection *gc, const char *username, guint code); 423 GList *jabber_attention_types(PurpleAccount *account); 424 void jabber_convo_closed(PurpleConnection *gc, const char *who); 425 PurpleChat *jabber_find_blist_chat(PurpleAccount *account, const char *name); 426 gboolean jabber_offline_message(const PurpleBuddy *buddy); 427 int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len); 428 GList *jabber_actions(PurplePlugin *plugin, gpointer context); 429 430 gboolean jabber_audio_enabled(JabberStream *js, const char *unused); 431 gboolean jabber_video_enabled(JabberStream *js, const char *unused); 432 gboolean jabber_initiate_media(PurpleAccount *account, const char *who, 433 PurpleMediaSessionType type); 434 PurpleMediaCaps jabber_get_media_caps(PurpleAccount *account, const char *who); 435 gboolean jabber_can_receive_file(PurpleConnection *gc, const gchar *who); 436 437 void jabber_plugin_init(PurplePlugin *plugin); 438 void jabber_plugin_uninit(PurplePlugin *plugin); 439 440 #endif /* PURPLE_JABBER_H_ */ 441