7014
|
1 /*
|
|
2 * gaim - Jabber Protocol Plugin
|
3127
|
3 *
|
7014
|
4 * Copyright (C) 2003, Nathan Walp <faceprint@faceprint.com>
|
3127
|
5 *
|
7014
|
6 * This program is free software; you can redistribute it and/or modify
|
|
7 * it under the terms of the GNU General Public License as published by
|
|
8 * the Free Software Foundation; either version 2 of the License, or
|
|
9 * (at your option) any later version.
|
3127
|
10 *
|
7014
|
11 * This program is distributed in the hope that it will be useful,
|
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 * GNU General Public License for more details.
|
|
15 *
|
|
16 * You should have received a copy of the GNU General Public License
|
|
17 * along with this program; if not, write to the Free Software
|
|
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
3127
|
19 *
|
7014
|
20 */
|
|
21 #include "internal.h"
|
|
22 #include "server.h"
|
8043
|
23 #include "util.h"
|
7014
|
24
|
7322
|
25 #include "chat.h"
|
7014
|
26 #include "presence.h"
|
|
27 #include "jutil.h"
|
3127
|
28
|
7014
|
29 const char *jabber_get_state_string(int s) {
|
|
30 switch(s) {
|
|
31 case JABBER_STATE_AWAY:
|
|
32 return _("Away");
|
|
33 break;
|
|
34 case JABBER_STATE_CHAT:
|
|
35 return _("Chatty");
|
|
36 break;
|
|
37 case JABBER_STATE_XA:
|
|
38 return _("Extended Away");
|
|
39 break;
|
|
40 case JABBER_STATE_DND:
|
|
41 return _("Do Not Disturb");
|
|
42 break;
|
|
43 default:
|
|
44 return _("Available");
|
|
45 break;
|
|
46 }
|
2086
|
47 }
|
|
48
|
7310
|
49 gboolean jabber_nodeprep_validate(const char *str)
|
|
50 {
|
|
51 const char *c;
|
|
52
|
|
53 if(!str)
|
|
54 return TRUE;
|
|
55
|
|
56 if(strlen(str) > 1023)
|
|
57 return FALSE;
|
|
58
|
|
59 c = str;
|
|
60 while(c && *c) {
|
|
61 gunichar ch = g_utf8_get_char(c);
|
|
62 if(ch == '\"' || ch == '&' || ch == '\'' || ch == '/' || ch == ':' ||
|
|
63 ch == '<' || ch == '>' || ch == '@' || !g_unichar_isgraph(ch)) {
|
|
64 return FALSE;
|
|
65 }
|
|
66 c = g_utf8_next_char(c);
|
|
67 }
|
|
68
|
|
69 return TRUE;
|
|
70 }
|
|
71
|
|
72 gboolean jabber_nameprep_validate(const char *str)
|
|
73 {
|
|
74 const char *c;
|
|
75
|
|
76 if(!str)
|
|
77 return TRUE;
|
|
78
|
|
79 if(strlen(str) > 1023)
|
|
80 return FALSE;
|
|
81
|
|
82 c = str;
|
|
83 while(c && *c) {
|
|
84 gunichar ch = g_utf8_get_char(c);
|
|
85 if(!g_unichar_isgraph(ch))
|
|
86 return FALSE;
|
|
87
|
|
88 c = g_utf8_next_char(c);
|
|
89 }
|
|
90
|
|
91
|
|
92 return TRUE;
|
|
93 }
|
|
94
|
|
95 gboolean jabber_resourceprep_validate(const char *str)
|
|
96 {
|
|
97 const char *c;
|
|
98
|
|
99 if(!str)
|
|
100 return TRUE;
|
|
101
|
|
102 if(strlen(str) > 1023)
|
|
103 return FALSE;
|
|
104
|
|
105 c = str;
|
|
106 while(c && *c) {
|
|
107 gunichar ch = g_utf8_get_char(c);
|
7419
|
108 if(!g_unichar_isgraph(ch) && ch != ' ')
|
7310
|
109 return FALSE;
|
|
110
|
|
111 c = g_utf8_next_char(c);
|
|
112 }
|
|
113
|
|
114 return TRUE;
|
|
115 }
|
|
116
|
|
117
|
7014
|
118 JabberID*
|
|
119 jabber_id_new(const char *str)
|
2086
|
120 {
|
7014
|
121 char *at;
|
|
122 char *slash;
|
|
123 JabberID *jid;
|
2086
|
124
|
7306
|
125 if(!str || !g_utf8_validate(str, -1, NULL))
|
7014
|
126 return NULL;
|
2086
|
127
|
7014
|
128 jid = g_new0(JabberID, 1);
|
|
129
|
7306
|
130 at = g_utf8_strchr(str, -1, '@');
|
|
131 slash = g_utf8_strchr(str, -1, '/');
|
2086
|
132
|
7014
|
133 if(at) {
|
7306
|
134 jid->node = g_utf8_normalize(str, at-str, G_NORMALIZE_NFKC);
|
7014
|
135 if(slash) {
|
7306
|
136 jid->domain = g_utf8_normalize(at+1, slash-(at+1), G_NORMALIZE_NFKC);
|
|
137 jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
|
7014
|
138 } else {
|
7306
|
139 jid->domain = g_utf8_normalize(at+1, -1, G_NORMALIZE_NFKC);
|
7014
|
140 }
|
|
141 } else {
|
|
142 if(slash) {
|
7306
|
143 jid->domain = g_utf8_normalize(str, slash-str, G_NORMALIZE_NFKC);
|
|
144 jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC);
|
7014
|
145 } else {
|
7306
|
146 jid->domain = g_utf8_normalize(str, -1, G_NORMALIZE_NFKC);
|
|
147 }
|
|
148 }
|
|
149
|
|
150
|
7310
|
151 if(!jabber_nodeprep_validate(jid->node) ||
|
|
152 !jabber_nameprep_validate(jid->domain) ||
|
|
153 !jabber_resourceprep_validate(jid->resource)) {
|
7306
|
154 jabber_id_free(jid);
|
|
155 return NULL;
|
|
156 }
|
|
157
|
7014
|
158 return jid;
|
2086
|
159 }
|
|
160
|
7014
|
161 void
|
|
162 jabber_id_free(JabberID *jid)
|
2086
|
163 {
|
7014
|
164 if(jid) {
|
|
165 if(jid->node)
|
|
166 g_free(jid->node);
|
|
167 if(jid->domain)
|
|
168 g_free(jid->domain);
|
|
169 if(jid->resource)
|
|
170 g_free(jid->resource);
|
|
171 g_free(jid);
|
|
172 }
|
2086
|
173 }
|
|
174
|
7014
|
175
|
7306
|
176 char *jabber_get_resource(const char *in)
|
7014
|
177 {
|
7306
|
178 JabberID *jid = jabber_id_new(in);
|
|
179 char *out;
|
7014
|
180
|
7306
|
181 if(!jid)
|
7014
|
182 return NULL;
|
7306
|
183
|
|
184 out = g_strdup(jid->resource);
|
|
185 jabber_id_free(jid);
|
|
186
|
|
187 return out;
|
7014
|
188 }
|
|
189
|
7306
|
190 char *jabber_get_bare_jid(const char *in)
|
7014
|
191 {
|
7306
|
192 JabberID *jid = jabber_id_new(in);
|
|
193 char *out;
|
7014
|
194
|
7306
|
195 if(!jid)
|
|
196 return NULL;
|
|
197
|
7322
|
198 out = g_strdup_printf("%s%s%s", jid->node ? jid->node : "",
|
|
199 jid->node ? "@" : "", jid->domain);
|
7306
|
200 jabber_id_free(jid);
|
|
201
|
|
202 return out;
|
7014
|
203 }
|
7261
|
204
|
7322
|
205 const char *jabber_normalize(const GaimAccount *account, const char *in)
|
7261
|
206 {
|
7322
|
207 GaimConnection *gc = account ? account->gc : NULL;
|
|
208 JabberStream *js = gc ? gc->proto_data : NULL;
|
|
209 static char buf[3072]; /* maximum legal length of a jabber jid */
|
|
210 JabberID *jid;
|
7445
|
211 char *node, *domain;
|
7261
|
212
|
7322
|
213 jid = jabber_id_new(in);
|
7310
|
214
|
7322
|
215 if(!jid)
|
7310
|
216 return NULL;
|
|
217
|
7445
|
218 node = jid->node ? g_utf8_strdown(jid->node, -1) : NULL;
|
|
219 domain = g_utf8_strdown(jid->domain, -1);
|
|
220
|
|
221
|
|
222 if(js && node && jid->resource &&
|
|
223 jabber_chat_find(js, node, domain))
|
|
224 g_snprintf(buf, sizeof(buf), "%s@%s/%s", node, domain,
|
7322
|
225 jid->resource);
|
|
226 else
|
7445
|
227 g_snprintf(buf, sizeof(buf), "%s%s%s", node ? node : "",
|
|
228 node ? "@" : "", domain);
|
7322
|
229
|
7429
|
230 jabber_id_free(jid);
|
7445
|
231 g_free(node);
|
|
232 g_free(domain);
|
7429
|
233
|
7261
|
234 return buf;
|
|
235 }
|
7306
|
236
|
8043
|
237 GaimConversation *
|
|
238 jabber_find_unnormalized_conv(const char *name, GaimAccount *account)
|
|
239 {
|
|
240 GaimConversation *c = NULL;
|
|
241 GList *cnv;
|
|
242
|
|
243 g_return_val_if_fail(name != NULL, NULL);
|
|
244
|
|
245 for(cnv = gaim_get_conversations(); cnv; cnv = cnv->next) {
|
|
246 c = (GaimConversation*)cnv->data;
|
|
247 if(gaim_conversation_get_type(c) == GAIM_CONV_IM &&
|
|
248 !gaim_utf8_strcasecmp(name, gaim_conversation_get_name(c)) &&
|
|
249 account == gaim_conversation_get_account(c))
|
|
250 return c;
|
|
251 }
|
|
252
|
|
253 return NULL;
|
|
254 }
|
8401
|
255
|