Annotation of ChivanetAimPidgin/oscarprpl/src/c/util.c, revision 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>