#include <ctype.h>
#include <mem.h>
#include <string.h>
#include <rtos.h>
#include <net.h>
#include <httpd.h>

#ifdef __DJGPP__
#define movmem(s,d,n)   memmove (d,s,n)
#endif

static BYTE read_hex( char *p )
{
    BYTE x;
    char ch;

    ch = toupper( p[0] );
    x = ( ch - (( ch < 'A' ) ? '0' : 'A' - 10 )) * 0x10;
    ch = toupper( p[1] );
    x |= ( ch - (( ch < 'A' ) ? '0' : 'A' - 10 ));
    return( x );
}


stringlist *cgi_getstrings( tcp_Socket *s )
{
    char *buf, *p, *q, *t, *data;
    stringlist *sl;
    int len;
#define READBUF 8192

    buf = kcalloc( READBUF, 1 );
    if ( buf == NULL )
        return( NULL );

    sock_mode( s, TCP_MODE_ASCII );
    memset( buf, 0, READBUF );
//    sock_fastread( s, buf, READBUF );   /* real data */

    // read until we have a complete string, or the connection is dead
    while ( len = sock_rbused( s ) ) {
        if ( sock_rbleft( s ) == 0 )
            break;
        if ( len >= READBUF )
            break;
        if ( sock_gets( s, buf, READBUF ) > 0 ) break;
        tcp_tick( s );
        rt_yield();
    }

    /* fix up string in various ways */
    /* convert + to spaces */
    while (( q = strchr( buf, '+' )) != NULL )
        *q = ' ';

    /* convert %xx to characters */
    while ( (q = strchr( buf, '%')) != NULL ) {
        *q++ = read_hex( q+1 );
        movmem( q + 2, q, strlen( q + 2 )+1);
    }

    sl = strlst_new();
    if ( sl == NULL ) goto fail;

    /* now parse it */
    p = buf;

    /* skip leading \n and \r */
    do {
        if ( *p == '\n' ) p++;
        else if ( *p == '\r' ) p++;
        else break;
    } while ( 1 );

    /* kill trailing \r or \n */
    rip( p );

    while ( *p != 0 ) {
        data = NULL;
        q = strchr( p, '&');
        if ( q != NULL ) *q = 0;
        t = strchr( p, '=');
        if ( t ) {
            *t++ = 0;
            data = kstrdup( t );
        }
        strlst_adddata( sl, p, data );
        if ( q == NULL ) break;
        p = q + 1;
    }
    kfree( buf );
    return( sl );

fail:
    kfree( buf );
    return( NULL );
}

void cgi_freestrings( stringlist *sl )
{
    char *data, *p;
    void *x;

    p = strlst_getfirst( sl, &x, &data );
    while ( p != NULL ) {
        if ( data != NULL ) kfree( data );
        p = strlst_getnext( sl, &x, &data );
    }
    strlst_freeall( sl );
}
