/*************************************************************************
 * Ralink Tech Inc.                                                      *
 * 4F, No. 2 Technology 5th Rd.                                          *
 * Science-based Industrial Park                                         *
 * Hsin-chu, Taiwan, R.O.C.                                              *
 *                                                                       *
 * (c) Copyright 2002, Ralink Technology, Inc.                           *
 *                                                                       *
 * This program is free software; you can redistribute it and/or modify  * 
 * it under the terms of the GNU General Public License as published by  * 
 * the Free Software Foundation; either version 2 of the License, or     * 
 * (at your option) any later version.                                   * 
 *                                                                       * 
 * This program is distributed in the hope that it will be useful,       * 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        * 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         * 
 * GNU General Public License for more details.                          * 
 *                                                                       * 
 * You should have received a copy of the GNU General Public License     * 
 * along with this program; if not, write to the                         * 
 * Free Software Foundation, Inc.,                                       * 
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             * 
 *                                                                       * 
 *************************************************************************

    Module Name:
    configapi.cpp

    Abstract:
        Implement getkeystring / writekeystring like windows API.

    Revision History:
    Who            When          What
    --------    ----------      ----------------------------------------------
    Paul Wu     01-22-2003      created

*/

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

#include "configapi.h"

int isfound(char *ptr, char *ini_buffer)
{
    if(ptr == ini_buffer)
        return (1);
    else if(ptr>ini_buffer)
    {
        while(ptr > ini_buffer)
        {
            ptr--;

            if(*ptr == 0x0a)
                return (1);
            else if( (*ptr == ' ') || (*ptr == '\t'))
                continue;
            else
                return (0);
        }
        return (1);
    }
    return (0);
}

char *find_header(char *ini_buffer, char *header_name)
{
    char temp_buf[MAX_CHARS];
    char *ptr;

    strcpy(temp_buf, "[");                  /*  and the opening bracket [  */
    strcat(temp_buf, header_name);
    strcat(temp_buf, "]");

    if((ptr = strstr(ini_buffer, temp_buf)) != NULL)
    {
        if(isfound(ptr, ini_buffer))
            return (ptr+strlen(NEWLINE));
        else
            return NULL;
    }
    else
        return NULL;
}

int get_parameter(char *str, int strsize, char *key, char *offset)
{
    char temp_buf1[MAX_CHARS];
    char temp_buf2[MAX_CHARS];
    char *start_ptr;
    char *end_ptr;
    char *ptr;
    char *too_far_ptr;
    int  len;

    strcpy(temp_buf1, NEWLINE);
    strcat(temp_buf1, key);
    strcat(temp_buf1, "=");

    if((start_ptr=strstr(offset, temp_buf1))==NULL)
    {
        *str=0x00;
        return (0);
    }
    start_ptr+=strlen(NEWLINE);

    if((too_far_ptr=strstr(offset+1, "["))==NULL)
        too_far_ptr=offset+strlen(offset);

    if((end_ptr=strstr(start_ptr, NEWLINE))==NULL)
        end_ptr=start_ptr+strlen(start_ptr);

    if (too_far_ptr<start_ptr)
    {
        *str=0x00;
        return(0);
    }

    memcpy(temp_buf2, start_ptr, end_ptr-start_ptr);
    temp_buf2[end_ptr-start_ptr]='\0';
    len = strlen(temp_buf2);
    strcpy(temp_buf1, temp_buf2);
    if((start_ptr=strstr(temp_buf1, "=")) == NULL)
    {
        *str=0x00;
        return (0);
    }

    strcpy(temp_buf2, start_ptr+1);

    ptr = temp_buf2;
    while(*ptr != 0x00)
    {
        if( (*ptr == ' ') || (*ptr == '\t') )
            ptr++;
        else
            break;
    }
    len = strlen(ptr);
    memset(str, 0x00, strsize);
    strncpy(str, ptr, len >= strsize ?  strsize: len);
    return (1);
}

char *find_parameter(char *key, char *offset, int *length)
{
    char temp_buf1[MAX_CHARS];
    char temp_buf2[MAX_CHARS];
    char *start_ptr;
    char *end_ptr;
    char *ptr;
    //char *too_far_ptr;
    //int  len;

    strcpy(temp_buf1, NEWLINE);
    strcat(temp_buf1, key);
    strcat(temp_buf1, "=");
    strcpy(temp_buf2, NEWLINE);
    strcat(temp_buf2, "[");
    *length = 0;

    end_ptr=strstr(offset+1, temp_buf2);
    start_ptr=strstr(offset, temp_buf1);
    if(start_ptr==NULL)
    { //not found key;

        ptr = strstr(offset, temp_buf2);
        if(ptr == NULL)
            *length = strlen(offset)-1;
        else
            *length = ptr - offset;
        return NULL;
    }
    else if((end_ptr == NULL) || (start_ptr < end_ptr) )
    {
       ptr = strstr(start_ptr+1, NEWLINE);
       if(ptr == NULL)
            *length = strlen(start_ptr)+strlen(NEWLINE);
       else 
            *length = ptr - start_ptr;
       return (start_ptr+strlen(NEWLINE));
    }
    else
        *length = end_ptr-offset-strlen(NEWLINE);

    return NULL;
}

/*
  TRUE - Success
  FALSE - Fail
*/
int writekeystring(char *section, char *key, char *str, char *path, char *filename)
{
    char    *cfgfile;
    char    *offset;
    int     length;
    int     templen;
    long    filesize;
    FILE    *handle;
    char    temp_buf[MAX_CHARS];
    char    *ini_buffer;             /* storage area for .INI file */
    char    *ptr;
    //char *rest=" ";

    if ((cfgfile=(char *)malloc(strlen(path)+strlen(filename)+2))==NULL)
        return (FALSE);   //out of memory

    sprintf(cfgfile, "%s/%s", path, filename);
    if ((handle=fopen(cfgfile, "r+b"))==NULL)     /* Binary mode, no CR/LF */
    {
       sprintf(temp_buf, "mkdir -p %s", path);
       system(temp_buf);
       //printf("%s\n", cfgfile);
       if((handle = fopen(cfgfile, "wb")) != NULL)
       {
            fprintf(handle, "[%s]\n%s=%s\n", section, key, str);
            fclose(handle);
            return (TRUE);
       }
       else
       {
            //printf("open failed\n");
            return (FALSE);
       }
    }
    if ((fseek(handle, 0, SEEK_END))!=0)
        return (FALSE);
    filesize=ftell(handle);
    rewind(handle);

    if(filesize == 0)
    {
        fprintf(handle, "[%s]\n%s=%s\n", section, key, str);
        fclose(handle);
        return (TRUE);    
    }

    if (filesize >65534)  //File to big
        return (FALSE);

    if ((ini_buffer=(char *)malloc(filesize + 1))==NULL)
        return (FALSE);   //out of memory

    fread(ini_buffer, filesize, 1, handle);
    fclose(handle);
    if((handle = fopen(cfgfile, "wb")) == NULL)
         return (FALSE);

    ini_buffer[filesize]='\0';
    if((offset=find_header(ini_buffer, section)) == NULL)
    {//not found section.
        fprintf(handle, "%s", ini_buffer);
        fprintf(handle, "\n[%s]\n%s=%s\n", section, key, str);
        fclose(handle);
        return (TRUE);
    }
    if((ptr=find_parameter(key, offset, &length)) == NULL)
    { //not found key;
        rewind(handle);
        templen = offset - ini_buffer;
        fwrite(ini_buffer, templen+length, 1, handle);
        fprintf(handle, "\n%s=%s%s", key, str, ini_buffer+templen+length);
        fclose(handle);
        return (TRUE);
    }
    else
    {
        rewind(handle);
        templen = ptr - ini_buffer;
        fwrite(ini_buffer, templen, 1, handle);
        fprintf(handle, "%s=%s\n%s", key, str, ini_buffer+templen+length);
        fclose(handle);
        return (TRUE);
    }

    return (FALSE);
}

/*
  TRUE - Success
  FALSE - Fail
*/
int getkeystring(char *section, char *key, char *dest, int strsize, char *path, char *filename)
{
    char *cfgfile;
    char *offset;
    //int     length;
    long len;
    FILE *handle;
    //char temp_buf[MAX_CHARS];
    char *ini_buffer;             /* storage area for .INI file          */

    if ((cfgfile=(char *)malloc(strlen(path)+strlen(filename)+2))==NULL)
        return (FALSE);   //out of memory

    sprintf(cfgfile, "%s/%s", path, filename);

    if ((handle=fopen(cfgfile, "rb"))==NULL)     /* Binary mode, no CR/LF */
        return (FALSE);
    if ((fseek(handle, 0, SEEK_END))!=0)
        return (FALSE);
    len=ftell(handle);
    rewind(handle);

    if (len >65534)
        return (FALSE);

    if ((ini_buffer=(char *)malloc(len + 1))==NULL)
        return (FALSE);

    fread(ini_buffer, len, 1, handle);
    fclose(handle);
    ini_buffer[len]='\0';
    if((offset=find_header(ini_buffer, section)) == NULL)
        return (FALSE);
    if(get_parameter(dest, strsize, key, offset) == 0)
        return (FALSE);

    return (TRUE);
}

/*
int main(void)
{
    char dest[MAX_CHARS];
    //int getkeystring(char *section, char *key, char *str, int strsize, char *filename)
   
    if(getkeystring("RT2460", "Profile2", dest, MAX_CHARS, "/etc/cfg", "sample.ini"))
        printf("dest=%s\n", dest);
    else
        printf("not found\n");

    if(writekeystring("RT2460", "Profile2",  "ok", "/etc/cfg", "sample.ini"))
        printf("=== End ===\n");
    return 0;
}
*/
