Sun, 10 Aug 2008 18:46:32 +0000
Reapplied changes that were overwritten by 91f0294f2377e3870982f3e573e0dfb4230d9c11.
applied changes from b53b1ff4bbd75647c953e5f02eaca17c85d2113e
through 586238415076c2a3a3079812de64aff5841cde39
applied changes from 918c72f0ff7f7e3c545d3baf6368ccbd2ba21427
through e8404ca19a538f5254f1a156feb894d0618588d2
applied changes from e8404ca19a538f5254f1a156feb894d0618588d2
through 398b1414aa67f63ae191264603994be045df42f5
applied changes from 398b1414aa67f63ae191264603994be045df42f5
through b53b1ff4bbd75647c953e5f02eaca17c85d2113e
| 7014 | 1 | /* |
| 15884 | 2 | * purple - 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 | |
|
19859
71d37b57eff2
The FSF changed its address a while ago; our files were out of date.
John Bailey <rekkanoryo@rekkanoryo.org>
parents:
15952
diff
changeset
|
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA |
| 3127 | 19 | * |
| 7014 | 20 | */ |
| 21 | #include "internal.h" | |
|
15952
c087855dc551
Re-arrange #includes so 'make check' stands a chance of passing during
Stu Tomlinson <nosnilmot@pidgin.im>
parents:
15884
diff
changeset
|
22 | #include "account.h" |
|
c087855dc551
Re-arrange #includes so 'make check' stands a chance of passing during
Stu Tomlinson <nosnilmot@pidgin.im>
parents:
15884
diff
changeset
|
23 | #include "conversation.h" |
| 7014 | 24 | #include "server.h" |
| 8043 | 25 | #include "util.h" |
|
15952
c087855dc551
Re-arrange #includes so 'make check' stands a chance of passing during
Stu Tomlinson <nosnilmot@pidgin.im>
parents:
15884
diff
changeset
|
26 | #include "xmlnode.h" |
| 7014 | 27 | |
| 7322 | 28 | #include "chat.h" |
| 7014 | 29 | #include "presence.h" |
| 30 | #include "jutil.h" | |
| 3127 | 31 | |
| 7310 | 32 | gboolean jabber_nodeprep_validate(const char *str) |
| 33 | { | |
| 34 | const char *c; | |
| 35 | ||
| 36 | if(!str) | |
| 37 | return TRUE; | |
| 38 | ||
| 39 | if(strlen(str) > 1023) | |
| 40 | return FALSE; | |
| 41 | ||
| 42 | c = str; | |
| 43 | while(c && *c) { | |
| 44 | gunichar ch = g_utf8_get_char(c); | |
| 45 | if(ch == '\"' || ch == '&' || ch == '\'' || ch == '/' || ch == ':' || | |
| 46 | ch == '<' || ch == '>' || ch == '@' || !g_unichar_isgraph(ch)) { | |
| 47 | return FALSE; | |
| 48 | } | |
| 49 | c = g_utf8_next_char(c); | |
| 50 | } | |
| 51 | ||
| 52 | return TRUE; | |
| 53 | } | |
| 54 | ||
| 55 | gboolean jabber_nameprep_validate(const char *str) | |
| 56 | { | |
| 57 | const char *c; | |
| 58 | ||
| 59 | if(!str) | |
| 60 | return TRUE; | |
| 61 | ||
| 62 | if(strlen(str) > 1023) | |
| 63 | return FALSE; | |
| 64 | ||
| 65 | c = str; | |
| 66 | while(c && *c) { | |
| 67 | gunichar ch = g_utf8_get_char(c); | |
| 68 | if(!g_unichar_isgraph(ch)) | |
| 69 | return FALSE; | |
| 70 | ||
| 71 | c = g_utf8_next_char(c); | |
| 72 | } | |
| 73 | ||
| 74 | ||
| 75 | return TRUE; | |
| 76 | } | |
| 77 | ||
| 78 | gboolean jabber_resourceprep_validate(const char *str) | |
| 79 | { | |
| 80 | const char *c; | |
| 81 | ||
| 82 | if(!str) | |
| 83 | return TRUE; | |
| 84 | ||
| 85 | if(strlen(str) > 1023) | |
| 86 | return FALSE; | |
| 87 | ||
| 88 | c = str; | |
| 89 | while(c && *c) { | |
| 90 | gunichar ch = g_utf8_get_char(c); | |
| 7419 | 91 | if(!g_unichar_isgraph(ch) && ch != ' ') |
| 7310 | 92 | return FALSE; |
| 93 | ||
| 94 | c = g_utf8_next_char(c); | |
| 95 | } | |
| 96 | ||
| 97 | return TRUE; | |
| 98 | } | |
| 99 | ||
| 100 | ||
| 7014 | 101 | JabberID* |
| 102 | jabber_id_new(const char *str) | |
| 2086 | 103 | { |
| 7014 | 104 | char *at; |
| 105 | char *slash; | |
| 106 | JabberID *jid; | |
| 2086 | 107 | |
| 7306 | 108 | if(!str || !g_utf8_validate(str, -1, NULL)) |
| 7014 | 109 | return NULL; |
| 2086 | 110 | |
| 7014 | 111 | jid = g_new0(JabberID, 1); |
| 112 | ||
| 7306 | 113 | at = g_utf8_strchr(str, -1, '@'); |
| 114 | slash = g_utf8_strchr(str, -1, '/'); | |
| 2086 | 115 | |
| 7014 | 116 | if(at) { |
| 7306 | 117 | jid->node = g_utf8_normalize(str, at-str, G_NORMALIZE_NFKC); |
| 7014 | 118 | if(slash) { |
| 7306 | 119 | jid->domain = g_utf8_normalize(at+1, slash-(at+1), G_NORMALIZE_NFKC); |
| 120 | jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); | |
| 7014 | 121 | } else { |
| 7306 | 122 | jid->domain = g_utf8_normalize(at+1, -1, G_NORMALIZE_NFKC); |
| 7014 | 123 | } |
| 124 | } else { | |
| 125 | if(slash) { | |
| 7306 | 126 | jid->domain = g_utf8_normalize(str, slash-str, G_NORMALIZE_NFKC); |
| 127 | jid->resource = g_utf8_normalize(slash+1, -1, G_NORMALIZE_NFKC); | |
| 7014 | 128 | } else { |
| 7306 | 129 | jid->domain = g_utf8_normalize(str, -1, G_NORMALIZE_NFKC); |
| 130 | } | |
| 131 | } | |
| 132 | ||
| 133 | ||
| 7310 | 134 | if(!jabber_nodeprep_validate(jid->node) || |
| 135 | !jabber_nameprep_validate(jid->domain) || | |
| 136 | !jabber_resourceprep_validate(jid->resource)) { | |
| 7306 | 137 | jabber_id_free(jid); |
| 138 | return NULL; | |
| 139 | } | |
| 140 | ||
| 7014 | 141 | return jid; |
| 2086 | 142 | } |
| 143 | ||
| 7014 | 144 | void |
| 145 | jabber_id_free(JabberID *jid) | |
| 2086 | 146 | { |
| 7014 | 147 | if(jid) { |
| 148 | if(jid->node) | |
| 149 | g_free(jid->node); | |
| 150 | if(jid->domain) | |
| 151 | g_free(jid->domain); | |
| 152 | if(jid->resource) | |
| 153 | g_free(jid->resource); | |
| 154 | g_free(jid); | |
| 155 | } | |
| 2086 | 156 | } |
| 157 | ||
| 7014 | 158 | |
| 7306 | 159 | char *jabber_get_resource(const char *in) |
| 7014 | 160 | { |
| 7306 | 161 | JabberID *jid = jabber_id_new(in); |
| 162 | char *out; | |
| 7014 | 163 | |
| 7306 | 164 | if(!jid) |
| 7014 | 165 | return NULL; |
| 7306 | 166 | |
| 167 | out = g_strdup(jid->resource); | |
| 168 | jabber_id_free(jid); | |
| 169 | ||
| 170 | return out; | |
| 7014 | 171 | } |
| 172 | ||
| 7306 | 173 | char *jabber_get_bare_jid(const char *in) |
| 7014 | 174 | { |
| 7306 | 175 | JabberID *jid = jabber_id_new(in); |
| 176 | char *out; | |
| 7014 | 177 | |
| 7306 | 178 | if(!jid) |
| 179 | return NULL; | |
| 180 | ||
| 7322 | 181 | out = g_strdup_printf("%s%s%s", jid->node ? jid->node : "", |
| 182 | jid->node ? "@" : "", jid->domain); | |
| 7306 | 183 | jabber_id_free(jid); |
| 184 | ||
| 185 | return out; | |
| 7014 | 186 | } |
| 7261 | 187 | |
| 15884 | 188 | const char *jabber_normalize(const PurpleAccount *account, const char *in) |
| 7261 | 189 | { |
| 15884 | 190 | PurpleConnection *gc = account ? account->gc : NULL; |
| 7322 | 191 | JabberStream *js = gc ? gc->proto_data : NULL; |
| 192 | static char buf[3072]; /* maximum legal length of a jabber jid */ | |
| 193 | JabberID *jid; | |
| 7445 | 194 | char *node, *domain; |
| 7261 | 195 | |
| 7322 | 196 | jid = jabber_id_new(in); |
| 7310 | 197 | |
| 7322 | 198 | if(!jid) |
| 7310 | 199 | return NULL; |
| 200 | ||
| 7445 | 201 | node = jid->node ? g_utf8_strdown(jid->node, -1) : NULL; |
| 202 | domain = g_utf8_strdown(jid->domain, -1); | |
| 203 | ||
| 204 | ||
| 205 | if(js && node && jid->resource && | |
| 206 | jabber_chat_find(js, node, domain)) | |
| 207 | g_snprintf(buf, sizeof(buf), "%s@%s/%s", node, domain, | |
| 7322 | 208 | jid->resource); |
| 209 | else | |
| 7445 | 210 | g_snprintf(buf, sizeof(buf), "%s%s%s", node ? node : "", |
| 211 | node ? "@" : "", domain); | |
| 7322 | 212 | |
| 7429 | 213 | jabber_id_free(jid); |
| 7445 | 214 | g_free(node); |
| 215 | g_free(domain); | |
| 7429 | 216 | |
| 7261 | 217 | return buf; |
| 218 | } | |
| 7306 | 219 | |
| 15884 | 220 | PurpleConversation * |
| 221 | jabber_find_unnormalized_conv(const char *name, PurpleAccount *account) | |
| 8043 | 222 | { |
| 15884 | 223 | PurpleConversation *c = NULL; |
| 8043 | 224 | GList *cnv; |
| 225 | ||
| 226 | g_return_val_if_fail(name != NULL, NULL); | |
| 227 | ||
| 15884 | 228 | for(cnv = purple_get_conversations(); cnv; cnv = cnv->next) { |
| 229 | c = (PurpleConversation*)cnv->data; | |
| 230 | if(purple_conversation_get_type(c) == PURPLE_CONV_TYPE_IM && | |
| 231 | !purple_utf8_strcasecmp(name, purple_conversation_get_name(c)) && | |
| 232 | account == purple_conversation_get_account(c)) | |
| 8043 | 233 | return c; |
| 234 | } | |
| 235 | ||
| 236 | return NULL; | |
| 237 | } | |
| 8401 | 238 |