/*
 * Copyright (c) 2001-2003 Shiman Associates Inc. All Rights Reserved.
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use, copy,
 * modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "net_common.h"

#define LFCHAR 10

int32
net_parse_authmsg( char *payload, int len, char **arg, struct mas_package *infopack, char **version )
{
    int i;
    char *info_block = NULL;
    int info_block_len = 0;
    char *vp = NULL;
    char *ap = NULL;

    /* authmsg looks like this:
       MAS 1.2.3 [arg]
       ... some information ...

       1. 1, 2, and 3 are major, minor, teeny version numbers.
       2. [arg] is "OK", or "CONTROL", or "DATA", (without quotes)
          if everything is hunky-dory.  Otherwise, fail. 
       3. A linefeed character (ASCII 10) breaks the line.
       4. The "some information" is a free-form package and subject
          to change. 
       5, This is not a substitute for an authentication scheme.  But,
          it is all we have for now. */
    
    /* find the first line feed */
    for (i=0; i<len && payload[i] != LFCHAR; )
        i++;

    /* i is now ON the line feed, or one char past the end of the
       string. */
    if ( len - i > 0 )
    {
        /* i is within the string.  mark the start of the info block
           just after the line feed. */
        info_block = &(payload[i+1]);
        info_block_len = len - i - 1;
    }
    else
    {
        /* did we even find a linefeed? */
        if ( payload[i] != LFCHAR )
            return mas_error(MERR_INVALID);

        /* Yes, but there's no info section */
    }

    /* Create a string starting at payload, with the terminator where
       the LF was. */
    payload[i] = 0;
    
    /* and trim any whitespace, just to be sure */
    masc_trim_string( payload );

    /* Look for the first space char from the end of the string.
     * Between there and the end is arg.  Copy it.*/
    for ( i = strlen( payload ) - 1; i > 0 && payload[i] != ' '; )
        i--;
    if ( i != 0 && payload[i] == ' ' )
    {
        ap = &(payload[i + 1]);
        *arg = masc_rtalloc( strlen( ap ) + 1 );
        if ( *arg == NULL ) return mas_error(MERR_MEMORY);
        memcpy( *arg, ap, strlen( ap ) + 1 );
    }
    
    /* skip over "MAS ", terminate the string at the whitespace prior
     * to the arg, then copy the result into *version. */
    vp = &(payload[4]);
    payload[i] = 0;
    masc_trim_string( vp );
    *version = masc_rtalloc( strlen(vp) + 1 );
    if ( *version == NULL ) return mas_error(MERR_MEMORY);
    memcpy( *version, vp, strlen(vp) + 1 );

    /* If there is an info section, alloc the info package from it. */
    if ( info_block_len > 0 )
    {
        infopack->contents = masc_rtalloc( info_block_len );
        if ( infopack->contents == NULL )
            return mas_error(MERR_MEMORY);
        memcpy( infopack->contents, info_block, info_block_len );
        masc_setup_package( infopack, infopack->contents, info_block_len, MASC_PACKAGE_EXTRACT );
    }

    return 0;
}

int32
net_create_authmsg( char *version, char *arg, struct mas_package *infopack, char **authmsg_retval, int *authmsg_len )
{
    char ident[2048];
    int len;

    snprintf(ident, sizeof ident, "MAS %s %s%c", version, arg, LFCHAR );
    if ( infopack )
    {
        len = strlen(ident) + infopack->size;
    }
    else
    {
        len = strlen(ident); /* no terminator */
    }
    
    *authmsg_retval = masc_rtalloc( len );
    memcpy( *authmsg_retval, ident, strlen(ident) );
    if ( infopack )
        memcpy( *authmsg_retval + strlen(ident), infopack->contents, infopack->size );
    
    *authmsg_len = len;
    
    return 0;
}
