Mercurial > ~mikael > mcabber > hg
comparison mcabber/src/utils.c @ 1639:d9913c1b35e7
Add support for libidn
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 25 Oct 2009 23:25:14 +0100 |
parents | 9ca672ee884f |
children | bf2258e29834 |
comparison
equal
deleted
inserted
replaced
1638:3b3b5c1f8327 | 1639:d9913c1b35e7 |
---|---|
19 * along with this program; if not, write to the Free Software | 19 * along with this program; if not, write to the Free Software |
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 |
21 * USA | 21 * USA |
22 */ | 22 */ |
23 | 23 |
24 #include <config.h> | |
25 | |
24 #include <stdio.h> | 26 #include <stdio.h> |
25 #include <stdlib.h> | 27 #include <stdlib.h> |
26 #include <string.h> | 28 #include <string.h> |
27 #include <stdarg.h> | 29 #include <stdarg.h> |
28 | 30 |
31 #ifdef HAVE_LIBIDN | |
32 #include <idna.h> | |
33 #include <stringprep.h> | |
34 static char idnprep[1024]; | |
35 #endif | |
36 | |
37 #include <glib.h> | |
29 #include <glib/gprintf.h> | 38 #include <glib/gprintf.h> |
30 | 39 |
31 /* For Cygwin (thanks go to Yitzchak Scott-Thoennes) */ | 40 /* For Cygwin (thanks go to Yitzchak Scott-Thoennes) */ |
32 #ifdef __CYGWIN__ | 41 #ifdef __CYGWIN__ |
33 # define timezonevar | 42 # define timezonevar |
36 #include <time.h> | 45 #include <time.h> |
37 #include <unistd.h> | 46 #include <unistd.h> |
38 #include <sys/types.h> | 47 #include <sys/types.h> |
39 #include <sys/stat.h> | 48 #include <sys/stat.h> |
40 #include <ctype.h> | 49 #include <ctype.h> |
41 #include <glib.h> | 50 |
42 | |
43 #include <config.h> | |
44 #include "utils.h" | 51 #include "utils.h" |
45 #include "logprint.h" | 52 #include "logprint.h" |
46 | 53 |
47 static int DebugEnabled; | 54 static int DebugEnabled; |
48 static char *FName; | 55 static char *FName; |
400 int check_jid_syntax(const char *fjid) | 407 int check_jid_syntax(const char *fjid) |
401 { | 408 { |
402 const char *str; | 409 const char *str; |
403 const char *domain, *resource; | 410 const char *domain, *resource; |
404 int domlen; | 411 int domlen; |
412 #ifdef HAVE_LIBIDN | |
413 char *idnpp, *ascidnp; | |
414 int r; | |
415 #endif | |
405 | 416 |
406 if (!fjid) return 1; | 417 if (!fjid) return 1; |
407 | 418 |
408 domain = strchr(fjid, JID_DOMAIN_SEPARATOR); | 419 domain = strchr(fjid, JID_DOMAIN_SEPARATOR); |
409 | 420 |
414 /* node identifiers may not be longer than 1023 bytes */ | 425 /* node identifiers may not be longer than 1023 bytes */ |
415 if ((domain == fjid) || (domain-fjid > 1023)) | 426 if ((domain == fjid) || (domain-fjid > 1023)) |
416 return 1; | 427 return 1; |
417 domain++; | 428 domain++; |
418 | 429 |
430 #ifdef HAVE_LIBIDN | |
431 idnpp = idnprep; | |
432 str = fjid; | |
433 while (*str != JID_DOMAIN_SEPARATOR) | |
434 *idnpp++ = *str++; | |
435 *idnpp = 0; | |
436 | |
437 r = stringprep(idnprep, 1023, 0, stringprep_xmpp_nodeprep); | |
438 if (r != STRINGPREP_OK || !idnprep[0]) | |
439 return 1; | |
440 | |
441 // check the string hasn't been modified, in which case we consider | |
442 // it's a failure (as fjid is read-only) | |
443 idnpp = idnprep; | |
444 str = fjid; | |
445 while (*idnpp) { | |
446 if (*idnpp++ != *str++) | |
447 return 1; | |
448 } | |
449 scr_LogPrint(LPRINT_LOGNORM, "Stringprep'd node: [%s]", idnprep); // XXX | |
450 /* the username looks okay */ | |
451 #else | |
419 /* check for low and invalid ascii characters in the username */ | 452 /* check for low and invalid ascii characters in the username */ |
420 for (str = fjid; *str != JID_DOMAIN_SEPARATOR; str++) { | 453 for (str = fjid; *str != JID_DOMAIN_SEPARATOR; str++) { |
421 if (*str <= ' ' || *str == ':' || *str == JID_DOMAIN_SEPARATOR || | 454 if (*str <= ' ' || *str == ':' || *str == JID_DOMAIN_SEPARATOR || |
422 *str == '<' || *str == '>' || *str == '\'' || | 455 *str == '<' || *str == '>' || *str == '\'' || |
423 *str == '"' || *str == '&') { | 456 *str == '"' || *str == '&') { |
424 return 1; | 457 return 1; |
425 } | 458 } |
426 } | 459 } |
427 /* the username is okay as far as we can tell without LIBIDN */ | 460 /* the username is okay as far as we can tell without LIBIDN */ |
461 #endif | |
428 } | 462 } |
429 | 463 |
430 resource = strchr(domain, JID_RESOURCE_SEPARATOR); | 464 resource = strchr(domain, JID_RESOURCE_SEPARATOR); |
431 | 465 |
432 /* the resource is optional */ | 466 /* the resource is optional */ |
434 domlen = resource - domain; | 468 domlen = resource - domain; |
435 resource++; | 469 resource++; |
436 /* resources may not be longer than 1023 bytes */ | 470 /* resources may not be longer than 1023 bytes */ |
437 if ((*resource == '\0') || strlen(resource) > 1023) | 471 if ((*resource == '\0') || strlen(resource) > 1023) |
438 return 1; | 472 return 1; |
473 #ifdef HAVE_LIBIDN | |
474 strncpy(idnprep, resource, sizeof(idnprep)); | |
475 r = stringprep(idnprep, 1023, 0, stringprep_xmpp_resourceprep); | |
476 if (r != STRINGPREP_OK || !idnprep[0]) | |
477 return 1; | |
478 #endif | |
439 } else { | 479 } else { |
440 domlen = strlen(domain); | 480 domlen = strlen(domain); |
441 } | 481 } |
442 | 482 |
443 /* there must be a domain identifier */ | 483 /* there must be a domain identifier */ |
444 if (domlen == 0) return 1; | 484 if (domlen == 0) return 1; |
445 | 485 |
446 /* and it must not be longer than 1023 bytes */ | 486 /* and it must not be longer than 1023 bytes */ |
447 if (domlen > 1023) return 1; | 487 if (domlen > 1023) return 1; |
448 | 488 |
489 #ifdef HAVE_LIBIDN | |
490 idnpp = idnprep; | |
491 str = domain; | |
492 while (*str != '\0' && *str != JID_RESOURCE_SEPARATOR) | |
493 *idnpp++ = *str++; | |
494 *idnpp = 0; | |
495 | |
496 r = stringprep_nameprep(idnprep, 1023); | |
497 if (r != STRINGPREP_OK || !idnprep[0]) | |
498 return 1; | |
499 | |
500 if (idna_to_ascii_8z(idnprep, &ascidnp, IDNA_USE_STD3_ASCII_RULES) != | |
501 IDNA_SUCCESS) | |
502 return 1; | |
503 else | |
504 free(ascidnp); | |
505 | |
506 // check the string hasn't been modified, in which case we consider | |
507 // it's a failure (as fjid is read-only) | |
508 idnpp = idnprep; | |
509 str = domain; | |
510 while (*idnpp) { | |
511 if (*idnpp++ != *str++) | |
512 return 1; | |
513 } | |
514 #else | |
449 /* make sure the hostname is valid characters */ | 515 /* make sure the hostname is valid characters */ |
450 for (str = domain; *str != '\0' && *str != JID_RESOURCE_SEPARATOR; str++) { | 516 for (str = domain; *str != '\0' && *str != JID_RESOURCE_SEPARATOR; str++) { |
451 if (!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) | 517 if (!(isalnum(*str) || *str == '.' || *str == '-' || *str == '_')) |
452 return 1; | 518 return 1; |
453 } | 519 } |
454 | 520 #endif |
455 /* it's okay as far as we can tell without LIBIDN */ | 521 |
522 /* it's okay as far as we can tell */ | |
456 return 0; | 523 return 0; |
457 } | 524 } |
458 | 525 |
459 | 526 |
460 inline void mc_strtolower(char *str) | 527 inline void mc_strtolower(char *str) |