示例#1
0
/** Invite us to the focus callback */
static gboolean
process_invite_conf_focus_response(struct sipe_core_private *sipe_private,
				   struct sipmsg *msg,
				   SIPE_UNUSED_PARAMETER struct transaction *trans)
{
	struct sip_session *session = NULL;
	char *focus_uri = parse_from(sipmsg_find_header(msg, "To"));

	session = sipe_session_find_conference(sipe_private, focus_uri);

	if (!session) {
		SIPE_DEBUG_INFO("process_invite_conf_focus_response: unable to find conf session with focus=%s", focus_uri);
		g_free(focus_uri);
		return FALSE;
	}

	if (!session->focus_dialog) {
		SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: session's focus_dialog is NULL");
		g_free(focus_uri);
		return FALSE;
	}

	sipe_dialog_parse(session->focus_dialog, msg, TRUE);

	if (msg->response >= 200) {
		/* send ACK to focus */
		session->focus_dialog->cseq = 0;
		sip_transport_ack(sipe_private, session->focus_dialog);
		session->focus_dialog->outgoing_invite = NULL;
		session->focus_dialog->is_established = TRUE;
	}

	if (msg->response >= 400) {
		SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus.");
		/* @TODO notify user of failure to join focus */
		sipe_session_remove(sipe_private, session);
		g_free(focus_uri);
		return FALSE;
	} else if (msg->response == 200) {
		sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen);
		const gchar *code = sipe_xml_attribute(xn_response, "code");
		if (sipe_strequal(code, "success")) {
			/* subscribe to focus */
			sipe_subscribe_conference(sipe_private, session, FALSE);
		}
		sipe_xml_free(xn_response);
	}

	g_free(focus_uri);
	return TRUE;
}
gboolean sipe_certificate_init(struct sipe_core_private *sipe_private)
{
	struct sipe_certificate *sc;
	struct sipe_cert_crypto *ssc;

	if (sipe_private->certificate)
		return(TRUE);

	ssc = sipe_cert_crypto_init();
	if (!ssc) {
		SIPE_DEBUG_ERROR_NOFORMAT("sipe_certificate_init: crypto backend init FAILED!");
		return(FALSE);
	}

	sc = g_new0(struct sipe_certificate, 1);
	sc->certificates = g_hash_table_new_full(g_str_hash, g_str_equal,
						 g_free,
						 sipe_cert_crypto_destroy);
	sc->backend = ssc;

	SIPE_DEBUG_INFO_NOFORMAT("sipe_certificate_init: DONE");

	sipe_private->certificate = sc;
	return(TRUE);
}
示例#3
0
gssize sipe_backend_ft_write(struct sipe_file_transfer * /*ft*/,
        const guchar * /*data*/,
        gsize /*size*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_ft_write");
    return 0;
}
/** Create conference callback */
static gboolean
process_conf_add_response(struct sipe_core_private *sipe_private,
			  struct sipmsg *msg,
			  struct transaction *trans)
{
	if (msg->response >= 400) {
		SIPE_DEBUG_INFO_NOFORMAT("process_conf_add_response: SERVICE response is not 200. Failed to create conference.");
		/* @TODO notify user of failure to create conference */
		return FALSE;
	}
	if (msg->response == 200) {
		sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen);
		if (sipe_strequal("success", sipe_xml_attribute(xn_response, "code")))
		{
			gchar *who = trans->payload->data;
			const sipe_xml *xn_conference_info = sipe_xml_child(xn_response, "addConference/conference-info");
			struct sip_session *session = sipe_conf_create(sipe_private,
								       NULL,
								       sipe_xml_attribute(xn_conference_info,
											  "entity"));

			SIPE_DEBUG_INFO("process_conf_add_response: session->focus_uri=%s",
					session->chat_session->id);

			session->pending_invite_queue = sipe_utils_slist_insert_unique_sorted(session->pending_invite_queue,
											      g_strdup(who),
											      (GCompareFunc)strcmp,
											      g_free);
		}
		sipe_xml_free(xn_response);
	}

	return TRUE;
}
示例#5
0
void sipe_backend_ft_incoming(struct sipe_core_public * /*sipe_public*/,
        struct sipe_file_transfer * /*ft*/,
        const gchar * /*who*/,
        const gchar * /*file_name*/,
        gsize /*file_size*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_ft_incoming");
}
示例#6
0
void sipe_backend_user_ask(struct sipe_core_public * /*sipe_public*/,
        const gchar * /*message*/,
        const gchar * /*accept_label*/,
        const gchar * /*decline_label*/,
        gpointer /*key*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_user_ask");
}
示例#7
0
/**
 * Updates contact's status
 * based on their calendar information.
 */
static void update_calendar_status(struct sipe_core_private *sipe_private,
                                   SIPE_UNUSED_PARAMETER void *unused)
{
    SIPE_DEBUG_INFO_NOFORMAT("update_calendar_status() started.");
    sipe_buddy_foreach(sipe_private,
                       (GHFunc) update_calendar_status_cb,
                       sipe_private);

    /* repeat scheduling */
    sipe_ocs2005_schedule_status_update(sipe_private,
                                        time(NULL) + 3 * 60 /* 3 min */);
}
示例#8
0
char * sip_sec_make_signature(SipSecContext context, const char *message)
{
	SipSecBuffer signature;
	char *signature_hex;

	if(((*context->make_signature_func)(context, message, &signature)) != SIP_SEC_E_OK) {
		SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_make_signature failed. Unable to sign message!");
		return NULL;
	}
	signature_hex = buff_to_hex_str(signature.value, signature.length);
	g_free(signature.value);
	return signature_hex;
}
static void certprov_webticket(struct sipe_core_private *sipe_private,
			       const gchar *base_uri,
			       const gchar *auth_uri,
			       const gchar *wsse_security,
			       const gchar *failure_msg,
			       gpointer callback_data)
{
	struct certificate_callback_data *ccd = callback_data;

	if (wsse_security) {
		/* Got a Web Ticket for Certificate Provisioning Service */
		gchar *certreq_base64 = create_certreq(sipe_private,
						       sipe_private->username);

		SIPE_DEBUG_INFO("certprov_webticket: got ticket for %s",
				base_uri);

		if (certreq_base64) {

			SIPE_DEBUG_INFO_NOFORMAT("certprov_webticket: created certificate request");

			if (sipe_svc_get_and_publish_cert(sipe_private,
							  ccd->session,
							  auth_uri,
							  wsse_security,
							  certreq_base64,
							  get_and_publish_cert,
							  ccd))
				/* callback data passed down the line */
				ccd = NULL;

			g_free(certreq_base64);
		}

	        if (ccd) {
			certificate_failure(sipe_private,
					    _("Certificate request to %s failed"),
					    base_uri,
					    NULL);
		}

	} else if (auth_uri) {
		certificate_failure(sipe_private,
				    _("Web ticket request to %s failed"),
				    base_uri,
				    failure_msg);
	}

	if (ccd)
		callback_data_free(ccd);
}
static void get_and_publish_cert(struct sipe_core_private *sipe_private,
				 const gchar *uri,
				 SIPE_UNUSED_PARAMETER const gchar *raw,
				 sipe_xml *soap_body,
				 gpointer callback_data)
{
	struct certificate_callback_data *ccd = callback_data;
	gboolean success = (uri == NULL); /* abort case */

	if (soap_body) {
		gchar *cert_base64 = sipe_xml_data(sipe_xml_child(soap_body,
								  "Body/GetAndPublishCertResponse/RequestSecurityTokenResponse/RequestedSecurityToken/BinarySecurityToken"));

		SIPE_DEBUG_INFO("get_and_publish_cert: received valid SOAP message from service %s",
				uri);

		if (cert_base64) {
			gpointer opaque = sipe_cert_crypto_decode(sipe_private->certificate->backend,
								  cert_base64);

			SIPE_DEBUG_INFO_NOFORMAT("get_and_publish_cert: found certificate");

			if (opaque) {
				add_certificate(sipe_private,
						ccd->target,
						opaque);
				SIPE_DEBUG_INFO("get_and_publish_cert: certificate for target '%s' added",
						ccd->target);

				/* Let's try this again... */
				sip_transport_authentication_completed(sipe_private);
				success = TRUE;
			}

			g_free(cert_base64);
		}

	}

	if (!success) {
		certificate_failure(sipe_private,
				    _("Certificate request to %s failed"),
				    uri,
				    NULL);
	}

	callback_data_free(ccd);
}
示例#11
0
char *
sip_sec_init_context(SipSecContext *context,
		     int *expires,
		     guint type,
		     const int  sso,
		     const char *domain,
		     const char *username,
		     const char *password,
		     const char *target,
		     const char *input_toked_base64)
{
	sip_uint32 ret;
	char *output_toked_base64 = NULL;
	int exp;

	*context = sip_sec_create_context(type,
					  sso,
					  0, /* Connectionless for SIP */
					  domain,
					  username,
					  password);
	if (!*context) {
		SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context: failed sip_sec_create_context()");
		return NULL;
	}

	ret = sip_sec_init_context_step(*context,
					target,
					NULL,
					&output_toked_base64,
					&exp);

	/* for NTLM type 3 */
	if (ret == SIP_SEC_I_CONTINUE_NEEDED) {
		g_free(output_toked_base64);
		ret = sip_sec_init_context_step(*context,
						target,
						input_toked_base64,
						&output_toked_base64,
						&exp);
	}

	if (expires) {
		*expires = exp;
	}

	return output_toked_base64;
}
static void socket_connected(GObject *client,
			     GAsyncResult *result,
			     gpointer data)
{
	struct sipe_transport_telepathy *transport = data;
	GError *error = NULL;

	transport->socket = g_socket_client_connect_finish(G_SOCKET_CLIENT(client),
							   result,
							   &error);

	if (transport->socket == NULL) {
		if (transport->tls_info) {
			SIPE_DEBUG_INFO_NOFORMAT("socket_connected: need to wait for user interaction");
			sipe_telepathy_tls_verify_async(G_OBJECT(transport->private->connection),
							transport->tls_info,
							certificate_result,
							transport);
		} else {
示例#13
0
static gboolean
sip_sec_acquire_cred__basic(SipSecContext context,
			    SIPE_UNUSED_PARAMETER const gchar *domain,
			    const gchar *username,
			    const gchar *password)
{
	context_basic ctx = (context_basic) context;

	SIPE_DEBUG_INFO_NOFORMAT("sip_sec_acquire_cred__basic: entering");

	if (!username || !password)
		return(FALSE);

	/* calculate Basic token (RFC1945 section 11.1) */
	ctx->token  = g_strdup_printf("%s:%s", username, password);
	ctx->length = strlen(ctx->token);

	return(TRUE);
}
示例#14
0
/**
 * Modify Conference Lock
 * Sends request to Focus.
 * INFO method is a carrier of application/cccp+xml
 */
void
sipe_core_chat_modify_lock(struct sipe_core_public *sipe_public,
			   struct sipe_chat_session *chat_session,
			   const gboolean locked)
{
	struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
	gchar *hdr;
	gchar *body;
	gchar *self;

	struct sip_session *session = sipe_session_find_chat(sipe_private,
							     chat_session);

	if (!session) return;
	if (!session->focus_dialog || !session->focus_dialog->is_established) {
		SIPE_DEBUG_INFO_NOFORMAT("sipe_conf_modify_conference_lock: no dialog with focus, exiting.");
		return;
	}

	hdr = g_strdup(
		"Content-Type: application/cccp+xml\r\n");

	/* @TODO put request_id to queue to further compare with incoming one */
	self = sip_uri_self(sipe_private);
	body = g_strdup_printf(
		SIPE_SEND_CONF_MODIFY_CONF_LOCK,
		session->focus_dialog->with,
		self,
		session->request_id++,
		session->focus_dialog->with,
		locked ? "true" : "false");
	g_free(self);

	sip_transport_info(sipe_private,
			   hdr,
			   body,
			   session->focus_dialog,
			   NULL);
	g_free(body);
	g_free(hdr);
}
示例#15
0
void sipe_core_init(void)
{
	srand(time(NULL));
	sip_sec_init();

#ifdef ENABLE_NLS
	SIPE_DEBUG_INFO("bindtextdomain = %s",
			bindtextdomain(PACKAGE_NAME, LOCALEDIR));
	SIPE_DEBUG_INFO("bind_textdomain_codeset = %s",
			bind_textdomain_codeset(PACKAGE_NAME, "UTF-8"));
	textdomain(PACKAGE_NAME);
#endif
#ifdef HAVE_NSS
	if (!NSS_IsInitialized()) {
		NSS_NoDB_Init(".");
		SIPE_DEBUG_INFO_NOFORMAT("NSS initialised");
	}
#endif
#ifdef HAVE_GMIME
	g_mime_init(0);
#endif
}
static gchar *create_certreq(struct sipe_core_private *sipe_private,
			     const gchar *subject)
{
	gchar *base64;

	if (!sipe_certificate_init(sipe_private))
		return(NULL);

	SIPE_DEBUG_INFO_NOFORMAT("create_req: generating new certificate request");

	base64 = sipe_cert_crypto_request(sipe_private->certificate->backend,
					  subject);
	if (base64) {
		GString *format = g_string_new(NULL);
		gsize count     = strlen(base64);
		const gchar *p  = base64;

		/* Base64 needs to be formated correctly */
#define CERTREQ_BASE64_LINE_LENGTH 76
		while (count > 0) {
			gsize chunk = count > CERTREQ_BASE64_LINE_LENGTH ?
				CERTREQ_BASE64_LINE_LENGTH : count;
			g_string_append_len(format, p, chunk);
			if (chunk == CERTREQ_BASE64_LINE_LENGTH)
				g_string_append(format, "\r\n");
			count -= chunk;
			p     += chunk;
		}

		/* swap Base64 buffers */
		g_free(base64);
		base64 = format->str;
		g_string_free(format, FALSE);
	}

	return(base64);
}
示例#17
0
/* sip_sec API methods */
SipSecContext
sip_sec_create_context(guint type,
		       const int  sso,
		       int is_connection_based,
		       const char *domain,
		       const char *username,
		       const char *password)
{
	SipSecContext context = NULL;

	/* Map authentication type to module initialization hook & name */
	static sip_sec_create_context_func const auth_to_hook[] = {
		sip_sec_create_context__NONE,      /* AUTH_TYPE_UNSET     */
		sip_sec_create_context__NONE,      /* AUTH_TYPE_DIGEST    */
		sip_sec_create_context__NTLM,      /* AUTH_TYPE_NTLM      */
		sip_sec_create_context__Kerberos,  /* AUTH_TYPE_KERBEROS  */
		sip_sec_create_context__Negotiate, /* AUTH_TYPE_NEGOTIATE */
	};

	context = (*(auth_to_hook[type]))(type);
	if (context) {
		sip_uint32 ret;

		context->sso = sso;
		context->is_connection_based = is_connection_based;

		ret = (*context->acquire_cred_func)(context, domain, username, password);
		if (ret != SIP_SEC_E_OK) {
			SIPE_DEBUG_INFO_NOFORMAT("ERROR: sip_sec_init_context failed to acquire credentials.");
			(*context->destroy_context_func)(context);
			context = NULL;
		}
	}

	return(context);
}
示例#18
0
/** Modify Delete User */
void
sipe_conf_delete_user(struct sipe_core_private *sipe_private,
		      struct sip_session *session,
		      const gchar* who)
{
	gchar *hdr;
	gchar *body;
	gchar *self;

	if (!session->focus_dialog || !session->focus_dialog->is_established) {
		SIPE_DEBUG_INFO_NOFORMAT("sipe_conf_delete_user: no dialog with focus, exiting.");
		return;
	}

	hdr = g_strdup(
		"Content-Type: application/cccp+xml\r\n");

	/* @TODO put request_id to queue to further compare with incoming one */
	self = sip_uri_self(sipe_private);
	body = g_strdup_printf(
		SIPE_SEND_CONF_DELETE_USER,
		session->focus_dialog->with,
		self,
		session->request_id++,
		session->focus_dialog->with,
		who);
	g_free(self);

	sip_transport_info(sipe_private,
			   hdr,
			   body,
			   session->focus_dialog,
			   NULL);
	g_free(body);
	g_free(hdr);
}
void process_incoming_bye(struct sipe_core_private *sipe_private,
			  struct sipmsg *msg)
{
	const gchar *callid = sipmsg_find_header(msg, "Call-ID");
	gchar *from = parse_from(sipmsg_find_header(msg, "From"));
	struct sip_session *session;
	struct sip_dialog *dialog;

#ifdef HAVE_VV
	if (is_media_session_msg(sipe_private->media_call, msg)) {
		// BYE ends a media call
		sipe_media_hangup(sipe_private->media_call);
	}
#endif

	/* collect dialog identification
	 * we need callid, ourtag and theirtag to unambiguously identify dialog
	 */
	/* take data before 'msg' will be modified by sip_transport_response */
	dialog = g_new0(struct sip_dialog, 1);
	dialog->callid = g_strdup(callid);
	dialog->cseq = sipmsg_parse_cseq(msg);
	dialog->with = g_strdup(from);
	sipe_dialog_parse(dialog, msg, FALSE);

	sip_transport_response(sipe_private, msg, 200, "OK", NULL);

	session = sipe_session_find_chat_or_im(sipe_private, callid, from);
	if (!session) {
		SIPE_DEBUG_INFO_NOFORMAT("process_incoming_bye: couldn't find session. Ignoring");
		sipe_dialog_free(dialog);
		g_free(from);
		return;
	}

	SIPE_DEBUG_INFO("process_incoming_bye: session found (chat ID %s)",
			(session->chat_session && session->chat_session->id) ?
			session->chat_session->id : "<NO CHAT>");

	if (session->chat_session &&
	    (session->chat_session->type == SIPE_CHAT_TYPE_MULTIPARTY) &&
	    session->chat_session->id &&
	    !g_ascii_strcasecmp(from, session->chat_session->id))
		sipe_chat_set_roster_manager(session, NULL);

	sipe_im_cancel_unconfirmed(sipe_private, session, callid, from);

	/* This what BYE is essentially for - terminating dialog */
	sipe_dialog_remove_3(session, dialog);
	sipe_dialog_free(dialog);
	if (session->chat_session) {
		if ((session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE) &&
		    !g_ascii_strcasecmp(from, session->im_mcu_uri)) {
			SIPE_DEBUG_INFO("process_incoming_bye: disconnected from conference %s",
					session->im_mcu_uri);
			sipe_conf_immcu_closed(sipe_private, session);
		} else if (session->chat_session->type == SIPE_CHAT_TYPE_MULTIPARTY) {
			SIPE_DEBUG_INFO_NOFORMAT("process_incoming_bye: disconnected from multiparty chat");
			sipe_backend_chat_remove(session->chat_session->backend,
						 from);
		}
	}

	g_free(from);
}
示例#20
0
void sipe_backend_im_message(struct sipe_core_public * /*sipe_public*/,
        const gchar * /*from*/,
        const gchar * /*html*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_im_message");
}
示例#21
0
void sipe_backend_im_topic(struct sipe_core_public * /*sipe_public*/,
        const gchar * /*with*/,
        const gchar * /*topic*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_im_topic");
}
static void read_completed(GObject *stream,
			   GAsyncResult *result,
			   gpointer data)
{
	struct sipe_transport_telepathy *transport = data;
	struct sipe_transport_connection *conn = SIPE_TRANSPORT_CONNECTION;

	do {
		if (conn->buffer_length < conn->buffer_used + BUFFER_SIZE_INCREMENT) {
			conn->buffer_length += BUFFER_SIZE_INCREMENT;
			conn->buffer = g_realloc(conn->buffer, conn->buffer_length);
			SIPE_DEBUG_INFO("read_completed: new buffer length %" G_GSIZE_FORMAT,
					conn->buffer_length);
		}

		/* callback result is valid */
		if (result) {
			GError *error = NULL;
			gssize len    = g_input_stream_read_finish(G_INPUT_STREAM(stream),
								   result,
								   &error);

			if (len < 0) {
				const gchar *msg = error ? error->message : "UNKNOWN";
				SIPE_DEBUG_ERROR("read_completed: error: %s", msg);
				if (transport->error)
					transport->error(conn, msg);
				g_error_free(error);
				return;
			} else if (len == 0) {
				SIPE_DEBUG_ERROR_NOFORMAT("read_completed: server has disconnected");
				transport->error(conn, _("Server has disconnected"));
				return;
			} else if (transport->do_flush) {
				/* read completed while disconnected transport is flushing */
				SIPE_DEBUG_INFO_NOFORMAT("read_completed: ignored during flushing");
				return;
			} else if (g_cancellable_is_cancelled(transport->cancel)) {
				/* read completed when transport was disconnected */
				SIPE_DEBUG_INFO_NOFORMAT("read_completed: cancelled");
				return;
			}

			/* Forward data to core */
			conn->buffer_used               += len;
			conn->buffer[conn->buffer_used]  = '\0';
			transport->input(conn);

			/* we processed the result */
			result = NULL;
		}

		/* buffer too short? */
	} while (conn->buffer_length - conn->buffer_used - 1 == 0);

	/* setup next read */
	g_input_stream_read_async(G_INPUT_STREAM(stream),
				  conn->buffer + conn->buffer_used,
				  conn->buffer_length - conn->buffer_used - 1,
				  G_PRIORITY_DEFAULT,
				  transport->cancel,
				  read_completed,
				  transport);
}
示例#23
0
static void
sipe_domino_process_calendar_response(int return_code,
				 const char *body,
				 const char *content_type,
				 HttpConn *conn,
				 void *data)
{
	struct sipe_calendar *cal = data;

	SIPE_DEBUG_INFO_NOFORMAT("sipe_domino_process_calendar_response: cb started.");

	http_conn_set_close(conn);
	cal->http_conn = NULL;

	if (content_type && !g_str_has_prefix(content_type, "text/xml")) {
		cal->is_domino_disabled = TRUE;
		SIPE_DEBUG_INFO_NOFORMAT("sipe_domino_process_calendar_response: not XML, disabling.");
		return;
	}

	if (return_code == 200 && body) {
		const sipe_xml *node, *node2, *node3;
		sipe_xml *xml;

		SIPE_DEBUG_INFO("sipe_domino_process_calendar_response: SUCCESS, ret=%d", return_code);
		xml = sipe_xml_parse(body, strlen(body));

		sipe_cal_events_free(cal->cal_events);
		cal->cal_events = NULL;
		/* viewentry */
		for (node = sipe_xml_child(xml, "viewentry");
		     node;
		     node = sipe_xml_twin(node))
		{
			struct sipe_cal_event *cal_event = g_new0(struct sipe_cal_event, 1);
			cal->cal_events = g_slist_append(cal->cal_events, cal_event);
			cal_event->cal_status = SIPE_CAL_BUSY;
			cal_event->is_meeting = TRUE;

			/* SIPE_DEBUG_INFO("viewentry unid=%s", sipe_xml_attribute(node, "unid")); */

			/* entrydata */
			for (node2 = sipe_xml_child(node, "entrydata");
			     node2;
			     node2 = sipe_xml_twin(node2))
			{
				const char *name = sipe_xml_attribute(node2, "name");

				SIPE_DEBUG_INFO("\tentrydata name=%s", name);

				if (sipe_strequal(name, VIEWENTITY_START0_TIME) ||
				    sipe_strequal(name, VIEWENTITY_START_TIME) ||
				    sipe_strequal(name, VIEWENTITY_END_TIME))
				{
					char *tmp = sipe_xml_data(sipe_xml_child(node2, "datetime"));
					time_t time_val = sipe_utils_str_to_time(tmp);

					if (sipe_strequal(name, VIEWENTITY_START_TIME)) {
						cal_event->start_time = time_val;
					} else if (sipe_strequal(name, VIEWENTITY_END_TIME)) {
						cal_event->end_time = time_val;
					}

					SIPE_DEBUG_INFO("\t\tdatetime=%s", asctime(gmtime(&time_val)));
					g_free(tmp);
				} else if (sipe_strequal(name, VIEWENTITY_TEXT_LIST)) {
					int i = 0;

					/* test */
					for (node3 = sipe_xml_child(node2, "textlist/text");
					     node3;
					     node3 = sipe_xml_twin(node3))
					{
						char *tmp = sipe_xml_data(node3);

						if (!tmp) continue;

						SIPE_DEBUG_INFO("\t\ttext=%s", tmp);
						if (i == 0) {
							cal_event->subject = g_strdup(tmp);
							SIPE_DEBUG_INFO("\t\t*Subj.=%s", tmp);
						} else {
							/* plain English, don't localize! */
							if (!g_ascii_strncasecmp(tmp, "Location:", 9)) {
								if (strlen(tmp) > 9) {
									cal_event->location = g_strdup(g_strstrip(tmp+9));
									SIPE_DEBUG_INFO("\t\t*Loc.=%s", cal_event->location);
								}
							/* Translators: (!) should be as in localized Lotus Notes to be able to extract meeting location */
							} else if (g_str_has_prefix(tmp, _("Location:"))) {
								guint len = strlen(_("Location:"));
								if (strlen(tmp) > len) {
									cal_event->location = g_strdup(g_strstrip(tmp+len));
									SIPE_DEBUG_INFO("\t\t*Loc.=%s", cal_event->location);
								}
							}
						}
						i++;
						g_free(tmp);
					}
				}
			}
		}
		sipe_xml_free(xml);

		/* creates FreeBusy from cal->cal_events */
		g_free(cal->free_busy);
		cal->free_busy = sipe_domino_get_free_busy(cal->fb_start, cal->cal_events);

		/* update SIP server */
		cal->is_updated = TRUE;
		if (cal->sip->ocs2007) {
			/* sipe.h */
			publish_calendar_status_self(cal->sip->private,
						     NULL);
		} else {
示例#24
0
void sipe_backend_user_feedback_typing(struct sipe_core_public * /*sipe_public*/,
        const gchar * /*from*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_user_feedback_typing");
}
示例#25
0
static void
sipe_ews_process_avail_response(int return_code,
				const char *body,
				SIPE_UNUSED_PARAMETER const char *content_type,
				HttpConn *conn,
				void *data)
{
	struct sipe_calendar *cal = data;

	SIPE_DEBUG_INFO_NOFORMAT("sipe_ews_process_avail_response: cb started.");

	if(!sipe_strequal(cal->as_url, cal->oof_url)) { /* whether reuse conn */
		http_conn_set_close(conn);
		cal->http_conn = NULL;
	}

	if (return_code == 200 && body) {
		const sipe_xml *node;
		const sipe_xml *resp;
		/** ref: [MS-OXWAVLS] */
		sipe_xml *xml = sipe_xml_parse(body, strlen(body));
		/*
Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/ResponseMessage@ResponseClass="Success"
Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/MergedFreeBusy
Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/CalendarEventArray/CalendarEvent
Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/WorkingHours
		 */
		resp = sipe_xml_child(xml, "Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse");
		if (!resp) return; /* rather soap:Fault */
		if (!sipe_strequal(sipe_xml_attribute(sipe_xml_child(resp, "ResponseMessage"), "ResponseClass"), "Success")) {
			return; /* Error response */
		}

		/* MergedFreeBusy */
		g_free(cal->free_busy);
		cal->free_busy = sipe_xml_data(sipe_xml_child(resp, "FreeBusyView/MergedFreeBusy"));

		/* WorkingHours */
		node = sipe_xml_child(resp, "FreeBusyView/WorkingHours");
		g_free(cal->working_hours_xml_str);
		cal->working_hours_xml_str = sipe_xml_stringify(node);
		SIPE_DEBUG_INFO("sipe_ews_process_avail_response: cal->working_hours_xml_str:\n%s",
				cal->working_hours_xml_str ? cal->working_hours_xml_str : "");

		sipe_cal_events_free(cal->cal_events);
		cal->cal_events = NULL;
		/* CalendarEvents */
		for (node = sipe_xml_child(resp, "FreeBusyView/CalendarEventArray/CalendarEvent");
		     node;
		     node = sipe_xml_twin(node))
		{
			char *tmp;
/*
      <CalendarEvent>
	<StartTime>2009-12-07T13:30:00</StartTime>
	<EndTime>2009-12-07T14:30:00</EndTime>
	<BusyType>Busy</BusyType>
	<CalendarEventDetails>
	  <ID>0000000...</ID>
	  <Subject>Lunch</Subject>
	  <Location>Cafe</Location>
	  <IsMeeting>false</IsMeeting>
	  <IsRecurring>true</IsRecurring>
	  <IsException>false</IsException>
	  <IsReminderSet>true</IsReminderSet>
	  <IsPrivate>false</IsPrivate>
	</CalendarEventDetails>
      </CalendarEvent>
*/
			struct sipe_cal_event *cal_event = g_new0(struct sipe_cal_event, 1);
			cal->cal_events = g_slist_append(cal->cal_events, cal_event);

			tmp = sipe_xml_data(sipe_xml_child(node, "StartTime"));
			cal_event->start_time = sipe_utils_str_to_time(tmp);
			g_free(tmp);

			tmp = sipe_xml_data(sipe_xml_child(node, "EndTime"));
			cal_event->end_time = sipe_utils_str_to_time(tmp);
			g_free(tmp);

			tmp = sipe_xml_data(sipe_xml_child(node, "BusyType"));
			if (sipe_strequal("Free", tmp)) {
				cal_event->cal_status = SIPE_CAL_FREE;
			} else if (sipe_strequal("Tentative", tmp)) {
				cal_event->cal_status = SIPE_CAL_TENTATIVE;
			} else if (sipe_strequal("Busy", tmp)) {
				cal_event->cal_status = SIPE_CAL_BUSY;
			} else if (sipe_strequal("OOF", tmp)) {
				cal_event->cal_status = SIPE_CAL_OOF;
			} else {
				cal_event->cal_status = SIPE_CAL_NO_DATA;
			}
			g_free(tmp);

			cal_event->subject = sipe_xml_data(sipe_xml_child(node, "CalendarEventDetails/Subject"));
			cal_event->location = sipe_xml_data(sipe_xml_child(node, "CalendarEventDetails/Location"));

			tmp = sipe_xml_data(sipe_xml_child(node, "CalendarEventDetails/IsMeeting"));
			cal_event->is_meeting = tmp ? sipe_strequal(tmp, "true") : TRUE;
			g_free(tmp);
		}

		sipe_xml_free(xml);

		cal->state = SIPE_EWS_STATE_AVAILABILITY_SUCCESS;
		sipe_ews_run_state_machine(cal);

	} else {
		if (return_code < 0) {
示例#26
0
void sipe_backend_user_close_ask(gpointer /*key*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_user_close_ask");
}
示例#27
0
/** Invite us to the focus callback */
static gboolean
process_invite_conf_focus_response(struct sipe_core_private *sipe_private,
				   struct sipmsg *msg,
				   SIPE_UNUSED_PARAMETER struct transaction *trans)
{
	struct sip_session *session = NULL;
	char *focus_uri = parse_from(sipmsg_find_header(msg, "To"));

	session = sipe_session_find_conference(sipe_private, focus_uri);

	if (!session) {
		SIPE_DEBUG_INFO("process_invite_conf_focus_response: unable to find conf session with focus=%s", focus_uri);
		g_free(focus_uri);
		return FALSE;
	}

	if (!session->focus_dialog) {
		SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: session's focus_dialog is NULL");
		g_free(focus_uri);
		return FALSE;
	}

	sipe_dialog_parse(session->focus_dialog, msg, TRUE);

	if (msg->response >= 200) {
		/* send ACK to focus */
		session->focus_dialog->cseq = 0;
		sip_transport_ack(sipe_private, session->focus_dialog);
		session->focus_dialog->outgoing_invite = NULL;
		session->focus_dialog->is_established = TRUE;
	}

	if (msg->response >= 400) {
		gchar *reason = sipmsg_get_ms_diagnostics_reason(msg);

		SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus.");
		sipe_backend_notify_error(SIPE_CORE_PUBLIC,
					  _("Failed to join the conference"),
					  reason ? reason : _("no reason given"));
		g_free(reason);

		sipe_session_remove(sipe_private, session);
		g_free(focus_uri);
		return FALSE;
	} else if (msg->response == 200) {
		sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen);
		const gchar *code = sipe_xml_attribute(xn_response, "code");
		if (sipe_strequal(code, "success")) {
			/* subscribe to focus */
			sipe_subscribe_conference(sipe_private,
						  session->chat_session->id,
						  FALSE);
#ifdef HAVE_VV
			if (session->is_call)
				sipe_core_media_connect_conference(SIPE_CORE_PUBLIC,
								   session->chat_session);
#endif
		}
		sipe_xml_free(xn_response);
	}

	g_free(focus_uri);
	return TRUE;
}
void process_incoming_message(struct sipe_core_private *sipe_private,
			      struct sipmsg *msg)
{
	gchar *from;
	const gchar *contenttype;
	gboolean found = FALSE;

	from = parse_from(sipmsg_find_header(msg, "From"));

	if (!from) return;

	SIPE_DEBUG_INFO("got message from %s: %s", from, msg->body);

	contenttype = sipmsg_find_header(msg, "Content-Type");
	if (g_str_has_prefix(contenttype, "text/plain")
	    || g_str_has_prefix(contenttype, "text/html")
	    || g_str_has_prefix(contenttype, "multipart/related")
	    || g_str_has_prefix(contenttype, "multipart/alternative"))
	{
		const gchar *callid = sipmsg_find_header(msg, "Call-ID");
		gchar *html = get_html_message(contenttype, msg->body);

		struct sip_session *session = sipe_session_find_chat_or_im(sipe_private,
									   callid,
									   from);
		if (session && session->chat_session) {
			if (session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE) { /* a conference */
				gchar *tmp = parse_from(sipmsg_find_header(msg, "Ms-Sender"));
				gchar *sender = parse_from(tmp);
				g_free(tmp);
				sipe_backend_chat_message(SIPE_CORE_PUBLIC,
							  session->chat_session->backend,
							  sender,
							  0,
							  html);
				g_free(sender);
			} else { /* a multiparty chat */
				sipe_backend_chat_message(SIPE_CORE_PUBLIC,
							  session->chat_session->backend,
							  from,
							  0,
							  html);
			}
		} else {
			sipe_backend_im_message(SIPE_CORE_PUBLIC,
						from,
						html);
		}
		g_free(html);
		sip_transport_response(sipe_private, msg, 200, "OK", NULL);
		found = TRUE;

	} else if (g_str_has_prefix(contenttype, "application/im-iscomposing+xml")) {
		sipe_xml *isc = sipe_xml_parse(msg->body, msg->bodylen);
		const sipe_xml *state;
		gchar *statedata;

		if (!isc) {
			SIPE_DEBUG_INFO_NOFORMAT("process_incoming_message: can not parse iscomposing");
			g_free(from);
			return;
		}

		state = sipe_xml_child(isc, "state");

		if (!state) {
			SIPE_DEBUG_INFO_NOFORMAT("process_incoming_message: no state found");
			sipe_xml_free(isc);
			g_free(from);
			return;
		}

		statedata = sipe_xml_data(state);
		if (statedata) {
			if (strstr(statedata, "active")) {
				sipe_backend_user_feedback_typing(SIPE_CORE_PUBLIC,
								  from);
			} else {
				sipe_backend_user_feedback_typing_stop(SIPE_CORE_PUBLIC,
								       from);
			}
			g_free(statedata);
		}
		sipe_xml_free(isc);
		sip_transport_response(sipe_private, msg, 200, "OK", NULL);
		found = TRUE;
	} else if (g_str_has_prefix(contenttype, "text/x-msmsgsinvite")) {
		const gchar *callid = sipmsg_find_header(msg, "Call-ID");
		struct sip_session *session = sipe_session_find_chat_or_im(sipe_private,
									   callid,
									   from);
		if (session) {
			struct sip_dialog *dialog = sipe_dialog_find(session, from);
			GSList *body = sipe_ft_parse_msg_body(msg->body);
			found = sipe_process_incoming_x_msmsgsinvite(sipe_private, dialog, body);
			sipe_utils_nameval_free(body);
			if (found) {
				sip_transport_response(sipe_private, msg, 200, "OK", NULL);
			}
		} else {
			sip_transport_response(sipe_private, msg, 481,
					       "Call Leg/Transaction Does Not Exist", NULL);
			found = TRUE;
		}
	}
	if (!found) {
		const gchar *callid = sipmsg_find_header(msg, "Call-ID");
		struct sip_session *session = sipe_session_find_chat_or_im(sipe_private,
									   callid,
									   from);
		if (session) {
			gchar *errmsg = g_strdup_printf(_("Received a message with unrecognized contents from %s"),
							from);
			sipe_user_present_error(sipe_private, session, errmsg);
			g_free(errmsg);
		}

		SIPE_DEBUG_INFO("got unknown mime-type '%s'", contenttype);
		sip_transport_response(sipe_private, msg, 415, "Unsupported media type", NULL);
	}
	g_free(from);
}
void process_incoming_invite(struct sipe_core_private *sipe_private,
			     struct sipmsg *msg)
{
	gchar *newTag;
	const gchar *oldHeader;
	gchar *newHeader;
	gboolean is_multiparty = FALSE;
	gboolean was_multiparty = TRUE;
	gboolean just_joined = FALSE;
	gchar *from;
	const gchar *callid         = sipmsg_find_header(msg, "Call-ID");
	const gchar *roster_manager = sipmsg_find_header(msg, "Roster-Manager");
	const gchar *end_points_hdr = sipmsg_find_header(msg, "EndPoints");
	const gchar *trig_invite    = sipmsg_find_header(msg, "TriggeredInvite");
	const gchar *content_type   = sipmsg_find_header(msg, "Content-Type");
	const gchar *subject        = sipmsg_find_header(msg, "Subject");
	GSList *end_points = NULL;
	struct sip_session *session;
	struct sip_dialog *dialog;
	const gchar *ms_text_format;
	gboolean dont_delay = FALSE;

#ifdef HAVE_VV
	if (g_str_has_prefix(content_type, "multipart/alternative")) {
		sipe_mime_parts_foreach(content_type, msg->body, sipe_invite_mime_cb, msg);
		/* Reload Content-Type to get type of the selected message part */
		content_type = sipmsg_find_header(msg, "Content-Type");
	}
#endif

	if (g_str_has_prefix(content_type, "multipart/mixed")) {
		sipe_mime_parts_foreach(content_type, msg->body, sipe_invite_mime_mixed_cb, msg);
		/* Reload Content-Type to get type of the selected message part */
		content_type = sipmsg_find_header(msg, "Content-Type");
	}

	/* Lync 2010 file transfer */
	if (g_str_has_prefix(content_type, "application/ms-filetransfer+xml")) {
		sip_transport_response(sipe_private, msg, 488, "Not Acceptable Here", NULL);
		return;
	}

	/* Invitation to join conference */
	if (g_str_has_prefix(content_type, "application/ms-conf-invite+xml")) {
		process_incoming_invite_conf(sipe_private, msg);
		return;
	}

#ifdef HAVE_VV
	/* Invitation to audio call */
	if (msg->body && strstr(msg->body, "m=audio")) {
		process_incoming_invite_call(sipe_private, msg);
		return;
	}
#endif

	/* Only accept text invitations */
	if (msg->body && !(strstr(msg->body, "m=message") || strstr(msg->body, "m=x-ms-message"))) {
		sip_transport_response(sipe_private, msg, 501, "Not implemented", NULL);
		return;
	}

	// TODO There *must* be a better way to clean up the To header to add a tag...
	SIPE_DEBUG_INFO_NOFORMAT("Adding a Tag to the To Header on Invite Request...");
	oldHeader = sipmsg_find_header(msg, "To");
	newTag = gentag();
	newHeader = g_strdup_printf("%s;tag=%s", oldHeader, newTag);
	g_free(newTag);
	sipmsg_remove_header_now(msg, "To");
	sipmsg_add_header_now(msg, "To", newHeader);
	g_free(newHeader);

	if (end_points_hdr) {
		end_points = sipmsg_parse_endpoints_header(end_points_hdr);

		if (g_slist_length(end_points) > 2) {
			is_multiparty = TRUE;
		}
	}
	if (trig_invite && !g_ascii_strcasecmp(trig_invite, "TRUE")) {
		is_multiparty = TRUE;
	}

	/* Multiparty session */
	session = sipe_session_find_chat_by_callid(sipe_private, callid);
	if (is_multiparty) {

		if (session) {
			if (session->chat_session) {
				/* Update roster manager for existing multiparty session */
				if (roster_manager)
					sipe_chat_set_roster_manager(session, roster_manager);

			} else {
				gchar *chat_title = sipe_chat_get_name();

				/* Convert IM session to multiparty session */
				g_free(session->with);
				session->with = NULL;
				was_multiparty = FALSE;
				session->chat_session = sipe_chat_create_session(SIPE_CHAT_TYPE_MULTIPARTY,
										 roster_manager,
										 chat_title);

				g_free(chat_title);
			}
		} else {
			/* New multiparty session */
			session = sipe_session_add_chat(sipe_private,
							NULL,
							TRUE,
							roster_manager);
		}

		/* Create chat */
		if (!session->chat_session->backend) {
			gchar *self = sip_uri_self(sipe_private);
			session->chat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC,
										  session->chat_session,
										  session->chat_session->title,
										  self);
			g_free(self);
		}
	}

	/* IM session */
	from = parse_from(sipmsg_find_header(msg, "From"));
	if (!session)
		session = sipe_session_find_or_add_im(sipe_private, from);

	/* session is now initialized */
	g_free(session->callid);
	session->callid = g_strdup(callid);

	if (is_multiparty && end_points) {
		gchar *to = parse_from(sipmsg_find_header(msg, "To"));
		GSList *entry = end_points;
		while (entry) {
			struct sipendpoint *end_point = entry->data;
			entry = entry->next;

			if (!g_ascii_strcasecmp(from, end_point->contact) ||
			    !g_ascii_strcasecmp(to,   end_point->contact))
				continue;

			dialog = sipe_dialog_find(session, end_point->contact);
			if (dialog) {
				g_free(dialog->theirepid);
				dialog->theirepid = end_point->epid;
				end_point->epid = NULL;
			} else {
				dialog = sipe_dialog_add(session);

				dialog->callid = g_strdup(session->callid);
				dialog->with = end_point->contact;
				end_point->contact = NULL;
				dialog->theirepid = end_point->epid;
				end_point->epid = NULL;

				just_joined = TRUE;

				/* send triggered INVITE */
				sipe_im_invite(sipe_private, session, dialog->with, NULL, NULL, NULL, TRUE);
			}
		}
		g_free(to);
	}

	if (end_points) {
		GSList *entry = end_points;
		while (entry) {
			struct sipendpoint *end_point = entry->data;
			entry = entry->next;
			g_free(end_point->contact);
			g_free(end_point->epid);
			g_free(end_point);
		}
		g_slist_free(end_points);
	}

	dialog = sipe_dialog_find(session, from);
	if (dialog) {
		sipe_im_cancel_dangling(sipe_private, session, dialog, from,
					sipe_im_reenqueue_unconfirmed);
		/* dialog is no longer valid */
	} else {
		just_joined = TRUE;
	}

	dialog = sipe_dialog_add(session);
	dialog->with = g_strdup(from);
	dialog->callid = g_strdup(session->callid);
	dialog->is_established = TRUE;
	sipe_dialog_parse(dialog, msg, FALSE);

	if (is_multiparty && !was_multiparty) {
		/* add current IM counterparty to chat */
		sipe_backend_chat_add(session->chat_session->backend,
				      sipe_dialog_first(session)->with,
				      FALSE);
	}

	/* add inviting party to chat */
	if (just_joined && session->chat_session) {
		sipe_backend_chat_add(session->chat_session->backend,
				      from,
				      TRUE);
	}

	if (!is_multiparty && subject)
		sipe_im_topic(sipe_private, session, subject);

	/* ms-text-format: text/plain; charset=UTF-8;msgr=WAAtAE0...DIADQAKAA0ACgA;ms-body=SGk= */

	/* This used only in 2005 official client, not 2007 or Reuters.
	   Disabled for most cases as interfering with audit of messages which only is applied to regular MESSAGEs.
	   Only enabled for 2005 multiparty chats as otherwise the first message got lost completely.
	*/
	/* also enabled for 2005 file transfer. Didn't work otherwise. */
	ms_text_format = sipmsg_find_header(msg, "ms-text-format");
	if (is_multiparty ||
	    (ms_text_format && g_str_has_prefix(ms_text_format, "text/x-msmsgsinvite")) )
	{
		if (ms_text_format) {
			if (g_str_has_prefix(ms_text_format, "text/x-msmsgsinvite"))
			{
				dont_delay = TRUE;
			}
			else if (g_str_has_prefix(ms_text_format, "text/plain") || g_str_has_prefix(ms_text_format, "text/html"))
			{
				/* please do not optimize logic inside as this code may be re-enabled for other cases */
				gchar *html = get_html_message(ms_text_format, NULL);
				if (html) {
					if (is_multiparty) {
						sipe_backend_chat_message(SIPE_CORE_PUBLIC,
									  session->chat_session->backend,
									  from,
									  0,
									  html);
					} else {
						sipe_backend_im_message(SIPE_CORE_PUBLIC,
									from,
									html);
					}
					g_free(html);
					sipmsg_add_header(msg, "Supported", "ms-text-format"); /* accepts received message */
					dont_delay = TRUE;
				}
			}
		}
	}

	g_free(from);

	sipmsg_add_header(msg, "Supported", "com.microsoft.rtc-multiparty");

	if (dont_delay || !SIPE_CORE_PRIVATE_FLAG_IS(MPOP)) {
		send_invite_response(sipe_private, msg);
	} else {
		delayed_invite_response(sipe_private, msg, session->callid);
	}
}
示例#30
0
const gchar *sipe_backend_setting(struct sipe_core_public * /*sipe_public*/,
        sipe_setting /*type*/)
{
    SIPE_DEBUG_INFO_NOFORMAT("STUB sipe_backend_setting");
    return "";
}