Esempio n. 1
0
PurpleBOSHConnection*
jabber_bosh_connection_init(JabberStream *js, const char *url)
{
	PurpleBOSHConnection *conn;
	char *host, *path, *user, *passwd;
	int port;

	if (!purple_url_parse(url, &host, &port, &path, &user, &passwd)) {
		purple_debug_info("jabber", "Unable to parse given URL.\n");
		return NULL;
	}

	conn = g_new0(PurpleBOSHConnection, 1);
	conn->host = host;
	conn->port = port;
	conn->path = g_strdup_printf("/%s", path);
	g_free(path);
	conn->pipelining = TRUE;

	if (purple_ip_address_is_valid(host))
		js->serverFQDN = g_strdup(js->user->domain);
	else
		js->serverFQDN = g_strdup(host);

	if ((user && user[0] != '\0') || (passwd && passwd[0] != '\0')) {
		purple_debug_info("jabber", "Ignoring unexpected username and password "
		                            "in BOSH URL.\n");
	}

	g_free(user);
	g_free(passwd);

	conn->js = js;

	/*
	 * Random 64-bit integer masked off by 2^52 - 1.
	 *
	 * This should produce a random integer in the range [0, 2^52). It's
	 * unlikely we'll send enough packets in one session to overflow the rid.
	 */
	conn->rid = ((guint64)g_random_int() << 32) | g_random_int();
	conn->rid &= 0xFFFFFFFFFFFFFLL;

	conn->pending = purple_circ_buffer_new(0 /* default grow size */);

	conn->state = BOSH_CONN_OFFLINE;
	if (purple_strcasestr(url, "https://") != NULL)
		conn->ssl = TRUE;
	else
		conn->ssl = FALSE;

	conn->connections[0] = jabber_bosh_http_connection_init(conn);

	return conn;
}
Esempio n. 2
0
void BuddyListNode::updateFilterVisibility(const char *name)
{
  if (!isVisible())
    return;

  const char *filter = BUDDYLIST->getFilterString();
  if (!filter[0])
    return;

  // filtering is active
  setVisibility(purple_strcasestr(name, filter));
}
Esempio n. 3
0
static void search_cb(GtkWidget *button, PidginLogViewer *lv)
{
	const char *search_term = gtk_entry_get_text(GTK_ENTRY(lv->entry));
	GList *logs;

	if (!(*search_term)) {
		/* reset the tree */
		gtk_tree_store_clear(lv->treestore);
		populate_log_tree(lv);
		g_free(lv->search);
		lv->search = NULL;
		gtk_imhtml_search_clear(GTK_IMHTML(lv->imhtml));
		select_first_log(lv);
		return;
	}

	if (lv->search != NULL && !strcmp(lv->search, search_term))
	{
		/* Searching for the same term acts as "Find Next" */
		gtk_imhtml_search_find(GTK_IMHTML(lv->imhtml), lv->search);
		return;
	}

	pidgin_set_cursor(lv->window, GDK_WATCH);

	g_free(lv->search);
	lv->search = g_strdup(search_term);

	gtk_tree_store_clear(lv->treestore);
	gtk_imhtml_clear(GTK_IMHTML(lv->imhtml));

	for (logs = lv->logs; logs != NULL; logs = logs->next) {
		char *read = purple_log_read((PurpleLog*)logs->data, NULL);
		if (read && *read && purple_strcasestr(read, search_term)) {
			GtkTreeIter iter;
			PurpleLog *log = logs->data;

			gtk_tree_store_append (lv->treestore, &iter, NULL);
			gtk_tree_store_set(lv->treestore, &iter,
					   0, log_get_date(log),
					   1, log, -1);
		}
		g_free(read);
	}

	select_first_log(lv);
	pidgin_clear_cursor(lv->window);
}
Esempio n. 4
0
static void
jabber_bosh_http_connection_process(PurpleHTTPConnection *conn)
{
	const char *cursor;

	cursor = conn->read_buf->str + conn->handled_len;

	if (purple_debug_is_verbose())
		purple_debug_misc("jabber", "BOSH server sent: %s\n", cursor);

	/* TODO: Chunked encoding and check response version :/ */
	if (!conn->headers_done) {
		const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length:");
		const char *connection = purple_strcasestr(cursor, "\r\nConnection:");
		const char *end_of_headers = strstr(cursor, "\r\n\r\n");

		/* Make sure Content-Length is in headers, not body */
		if (content_length && (!end_of_headers || content_length < end_of_headers)) {
			int len;

			if (strstr(content_length, "\r\n") == NULL)
				/*
				 * The packet ends in the middle of the Content-Length line.
				 * We'll try again later when we have more.
				 */
				return;

			len = atoi(content_length + strlen("\r\nContent-Length:"));
			if (len == 0)
				purple_debug_warning("jabber", "Found mangled Content-Length header, or server returned 0-length response.\n");

			conn->body_len = len;
		}

		if (connection && (!end_of_headers || content_length < end_of_headers)) {
			const char *tmp;
			if (strstr(connection, "\r\n") == NULL)
				return;


			tmp = connection + strlen("\r\nConnection:");
			while (*tmp && (*tmp == ' ' || *tmp == '\t'))
				++tmp;

			if (!g_ascii_strncasecmp(tmp, "close", strlen("close"))) {
				conn->close = TRUE;
				jabber_bosh_disable_pipelining(conn->bosh);
			}
		}

		if (end_of_headers) {
			conn->headers_done = TRUE;
			conn->handled_len = end_of_headers - conn->read_buf->str + 4;
		} else {
			conn->handled_len = conn->read_buf->len;
			return;
		}
	}

	/* Have we handled everything in the buffer? */
	if (conn->handled_len >= conn->read_buf->len)
		return;

	/* Have we read all that the Content-Length promised us? */
	if (conn->read_buf->len - conn->handled_len < conn->body_len)
		return;

	--conn->requests;
	--conn->bosh->requests;

	http_received_cb(conn->read_buf->str + conn->handled_len, conn->body_len,
	                 conn->bosh);

	/* Connection: Close? */
	if (conn->close && conn->state == HTTP_CONN_CONNECTED) {
		if (purple_debug_is_verbose())
			purple_debug_misc("jabber", "bosh (%p), server sent Connection: "
			                            "close\n", conn);
		http_connection_disconnected(conn);
	}

	if (conn->bosh->state == BOSH_CONN_ONLINE &&
			(conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0)) {
		purple_debug_misc("jabber", "BOSH: Sending an empty request\n");
		jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL);
	}

	g_string_free(conn->read_buf, TRUE);
	conn->read_buf = NULL;
	conn->headers_done = FALSE;
	conn->handled_len = conn->body_len = 0;
}
Esempio n. 5
0
static gboolean
msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf,
						size_t size, char **ret_buf, size_t *ret_size,
						gboolean *error)
{
	const char *s, *c;
	char *header, *body;
	const char *body_start;
	char *tmp;
	size_t body_len = 0;

	g_return_val_if_fail(httpconn != NULL, FALSE);
	g_return_val_if_fail(buf      != NULL, FALSE);
	g_return_val_if_fail(size      > 0,    FALSE);
	g_return_val_if_fail(ret_buf  != NULL, FALSE);
	g_return_val_if_fail(ret_size != NULL, FALSE);
	g_return_val_if_fail(error    != NULL, FALSE);

#if 0
	purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf);
#endif

	/* Healthy defaults. */
	body = NULL;

	*ret_buf  = NULL;
	*ret_size = 0;
	*error    = FALSE;

	/* First, some tests to see if we have a full block of stuff. */
	if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) &&
		 (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) &&
		((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) &&
		 (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0)))
	{
		*error = TRUE;

		return FALSE;
	}

	if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)
	{
		if ((s = strstr(buf, "\r\n\r\n")) == NULL)
			return FALSE;

		s += 4;

		if (*s == '\0')
		{
			*ret_buf = g_strdup("");
			*ret_size = 0;

			msn_httpconn_process_queue(httpconn);

			return TRUE;
		}

		buf = s;
		size -= (s - buf);
	}

	if ((s = strstr(buf, "\r\n\r\n")) == NULL)
		/* Need to wait for the full HTTP header to arrive */
		return FALSE;

	s += 4; /* Skip \r\n\r\n */
	header = g_strndup(buf, s - buf);
	body_start = s;
	body_len = size - (body_start - buf);

	if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL)
	{
		int tmp_len;

		s += strlen("Content-Length: ");

		if ((c = strchr(s, '\r')) == NULL)
		{
			g_free(header);

			return FALSE;
		}

		tmp = g_strndup(s, c - s);
		tmp_len = atoi(tmp);
		g_free(tmp);

		if (body_len != tmp_len)
		{
			/* Need to wait for the full packet to arrive */

			g_free(header);

#if 0
			purple_debug_warning("msn",
							   "body length (%d) != content length (%d)\n",
							   body_len, tmp_len);
#endif

			return FALSE;
		}
	}

	body = g_malloc(body_len + 1);
	memcpy(body, body_start, body_len);
	body[body_len] = '\0';

#ifdef MSN_DEBUG_HTTP
	purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s}\n",
					header);
#endif

	/* Now we should be able to process the data. */
	if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL)
	{
		gchar *full_session_id = NULL, *gw_ip = NULL, *session_action = NULL;
		char *t, *session_id;
		char **elems, **cur, **tokens;

		full_session_id = gw_ip = session_action = NULL;

		s += strlen("X-MSN-Messenger: ");

		if ((c = strchr(s, '\r')) == NULL)
		{
			msn_session_set_error(httpconn->session,
								  MSN_ERROR_HTTP_MALFORMED, NULL);
			purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n",
							 buf);

			g_free(header);
			g_free(body);
			return FALSE;
		}

		tmp = g_strndup(s, c - s);

		elems = g_strsplit(tmp, "; ", 0);

		for (cur = elems; *cur != NULL; cur++)
		{
			tokens = g_strsplit(*cur, "=", 2);

			if (strcmp(tokens[0], "SessionID") == 0) {
				g_free(full_session_id);
				full_session_id = tokens[1];
			} else if (strcmp(tokens[0], "GW-IP") == 0) {
				g_free(gw_ip);
				gw_ip = tokens[1];
			} else if (strcmp(tokens[0], "Session") == 0) {
				g_free(session_action);
				session_action = tokens[1];
			} else
				g_free(tokens[1]);

			g_free(tokens[0]);
			/* Don't free each of the tokens, only the array. */
			g_free(tokens);
		}

		g_strfreev(elems);

		g_free(tmp);

		t = strchr(full_session_id, '.');
		if (t != NULL)
			session_id = g_strndup(full_session_id, t - full_session_id);
		else {
			purple_debug_error("msn", "Malformed full_session_id[%s]\n",
					   full_session_id ? full_session_id : NULL);
			session_id = g_strdup(full_session_id);
		}

		if (session_action == NULL || strcmp(session_action, "close") != 0)
		{
			g_free(httpconn->full_session_id);
			httpconn->full_session_id = full_session_id;

			g_free(httpconn->session_id);
			httpconn->session_id = session_id;

			g_free(httpconn->host);
			httpconn->host = gw_ip;
		}
		else
		{
			MsnServConn *servconn;

			/* It's going to die. */
			/* poor thing */

			servconn = httpconn->servconn;

			/* I'll be honest, I don't fully understand all this, but this
			 * causes crashes, Stu. */
			/* if (servconn != NULL)
				servconn->wasted = TRUE; */

			g_free(full_session_id);
			g_free(session_id);
			g_free(gw_ip);
		}

		g_free(session_action);
	}

	g_free(header);

	*ret_buf  = body;
	*ret_size = body_len;

	msn_httpconn_process_queue(httpconn);

	return TRUE;
}
Esempio n. 6
0
/*------------------------------------------------------------------------
 * Callback when data is received from the HTTP server.
 *
 *  @param user_data		The MXit session object
 *  @param source			The file-descriptor on which data was received
 *  @param cond				Condition which caused the callback (PURPLE_INPUT_READ)
 */
static void mxit_cb_http_read( gpointer user_data, gint source, PurpleInputCondition cond )
{
	struct MXitSession*	session		= (struct MXitSession*) user_data;
	char				buf[256];
	int					buflen;
	char*				body;
	int					bodylen;
	char*				ch;
	int					len;
	char*				tmp;
	int					res;
	char*				next;

	purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_read\n" );

	if ( session->rx_state == RX_STATE_RLEN ) {
		/* we are reading in the HTTP headers */

		/* copy partial headers if we have any part saved */
		memcpy( buf, session->rx_dbuf, session->rx_i );
		buflen = session->rx_i;

		/* read bytes from the socket */
		len = read( session->fd, buf + buflen, sizeof( buf ) - ( buflen + 1 ) );
		if ( len <= 0 ) {
			/* connection has been terminated, or error occurred */
			goto done;
		}
		buf[buflen+len] = '\0';

//nextpacket:

#ifdef	DEBUG_HTTP
		purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 1: (%i)\n", len );
		dump_bytes( session, buf + buflen, len );
#endif

		/* see if we have all the HTTP headers yet */
		ch = strstr( buf, HTTP_11_SEPERATOR );
		if ( !ch ) {
			/* we need to wait for more input, so save what we have */
			session->rx_i = buflen + len;
			memcpy( session->rx_dbuf, buf, session->rx_i );
			return;
		}
		buflen += len;

		/* we have the header's end now skip over the http separator to get the body offset */
		ch += strlen( HTTP_11_SEPERATOR );
		*(ch - 1) = '\0';
		body = ch;

		res = buflen - ( ch - buf );
		if ( res > 0 ) {
			/* we read more bytes than just the header so copy it over */
			memcpy( session->rx_dbuf, ch, res );
			session->rx_i = res;
		}
		else {
			session->rx_i = 0;
		}

		/* test for a good response */
		if ( ( strncmp( buf, HTTP_11_200_OK, strlen( HTTP_11_200_OK ) ) != 0 ) && ( strncmp( buf, HTTP_11_100_CONT, strlen( HTTP_11_100_CONT ) ) != 0 ) ) {
			/* bad result */
			purple_debug_error( MXIT_PLUGIN_ID, "HTTP error: %s\n", ch );
			goto done;
		}

		/* find the content-length */
		ch = (char*) purple_strcasestr( buf, HTTP_CONTENT_LEN );
		if ( !ch ) {
			/* bad request. it does not contain a content-length header */
			purple_debug_error( MXIT_PLUGIN_ID, "HTTP reply received without content-length header (ignoring packet)\n" );
			goto done;
		}

		/* parse the content-length */
		ch += strlen( HTTP_CONTENT_LEN );
		tmp = strchr( ch, '\r' );
		if ( !tmp ) {
			purple_debug_error( MXIT_PLUGIN_ID, "Received bad HTTP reply packet (ignoring packet)\n" );
			goto done;
		}
		tmp = g_strndup( ch, tmp - ch );
		bodylen = atoi( tmp );
		g_free( tmp );
		tmp = NULL;

		if ( buflen + bodylen >= CP_MAX_PACKET ) {
			/* this packet is way to big */
			goto done;
		}
		else if ( buflen > ( ( body - buf ) + bodylen ) ) {
			/* we have a second packet here */
			next = body + bodylen;
			session->rx_res = 0;
		}
		else {
			session->rx_res = bodylen - session->rx_i;
		}

		if ( session->rx_res == 0 ) {
			/* we have read all the data */
			session->rx_i = bodylen;
			session->rx_state = RX_STATE_PROC;
		}
		else {
			/* there is still some data outstanding */
			session->rx_state = RX_STATE_DATA;
		}
	}
	else if ( session->rx_state == RX_STATE_DATA ) {
		/* we are reading the HTTP content (body) */

		/* read bytes from the socket */
		len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
		if ( len <= 0 ) {
			/* connection has been terminated, or error occurred */
			goto done;
		}

#ifdef	DEBUG_HTTP
		purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 2: (%i)\n", len );
		dump_bytes( session, &session->rx_dbuf[session->rx_i], len );
#endif
		session->rx_i += len;
		session->rx_res -= len;

		if ( session->rx_res == 0 ) {
			/* ok, so now we have read in the whole packet */
			session->rx_state = RX_STATE_PROC;
		}
	}

	if ( session->rx_state == RX_STATE_PROC ) {
		mxit_parse_packet( session );

#if	0
		if ( next ) {
			/* there is another packet of which we read some data */

			/* reset input */
			session->rx_state = RX_STATE_RLEN;
			session->rx_lbuf[0] = '\0';
			session->rx_i = 0;
			session->rx_res = 0;

			/* move read data */
			len = next - buf;
			buflen = len;
			memcpy( buf, next, len );
			goto nextpacket;
		}
#endif

		/* we are done */
		goto done;
	}

	return;
done:
	close( session->fd );
	purple_input_remove( session->http_handler );
	session->http_handler = 0;
}
Esempio n. 7
0
/*--------------------------------------------------------------------------*
 * PUBLIC FUNCTIONS                                                         *
 *--------------------------------------------------------------------------*/
void ap_gtk_add_message (APUpdateType update_type, APMessageType type, 
                const gchar *text) 
{
  GtkTreeIter iter;
  struct tm *cur_time;
  char *time_string, *simple_text, *s;
  time_t *general_time;
  gchar *type_string;
  
  // Create the time string 
  general_time = (time_t *) malloc (sizeof(time_t));
  time (general_time);
  cur_time = ap_localtime (general_time);
  free (general_time);

  time_string = (char *) malloc (sizeof(char[32]));
  *time_string = '\0';

  strftime (time_string, 31, "<b>%I:%M %p</b>", cur_time);
  free (cur_time);
 
  // Create the type string
  type_string = strdup("<b>Status</b>");
  switch (type) {
    case AP_MESSAGE_TYPE_PROFILE:
      type_string = strdup (_("<b>User profile</b>"));
      break;
    case AP_MESSAGE_TYPE_AWAY:
      type_string = strdup (_("<b>Away message</b>"));
      break;
    case AP_MESSAGE_TYPE_AVAILABLE:
      type_string = strdup (_("<b>Available message</b>"));
      break;
    case AP_MESSAGE_TYPE_STATUS:
      type_string = strdup (_("<b>Status message</b>"));
      break;
    default:
      type_string = strdup (_("<b>Other</b>"));
      break;
  }

  // Simplify the text
  if (text != NULL) {
    simple_text = strdup (text);

    // Only show the first line 
    s = (gchar *) purple_strcasestr (simple_text, "<br>");
    if (s != NULL) {
      *s++ = '.';
      *s++ = '.';
      *s++ = '.';
      *s   = '\0';
    }

    // Strip HTML
    s = simple_text;
    simple_text = purple_markup_strip_html (simple_text);
    free (s);
    
  } else {
    simple_text = NULL;
  }  

  // Add it 
  gtk_list_store_prepend (message_list, &iter);
  gtk_list_store_set (message_list, &iter,
                      0, time_string,
                      1, type_string,
                      2, simple_text,
                      3, text,
                      -1);
  free (type_string);
  free (time_string);
  if (simple_text) free (simple_text);

  // Delete if too many
  if (gtk_tree_model_iter_nth_child 
        (GTK_TREE_MODEL(message_list), &iter, NULL, 
         AP_GTK_MAX_MESSAGES)) {
    gtk_list_store_remove (message_list, &iter);
  }

  // Move the timeout bar
  ap_gtk_timeout_start (update_type);

  // Check if it needs to be visible or not
  if (type != AP_MESSAGE_TYPE_PROFILE && 
      ap_is_currently_away () != ap_previously_away) {
    update_summary_visibility ();
  }
}
Esempio n. 8
0
static void
jabber_bosh_http_connection_process(PurpleHTTPConnection *conn)
{
	const char *cursor;

	cursor = conn->read_buf->str + conn->handled_len;

	if (!conn->headers_done) {
		const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length");
		const char *end_of_headers = strstr(cursor, "\r\n\r\n");

		/* Make sure Content-Length is in headers, not body */
		if (content_length && (!end_of_headers || content_length < end_of_headers)) {
			const char *sep;
			const char *eol;
			int len;

			if ((sep = strstr(content_length, ": ")) == NULL ||
					(eol = strstr(sep, "\r\n")) == NULL)
				/*
				 * The packet ends in the middle of the Content-Length line.
				 * We'll try again later when we have more.
				 */
				return;

			len = atoi(sep + 2);
			if (len == 0)
				purple_debug_warning("jabber", "Found mangled Content-Length header.\n");

			conn->body_len = len;
		}

		if (end_of_headers) {
			conn->headers_done = TRUE;
			conn->handled_len = end_of_headers - conn->read_buf->str + 4;
			cursor = end_of_headers + 4;
		} else {
			conn->handled_len = conn->read_buf->len;
			return;
		}
	}

	/* Have we handled everything in the buffer? */
	if (conn->handled_len >= conn->read_buf->len)
		return;

	/* Have we read all that the Content-Length promised us? */
	if (conn->read_buf->len - conn->handled_len < conn->body_len)
		return;

	--conn->requests;
	--conn->bosh->requests;

	http_received_cb(conn->read_buf->str + conn->handled_len, conn->body_len,
	                 conn->bosh);

	if (conn->bosh->state == BOSH_CONN_ONLINE &&
			(conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0)) {
		purple_debug_misc("jabber", "BOSH: Sending an empty request\n");
		jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL);
	}

	g_string_free(conn->read_buf, TRUE);
	conn->read_buf = NULL;
	conn->headers_done = FALSE;
	conn->handled_len = conn->body_len = 0;
}