ldmud-3.3.719/
ldmud-3.3.719/doc/
ldmud-3.3.719/doc/efun.de/
ldmud-3.3.719/doc/efun/
ldmud-3.3.719/doc/man/
ldmud-3.3.719/doc/other/
ldmud-3.3.719/mud/
ldmud-3.3.719/mud/heaven7/
ldmud-3.3.719/mud/lp-245/
ldmud-3.3.719/mud/lp-245/banish/
ldmud-3.3.719/mud/lp-245/doc/
ldmud-3.3.719/mud/lp-245/doc/examples/
ldmud-3.3.719/mud/lp-245/doc/sefun/
ldmud-3.3.719/mud/lp-245/log/
ldmud-3.3.719/mud/lp-245/obj/Go/
ldmud-3.3.719/mud/lp-245/players/lars/
ldmud-3.3.719/mud/lp-245/room/death/
ldmud-3.3.719/mud/lp-245/room/maze1/
ldmud-3.3.719/mud/lp-245/room/sub/
ldmud-3.3.719/mud/lp-245/secure/
ldmud-3.3.719/mud/sticklib/
ldmud-3.3.719/mud/sticklib/src/
ldmud-3.3.719/mudlib/deprecated/
ldmud-3.3.719/mudlib/uni-crasher/
ldmud-3.3.719/pkg/
ldmud-3.3.719/pkg/debugger/
ldmud-3.3.719/pkg/diff/
ldmud-3.3.719/pkg/misc/
ldmud-3.3.719/src/
ldmud-3.3.719/src/autoconf/
ldmud-3.3.719/src/ptmalloc/
ldmud-3.3.719/src/util/
ldmud-3.3.719/src/util/erq/
ldmud-3.3.719/src/util/indent/hosts/next/
ldmud-3.3.719/src/util/xerq/
ldmud-3.3.719/src/util/xerq/lpc/
ldmud-3.3.719/src/util/xerq/lpc/www/
ldmud-3.3.719/test/generic/
ldmud-3.3.719/test/inc/
ldmud-3.3.719/test/t-0000398/
ldmud-3.3.719/test/t-0000548/
ldmud-3.3.719/test/t-030925/
ldmud-3.3.719/test/t-040413/
ldmud-3.3.719/test/t-041124/
ldmud-3.3.719/test/t-language/
/*------------------------------------------------------------------
 * IDNA Efuns.
 *
 *------------------------------------------------------------------
 * This file holds the efuns interfacing with the International
 * Domainname library.
 *
 *   efun: idna_to_ascii()
 *   efun: idna_to_unicode()
 *   efun: idna_stringprep()
 *------------------------------------------------------------------
 */

#include "driver.h"

#ifdef HAS_IDN

#include "pkg-idna.h" 

#include <idna.h>
#include <stringprep.h>
#include <stdlib.h>

#include "typedefs.h"

#include "interpret.h"
#include "mstrings.h"
#include "simulate.h"
#include "xalloc.h"

#include "../mudlib/sys/idn.h"

/*-------------------------------------------------------------------------*/

/*=========================================================================*/

/*                           EFUNS                                         */

/*-------------------------------------------------------------------------*/
svalue_t *
f_idna_to_ascii (svalue_t *sp)

/* EFUN idna_to_ascii()
 *
 *     string idna_to_ascii (string name)
 *
 * Converts string name from utf-8 to idna representation (8z punycode)
 */

{
    char *out = NULL; 
    int rc;

    rc = idna_to_ascii_8z(get_txt(sp->u.str), &out, 0);

    free_svalue(sp);

    if (rc == IDNA_SUCCESS)
    {
        put_c_string(sp, out);
        free(out);
    }
    else
    {
        put_number(sp, -1);
        errorf("idna_to_ascii(): Error %s", idna_strerror(rc));
        /* NOTREACHED */
    }

    return sp;
} /* idna_to_ascii */

/*--------------------------------------------------------------------*/
svalue_t *
f_idna_to_unicode (svalue_t *sp)

/* EFUN idna_to_unicode()
 *
 *     string idna_to_unicode (string input)
 *
 * Converts string input from idna (punycode) to a utf-8 string 
 */
{
    char *out = NULL; 
    int rc;

    rc = idna_to_unicode_8z8z(get_txt(sp->u.str), &out, 0);

    free_svalue(sp);

    if (rc == IDNA_SUCCESS)
    {
        put_c_string(sp, out);
        free(out);
    }
    else
    {
        put_number(sp, -1);
        errorf("idna_to_unicode(): Error %s", idna_strerror(rc));
        /* NOTREACHED */
    }

    return sp;
} /* idna_to_unicode() */

/*--------------------------------------------------------------------*/
svalue_t *
f_idna_stringprep (svalue_t *sp)

/* EFUN idna_stringprep()
 *
 *   string idna_stringprep(string str, int profile, int flags = 0)
 *
 * Prepare the UTF-8 string str according to the stringprep profile
 * see also libidn stringprep(3)
 *
 * profile is one of the stringprep profiles defined in ldmuds idn.h
 * str is assumed to be in utf-8 charset (see convert_charset)
 * flags is one of the stringprep flags defined in LDMud's idn.h .
 */
{
    char *buf;
    size_t size;
    int flags = 0;
    int prof = 0; 
    int ret;
    const Stringprep_profile *profile;
    string_t *s;

    /* Get and check the flags. */
    {
        p_uint argflags = (p_uint)sp->u.number;
        sp--;

        if (argflags > (STRINGPREP_FLAG_MAX << 1)-1
         || argflags & (STRINGPREP_NO_NFKC_FLAG | STRINGPREP_NO_BIDI_FLAG)
           )
        {
            errorf("idna_stringprep(): Unsupported flag value %ld\n", (long)argflags);
            /* NOTREACHED */
            return sp;
        }

        flags = 0;
        if (argflags & STRINGPREP_NO_NFKC_FLAG) flags |= STRINGPREP_NO_NFKC;
        if (argflags & STRINGPREP_NO_BIDI_FLAG) flags |= STRINGPREP_NO_BIDI;
        if (argflags & STRINGPREP_NO_UNASSIGNED_FLAG) flags |= STRINGPREP_NO_UNASSIGNED;
    }

    /* Get and check the profile */
    prof = (int)sp->u.number;
    sp--;

    /* select the profile */
    switch(prof)
    {
    case STRINGPREP_NAMEPREP:
        profile = stringprep_nameprep;
        break;
    case STRINGPREP_SASLPREP:
        profile = stringprep_saslprep;
        break;
    case STRINGPREP_PLAIN:
        profile = stringprep_plain;
        break;
    case STRINGPREP_TRACE:
        profile = stringprep_trace;
        break;
    case STRINGPREP_KERBEROS5:
        profile = stringprep_kerberos5;
        break;
    case STRINGPREP_XMPP_NODEPREP:
        profile = stringprep_xmpp_nodeprep;
        break;
    case STRINGPREP_XMPP_RESOURCEPREP:
        profile = stringprep_xmpp_resourceprep;
        break;
    case STRINGPREP_ISCSI:
        profile = stringprep_iscsi;
        break;
    default:
        /* unknown profile */
        errorf("stringprep(): unknown profile %d.\n", prof);
        break; /* NOTREACHED */
    }

    /* Get the string */
    s = sp->u.str;

    /* this assumes that most strings will pass stringprep unchanged */
    size = mstrsize(s)+1; 
    memsafe(buf = xalloc(size), size, "stringprep buffer");

    memcpy(buf, get_txt(s), mstrsize(s));
    buf[mstrsize(s)] = 0;

    ret = stringprep(buf, size, flags, profile);
    while (ret == STRINGPREP_TOO_SMALL_BUFFER)
    {
        /* Increase the size until it fits. */
        /* TODO: Same pattern as in convert_charset() - make it a utility function?
         */
        size = size > 65536 ? (size + 33) : (2 * size);
        memsafe(buf = rexalloc(buf, size), size, "stringprep buffer");
        ret = stringprep(buf, size, flags, profile);
    }

    if (ret != STRINGPREP_OK)
    {
        errorf("stringprep(): Error %s", stringprep_strerror(ret));
        /* NOTREACHED */
    }
    else 
    {
        // free the string argument
        free_svalue(sp);
        put_c_string(sp, buf);
    }

    return sp;
} /* f_idna_stringprep */

/***************************************************************************/

#endif /* HAS_IDN */