/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          CHttpParams.cpp  -  description
                             -------------------
    begin                : July 22 2003
    copyright            : (C) 2003-2006 by Alexey Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library 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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#include <sptk3/CHttpParams.h>
#include <sptk3/CBuffer.h>
#include <sptk3/CStrings.h>
#include <sptk3/string_ext.h>

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

#include <vector>

using namespace std;
using namespace sptk;

string CHttpParams::encodeString(string& str) {
   unsigned cnt = str.length();
   const char *src = str.c_str();
   char *buffer = (char *)calloc(cnt*3+1,1);
   char *dest = buffer;
   while (*src) {
      if (isalnum(*src)) {
         *dest = *src;
         dest++;
      } else {
         switch (*src) {
            case ' ':
               *dest = '+';
               dest++;
               break;
            case '.':
            case '-':
               *dest = *src;
               dest++;
               break;
            default:
               sprintf(dest,"%%%02X",(unsigned)*src);
               dest += 3;
               break;
         }
      }
      src++;
   }
   string result(buffer);
   free(buffer);
   return result;
}

int hexCharToInt(unsigned char ch) {
   if (ch > '@')
      return ch - 'A' + 10;
   return ch - '0';
}

string CHttpParams::decodeString(string& str) {
   unsigned cnt = str.length();
   const char *src = str.c_str();
   char *buffer = (char *)calloc(cnt+1,1);
   char *dest = buffer;
   while (*src) {
      switch (*src) {
         case '+':
            *dest = ' ';
            src++;
            break;
         default:
            *dest = *src;
            src++;
            break;
         case '%':
            src++;
            *dest = hexCharToInt(*src) * 16 + hexCharToInt(src[1]);
            src += 2;
            break;
      }
      dest++;
   }
   string result(buffer);
   free(buffer);
   return result;
}

void CHttpParams::decode(const CBuffer& cb,bool lowerCaseNames) {
   clear();

   CStrings sl(cb.data(),"&");
   for (unsigned i=0; i < sl.size(); i++) {
      string& s = sl[i];
      int pos = s.find("=");
      if (pos > 0) {
         string value = s.substr(pos+1,s.length());
         s[pos] = 0;
         (*this)[s] = decodeString(value);
      }
      else 
         (*this)[s] = "";
   }
}

void CHttpParams::encode(CBuffer& result) {
   CHttpParams::iterator itor = begin();
   unsigned cnt = 0;
   for (; itor != end(); itor++) {
      string param;
      param = itor->first + "=" + encodeString( itor->second );
      if (cnt)
         result.append("&",1);
      result.append(param);
      cnt++;
   }
}
