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)