//
// Split the components of a CGI result string into
//  individual sub strings
//
// For example the string
//   name=Your+name&action=%2B10%25&log=~mas/log
//
// is composed of three named elements:
//
//     Element    String associated with element
//     name       Your name
//     action     +10%
//     log        /usr/staff/mas/log
//
// (C) M.A.Smith University of Brighton
// Permission is granted to use this code
//   provided this declaration and copyright notice remains intact.
// 21 October 1995
//
//
// I m p l e m e n t a t i o n

#ifndef CLASS_PARSE_IMP
#define CLASS_PARSE_IMP

#include "parse.h"

#include <string.h>
#include <ctype.h>
#ifndef NO_MAP
# include <pwd.h>
#endif

Parse::Parse( char list[] )
{
  the_str = NULL;
  set( list );
}

Parse::~Parse()
{
  if ( the_str != NULL ) {          // Release storage
    delete the_str;
  }
}

void Parse::set( char list[] )
{
  if ( the_str != NULL ) {          // Release storage
    delete the_str;
  }
  the_length = strlen( list );      // Length of string
  the_str = new char[the_length+1]; // Allocate area
  strcpy( the_str, list );          // copy to
}

char *Parse::get_item( char name[], int pos, bool file )
{
  int len = strlen( name );
  int cur_tag = 1;
  for( int i=0; i<the_length-len; i++ )
  {
    if ( the_str[i] == name[0]  &&
         strncmp( &the_str[i], name, len ) == 0 )
    {
      if ( the_str[i+len] == '=' )
      {
        if ( cur_tag == pos )
        {
          int start = i+len+1; int j = start;
          while ( the_str[j] != SEP && the_str[j] != '\0' ) j++;
          int str_len = j-start;
          char *mes = new char[ str_len+1 ];
          strncpy( mes, &the_str[start], str_len );
          mes[str_len] = '\0';
          remove_escape( mes );
#         ifndef NO_MAP
          return file ? map_uname(mes) : mes;
#         else
          return file ? mes : mes;
#         endif
        } else {
          cur_tag++;
        }
      }
    }
  }
  return NULL;
}

char *Parse::get_item_n( char name[], int pos, bool file )
{
  char *res = get_item( name, pos, file );
  return res == NULL ? "" : res;
}

void Parse::remove_escape(char str[])
{
  char * from = &str[0];
  char * to   = &str[0];
  while ( *from != '\0' )
  {
    char ch = *from++;
    switch ( ch )
    {
      case '%' :
	ch = (hex(*from++)<<4) | hex(*from++);
        break;
      case '+' :
	ch = ' '; break;
    }
    *to++ = ch;
  }
  *to = '\0';
}

int Parse::hex( char c )
{
  if ( isdigit( c ) )
    return c-'0';
  if ( isalpha( c ) )
    return tolower(c)-'a'+10;
  return 0;
}

char* Parse::map_uname( char *path )
{
#ifndef NO_MAP
  if ( path[0] == '~' )
  {
     char uname[255];                       // Holds user name
     char *rest = &path[1];                 // omit ~ 
     char *p = &uname[0];                   // user

     while ( *rest != '/' && *rest != '\0' )
     {
       *p++ = *rest++;
     }
     *p = '\0';                             // Terminator
     char *root = uname;                    // If fails
     passwd *pw = getpwnam( uname );        // Structure about user
     if ( pw != NULL )
     {
       root = pw->pw_dir;                   // Users home directory
     }
     int len_root = strlen(root);
     int len_path  = len_root + strlen(rest);
     char *new_path = new char[len_path+1]; // Dynamic string

     strcpy( &new_path[0], root );          // abs user path
     strcpy( &new_path[len_root], rest );   // remainder
     return new_path;
  } else {
    return path;
  }
#endif
 return path;
}
#endif
