Mercurial > pidgin
comparison src/util.c @ 7108:6faeeecab0dc
[gaim-migrate @ 7673]
Put the rest of util.[ch] into namespaces and sectioned off the functions.
committer: Tailor Script <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Wed, 01 Oct 2003 07:15:53 +0000 |
| parents | 9220c7490cd1 |
| children | b003397b16fe |
comparison
equal
deleted
inserted
replaced
| 7107:9220c7490cd1 | 7108:6faeeecab0dc |
|---|---|
| 58 } GaimFetchUrlData; | 58 } GaimFetchUrlData; |
| 59 | 59 |
| 60 | 60 |
| 61 static char home_dir[MAXPATHLEN]; | 61 static char home_dir[MAXPATHLEN]; |
| 62 | 62 |
| 63 char *full_date() | 63 |
| 64 { | 64 /************************************************************************** |
| 65 char *date; | 65 * Base16 Functions |
| 66 time_t tme; | 66 **************************************************************************/ |
| 67 | 67 unsigned char * |
| 68 time(&tme); | 68 gaim_base16_encode(const unsigned char *data, int length) |
| 69 date = ctime(&tme); | 69 { |
| 70 date[strlen(date) - 1] = '\0'; | 70 int i; |
| 71 return date; | 71 unsigned char *ascii = NULL; |
| 72 } | 72 |
| 73 | 73 g_return_val_if_fail(data != NULL, NULL); |
| 74 G_GNUC_CONST static gint badchar(char c) | 74 g_return_val_if_fail(length > 0, NULL); |
| 75 { | 75 |
| 76 switch (c) { | 76 ascii = g_malloc(length * 2 + 1); |
| 77 case ' ': | 77 |
| 78 case ',': | 78 for (i = 0; i < length; i++) |
| 79 case '(': | 79 snprintf(&ascii[i * 2], 3, "%02hhx", data[i]); |
| 80 case ')': | 80 |
| 81 case '\0': | 81 return ascii; |
| 82 case '\n': | 82 } |
| 83 case '<': | 83 |
| 84 case '>': | 84 int |
| 85 case '"': | 85 gaim_base16_decode(const char *ascii, unsigned char **raw) |
| 86 case '\'': | 86 { |
| 87 return 1; | 87 int len, i, accumulator = 0; |
| 88 default: | 88 unsigned char *data; |
| 89 return 0; | 89 |
| 90 } | 90 g_return_val_if_fail(ascii != NULL, 0); |
| 91 } | 91 |
| 92 | 92 len = strlen(ascii); |
| 93 | 93 |
| 94 gchar *sec_to_text(guint sec) | 94 g_return_val_if_fail(strlen(ascii) > 0, 0); |
| 95 { | 95 g_return_val_if_fail(len % 2 > 0, 0); |
| 96 guint daze, hrs, min; | 96 |
| 97 char *ret = NULL; | 97 data = g_malloc(len / 2); |
| 98 | 98 |
| 99 daze = sec / (60 * 60 * 24); | 99 for (i = 0; i < len; i++) |
| 100 hrs = (sec % (60 * 60 * 24)) / (60 * 60); | 100 { |
| 101 min = (sec % (60 * 60)) / 60; | 101 if ((i % 2) == 0) |
| 102 sec = min % 60; | 102 accumulator = 0; |
| 103 | 103 else |
| 104 if (daze) { | 104 accumulator <<= 4; |
| 105 if (hrs || min) { | 105 |
| 106 if (hrs) { | 106 if (isdigit(ascii[i])) |
| 107 if (min) { | 107 accumulator |= ascii[i] - 48; |
| 108 ret = g_strdup_printf( | 108 else |
| 109 "%d %s, %d %s, %d %s.", | 109 { |
| 110 daze, ngettext("day","days",daze), | 110 switch(ascii[i]) |
| 111 hrs, ngettext("hour","hours",hrs), min, ngettext("minute","minutes",min)); | 111 { |
| 112 } else { | 112 case 'a': case 'A': accumulator |= 10; break; |
| 113 ret = g_strdup_printf( | 113 case 'b': case 'B': accumulator |= 11; break; |
| 114 "%d %s, %d %s.", | 114 case 'c': case 'C': accumulator |= 12; break; |
| 115 daze, ngettext("day","days",daze), hrs, ngettext("hour","hours",hrs)); | 115 case 'd': case 'D': accumulator |= 13; break; |
| 116 } | 116 case 'e': case 'E': accumulator |= 14; break; |
| 117 } else { | 117 case 'f': case 'F': accumulator |= 15; break; |
| 118 ret = g_strdup_printf( | 118 } |
| 119 "%d %s, %d %s.", | 119 } |
| 120 daze, ngettext("day","days",daze), min, ngettext("minute","minutes",min)); | 120 |
| 121 } | 121 if (i % 2) |
| 122 } else | 122 data[(i - 1) / 2] = accumulator; |
| 123 ret = g_strdup_printf("%d %s.", daze, ngettext("day","days",daze)); | 123 } |
| 124 } else { | 124 |
| 125 if (hrs) { | 125 *raw = data; |
| 126 if (min) { | 126 |
| 127 ret = g_strdup_printf( | 127 return (len / 2); |
| 128 "%d %s, %d %s.", | 128 } |
| 129 hrs, ngettext("hour","hours",hrs), min, ngettext("minute","minutes",min)); | 129 |
| 130 } else { | 130 /************************************************************************** |
| 131 ret = g_strdup_printf("%d %s.", hrs, ngettext("hour","hours",hrs)); | 131 * Base64 Functions |
| 132 } | 132 **************************************************************************/ |
| 133 } else { | |
| 134 ret = g_strdup_printf("%d %s.", min, ngettext("minute","minutes",min)); | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 return ret; | |
| 139 } | |
| 140 | |
| 141 | |
| 142 static const char alphabet[] = | 133 static const char alphabet[] = |
| 143 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" | 134 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" |
| 144 "0123456789+/"; | 135 "0123456789+/"; |
| 145 | 136 |
| 146 char *gaim_base64_encode(const unsigned char *in, size_t inlen) | 137 unsigned char * |
| 138 gaim_base64_encode(const unsigned char *in, size_t inlen) | |
| 147 { | 139 { |
| 148 char *out, *rv; | 140 char *out, *rv; |
| 149 | 141 |
| 142 g_return_val_if_fail(in != NULL, NULL); | |
| 143 g_return_val_if_fail(inlen > 0, NULL); | |
| 144 | |
| 150 rv = out = g_malloc((4 * (inlen + 1)) / 3 + 1); | 145 rv = out = g_malloc((4 * (inlen + 1)) / 3 + 1); |
| 151 | 146 |
| 152 for (; inlen >= 3; inlen -= 3) | 147 for (; inlen >= 3; inlen -= 3) |
| 153 { | 148 { |
| 154 *out++ = alphabet[in[0] >> 2]; | 149 *out++ = alphabet[in[0] >> 2]; |
| 155 *out++ = alphabet[((in[0] << 4) & 0x30) | (in[1] >> 4)]; | 150 *out++ = alphabet[((in[0] << 4) & 0x30) | (in[1] >> 4)]; |
| 156 *out++ = alphabet[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; | 151 *out++ = alphabet[((in[1] << 2) & 0x3c) | (in[2] >> 6)]; |
| 157 *out++ = alphabet[in[2] & 0x3f]; | 152 *out++ = alphabet[in[2] & 0x3f]; |
| 158 in += 3; | 153 in += 3; |
| 159 } | 154 } |
| 160 if (inlen > 0) | 155 |
| 161 { | 156 if (inlen > 0) |
| 162 unsigned char fragment; | 157 { |
| 163 | 158 unsigned char fragment; |
| 164 *out++ = alphabet[in[0] >> 2]; | 159 |
| 165 fragment = (in[0] << 4) & 0x30; | 160 *out++ = alphabet[in[0] >> 2]; |
| 166 if (inlen > 1) | 161 fragment = (in[0] << 4) & 0x30; |
| 167 fragment |= in[1] >> 4; | 162 |
| 168 *out++ = alphabet[fragment]; | 163 if (inlen > 1) |
| 169 *out++ = (inlen < 2) ? '=' : alphabet[(in[1] << 2) & 0x3c]; | 164 fragment |= in[1] >> 4; |
| 170 *out++ = '='; | 165 |
| 171 } | 166 *out++ = alphabet[fragment]; |
| 172 *out = '\0'; | 167 *out++ = (inlen < 2) ? '=' : alphabet[(in[1] << 2) & 0x3c]; |
| 168 *out++ = '='; | |
| 169 } | |
| 170 | |
| 171 *out = '\0'; | |
| 173 | 172 |
| 174 return rv; | 173 return rv; |
| 175 } | 174 } |
| 176 | 175 |
| 177 | 176 void |
| 178 void gaim_base64_decode(const char *text, char **data, int *size) | 177 gaim_base64_decode(const char *text, char **data, int *size) |
| 179 { | 178 { |
| 180 char *out = NULL; | 179 char *out = NULL; |
| 181 char tmp = 0; | 180 char tmp = 0; |
| 182 const char *c; | 181 const char *c; |
| 183 gint32 tmp2 = 0; | 182 gint32 tmp2 = 0; |
| 184 int len = 0, n = 0; | 183 int len = 0, n = 0; |
| 185 | 184 |
| 186 if (!text || !data) | 185 g_return_if_fail(text != NULL); |
| 187 return; | 186 g_return_if_fail(data != NULL); |
| 188 | 187 |
| 189 c = text; | 188 c = text; |
| 190 | 189 |
| 191 while (*c) { | 190 while (*c) { |
| 192 if (*c >= 'A' && *c <= 'Z') { | 191 if (*c >= 'A' && *c <= 'Z') { |
| 234 | 233 |
| 235 out = g_realloc(out, len + 1); | 234 out = g_realloc(out, len + 1); |
| 236 out[len] = 0; | 235 out[len] = 0; |
| 237 | 236 |
| 238 *data = out; | 237 *data = out; |
| 238 | |
| 239 if (size) | 239 if (size) |
| 240 *size = len; | 240 *size = len; |
| 241 } | 241 } |
| 242 | 242 |
| 243 /* | 243 |
| 244 * Converts raw data to a pretty, null-terminated base16 string. | 244 /************************************************************************** |
| 245 */ | 245 * Date/Time Functions |
| 246 unsigned char *gaim_base16_encode(const unsigned char *data, int length) | 246 **************************************************************************/ |
| 247 { | 247 char * |
| 248 int i; | 248 gaim_date(void) |
| 249 unsigned char *ascii = NULL; | |
| 250 | |
| 251 if (!data || !length) | |
| 252 return NULL; | |
| 253 | |
| 254 ascii = g_malloc(length*2 + 1); | |
| 255 | |
| 256 for (i=0; i<length; i++) | |
| 257 snprintf(&ascii[i*2], 3, "%02hhx", data[i]); | |
| 258 | |
| 259 return ascii; | |
| 260 } | |
| 261 | |
| 262 /* | |
| 263 * Converts a null-terminated string of hexidecimal to raw data. | |
| 264 */ | |
| 265 int gaim_base16_decode(const char *ascii, unsigned char **raw) | |
| 266 { | |
| 267 int len, i, accumulator=0; | |
| 268 unsigned char *data; | |
| 269 | |
| 270 if (!ascii || !(len = strlen(ascii)) || (len % 2)) | |
| 271 return 0; | |
| 272 | |
| 273 data = g_malloc(len/2); | |
| 274 for (i=0; i<len; i++) { | |
| 275 if (!(i % 2)) | |
| 276 accumulator = 0; | |
| 277 else | |
| 278 accumulator = accumulator << 4; | |
| 279 if (isdigit(ascii[i])) | |
| 280 accumulator |= ascii[i]-48; | |
| 281 else switch(ascii[i]) { | |
| 282 case 'a': case 'A': accumulator|=10; break; | |
| 283 case 'b': case 'B': accumulator|=11; break; | |
| 284 case 'c': case 'C': accumulator|=12; break; | |
| 285 case 'd': case 'D': accumulator|=13; break; | |
| 286 case 'e': case 'E': accumulator|=14; break; | |
| 287 case 'f': case 'F': accumulator|=15; break; | |
| 288 } | |
| 289 if (i % 2) | |
| 290 data[(i-1)/2] = accumulator; | |
| 291 } | |
| 292 | |
| 293 *raw = data; | |
| 294 return len/2; | |
| 295 } | |
| 296 | |
| 297 char *gaim_normalize(const char *s) | |
| 298 { | |
| 299 static char buf[BUF_LEN]; | |
| 300 char *tmp; | |
| 301 int i, j; | |
| 302 | |
| 303 g_return_val_if_fail((s != NULL), NULL); | |
| 304 | |
| 305 strncpy(buf, s, BUF_LEN); | |
| 306 for (i=0, j=0; buf[j]; i++, j++) { | |
| 307 while (buf[j] == ' ') | |
| 308 j++; | |
| 309 buf[i] = buf[j]; | |
| 310 } | |
| 311 buf[i] = '\0'; | |
| 312 | |
| 313 tmp = g_utf8_strdown(buf, -1); | |
| 314 g_snprintf(buf, sizeof(buf), "%s", tmp); | |
| 315 g_free(tmp); | |
| 316 tmp = g_utf8_normalize(buf, -1, G_NORMALIZE_DEFAULT); | |
| 317 g_snprintf(buf, sizeof(buf), "%s", tmp); | |
| 318 g_free(tmp); | |
| 319 | |
| 320 return buf; | |
| 321 } | |
| 322 | |
| 323 char *date() | |
| 324 { | 249 { |
| 325 static char date[80]; | 250 static char date[80]; |
| 326 time_t tme; | 251 time_t tme; |
| 252 | |
| 327 time(&tme); | 253 time(&tme); |
| 328 strftime(date, sizeof(date), "%H:%M:%S", localtime(&tme)); | 254 strftime(date, sizeof(date), "%H:%M:%S", localtime(&tme)); |
| 255 | |
| 329 return date; | 256 return date; |
| 330 } | 257 } |
| 331 | 258 |
| 332 /* Look for %n, %d, or %t in msg, and replace with the sender's name, date, | 259 char * |
| 333 or time */ | 260 gaim_date_full(void) |
| 334 char *away_subs(const char *msg, const char *name) | 261 { |
| 335 { | 262 char *date; |
| 336 char *c; | 263 time_t tme; |
| 337 static char cpy[BUF_LONG]; | 264 |
| 338 int cnt = 0; | 265 time(&tme); |
| 339 time_t t = time(0); | 266 date = ctime(&tme); |
| 340 struct tm *tme = localtime(&t); | 267 date[strlen(date) - 1] = '\0'; |
| 341 char tmp[20]; | 268 |
| 342 | 269 return date; |
| 343 cpy[0] = '\0'; | 270 } |
| 344 c = (char *)msg; | 271 |
| 345 while (*c) { | 272 time_t |
| 346 switch (*c) { | 273 gaim_time_build(int year, int month, int day, int hour, int min, int sec) |
| 347 case '%': | |
| 348 if (*(c + 1)) { | |
| 349 switch (*(c + 1)) { | |
| 350 case 'n': | |
| 351 /* append name */ | |
| 352 strcpy(cpy + cnt, name); | |
| 353 cnt += strlen(name); | |
| 354 c++; | |
| 355 break; | |
| 356 case 'd': | |
| 357 /* append date */ | |
| 358 strftime(tmp, 20, "%m/%d/%Y", tme); | |
| 359 strcpy(cpy + cnt, tmp); | |
| 360 cnt += strlen(tmp); | |
| 361 c++; | |
| 362 break; | |
| 363 case 't': | |
| 364 /* append time */ | |
| 365 strftime(tmp, 20, "%r", tme); | |
| 366 strcpy(cpy + cnt, tmp); | |
| 367 cnt += strlen(tmp); | |
| 368 c++; | |
| 369 break; | |
| 370 default: | |
| 371 cpy[cnt++] = *c; | |
| 372 } | |
| 373 } | |
| 374 break; | |
| 375 default: | |
| 376 cpy[cnt++] = *c; | |
| 377 } | |
| 378 c++; | |
| 379 } | |
| 380 cpy[cnt] = '\0'; | |
| 381 return (cpy); | |
| 382 } | |
| 383 | |
| 384 GSList *message_split(char *message, int limit) | |
| 385 { | |
| 386 static GSList *ret = NULL; | |
| 387 int lastgood = 0, curgood = 0, curpos = 0, len = strlen(message); | |
| 388 gboolean intag = FALSE; | |
| 389 | |
| 390 if (ret) { | |
| 391 GSList *tmp = ret; | |
| 392 while (tmp) { | |
| 393 g_free(tmp->data); | |
| 394 tmp = g_slist_remove(tmp, tmp->data); | |
| 395 } | |
| 396 ret = NULL; | |
| 397 } | |
| 398 | |
| 399 while (TRUE) { | |
| 400 if (lastgood >= len) | |
| 401 return ret; | |
| 402 | |
| 403 if (len - lastgood < limit) { | |
| 404 ret = g_slist_append(ret, g_strdup(&message[lastgood])); | |
| 405 return ret; | |
| 406 } | |
| 407 | |
| 408 curgood = curpos = 0; | |
| 409 intag = FALSE; | |
| 410 while (curpos <= limit) { | |
| 411 if (isspace(message[curpos + lastgood]) && !intag) | |
| 412 curgood = curpos; | |
| 413 if (message[curpos + lastgood] == '<') | |
| 414 intag = TRUE; | |
| 415 if (message[curpos + lastgood] == '>') | |
| 416 intag = FALSE; | |
| 417 curpos++; | |
| 418 } | |
| 419 | |
| 420 if (curgood) { | |
| 421 ret = g_slist_append(ret, g_strndup(&message[lastgood], curgood)); | |
| 422 if (isspace(message[curgood + lastgood])) | |
| 423 lastgood += curgood + 1; | |
| 424 else | |
| 425 lastgood += curgood; | |
| 426 } else { | |
| 427 /* whoops, guess we have to fudge it here */ | |
| 428 ret = g_slist_append(ret, g_strndup(&message[lastgood], limit)); | |
| 429 lastgood += limit; | |
| 430 } | |
| 431 } | |
| 432 } | |
| 433 | |
| 434 const gchar *gaim_home_dir() | |
| 435 { | |
| 436 #ifndef _WIN32 | |
| 437 if(g_get_home_dir()) | |
| 438 return g_get_home_dir(); | |
| 439 else | |
| 440 return NULL; | |
| 441 #else | |
| 442 return wgaim_data_dir(); | |
| 443 #endif | |
| 444 } | |
| 445 | |
| 446 /* returns a string of the form ~/.gaim, where ~ is replaced by the user's home | |
| 447 * dir. Note that there is no trailing slash after .gaim. */ | |
| 448 gchar *gaim_user_dir() | |
| 449 { | |
| 450 const gchar *hd = gaim_home_dir(); | |
| 451 if(hd) { | |
| 452 strcpy( (char*)&home_dir, hd ); | |
| 453 strcat( (char*)&home_dir, G_DIR_SEPARATOR_S ".gaim" ); | |
| 454 return (gchar*)&home_dir; | |
| 455 } | |
| 456 else { | |
| 457 return NULL; | |
| 458 } | |
| 459 } | |
| 460 | |
| 461 /* | |
| 462 * rcg10312000 This could be more robust, but it works for my current | |
| 463 * goal: to remove those annoying <BR> tags. :) | |
| 464 * dtf12162000 made the loop more readable. i am a neat freak. ;) */ | |
| 465 void strncpy_nohtml(gchar *dest, const gchar *src, size_t destsize) | |
| 466 { | |
| 467 gchar *ptr; | |
| 468 g_snprintf(dest, destsize, "%s", src); | |
| 469 | |
| 470 while ((ptr = strstr(dest, "<BR>")) != NULL) { | |
| 471 /* replace <BR> with a newline. */ | |
| 472 *ptr = '\n'; | |
| 473 memmove(ptr + 1, ptr + 4, strlen(ptr + 4) + 1); | |
| 474 } | |
| 475 } | |
| 476 | |
| 477 void strncpy_withhtml(gchar *dest, const gchar *src, size_t destsize) | |
| 478 { | |
| 479 gchar *end = dest + destsize; | |
| 480 | |
| 481 while (dest < end) { | |
| 482 if (*src == '\n' && dest < end - 5) { | |
| 483 strcpy(dest, "<BR>"); | |
| 484 src++; | |
| 485 dest += 4; | |
| 486 } else if(*src == '\r') { | |
| 487 src++; | |
| 488 } else { | |
| 489 *dest++ = *src; | |
| 490 if (*src == '\0') | |
| 491 return; | |
| 492 else | |
| 493 src++; | |
| 494 } | |
| 495 } | |
| 496 } | |
| 497 | |
| 498 | |
| 499 /* | |
| 500 * Like strncpy_withhtml (above), but malloc()'s the necessary space | |
| 501 * | |
| 502 * The caller is responsible for freeing the space pointed to by the | |
| 503 * return value. | |
| 504 */ | |
| 505 | |
| 506 gchar *strdup_withhtml(const gchar *src) | |
| 507 { | |
| 508 gchar *sp, *dest; | |
| 509 gulong destsize; | |
| 510 | |
| 511 if(!src) | |
| 512 return NULL; | |
| 513 | |
| 514 /* | |
| 515 * All we need do is multiply the number of newlines by 3 (the | |
| 516 * additional length of "<BR>" over "\n"), account for the | |
| 517 * terminator, malloc the space and call strncpy_withhtml. | |
| 518 */ | |
| 519 for(destsize = 0, sp = (gchar *)src; (sp = strchr(sp, '\n')) != NULL; ++sp, ++destsize) | |
| 520 ; | |
| 521 destsize *= 3; | |
| 522 destsize += strlen(src) + 1; | |
| 523 dest = g_malloc(destsize); | |
| 524 strncpy_withhtml(dest, src, destsize); | |
| 525 | |
| 526 return(dest); | |
| 527 } | |
| 528 | |
| 529 void strip_linefeed(gchar *text) | |
| 530 { | |
| 531 int i, j; | |
| 532 gchar *text2 = g_malloc(strlen(text) + 1); | |
| 533 | |
| 534 for (i = 0, j = 0; text[i]; i++) | |
| 535 if (text[i] != '\r') | |
| 536 text2[j++] = text[i]; | |
| 537 text2[j] = '\0'; | |
| 538 | |
| 539 strcpy(text, text2); | |
| 540 g_free(text2); | |
| 541 } | |
| 542 | |
| 543 char *add_cr(const char *text) | |
| 544 { | |
| 545 char *ret = NULL; | |
| 546 int count = 0, i, j; | |
| 547 | |
| 548 if (text[0] == '\n') | |
| 549 count++; | |
| 550 for (i = 1; i < strlen(text); i++) | |
| 551 if (text[i] == '\n' && text[i - 1] != '\r') | |
| 552 count++; | |
| 553 | |
| 554 if (count == 0) | |
| 555 return g_strdup(text); | |
| 556 | |
| 557 ret = g_malloc0(strlen(text) + count + 1); | |
| 558 | |
| 559 i = 0; j = 0; | |
| 560 if (text[i] == '\n') | |
| 561 ret[j++] = '\r'; | |
| 562 ret[j++] = text[i++]; | |
| 563 for (; i < strlen(text); i++) { | |
| 564 if (text[i] == '\n' && text[i - 1] != '\r') | |
| 565 ret[j++] = '\r'; | |
| 566 ret[j++] = text[i]; | |
| 567 } | |
| 568 | |
| 569 gaim_debug(GAIM_DEBUG_INFO, "add_cr", "got: %s, leaving with %s\n", | |
| 570 text, ret); | |
| 571 | |
| 572 return ret; | |
| 573 } | |
| 574 | |
| 575 time_t get_time(int year, int month, int day, int hour, int min, int sec) | |
| 576 { | 274 { |
| 577 struct tm tm; | 275 struct tm tm; |
| 578 | 276 |
| 579 tm.tm_year = year - 1900; | 277 tm.tm_year = year - 1900; |
| 580 tm.tm_mon = month - 1; | 278 tm.tm_mon = month - 1; |
| 581 tm.tm_mday = day; | 279 tm.tm_mday = day; |
| 582 tm.tm_hour = hour; | 280 tm.tm_hour = hour; |
| 583 tm.tm_min = min; | 281 tm.tm_min = min; |
| 584 tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60; | 282 tm.tm_sec = sec >= 0 ? sec : time(NULL) % 60; |
| 283 | |
| 585 return mktime(&tm); | 284 return mktime(&tm); |
| 586 } | 285 } |
| 587 | 286 |
| 588 /* | 287 |
| 589 * Like mkstemp() but returns a file pointer, uses a pre-set template, | 288 /************************************************************************** |
| 590 * uses the semantics of tempnam() for the directory to use and allocates | 289 * Markup Functions |
| 591 * the space for the filepath. | 290 **************************************************************************/ |
| 592 * | |
| 593 * Caller is responsible for closing the file and removing it when done, | |
| 594 * as well as freeing the space pointed-to by "path" with g_free(). | |
| 595 * | |
| 596 * Returns NULL on failure and cleans up after itself if so. | |
| 597 */ | |
| 598 static const char *gaim_mkstemp_templ = {"gaimXXXXXX"}; | |
| 599 | |
| 600 FILE *gaim_mkstemp(gchar **fpath) | |
| 601 { | |
| 602 const gchar *tmpdir; | |
| 603 #ifndef _WIN32 | |
| 604 int fd; | |
| 605 #endif | |
| 606 FILE *fp = NULL; | |
| 607 | |
| 608 if((tmpdir = (gchar*)g_get_tmp_dir()) != NULL) { | |
| 609 if((*fpath = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", tmpdir, gaim_mkstemp_templ)) != NULL) { | |
| 610 #ifdef _WIN32 | |
| 611 char* result = _mktemp( *fpath ); | |
| 612 if( result == NULL ) | |
| 613 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 614 "Problem creating the template\n"); | |
| 615 else | |
| 616 { | |
| 617 if( (fp = fopen( result, "w+" )) == NULL ) { | |
| 618 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 619 "Couldn't fopen() %s\n", result); | |
| 620 } | |
| 621 } | |
| 622 #else | |
| 623 if((fd = mkstemp(*fpath)) == -1) { | |
| 624 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 625 "Couldn't make \"%s\", error: %d\n", | |
| 626 *fpath, errno); | |
| 627 } else { | |
| 628 if((fp = fdopen(fd, "r+")) == NULL) { | |
| 629 close(fd); | |
| 630 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 631 "Couldn't fdopen(), error: %d\n", errno); | |
| 632 } | |
| 633 } | |
| 634 #endif | |
| 635 if(!fp) { | |
| 636 g_free(*fpath); | |
| 637 *fpath = NULL; | |
| 638 } | |
| 639 } | |
| 640 } else { | |
| 641 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 642 "g_get_tmp_dir() failed!"); | |
| 643 } | |
| 644 | |
| 645 return fp; | |
| 646 } | |
| 647 | |
| 648 gboolean program_is_valid(const char *program) | |
| 649 { | |
| 650 GError *error = NULL; | |
| 651 char **argv; | |
| 652 gchar *progname; | |
| 653 gboolean is_valid = FALSE; | |
| 654 | |
| 655 if (program == NULL || *program == '\0') { | |
| 656 return FALSE; | |
| 657 } | |
| 658 | |
| 659 if (!g_shell_parse_argv(program, NULL, &argv, &error)) { | |
| 660 gaim_debug(GAIM_DEBUG_ERROR, "program_is_valid", | |
| 661 "Could not parse program '%s': %s\n", | |
| 662 program, error->message); | |
| 663 g_error_free(error); | |
| 664 return FALSE; | |
| 665 } | |
| 666 | |
| 667 if (argv == NULL) { | |
| 668 return FALSE; | |
| 669 } | |
| 670 | |
| 671 progname = g_find_program_in_path(argv[0]); | |
| 672 is_valid = (progname != NULL); | |
| 673 | |
| 674 g_strfreev(argv); | |
| 675 g_free(progname); | |
| 676 | |
| 677 return is_valid; | |
| 678 } | |
| 679 | |
| 680 char *gaim_try_conv_to_utf8(const char *str) | |
| 681 { | |
| 682 gsize converted; | |
| 683 char *utf8; | |
| 684 | |
| 685 if (str == NULL) { | |
| 686 return NULL; | |
| 687 } | |
| 688 | |
| 689 if (g_utf8_validate(str, -1, NULL)) { | |
| 690 return g_strdup(str); | |
| 691 } | |
| 692 | |
| 693 utf8 = g_locale_to_utf8(str, -1, &converted, NULL, NULL); | |
| 694 if (utf8) | |
| 695 return(utf8); | |
| 696 | |
| 697 g_free(utf8); | |
| 698 | |
| 699 utf8 = g_convert(str, -1, "UTF-8", "ISO-8859-15", &converted, NULL, NULL); | |
| 700 if (utf8 && converted == strlen (str)) { | |
| 701 return(utf8); | |
| 702 } else if (utf8) { | |
| 703 g_free(utf8); | |
| 704 } | |
| 705 | |
| 706 return(NULL); | |
| 707 } | |
| 708 | |
| 709 char *gaim_getip_from_fd(int fd) | |
| 710 { | |
| 711 struct sockaddr addr; | |
| 712 socklen_t namelen = sizeof(addr); | |
| 713 | |
| 714 if (getsockname(fd, &addr, &namelen)) | |
| 715 return NULL; | |
| 716 | |
| 717 return g_strdup(inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr)); | |
| 718 } | |
| 719 | |
| 720 gint gaim_utf8_strcasecmp(const gchar *a, const gchar *b) { | |
| 721 gchar *a_norm=NULL; | |
| 722 gchar *b_norm=NULL; | |
| 723 gint ret=-1; | |
| 724 | |
| 725 if(!a && b) | |
| 726 return -1; | |
| 727 else if(!b && a) | |
| 728 return 1; | |
| 729 else if(!a && !b) | |
| 730 return 0; | |
| 731 | |
| 732 if(!g_utf8_validate(a, -1, NULL) || !g_utf8_validate(b, -1, NULL)) { | |
| 733 gaim_debug(GAIM_DEBUG_ERROR, "gaim_utf8_strcasecmp", "One or both parameters are invalid UTF8\n"); | |
| 734 return ret; | |
| 735 } | |
| 736 | |
| 737 a_norm = g_utf8_casefold(a, -1); | |
| 738 b_norm = g_utf8_casefold(b, -1); | |
| 739 ret = g_utf8_collate(a_norm, b_norm); | |
| 740 g_free(a_norm); | |
| 741 g_free(b_norm); | |
| 742 return ret; | |
| 743 } | |
| 744 | |
| 745 gchar *gaim_strreplace(const gchar *string, const gchar *delimiter, const gchar *replacement) { | |
| 746 gchar **split; | |
| 747 gchar *ret; | |
| 748 | |
| 749 split = g_strsplit(string, delimiter, 0); | |
| 750 ret = g_strjoinv(replacement, split); | |
| 751 g_strfreev(split); | |
| 752 | |
| 753 return ret; | |
| 754 } | |
| 755 | |
| 756 const char *gaim_strcasestr(const char *haystack, const char *needle) { | |
| 757 size_t hlen, nlen; | |
| 758 const char *tmp, *ret; | |
| 759 | |
| 760 g_return_val_if_fail(haystack != NULL, NULL); | |
| 761 g_return_val_if_fail(needle != NULL, NULL); | |
| 762 | |
| 763 hlen = strlen(haystack); | |
| 764 nlen = strlen(needle); | |
| 765 tmp = haystack, | |
| 766 ret = NULL; | |
| 767 | |
| 768 g_return_val_if_fail(hlen > 0, NULL); | |
| 769 g_return_val_if_fail(nlen > 0, NULL); | |
| 770 | |
| 771 while (*tmp && !ret) { | |
| 772 if (!g_ascii_strncasecmp(needle, tmp, nlen)) | |
| 773 ret = tmp; | |
| 774 else | |
| 775 tmp++; | |
| 776 } | |
| 777 | |
| 778 return ret; | |
| 779 } | |
| 780 | |
| 781 char * | |
| 782 gaim_str_size_to_units(size_t size) | |
| 783 { | |
| 784 static const char *size_str[4] = { "bytes", "KB", "MB", "GB" }; | |
| 785 float size_mag; | |
| 786 int size_index = 0; | |
| 787 | |
| 788 if (size == -1) { | |
| 789 return g_strdup(_("Calculating...")); | |
| 790 } | |
| 791 else if (size == 0) { | |
| 792 return g_strdup(_("Unknown.")); | |
| 793 } | |
| 794 else { | |
| 795 size_mag = (float)size; | |
| 796 | |
| 797 while ((size_index < 4) && (size_mag > 1024)) { | |
| 798 size_mag /= 1024; | |
| 799 size_index++; | |
| 800 } | |
| 801 | |
| 802 return g_strdup_printf("%.2f %s", size_mag, size_str[size_index]); | |
| 803 } | |
| 804 } | |
| 805 | |
| 806 gboolean | 291 gboolean |
| 807 gaim_markup_find_tag(const char *needle, const char *haystack, | 292 gaim_markup_find_tag(const char *needle, const char *haystack, |
| 808 const char **start, const char **end, GData **attributes) | 293 const char **start, const char **end, GData **attributes) |
| 809 { | 294 { |
| 810 GData *attribs; | 295 GData *attribs; |
| 1384 str2[j] = '\0'; | 869 str2[j] = '\0'; |
| 1385 | 870 |
| 1386 return str2; | 871 return str2; |
| 1387 } | 872 } |
| 1388 | 873 |
| 874 static gint | |
| 875 badchar(char c) | |
| 876 { | |
| 877 switch (c) { | |
| 878 case ' ': | |
| 879 case ',': | |
| 880 case '(': | |
| 881 case ')': | |
| 882 case '\0': | |
| 883 case '\n': | |
| 884 case '<': | |
| 885 case '>': | |
| 886 case '"': | |
| 887 case '\'': | |
| 888 return 1; | |
| 889 default: | |
| 890 return 0; | |
| 891 } | |
| 892 } | |
| 893 | |
| 1389 char * | 894 char * |
| 1390 gaim_markup_linkify(const char *text) | 895 gaim_markup_linkify(const char *text) |
| 1391 { | 896 { |
| 1392 const char *c, *t, *q = NULL; | 897 const char *c, *t, *q = NULL; |
| 1393 char *tmp; | 898 char *tmp; |
| 1593 tmp = ret->str; | 1098 tmp = ret->str; |
| 1594 g_string_free(ret, FALSE); | 1099 g_string_free(ret, FALSE); |
| 1595 return tmp; | 1100 return tmp; |
| 1596 } | 1101 } |
| 1597 | 1102 |
| 1103 | |
| 1104 /************************************************************************** | |
| 1105 * Path/Filename Functions | |
| 1106 **************************************************************************/ | |
| 1107 const char * | |
| 1108 gaim_home_dir(void) | |
| 1109 { | |
| 1110 #ifndef _WIN32 | |
| 1111 if(g_get_home_dir()) | |
| 1112 return g_get_home_dir(); | |
| 1113 else | |
| 1114 return NULL; | |
| 1115 #else | |
| 1116 return wgaim_data_dir(); | |
| 1117 #endif | |
| 1118 } | |
| 1119 | |
| 1120 /* returns a string of the form ~/.gaim, where ~ is replaced by the user's home | |
| 1121 * dir. Note that there is no trailing slash after .gaim. */ | |
| 1122 char * | |
| 1123 gaim_user_dir(void) | |
| 1124 { | |
| 1125 const gchar *hd = gaim_home_dir(); | |
| 1126 | |
| 1127 if(hd) | |
| 1128 { | |
| 1129 strcpy( (char*)&home_dir, hd ); | |
| 1130 strcat( (char*)&home_dir, G_DIR_SEPARATOR_S ".gaim" ); | |
| 1131 | |
| 1132 return (gchar*)&home_dir; | |
| 1133 } | |
| 1134 | |
| 1135 return NULL; | |
| 1136 } | |
| 1137 | |
| 1138 /* | |
| 1139 * Like mkstemp() but returns a file pointer, uses a pre-set template, | |
| 1140 * uses the semantics of tempnam() for the directory to use and allocates | |
| 1141 * the space for the filepath. | |
| 1142 * | |
| 1143 * Caller is responsible for closing the file and removing it when done, | |
| 1144 * as well as freeing the space pointed-to by "path" with g_free(). | |
| 1145 * | |
| 1146 * Returns NULL on failure and cleans up after itself if so. | |
| 1147 */ | |
| 1148 static const char *gaim_mkstemp_templ = {"gaimXXXXXX"}; | |
| 1149 | |
| 1150 FILE * | |
| 1151 gaim_mkstemp(char **fpath) | |
| 1152 { | |
| 1153 const gchar *tmpdir; | |
| 1154 #ifndef _WIN32 | |
| 1155 int fd; | |
| 1156 #endif | |
| 1157 FILE *fp = NULL; | |
| 1158 | |
| 1159 g_return_val_if_fail(fpath != NULL, NULL); | |
| 1160 | |
| 1161 if((tmpdir = (gchar*)g_get_tmp_dir()) != NULL) { | |
| 1162 if((*fpath = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s", tmpdir, gaim_mkstemp_templ)) != NULL) { | |
| 1163 #ifdef _WIN32 | |
| 1164 char* result = _mktemp( *fpath ); | |
| 1165 if( result == NULL ) | |
| 1166 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 1167 "Problem creating the template\n"); | |
| 1168 else | |
| 1169 { | |
| 1170 if( (fp = fopen( result, "w+" )) == NULL ) { | |
| 1171 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 1172 "Couldn't fopen() %s\n", result); | |
| 1173 } | |
| 1174 } | |
| 1175 #else | |
| 1176 if((fd = mkstemp(*fpath)) == -1) { | |
| 1177 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 1178 "Couldn't make \"%s\", error: %d\n", | |
| 1179 *fpath, errno); | |
| 1180 } else { | |
| 1181 if((fp = fdopen(fd, "r+")) == NULL) { | |
| 1182 close(fd); | |
| 1183 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 1184 "Couldn't fdopen(), error: %d\n", errno); | |
| 1185 } | |
| 1186 } | |
| 1187 #endif | |
| 1188 if(!fp) { | |
| 1189 g_free(*fpath); | |
| 1190 *fpath = NULL; | |
| 1191 } | |
| 1192 } | |
| 1193 } else { | |
| 1194 gaim_debug(GAIM_DEBUG_ERROR, "gaim_mkstemp", | |
| 1195 "g_get_tmp_dir() failed!"); | |
| 1196 } | |
| 1197 | |
| 1198 return fp; | |
| 1199 } | |
| 1200 | |
| 1201 gboolean | |
| 1202 gaim_program_is_valid(const char *program) | |
| 1203 { | |
| 1204 GError *error = NULL; | |
| 1205 char **argv; | |
| 1206 gchar *progname; | |
| 1207 gboolean is_valid = FALSE; | |
| 1208 | |
| 1209 g_return_val_if_fail(program != NULL, FALSE); | |
| 1210 g_return_val_if_fail(*program != '\0', FALSE); | |
| 1211 | |
| 1212 if (!g_shell_parse_argv(program, NULL, &argv, &error)) { | |
| 1213 gaim_debug(GAIM_DEBUG_ERROR, "program_is_valid", | |
| 1214 "Could not parse program '%s': %s\n", | |
| 1215 program, error->message); | |
| 1216 g_error_free(error); | |
| 1217 return FALSE; | |
| 1218 } | |
| 1219 | |
| 1220 if (argv == NULL) { | |
| 1221 return FALSE; | |
| 1222 } | |
| 1223 | |
| 1224 progname = g_find_program_in_path(argv[0]); | |
| 1225 is_valid = (progname != NULL); | |
| 1226 | |
| 1227 g_strfreev(argv); | |
| 1228 g_free(progname); | |
| 1229 | |
| 1230 return is_valid; | |
| 1231 } | |
| 1232 | |
| 1233 char * | |
| 1234 gaim_fd_get_ip(int fd) | |
| 1235 { | |
| 1236 struct sockaddr addr; | |
| 1237 socklen_t namelen = sizeof(addr); | |
| 1238 | |
| 1239 g_return_val_if_fail(fd != 0, NULL); | |
| 1240 | |
| 1241 if (getsockname(fd, &addr, &namelen)) | |
| 1242 return NULL; | |
| 1243 | |
| 1244 return g_strdup(inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr)); | |
| 1245 } | |
| 1246 | |
| 1247 | |
| 1248 /************************************************************************** | |
| 1249 * String Functions | |
| 1250 **************************************************************************/ | |
| 1251 char * | |
| 1252 gaim_normalize(const char *s) | |
| 1253 { | |
| 1254 static char buf[BUF_LEN]; | |
| 1255 char *tmp; | |
| 1256 int i, j; | |
| 1257 | |
| 1258 g_return_val_if_fail(s != NULL, NULL); | |
| 1259 | |
| 1260 strncpy(buf, s, BUF_LEN); | |
| 1261 for (i=0, j=0; buf[j]; i++, j++) { | |
| 1262 while (buf[j] == ' ') | |
| 1263 j++; | |
| 1264 buf[i] = buf[j]; | |
| 1265 } | |
| 1266 buf[i] = '\0'; | |
| 1267 | |
| 1268 tmp = g_utf8_strdown(buf, -1); | |
| 1269 g_snprintf(buf, sizeof(buf), "%s", tmp); | |
| 1270 g_free(tmp); | |
| 1271 tmp = g_utf8_normalize(buf, -1, G_NORMALIZE_DEFAULT); | |
| 1272 g_snprintf(buf, sizeof(buf), "%s", tmp); | |
| 1273 g_free(tmp); | |
| 1274 | |
| 1275 return buf; | |
| 1276 } | |
| 1277 | |
| 1278 /* Look for %n, %d, or %t in msg, and replace with the sender's name, date, | |
| 1279 or time */ | |
| 1280 char * | |
| 1281 gaim_str_sub_away_formatters(const char *msg, const char *name) | |
| 1282 { | |
| 1283 char *c; | |
| 1284 static char cpy[BUF_LONG]; | |
| 1285 int cnt = 0; | |
| 1286 time_t t; | |
| 1287 struct tm *tme; | |
| 1288 char tmp[20]; | |
| 1289 | |
| 1290 g_return_val_if_fail(msg != NULL, NULL); | |
| 1291 g_return_val_if_fail(name != NULL, NULL); | |
| 1292 | |
| 1293 t = time(NULL); | |
| 1294 tme = localtime(&t); | |
| 1295 | |
| 1296 cpy[0] = '\0'; | |
| 1297 c = (char *)msg; | |
| 1298 while (*c) { | |
| 1299 switch (*c) { | |
| 1300 case '%': | |
| 1301 if (*(c + 1)) { | |
| 1302 switch (*(c + 1)) { | |
| 1303 case 'n': | |
| 1304 /* append name */ | |
| 1305 strcpy(cpy + cnt, name); | |
| 1306 cnt += strlen(name); | |
| 1307 c++; | |
| 1308 break; | |
| 1309 case 'd': | |
| 1310 /* append date */ | |
| 1311 strftime(tmp, 20, "%m/%d/%Y", tme); | |
| 1312 strcpy(cpy + cnt, tmp); | |
| 1313 cnt += strlen(tmp); | |
| 1314 c++; | |
| 1315 break; | |
| 1316 case 't': | |
| 1317 /* append time */ | |
| 1318 strftime(tmp, 20, "%r", tme); | |
| 1319 strcpy(cpy + cnt, tmp); | |
| 1320 cnt += strlen(tmp); | |
| 1321 c++; | |
| 1322 break; | |
| 1323 default: | |
| 1324 cpy[cnt++] = *c; | |
| 1325 } | |
| 1326 } | |
| 1327 break; | |
| 1328 default: | |
| 1329 cpy[cnt++] = *c; | |
| 1330 } | |
| 1331 c++; | |
| 1332 } | |
| 1333 cpy[cnt] = '\0'; | |
| 1334 return (cpy); | |
| 1335 } | |
| 1336 | |
| 1337 /* | |
| 1338 * rcg10312000 This could be more robust, but it works for my current | |
| 1339 * goal: to remove those annoying <BR> tags. :) | |
| 1340 * dtf12162000 made the loop more readable. i am a neat freak. ;) */ | |
| 1341 void | |
| 1342 gaim_strncpy_nohtml(char *dest, const char *src, size_t destsize) | |
| 1343 { | |
| 1344 char *ptr; | |
| 1345 | |
| 1346 g_return_if_fail(dest != NULL); | |
| 1347 g_return_if_fail(src != NULL); | |
| 1348 g_return_if_fail(destsize > 0); | |
| 1349 | |
| 1350 g_snprintf(dest, destsize, "%s", src); | |
| 1351 | |
| 1352 while ((ptr = strstr(dest, "<BR>")) != NULL) { | |
| 1353 /* replace <BR> with a newline. */ | |
| 1354 *ptr = '\n'; | |
| 1355 memmove(ptr + 1, ptr + 4, strlen(ptr + 4) + 1); | |
| 1356 } | |
| 1357 } | |
| 1358 | |
| 1359 void | |
| 1360 gaim_strncpy_withhtml(gchar *dest, const gchar *src, size_t destsize) | |
| 1361 { | |
| 1362 gchar *end; | |
| 1363 | |
| 1364 g_return_if_fail(dest != NULL); | |
| 1365 g_return_if_fail(src != NULL); | |
| 1366 g_return_if_fail(destsize > 0); | |
| 1367 | |
| 1368 end = dest + destsize; | |
| 1369 | |
| 1370 while (dest < end) { | |
| 1371 if (*src == '\n' && dest < end - 5) { | |
| 1372 strcpy(dest, "<BR>"); | |
| 1373 src++; | |
| 1374 dest += 4; | |
| 1375 } else if(*src == '\r') { | |
| 1376 src++; | |
| 1377 } else { | |
| 1378 *dest++ = *src; | |
| 1379 if (*src == '\0') | |
| 1380 return; | |
| 1381 else | |
| 1382 src++; | |
| 1383 } | |
| 1384 } | |
| 1385 } | |
| 1386 | |
| 1387 /* | |
| 1388 * Like strncpy_withhtml (above), but malloc()'s the necessary space | |
| 1389 * | |
| 1390 * The caller is responsible for freeing the space pointed to by the | |
| 1391 * return value. | |
| 1392 */ | |
| 1393 char * | |
| 1394 gaim_strdup_withhtml(const char *src) | |
| 1395 { | |
| 1396 char *sp, *dest; | |
| 1397 gulong destsize; | |
| 1398 | |
| 1399 g_return_val_if_fail(src != NULL, NULL); | |
| 1400 | |
| 1401 /* | |
| 1402 * All we need do is multiply the number of newlines by 3 (the | |
| 1403 * additional length of "<BR>" over "\n"), account for the | |
| 1404 * terminator, malloc the space and call strncpy_withhtml. | |
| 1405 */ | |
| 1406 for(destsize = 0, sp = (gchar *)src; | |
| 1407 (sp = strchr(sp, '\n')) != NULL; | |
| 1408 ++sp, ++destsize) | |
| 1409 ; | |
| 1410 | |
| 1411 destsize *= 3; | |
| 1412 destsize += strlen(src) + 1; | |
| 1413 dest = g_malloc(destsize); | |
| 1414 gaim_strncpy_withhtml(dest, src, destsize); | |
| 1415 | |
| 1416 return dest; | |
| 1417 } | |
| 1418 | |
| 1419 char * | |
| 1420 gaim_str_add_cr(const char *text) | |
| 1421 { | |
| 1422 char *ret = NULL; | |
| 1423 int count = 0, i, j; | |
| 1424 | |
| 1425 g_return_val_if_fail(text != NULL, NULL); | |
| 1426 | |
| 1427 if (text[0] == '\n') | |
| 1428 count++; | |
| 1429 for (i = 1; i < strlen(text); i++) | |
| 1430 if (text[i] == '\n' && text[i - 1] != '\r') | |
| 1431 count++; | |
| 1432 | |
| 1433 if (count == 0) | |
| 1434 return g_strdup(text); | |
| 1435 | |
| 1436 ret = g_malloc0(strlen(text) + count + 1); | |
| 1437 | |
| 1438 i = 0; j = 0; | |
| 1439 if (text[i] == '\n') | |
| 1440 ret[j++] = '\r'; | |
| 1441 ret[j++] = text[i++]; | |
| 1442 for (; i < strlen(text); i++) { | |
| 1443 if (text[i] == '\n' && text[i - 1] != '\r') | |
| 1444 ret[j++] = '\r'; | |
| 1445 ret[j++] = text[i]; | |
| 1446 } | |
| 1447 | |
| 1448 gaim_debug_misc("gaim_str_add_cr", "got: %s, leaving with %s\n", | |
| 1449 text, ret); | |
| 1450 | |
| 1451 return ret; | |
| 1452 } | |
| 1453 | |
| 1454 void | |
| 1455 gaim_str_strip_linefeed(char *text) | |
| 1456 { | |
| 1457 int i, j; | |
| 1458 char *text2; | |
| 1459 | |
| 1460 g_return_if_fail(text != NULL); | |
| 1461 | |
| 1462 text2 = g_malloc(strlen(text) + 1); | |
| 1463 | |
| 1464 for (i = 0, j = 0; text[i]; i++) | |
| 1465 if (text[i] != '\r') | |
| 1466 text2[j++] = text[i]; | |
| 1467 text2[j] = '\0'; | |
| 1468 | |
| 1469 strcpy(text, text2); | |
| 1470 g_free(text2); | |
| 1471 } | |
| 1472 | |
| 1473 char * | |
| 1474 gaim_strreplace(const char *string, const char *delimiter, | |
| 1475 const char *replacement) | |
| 1476 { | |
| 1477 gchar **split; | |
| 1478 gchar *ret; | |
| 1479 | |
| 1480 g_return_val_if_fail(string != NULL, NULL); | |
| 1481 g_return_val_if_fail(delimiter != NULL, NULL); | |
| 1482 g_return_val_if_fail(replacement != NULL, NULL); | |
| 1483 | |
| 1484 split = g_strsplit(string, delimiter, 0); | |
| 1485 ret = g_strjoinv(replacement, split); | |
| 1486 g_strfreev(split); | |
| 1487 | |
| 1488 return ret; | |
| 1489 } | |
| 1490 | |
| 1491 const char * | |
| 1492 gaim_strcasestr(const char *haystack, const char *needle) | |
| 1493 { | |
| 1494 size_t hlen, nlen; | |
| 1495 const char *tmp, *ret; | |
| 1496 | |
| 1497 g_return_val_if_fail(haystack != NULL, NULL); | |
| 1498 g_return_val_if_fail(needle != NULL, NULL); | |
| 1499 | |
| 1500 hlen = strlen(haystack); | |
| 1501 nlen = strlen(needle); | |
| 1502 tmp = haystack, | |
| 1503 ret = NULL; | |
| 1504 | |
| 1505 g_return_val_if_fail(hlen > 0, NULL); | |
| 1506 g_return_val_if_fail(nlen > 0, NULL); | |
| 1507 | |
| 1508 while (*tmp && !ret) { | |
| 1509 if (!g_ascii_strncasecmp(needle, tmp, nlen)) | |
| 1510 ret = tmp; | |
| 1511 else | |
| 1512 tmp++; | |
| 1513 } | |
| 1514 | |
| 1515 return ret; | |
| 1516 } | |
| 1517 | |
| 1518 char * | |
| 1519 gaim_str_size_to_units(size_t size) | |
| 1520 { | |
| 1521 static const char *size_str[4] = { "bytes", "KB", "MB", "GB" }; | |
| 1522 float size_mag; | |
| 1523 int size_index = 0; | |
| 1524 | |
| 1525 if (size == -1) { | |
| 1526 return g_strdup(_("Calculating...")); | |
| 1527 } | |
| 1528 else if (size == 0) { | |
| 1529 return g_strdup(_("Unknown.")); | |
| 1530 } | |
| 1531 else { | |
| 1532 size_mag = (float)size; | |
| 1533 | |
| 1534 while ((size_index < 4) && (size_mag > 1024)) { | |
| 1535 size_mag /= 1024; | |
| 1536 size_index++; | |
| 1537 } | |
| 1538 | |
| 1539 return g_strdup_printf("%.2f %s", size_mag, size_str[size_index]); | |
| 1540 } | |
| 1541 } | |
| 1542 | |
| 1543 char * | |
| 1544 gaim_str_seconds_to_string(guint sec) | |
| 1545 { | |
| 1546 guint daze, hrs, min; | |
| 1547 char *ret = NULL; | |
| 1548 | |
| 1549 daze = sec / (60 * 60 * 24); | |
| 1550 hrs = (sec % (60 * 60 * 24)) / (60 * 60); | |
| 1551 min = (sec % (60 * 60)) / 60; | |
| 1552 sec = min % 60; | |
| 1553 | |
| 1554 if (daze) { | |
| 1555 if (hrs || min) { | |
| 1556 if (hrs) { | |
| 1557 if (min) { | |
| 1558 ret = g_strdup_printf( | |
| 1559 "%d %s, %d %s, %d %s.", | |
| 1560 daze, ngettext("day","days",daze), | |
| 1561 hrs, ngettext("hour","hours",hrs), min, ngettext("minute","minutes",min)); | |
| 1562 } else { | |
| 1563 ret = g_strdup_printf( | |
| 1564 "%d %s, %d %s.", | |
| 1565 daze, ngettext("day","days",daze), hrs, ngettext("hour","hours",hrs)); | |
| 1566 } | |
| 1567 } else { | |
| 1568 ret = g_strdup_printf( | |
| 1569 "%d %s, %d %s.", | |
| 1570 daze, ngettext("day","days",daze), min, ngettext("minute","minutes",min)); | |
| 1571 } | |
| 1572 } else | |
| 1573 ret = g_strdup_printf("%d %s.", daze, ngettext("day","days",daze)); | |
| 1574 } else { | |
| 1575 if (hrs) { | |
| 1576 if (min) { | |
| 1577 ret = g_strdup_printf( | |
| 1578 "%d %s, %d %s.", | |
| 1579 hrs, ngettext("hour","hours",hrs), min, ngettext("minute","minutes",min)); | |
| 1580 } else { | |
| 1581 ret = g_strdup_printf("%d %s.", hrs, ngettext("hour","hours",hrs)); | |
| 1582 } | |
| 1583 } else { | |
| 1584 ret = g_strdup_printf("%d %s.", min, ngettext("minute","minutes",min)); | |
| 1585 } | |
| 1586 } | |
| 1587 | |
| 1588 return ret; | |
| 1589 } | |
| 1590 | |
| 1591 /************************************************************************** | |
| 1592 * URI/URL Functions | |
| 1593 **************************************************************************/ | |
| 1598 gboolean | 1594 gboolean |
| 1599 gaim_url_parse(const char *url, char **ret_host, int *ret_port, | 1595 gaim_url_parse(const char *url, char **ret_host, int *ret_port, |
| 1600 char **ret_path) | 1596 char **ret_path) |
| 1601 { | 1597 { |
| 1602 char scan_info[255]; | 1598 char scan_info[255]; |
| 1918 destroy_fetch_url_data(gfud); | 1914 destroy_fetch_url_data(gfud); |
| 1919 | 1915 |
| 1920 cb(user_data, g_strdup(_("g003: Error opening connection.\n")), 0); | 1916 cb(user_data, g_strdup(_("g003: Error opening connection.\n")), 0); |
| 1921 } | 1917 } |
| 1922 } | 1918 } |
| 1919 | |
| 1920 | |
| 1921 /************************************************************************** | |
| 1922 * UTF8 String Functions | |
| 1923 **************************************************************************/ | |
| 1924 char * | |
| 1925 gaim_utf8_try_convert(const char *str) | |
| 1926 { | |
| 1927 gsize converted; | |
| 1928 char *utf8; | |
| 1929 | |
| 1930 g_return_val_if_fail(str != NULL, NULL); | |
| 1931 | |
| 1932 if (g_utf8_validate(str, -1, NULL)) { | |
| 1933 return g_strdup(str); | |
| 1934 } | |
| 1935 | |
| 1936 utf8 = g_locale_to_utf8(str, -1, &converted, NULL, NULL); | |
| 1937 if (utf8) | |
| 1938 return(utf8); | |
| 1939 | |
| 1940 g_free(utf8); | |
| 1941 | |
| 1942 utf8 = g_convert(str, -1, "UTF-8", "ISO-8859-15", &converted, NULL, NULL); | |
| 1943 if (utf8 && converted == strlen (str)) { | |
| 1944 return(utf8); | |
| 1945 } else if (utf8) { | |
| 1946 g_free(utf8); | |
| 1947 } | |
| 1948 | |
| 1949 return(NULL); | |
| 1950 } | |
| 1951 | |
| 1952 int | |
| 1953 gaim_utf8_strcasecmp(const char *a, const char *b) | |
| 1954 { | |
| 1955 char *a_norm = NULL; | |
| 1956 char *b_norm = NULL; | |
| 1957 int ret = -1; | |
| 1958 | |
| 1959 if(!a && b) | |
| 1960 return -1; | |
| 1961 else if(!b && a) | |
| 1962 return 1; | |
| 1963 else if(!a && !b) | |
| 1964 return 0; | |
| 1965 | |
| 1966 if(!g_utf8_validate(a, -1, NULL) || !g_utf8_validate(b, -1, NULL)) | |
| 1967 { | |
| 1968 gaim_debug_error("gaim_utf8_strcasecmp", | |
| 1969 "One or both parameters are invalid UTF8\n"); | |
| 1970 return ret; | |
| 1971 } | |
| 1972 | |
| 1973 a_norm = g_utf8_casefold(a, -1); | |
| 1974 b_norm = g_utf8_casefold(b, -1); | |
| 1975 ret = g_utf8_collate(a_norm, b_norm); | |
| 1976 g_free(a_norm); | |
| 1977 g_free(b_norm); | |
| 1978 | |
| 1979 return ret; | |
| 1980 } |
