6 * Copyright (C) 2010-2019 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include "sipe-common.h"
31 #include "sip-transport.h"
32 #include "sipe-backend.h"
33 #include "sipe-chat.h"
34 #include "sipe-core.h"
35 #include "sipe-core-private.h"
36 #include "sipe-dialog.h"
39 #include "sipe-session.h"
40 #include "sipe-user.h"
41 #include "sipe-utils.h"
43 void sipe_user_present_info(struct sipe_core_private
*sipe_private
,
44 struct sip_session
*session
,
47 sipe_backend_notify_message_info(SIPE_CORE_PUBLIC
,
48 session
->chat_session
? session
->chat_session
->backend
: NULL
,
53 void sipe_user_present_error(struct sipe_core_private
*sipe_private
,
54 struct sip_session
*session
,
57 sipe_backend_notify_message_error(SIPE_CORE_PUBLIC
,
58 session
->chat_session
? session
->chat_session
->backend
: NULL
,
63 void sipe_user_present_message_undelivered(struct sipe_core_private
*sipe_private
,
64 struct sip_session
*session
,
70 char *msg
, *msg_tmp
, *msg_tmp2
;
73 msg_tmp
= message
? sipe_backend_markup_strip_html(message
) : NULL
;
74 msg
= msg_tmp
? g_strdup_printf("<font color=\"#888888\"></b>%s<b></font>", msg_tmp
) : NULL
;
76 /* Service unavailable; Server Internal Error; Server Time-out */
77 if (sip_error
== 606 && sip_warning
== 309) { /* Not acceptable all. */ /* Message contents not allowed by policy */
78 label
= _("Your message or invitation was not delivered, possibly because it contains a hyperlink or other content that the system administrator has blocked.");
81 } else if (sip_error
== 500 || sip_error
== 503 || sip_error
== 504 || sip_error
== 603) {
82 label
= _("This message was not delivered to %s because the service is not available");
83 } else if (sip_error
== 486) { /* Busy Here */
84 label
= _("This message was not delivered to %s because one or more recipients do not want to be disturbed");
85 } else if (sip_error
== 415) { /* Unsupported media type */
86 label
= _("This message was not delivered to %s because one or more recipients don't support this type of message");
88 label
= _("This message was not delivered to %s because one or more recipients are offline");
91 msg_tmp
= g_strdup_printf( "%s%s\n%s" ,
92 msg_tmp2
= g_strdup_printf(label
, who
? who
: ""),
95 sipe_user_present_error(sipe_private
, session
, msg_tmp
);
101 static gboolean
process_info_typing_response(struct sipe_core_private
*sipe_private
,
103 SIPE_UNUSED_PARAMETER
struct transaction
*trans
)
105 /* Indicates dangling IM session which needs to be dropped */
106 if (msg
->response
== 408 || /* Request timeout */
107 msg
->response
== 480 || /* Temporarily Unavailable */
108 msg
->response
== 481) { /* Call/Transaction Does Not Exist */
109 gchar
*with
= sipmsg_parse_to_address(msg
);
110 struct sip_session
*session
= sipe_session_find_im(sipe_private
, with
);
111 struct sip_dialog
*dialog
= sipe_dialog_find(session
, with
);
113 sipe_im_cancel_dangling(sipe_private
, session
, dialog
, with
,
114 sipe_im_cancel_unconfirmed
);
120 void sipe_core_user_feedback_typing(struct sipe_core_public
*sipe_public
,
124 struct sipe_core_private
*sipe_private
= SIPE_CORE_PRIVATE
;
125 struct sip_session
*session
= sipe_session_find_im(sipe_private
, to
);
126 struct sip_dialog
*dialog
= sipe_dialog_find(session
, to
);
128 /* only enable this debug output while testing
129 SIPE_DEBUG_INFO("sipe_core_user_feedback_typing session %p (%s) dialog %p (%s) established %s",
130 session, session ? session->callid : "N/A",
131 dialog, dialog ? dialog->callid : "N/A",
132 (dialog && dialog->is_established) ? "YES" : "NO"); */
134 if (session
&& dialog
&& dialog
->is_established
) {
135 gchar
*body
= g_strdup_printf("<?xml version=\"1.0\"?>"
137 " <status status=\"%s\" />"
138 "</KeyboardActivity>",
139 typing
? "type" : "idle");
140 sip_transport_info(sipe_private
,
141 "Content-Type: application/xml\r\n",
144 process_info_typing_response
);
149 struct sipe_user_ask_ctx
{
150 struct sipe_core_private
*sipe_private
;
156 struct sipe_user_ask_ctx
* sipe_user_ask(struct sipe_core_private
*sipe_private
,
157 const gchar
*message
,
158 const gchar
*accept_label
,
159 SipeUserAskCb accept_cb
,
160 const gchar
*decline_label
,
161 SipeUserAskCb decline_cb
,
164 struct sipe_user_ask_ctx
*ctx
= g_new0(struct sipe_user_ask_ctx
, 1);
165 ctx
->sipe_private
= sipe_private
;
166 ctx
->accept_cb
= accept_cb
;
167 ctx
->decline_cb
= decline_cb
;
170 sipe_backend_user_ask(SIPE_CORE_PUBLIC
, message
,
171 accept_label
, decline_label
,
177 void sipe_core_user_ask_cb(gpointer context
, gboolean accepted
)
179 struct sipe_user_ask_ctx
*ctx
= context
;
181 if (accepted
&& ctx
->accept_cb
)
182 ((SipeUserAskCb
)ctx
->accept_cb
)(ctx
->sipe_private
, ctx
->data
);
183 else if (ctx
->decline_cb
)
184 ((SipeUserAskCb
)ctx
->decline_cb
)(ctx
->sipe_private
, ctx
->data
);
189 struct sipe_user_ask_ctx
* sipe_user_ask_choice(struct sipe_core_private
*sipe_private
,
190 const gchar
*message
,
192 SipeUserAskChoiceCb callback
,
195 struct sipe_user_ask_ctx
*ctx
= g_new0(struct sipe_user_ask_ctx
, 1);
196 ctx
->sipe_private
= sipe_private
;
197 ctx
->accept_cb
= callback
;
198 ctx
->decline_cb
= NULL
;
201 sipe_backend_user_ask_choice(SIPE_CORE_PUBLIC
, message
, choices
, ctx
);
206 void sipe_core_user_ask_choice_cb(gpointer context
, guint choice_id
)
208 struct sipe_user_ask_ctx
*ctx
= context
;
210 if (ctx
->accept_cb
) {
211 ((SipeUserAskChoiceCb
)ctx
->accept_cb
)(ctx
->sipe_private
,
212 ctx
->data
, choice_id
);
218 void sipe_user_close_ask(struct sipe_user_ask_ctx
*context
)
220 sipe_backend_user_close_ask(context
);