Annotation of ChivanetAimPidgin/oscarprpl/src/c/util.c, revision 1.1.1.1
1.1 snw 1: /*
2: * Purple'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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 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:
30: #include "core.h"
31:
32: #include <ctype.h>
33:
34: #ifdef _WIN32
35: #include "win32dep.h"
36: #endif
37:
38: static const char * const msgerrreason[] = {
39: N_("Invalid error"),
40: N_("Invalid SNAC"),
41: N_("Server rate limit exceeded"),
42: N_("Client rate limit exceeded"),
43: N_("Not logged in"),
44: N_("Service unavailable"),
45: N_("Service not defined"),
46: N_("Obsolete SNAC"),
47: N_("Not supported by host"),
48: N_("Not supported by client"),
49: N_("Refused by client"),
50: N_("Reply too big"),
51: N_("Responses lost"),
52: N_("Request denied"),
53: N_("Busted SNAC payload"),
54: N_("Insufficient rights"),
55: N_("In local permit/deny"),
56: N_("Warning level too high (sender)"),
57: N_("Warning level too high (receiver)"),
58: N_("User temporarily unavailable"),
59: N_("No match"),
60: N_("List overflow"),
61: N_("Request ambiguous"),
62: N_("Queue full"),
63: N_("Not while on AOL")
64: };
65: static const gsize msgerrreasonlen = G_N_ELEMENTS(msgerrreason);
66:
67: const char *oscar_get_msgerr_reason(size_t reason)
68: {
69: return (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason");
70: }
71:
72: int oscar_get_ui_info_int(const char *str, int default_value)
73: {
74: GHashTable *ui_info;
75:
76: ui_info = purple_core_get_ui_info();
77: if (ui_info != NULL) {
78: gpointer value;
79: if (g_hash_table_lookup_extended(ui_info, str, NULL, &value))
80: return GPOINTER_TO_INT(value);
81: }
82:
83: return default_value;
84: }
85:
86: const char *oscar_get_ui_info_string(const char *str, const char *default_value)
87: {
88: GHashTable *ui_info;
89: const char *value = NULL;
90:
91: ui_info = purple_core_get_ui_info();
92: if (ui_info != NULL)
93: value = g_hash_table_lookup(ui_info, str);
94: if (value == NULL)
95: value = default_value;
96:
97: return value;
98: }
99:
100: gchar *oscar_get_clientstring(void)
101: {
102: const char *name, *version;
103:
104: name = oscar_get_ui_info_string("name", "Purple");
105: version = oscar_get_ui_info_string("version", VERSION);
106:
107: return g_strdup_printf("%s/%s", name, version);;
108: }
109:
110: /**
111: * Calculate the checksum of a given icon.
112: */
113: guint16
114: aimutil_iconsum(const guint8 *buf, int buflen)
115: {
116: guint32 sum;
117: int i;
118:
119: for (i=0, sum=0; i+1<buflen; i+=2)
120: sum += (buf[i+1] << 8) + buf[i];
121: if (i < buflen)
122: sum += buf[i];
123: sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);
124:
125: return sum;
126: }
127:
128: /**
129: * Check if the given name is a valid AIM username.
130: * Example: BobDole
131: * Example: Henry_Ford@mac.com
132: * Example: 1KrazyKat@example.com
133: *
134: * @return TRUE if the name is valid, FALSE if not.
135: */
136: static gboolean
137: oscar_util_valid_name_aim(const char *name)
138: {
139: int i;
140:
141: if (purple_email_is_valid(name))
142: return TRUE;
143:
144: /* Normal AIM usernames can't start with a number, period or underscore */
145: if (isalnum(name[0]) == 0)
146: return FALSE;
147:
148: for (i = 0; name[i] != '\0'; i++) {
149: if (!isalnum(name[i]) && name[i] != ' ' && name[i] != '.' && name[i] != '_')
150: return FALSE;
151: }
152:
153: return TRUE;
154: }
155:
156: /**
157: * Check if the given name is a valid ICQ username.
158: * Example: 1234567
159: *
160: * @return TRUE if the name is valid, FALSE if not.
161: */
162: gboolean
163: oscar_util_valid_name_icq(const char *name)
164: {
165: int i;
166:
167: for (i = 0; name[i] != '\0'; i++) {
168: if (!isdigit(name[i]))
169: return FALSE;
170: }
171:
172: return TRUE;
173: }
174:
175: /**
176: * Check if the given name is a valid SMS username.
177: * Example: +19195551234
178: *
179: * @return TRUE if the name is valid, FALSE if not.
180: */
181: gboolean
182: oscar_util_valid_name_sms(const char *name)
183: {
184: int i;
185:
186: if (name[0] != '+')
187: return FALSE;
188:
189: for (i = 1; name[i] != '\0'; i++) {
190: if (!isdigit(name[i]))
191: return FALSE;
192: }
193:
194: return TRUE;
195: }
196:
197: /**
198: * Check if the given name is a valid oscar username.
199: *
200: * @return TRUE if the name is valid, FALSE if not.
201: */
202: gboolean
203: oscar_util_valid_name(const char *name)
204: {
205: if ((name == NULL) || (*name == '\0'))
206: return FALSE;
207:
208: return oscar_util_valid_name_icq(name)
209: || oscar_util_valid_name_sms(name)
210: || oscar_util_valid_name_aim(name);
211: }
212:
213: /**
214: * This takes two names and compares them using the rules
215: * on usernames for AIM/AOL. Mainly, this means case and space
216: * insensitivity (all case differences and spacing differences are
217: * ignored, with the exception that usernames can not start with
218: * a space).
219: *
220: * @return 0 if equal, non-0 if different
221: */
222: /* TODO: Do something different for email addresses. */
223: int
224: oscar_util_name_compare(const char *name1, const char *name2)
225: {
226:
227: if ((name1 == NULL) || (name2 == NULL))
228: return -1;
229:
230: do {
231: while (*name2 == ' ')
232: name2++;
233: while (*name1 == ' ')
234: name1++;
235: if (toupper(*name1) != toupper(*name2))
236: return 1;
237: } while ((*name1 != '\0') && name1++ && name2++);
238:
239: return 0;
240: }
241:
242: /**
243: * Looks for %n, %d, or %t in a string, and replaces them with the
244: * specified name, date, and time, respectively.
245: *
246: * @param str The string that may contain the special variables.
247: * @param name The sender name.
248: *
249: * @return A newly allocated string where the special variables are
250: * expanded. This should be g_free'd by the caller.
251: */
252: gchar *
253: oscar_util_format_string(const char *str, const char *name)
254: {
255: char *c;
256: GString *cpy;
257: time_t t;
258: struct tm *tme;
259:
260: g_return_val_if_fail(str != NULL, NULL);
261: g_return_val_if_fail(name != NULL, NULL);
262:
263: /* Create an empty GString that is hopefully big enough for most messages */
264: cpy = g_string_sized_new(1024);
265:
266: t = time(NULL);
267: tme = localtime(&t);
268:
269: c = (char *)str;
270: while (*c) {
271: switch (*c) {
272: case '%':
273: if (*(c + 1)) {
274: switch (*(c + 1)) {
275: case 'n':
276: /* append name */
277: g_string_append(cpy, name);
278: c++;
279: break;
280: case 'd':
281: /* append date */
282: g_string_append(cpy, purple_date_format_short(tme));
283: c++;
284: break;
285: case 't':
286: /* append time */
287: g_string_append(cpy, purple_time_format(tme));
288: c++;
289: break;
290: default:
291: g_string_append_c(cpy, *c);
292: }
293: } else {
294: g_string_append_c(cpy, *c);
295: }
296: break;
297: default:
298: g_string_append_c(cpy, *c);
299: }
300: c++;
301: }
302:
303: return g_string_free(cpy, FALSE);
304: }
305:
306: gchar *
307: oscar_format_buddies(GSList *buddies, const gchar *no_buddies_message)
308: {
309: GSList *cur;
310: GString *result;
311: if (!buddies) {
312: return g_strdup_printf("<i>%s</i>", no_buddies_message);
313: }
314: result = g_string_new("");
315: for (cur = buddies; cur != NULL; cur = cur->next) {
316: PurpleBuddy *buddy = cur->data;
317: const gchar *bname = purple_buddy_get_name(buddy);
318: const gchar *alias = purple_buddy_get_alias_only(buddy);
319: g_string_append(result, bname);
320: if (alias) {
321: g_string_append_printf(result, " (%s)", alias);
322: }
323: g_string_append(result, "<br>");
324: }
325: return g_string_free(result, FALSE);
326: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>