| |
1 /* |
| |
2 * Gaim's oscar protocol plugin |
| |
3 * This file is the legal property of its developers. |
| |
4 * Please see the AUTHORS file distributed alongside this file. |
| |
5 * |
| |
6 * This library is free software; you can redistribute it and/or |
| |
7 * modify it under the terms of the GNU Lesser General Public |
| |
8 * License as published by the Free Software Foundation; either |
| |
9 * version 2 of the License, or (at your option) any later version. |
| |
10 * |
| |
11 * This library 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 GNU |
| |
14 * Lesser General Public License for more details. |
| |
15 * |
| |
16 * You should have received a copy of the GNU Lesser General Public |
| |
17 * License along with this library; if not, write to the Free Software |
| |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| |
19 */ |
| |
20 |
| |
21 /* |
| |
22 * A little bit of this |
| |
23 * A little bit of that |
| |
24 * It started with a kiss |
| |
25 * Now we're up to bat |
| |
26 */ |
| |
27 |
| |
28 #include "oscar.h" |
| |
29 #include <ctype.h> |
| |
30 |
| |
31 #ifdef _WIN32 |
| |
32 #include "win32dep.h" |
| |
33 #endif |
| |
34 |
| |
35 /* |
| |
36 * Tokenizing functions. Used to portably replace strtok/sep. |
| |
37 * -- DMP. |
| |
38 * |
| |
39 */ |
| |
40 int |
| |
41 aimutil_tokslen(char *toSearch, int theindex, char dl) |
| |
42 { |
| |
43 int curCount = 1; |
| |
44 char *next; |
| |
45 char *last; |
| |
46 int toReturn; |
| |
47 |
| |
48 last = toSearch; |
| |
49 next = strchr(toSearch, dl); |
| |
50 |
| |
51 while(curCount < theindex && next != NULL) { |
| |
52 curCount++; |
| |
53 last = next + 1; |
| |
54 next = strchr(last, dl); |
| |
55 } |
| |
56 |
| |
57 if ((curCount < theindex) || (next == NULL)) |
| |
58 toReturn = strlen(toSearch) - (curCount - 1); |
| |
59 else |
| |
60 toReturn = next - toSearch - (curCount - 1); |
| |
61 |
| |
62 return toReturn; |
| |
63 } |
| |
64 |
| |
65 int |
| |
66 aimutil_itemcnt(char *toSearch, char dl) |
| |
67 { |
| |
68 int curCount; |
| |
69 char *next; |
| |
70 |
| |
71 curCount = 1; |
| |
72 |
| |
73 next = strchr(toSearch, dl); |
| |
74 |
| |
75 while(next != NULL) { |
| |
76 curCount++; |
| |
77 next = strchr(next + 1, dl); |
| |
78 } |
| |
79 |
| |
80 return curCount; |
| |
81 } |
| |
82 |
| |
83 char * |
| |
84 aimutil_itemindex(char *toSearch, int theindex, char dl) |
| |
85 { |
| |
86 int curCount; |
| |
87 char *next; |
| |
88 char *last; |
| |
89 char *toReturn; |
| |
90 |
| |
91 curCount = 0; |
| |
92 |
| |
93 last = toSearch; |
| |
94 next = strchr(toSearch, dl); |
| |
95 |
| |
96 while (curCount < theindex && next != NULL) { |
| |
97 curCount++; |
| |
98 last = next + 1; |
| |
99 next = strchr(last, dl); |
| |
100 } |
| |
101 next = strchr(last, dl); |
| |
102 |
| |
103 if (curCount < theindex) { |
| |
104 toReturn = malloc(sizeof(char)); |
| |
105 *toReturn = '\0'; |
| |
106 } else { |
| |
107 if (next == NULL) { |
| |
108 toReturn = malloc((strlen(last) + 1) * sizeof(char)); |
| |
109 strcpy(toReturn, last); |
| |
110 } else { |
| |
111 toReturn = malloc((next - last + 1) * sizeof(char)); |
| |
112 memcpy(toReturn, last, (next - last)); |
| |
113 toReturn[next - last] = '\0'; |
| |
114 } |
| |
115 } |
| |
116 return toReturn; |
| |
117 } |
| |
118 |
| |
119 /** |
| |
120 * Calculate the checksum of a given icon. |
| |
121 */ |
| |
122 guint16 |
| |
123 aimutil_iconsum(const guint8 *buf, int buflen) |
| |
124 { |
| |
125 guint32 sum; |
| |
126 int i; |
| |
127 |
| |
128 for (i=0, sum=0; i+1<buflen; i+=2) |
| |
129 sum += (buf[i+1] << 8) + buf[i]; |
| |
130 if (i < buflen) |
| |
131 sum += buf[i]; |
| |
132 sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff); |
| |
133 |
| |
134 return sum; |
| |
135 } |
| |
136 |
| |
137 /** |
| |
138 * Check if the given screen name is a valid AIM screen name. |
| |
139 * Example: BobDole |
| |
140 * Example: Henry_Ford@mac.com |
| |
141 * |
| |
142 * @return TRUE if the screen name is valid, FALSE if not. |
| |
143 */ |
| |
144 static gboolean |
| |
145 aim_snvalid_aim(const char *sn) |
| |
146 { |
| |
147 int i; |
| |
148 |
| |
149 for (i = 0; sn[i] != '\0'; i++) { |
| |
150 if (!isalnum(sn[i]) && (sn[i] != ' ') && |
| |
151 (sn[i] != '@') && (sn[i] != '.') && |
| |
152 (sn[i] != '_') && (sn[i] != '-')) |
| |
153 return FALSE; |
| |
154 } |
| |
155 |
| |
156 return TRUE; |
| |
157 } |
| |
158 |
| |
159 /** |
| |
160 * Check if the given screen name is a valid ICQ screen name. |
| |
161 * Example: 1234567 |
| |
162 * |
| |
163 * @return TRUE if the screen name is valid, FALSE if not. |
| |
164 */ |
| |
165 static gboolean |
| |
166 aim_snvalid_icq(const char *sn) |
| |
167 { |
| |
168 int i; |
| |
169 |
| |
170 for (i = 0; sn[i] != '\0'; i++) { |
| |
171 if (!isdigit(sn[i])) |
| |
172 return 0; |
| |
173 } |
| |
174 |
| |
175 return 1; |
| |
176 } |
| |
177 |
| |
178 /** |
| |
179 * Check if the given screen name is a valid SMS screen name. |
| |
180 * Example: +19195551234 |
| |
181 * |
| |
182 * @return TRUE if the screen name is valid, FALSE if not. |
| |
183 */ |
| |
184 static gboolean |
| |
185 aim_snvalid_sms(const char *sn) |
| |
186 { |
| |
187 int i; |
| |
188 |
| |
189 if (sn[0] != '+') |
| |
190 return 0; |
| |
191 |
| |
192 for (i = 1; sn[i] != '\0'; i++) { |
| |
193 if (!isdigit(sn[i])) |
| |
194 return 0; |
| |
195 } |
| |
196 |
| |
197 return 1; |
| |
198 } |
| |
199 |
| |
200 /** |
| |
201 * Check if the given screen name is a valid oscar screen name. |
| |
202 * |
| |
203 * @return TRUE if the screen name is valid, FALSE if not. |
| |
204 */ |
| |
205 gboolean |
| |
206 aim_snvalid(const char *sn) |
| |
207 { |
| |
208 if ((sn == NULL) || (*sn == '\0')) |
| |
209 return 0; |
| |
210 |
| |
211 if (isalpha(sn[0])) |
| |
212 return aim_snvalid_aim(sn); |
| |
213 else if (isdigit(sn[0])) |
| |
214 return aim_snvalid_icq(sn); |
| |
215 else if (sn[0] == '+') |
| |
216 return aim_snvalid_sms(sn); |
| |
217 |
| |
218 return 0; |
| |
219 } |
| |
220 |
| |
221 /** |
| |
222 * Determine if a given screen name is an ICQ screen name |
| |
223 * (i.e. it begins with a number). |
| |
224 * |
| |
225 * @sn A valid AIM or ICQ screen name. |
| |
226 * @return TRUE if the screen name is an ICQ screen name. Otherwise |
| |
227 * FALSE is returned. |
| |
228 */ |
| |
229 gboolean |
| |
230 aim_sn_is_icq(const char *sn) |
| |
231 { |
| |
232 if (isalpha(sn[0])) |
| |
233 return FALSE; |
| |
234 return TRUE; |
| |
235 } |
| |
236 |
| |
237 /** |
| |
238 * Determine if a given screen name is an SMS number |
| |
239 * (i.e. it begins with a +). |
| |
240 * |
| |
241 * @sn A valid AIM or ICQ screen name. |
| |
242 * @return TRUE if the screen name is an SMS number. Otherwise |
| |
243 * FALSE is returned. |
| |
244 */ |
| |
245 gboolean |
| |
246 aim_sn_is_sms(const char *sn) |
| |
247 { |
| |
248 if (sn[0] != '+') |
| |
249 return FALSE; |
| |
250 return TRUE; |
| |
251 } |
| |
252 |
| |
253 /** |
| |
254 * This takes a screen name and returns its length without |
| |
255 * spaces. If there are no spaces in the SN, then the |
| |
256 * return is equal to that of strlen(). |
| |
257 */ |
| |
258 int |
| |
259 aim_snlen(const char *sn) |
| |
260 { |
| |
261 int i = 0; |
| |
262 |
| |
263 if (!sn) |
| |
264 return 0; |
| |
265 |
| |
266 while (*sn != '\0') { |
| |
267 if (*sn != ' ') |
| |
268 i++; |
| |
269 sn++; |
| |
270 } |
| |
271 |
| |
272 return i; |
| |
273 } |
| |
274 |
| |
275 /** |
| |
276 * This takes two screen names and compares them using the rules |
| |
277 * on screen names for AIM/AOL. Mainly, this means case and space |
| |
278 * insensitivity (all case differences and spacing differences are |
| |
279 * ignored, with the exception that screen names can not start with |
| |
280 * a space). |
| |
281 * |
| |
282 * Return: 0 if equal |
| |
283 * non-0 if different |
| |
284 */ |
| |
285 int |
| |
286 aim_sncmp(const char *sn1, const char *sn2) |
| |
287 { |
| |
288 |
| |
289 if ((sn1 == NULL) || (sn2 == NULL)) |
| |
290 return -1; |
| |
291 |
| |
292 do { |
| |
293 while (*sn2 == ' ') |
| |
294 sn2++; |
| |
295 while (*sn1 == ' ') |
| |
296 sn1++; |
| |
297 if (toupper(*sn1) != toupper(*sn2)) |
| |
298 return 1; |
| |
299 } while ((*sn1 != '\0') && sn1++ && sn2++); |
| |
300 |
| |
301 return 0; |
| |
302 } |