1 /**
2  * @file sipe-status.c
3  *
4  * pidgin-sipe
5  *
6  * Copyright (C) 2011-2018 SIPE Project <http://sipe.sourceforge.net/>
7  *
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #include <time.h>
29 
30 #include <glib.h>
31 
32 #include "sipe-backend.h"
33 #include "sipe-cal.h"
34 #include "sipe-core.h"
35 #include "sipe-core-private.h"
36 #include "sipe-nls.h"
37 #include "sipe-ocs2005.h"
38 #include "sipe-ocs2007.h"
39 #include "sipe-status.h"
40 #include "sipe-utils.h"
41 
42 static struct
43 {
44 	const gchar *status_id;
45 	const gchar *desc;
46 } const sipe_activity_map[SIPE_ACTIVITY_NUM_TYPES] = {
47 /*
48  * This has nothing to do with Availability numbers, like 3500 (online).
49  * Just a mapping of Communicator Activities to tokens/translations
50  */
51 /* @TODO: NULL means "default translation from Pidgin"?
52  *        What about other backends?                    */
53 /* SIPE_ACTIVITY_UNSET       */ { "unset",                     NULL                            },
54 /* SIPE_ACTIVITY_AVAILABLE   */ { "available",                 NULL                            },
55 /* SIPE_ACTIVITY_ONLINE      */ { "online",                    NULL                            },
56 /* SIPE_ACTIVITY_INACTIVE    */ { "idle",                      N_("Inactive")                  },
57 /* SIPE_ACTIVITY_BUSY        */ { "busy",                      N_("Busy")                      },
58 /* SIPE_ACTIVITY_BUSYIDLE    */ { "busyidle",                  N_("Busy-Idle")                 },
59 /* SIPE_ACTIVITY_DND         */ { "do-not-disturb",            NULL                            },
60 /* SIPE_ACTIVITY_BRB         */ { "be-right-back",             N_("Be right back")             },
61 /* SIPE_ACTIVITY_AWAY        */ { "away",                      NULL                            },
62 /* SIPE_ACTIVITY_LUNCH       */ { "out-to-lunch",              N_("Out to lunch")              },
63 /* SIPE_ACTIVITY_INVISIBLE   */ { "invisible",                 NULL                            },
64 /* SIPE_ACTIVITY_OFFLINE     */ { "offline",                   NULL                            },
65 /* SIPE_ACTIVITY_ON_PHONE    */ { "on-the-phone",              N_("In a call")                 },
66 /* SIPE_ACTIVITY_IN_CONF     */ { "in-a-conference",           N_("In a conference")           },
67 /* SIPE_ACTIVITY_IN_MEETING  */ { "in-a-meeting",              N_("In a meeting")              },
68 /* SIPE_ACTIVITY_OOF         */ { "out-of-office",             N_("Out of office")             },
69 /* SIPE_ACTIVITY_URGENT_ONLY */ { "urgent-interruptions-only", N_("Urgent interruptions only") },
70 /* SIPE_ACTIVITY_IN_PRES     */ { "in-presentation",           N_("Presenting")                },
71 };
72 
73 static GHashTable *token_map;
74 
sipe_status_init(void)75 void sipe_status_init(void)
76 {
77 	guint index;
78 
79 	token_map = g_hash_table_new(g_str_hash, g_str_equal);
80 	for (index = SIPE_ACTIVITY_UNSET;
81 	     index < SIPE_ACTIVITY_NUM_TYPES;
82 	     index++) {
83 		g_hash_table_insert(token_map,
84 				    (gchar *) sipe_activity_map[index].status_id,
85 				    GUINT_TO_POINTER(index));
86 	}
87 }
88 
sipe_status_shutdown(void)89 void sipe_status_shutdown(void)
90 {
91 	g_hash_table_destroy(token_map);
92 }
93 
94 /* type == SIPE_ACTIVITY_xxx (see sipe-core.h) */
sipe_status_activity_to_token(guint type)95 const gchar *sipe_status_activity_to_token(guint type)
96 {
97 	return(sipe_activity_map[type].status_id);
98 }
99 
sipe_status_token_to_activity(const gchar * token)100 guint sipe_status_token_to_activity(const gchar *token)
101 {
102 	if (!token) return(SIPE_ACTIVITY_UNSET);
103 	return(GPOINTER_TO_UINT(g_hash_table_lookup(token_map, token)));
104 }
105 
sipe_core_activity_description(guint type)106 const gchar *sipe_core_activity_description(guint type)
107 {
108 	return(gettext(sipe_activity_map[type].desc));
109 }
110 
sipe_status_set_token(struct sipe_core_private * sipe_private,const gchar * status_id)111 void sipe_status_set_token(struct sipe_core_private *sipe_private,
112 			   const gchar *status_id)
113 {
114 	g_free(sipe_private->status);
115 	sipe_private->status = g_strdup(status_id);
116 }
117 
sipe_status_set_activity(struct sipe_core_private * sipe_private,guint activity)118 void sipe_status_set_activity(struct sipe_core_private *sipe_private,
119 			      guint activity)
120 {
121 	sipe_status_set_token(sipe_private,
122 			      sipe_status_activity_to_token(activity));
123 }
124 
sipe_core_reset_status(struct sipe_core_public * sipe_public)125 void sipe_core_reset_status(struct sipe_core_public *sipe_public)
126 {
127 	struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
128 
129 	SIPE_DEBUG_INFO_NOFORMAT("sipe_core_reset_status: start");
130 
131 	if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))
132 		sipe_ocs2007_reset_status(sipe_private);
133 	else
134 		sipe_ocs2005_reset_status(sipe_private);
135 }
136 
sipe_status_and_note(struct sipe_core_private * sipe_private,const gchar * status_id)137 void sipe_status_and_note(struct sipe_core_private *sipe_private,
138 			  const gchar *status_id)
139 {
140 	guint activity;
141 
142 	if (!status_id)
143 		status_id = sipe_private->status;
144 
145 	SIPE_DEBUG_INFO("sipe_status_and_note: switch to '%s' for the account", status_id);
146 
147 	activity = sipe_status_token_to_activity(status_id);
148 	if (sipe_backend_status_changed(SIPE_CORE_PUBLIC,
149 					activity,
150 					sipe_private->note)) {
151 		/* status has changed */
152 		SIPE_DEBUG_INFO_NOFORMAT("sipe_status_and_note: updating backend status");
153 
154 		/* update backend status */
155 		sipe_backend_status_and_note(SIPE_CORE_PUBLIC,
156 					     activity,
157 					     sipe_private->note);
158 	}
159 }
160 
sipe_core_status_set(struct sipe_core_public * sipe_public,gboolean set_by_user,guint activity,const gchar * note)161 void sipe_core_status_set(struct sipe_core_public *sipe_public,
162 			  gboolean set_by_user,
163 			  guint activity,
164 			  const gchar *note)
165 {
166 	struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
167 	gchar *tmp;
168 	const gchar *status_id = sipe_status_activity_to_token(activity);
169 
170 	SIPE_DEBUG_INFO("sipe_core_status_set: status: %s (%s)",
171 			status_id,
172 			set_by_user ? "USER" : "MACHINE");
173 
174 	sipe_private->status_set_by_user = set_by_user;
175 
176 	sipe_status_set_token(sipe_private, status_id);
177 
178 	/* hack to escape apostrof before comparison */
179 	tmp = note ? sipe_utils_str_replace(note, "'", "&apos;") : NULL;
180 
181 	/* this will preserve OOF flag as well */
182 	if (!sipe_strequal(tmp, sipe_private->note)) {
183 		SIPE_CORE_PRIVATE_FLAG_UNSET(OOF_NOTE);
184 		g_free(sipe_private->note);
185 		sipe_private->note = g_strdup(note);
186 		sipe_private->note_since = time(NULL);
187 	}
188 	g_free(tmp);
189 
190 	sipe_cal_presence_publish(sipe_private, FALSE);
191 }
192 
193 /*
194   Local Variables:
195   mode: c
196   c-file-style: "bsd"
197   indent-tabs-mode: t
198   tab-width: 8
199   End:
200 */
201