Mercurial > pidgin
annotate src/protocols/jabber/jutil.c @ 8273:f24172f53650
[gaim-migrate @ 8997]
This is Scott Lamb's eventloop abstraction patch. If it breaks things,
Scott Lamb will be glad to take the punishment. If it doesn't, it should
make integration into other event loops easier. Well, no, not easier,
harder actually, but it'll be done more appropriately and less hackily..
er, hacky. Is hackily a word?
committer: Tailor Script <tailor@pidgin.im>
author | Christian Hammond <chipx86@chipx86.com> |
---|---|
date | Tue, 17 Feb 2004 02:17:48 +0000 |
parents | 9a6df4d567e0 |
children | c13a4913a071 |
rev | line source |
---|---|
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 time_t str_to_time(const char *timestamp) |
30 { | |
31 struct tm t; | |
32 time_t retval = 0; | |
33 char buf[32]; | |
34 char *c; | |
35 int tzoff = 0; | |
2086 | 36 |
7014 | 37 time(&retval); |
38 localtime_r(&retval, &t); | |
39 | |
40 snprintf(buf, sizeof(buf), "%s", timestamp); | |
41 c = buf; | |
3717
988485669631
[gaim-migrate @ 3850]
Herman Bloggs <hermanator12002@yahoo.com>
parents:
3127
diff
changeset
|
42 |
7014 | 43 /* 4 digit year */ |
44 if(!sscanf(c, "%04d", &t.tm_year)) return 0; | |
45 c+=4; | |
46 if(*c == '-') | |
47 c++; | |
2086 | 48 |
7014 | 49 t.tm_year -= 1900; |
50 | |
51 /* 2 digit month */ | |
52 if(!sscanf(c, "%02d", &t.tm_mon)) return 0; | |
53 c+=2; | |
54 if(*c == '-') | |
55 c++; | |
56 | |
57 t.tm_mon -= 1; | |
2086 | 58 |
7014 | 59 /* 2 digit day */ |
60 if(!sscanf(c, "%02d", &t.tm_mday)) return 0; | |
61 c+=2; | |
62 if(*c == 'T') { /* we have more than a date, keep going */ | |
63 c++; /* skip the "T" */ | |
2086 | 64 |
7014 | 65 /* 2 digit hour */ |
66 if(sscanf(c, "%02d:%02d:%02d", &t.tm_hour, &t.tm_min, &t.tm_sec)) { | |
67 int tzhrs, tzmins; | |
68 c+=8; | |
69 if(*c == '.') /* dealing with precision we don't care about */ | |
70 c += 4; | |
2086 | 71 |
7014 | 72 if((*c == '+' || *c == '-') && |
73 sscanf(c+1, "%02d:%02d", &tzhrs, &tzmins)) { | |
74 tzoff = tzhrs*60*60 + tzmins*60; | |
75 if(*c == '+') | |
76 tzoff *= -1; | |
77 } | |
2086 | 78 |
7014 | 79 #ifdef HAVE_TM_GMTOFF |
80 tzoff += t.tm_gmtoff; | |
81 #else | |
82 # ifdef HAVE_TIMEZONE | |
83 tzset(); /* making sure */ | |
84 tzoff -= timezone; | |
85 # endif | |
86 #endif | |
87 } | |
2086 | 88 } |
7014 | 89 retval = mktime(&t); |
2086 | 90 |
7014 | 91 retval += tzoff; |
2086 | 92 |
7014 | 93 return retval; |
2086 | 94 } |
95 | |
7014 | 96 const char *jabber_get_state_string(int s) { |
97 switch(s) { | |
98 case JABBER_STATE_AWAY: | |
99 return _("Away"); | |
100 break; | |
101 case JABBER_STATE_CHAT: | |
102 return _("Chatty"); | |
103 break; | |
104 case JABBER_STATE_XA: | |
105 return _("Extended Away"); | |
106 break; | |
107 case JABBER_STATE_DND: | |
108 return _("Do Not Disturb"); | |
109 break; | |
110 default: | |
111 return _("Available"); | |
112 break; | |
113 } | |
2086 | 114 } |
115 | |
7310 | 116 gboolean jabber_nodeprep_validate(const char *str) |
117 { | |
118 const char *c; | |
119 | |
120 if(!str) | |
121 return TRUE; | |
122 | |
123 if(strlen(str) > 1023) | |
124 return FALSE; | |
125 | |
126 c = str; | |
127 while(c && *c) { | |
128 gunichar ch = g_utf8_get_char(c); | |
129 if(ch == '\"' || ch == '&' || ch == '\'' || ch == '/' || ch == ':' || | |
130 ch == '<' || ch == '>' || ch == '@' || !g_unichar_isgraph(ch)) { | |
131 return FALSE; | |
132 } | |
133 c = g_utf8_next_char(c); | |
134 } | |
135 | |
136 return TRUE; | |
137 } | |
138 | |
139 gboolean jabber_nameprep_validate(const char *str) | |
140 { | |
141 const char *c; | |
142 | |
143 if(!str) | |
144 return TRUE; | |
145 | |
146 if(strlen(str) > 1023) | |
147 return FALSE; | |
148 | |
149 c = str; | |
150 while(c && *c) { | |
151 gunichar ch = g_utf8_get_char(c); | |
152 if(!g_unichar_isgraph(ch)) | |
153 return FALSE; | |
154 | |
155 c = g_utf8_next_char(c); | |
156 } | |
157 | |
158 | |
159 return TRUE; | |
160 } | |
161 | |
162 gboolean jabber_resourceprep_validate(const char *str) | |
163 { | |
164 const char *c; | |
165 | |
166 if(!str) | |
167 return TRUE; | |
168 | |
169 if(strlen(str) > 1023) | |
170 return FALSE; | |
171 | |
172 c = str; | |
173 while(c && *c) { | |
174 gunichar ch = g_utf8_get_char(c); | |
7419 | 175 if(!g_unichar_isgraph(ch) && ch != ' ') |
7310 | 176 return FALSE; |
177 | |
178 c = g_utf8_next_char(c); | |
179 } | |
180 | |
181 return TRUE; | |
182 } | |
183 | |
184 | |
7014 | 185 JabberID* |
186 jabber_id_new(const char *str) | |
2086 | 187 { |
7014 | 188 char *at; |
189 char *slash; | |
190 JabberID *jid; | |
2086 | 191 |
7306 | 192 if(!str || !g_utf8_validate(str, -1, NULL)) |
7014 | 193 return NULL; |
2086 | 194 |
7014 | 195 jid = g_new0(JabberID, 1); |
196 | |
7306 | 197 at = g_utf8_strchr(str, -1, '@'); |
198 slash = g_utf8_strchr(str, -1, '/'); | |
2086 | 199 |
7014 | 200 if(at) { |
7306 | 201 jid->node = g_utf8_normalize(str, at-str, G_NORMALIZE_NFKC); |
7014 | 202 if(slash) { |
7306 | 203 jid->domain = g_utf8_normalize(at+1, slash-(at+1), G_NORMALIZE_NFKC); |
204 jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); | |
7014 | 205 } else { |
7306 | 206 jid->domain = g_utf8_normalize(at+1, -1, G_NORMALIZE_NFKC); |
7014 | 207 } |
208 } else { | |
209 if(slash) { | |
7306 | 210 jid->domain = g_utf8_normalize(str, slash-str, G_NORMALIZE_NFKC); |
211 jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); | |
7014 | 212 } else { |
7306 | 213 jid->domain = g_utf8_normalize(str, -1, G_NORMALIZE_NFKC); |
214 } | |
215 } | |
216 | |
217 | |
7310 | 218 if(!jabber_nodeprep_validate(jid->node) || |
219 !jabber_nameprep_validate(jid->domain) || | |
220 !jabber_resourceprep_validate(jid->resource)) { | |
7306 | 221 jabber_id_free(jid); |
222 return NULL; | |
223 } | |
224 | |
7014 | 225 return jid; |
2086 | 226 } |
227 | |
7014 | 228 void |
229 jabber_id_free(JabberID *jid) | |
2086 | 230 { |
7014 | 231 if(jid) { |
232 if(jid->node) | |
233 g_free(jid->node); | |
234 if(jid->domain) | |
235 g_free(jid->domain); | |
236 if(jid->resource) | |
237 g_free(jid->resource); | |
238 g_free(jid); | |
239 } | |
2086 | 240 } |
241 | |
7014 | 242 |
7306 | 243 char *jabber_get_resource(const char *in) |
7014 | 244 { |
7306 | 245 JabberID *jid = jabber_id_new(in); |
246 char *out; | |
7014 | 247 |
7306 | 248 if(!jid) |
7014 | 249 return NULL; |
7306 | 250 |
251 out = g_strdup(jid->resource); | |
252 jabber_id_free(jid); | |
253 | |
254 return out; | |
7014 | 255 } |
256 | |
7306 | 257 char *jabber_get_bare_jid(const char *in) |
7014 | 258 { |
7306 | 259 JabberID *jid = jabber_id_new(in); |
260 char *out; | |
7014 | 261 |
7306 | 262 if(!jid) |
263 return NULL; | |
264 | |
7322 | 265 out = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", |
266 jid->node ? "@" : "", jid->domain); | |
7306 | 267 jabber_id_free(jid); |
268 | |
269 return out; | |
7014 | 270 } |
7261 | 271 |
7322 | 272 const char *jabber_normalize(const GaimAccount *account, const char *in) |
7261 | 273 { |
7322 | 274 GaimConnection *gc = account ? account->gc : NULL; |
275 JabberStream *js = gc ? gc->proto_data : NULL; | |
276 static char buf[3072]; /* maximum legal length of a jabber jid */ | |
277 JabberID *jid; | |
7445 | 278 char *node, *domain; |
7261 | 279 |
7322 | 280 jid = jabber_id_new(in); |
7310 | 281 |
7322 | 282 if(!jid) |
7310 | 283 return NULL; |
284 | |
7445 | 285 node = jid->node ? g_utf8_strdown(jid->node, -1) : NULL; |
286 domain = g_utf8_strdown(jid->domain, -1); | |
287 | |
288 | |
289 if(js && node && jid->resource && | |
290 jabber_chat_find(js, node, domain)) | |
291 g_snprintf(buf, sizeof(buf), "%s@%s/%s", node, domain, | |
7322 | 292 jid->resource); |
293 else | |
7445 | 294 g_snprintf(buf, sizeof(buf), "%s%s%s", node ? node : "", |
295 node ? "@" : "", domain); | |
7322 | 296 |
7429 | 297 jabber_id_free(jid); |
7445 | 298 g_free(node); |
299 g_free(domain); | |
7429 | 300 |
7261 | 301 return buf; |
302 } | |
7306 | 303 |
8043 | 304 GaimConversation * |
305 jabber_find_unnormalized_conv(const char *name, GaimAccount *account) | |
306 { | |
307 GaimConversation *c = NULL; | |
308 GList *cnv; | |
309 | |
310 g_return_val_if_fail(name != NULL, NULL); | |
311 | |
312 for(cnv = gaim_get_conversations(); cnv; cnv = cnv->next) { | |
313 c = (GaimConversation*)cnv->data; | |
314 if(gaim_conversation_get_type(c) == GAIM_CONV_IM && | |
315 !gaim_utf8_strcasecmp(name, gaim_conversation_get_name(c)) && | |
316 account == gaim_conversation_get_account(c)) | |
317 return c; | |
318 } | |
319 | |
320 return NULL; | |
321 } |