/*
 * kbiffurl.cpp
 * Copyright (C) 1999-2002 Kurt Granroth <granroth@kde.org>
 * Copyright (C) 1999 Bjorn Hansson <Bjorn.Hansson@signal.uu.se>
 *
 * This file contains the implementation of KBiffURL and
 *
 * $Id$
 */
#include "kbiffurl.h"

KBiffURL::KBiffURL()
	: KURL()
{
}

KBiffURL::KBiffURL(const TQString& _url)
  : KURL(_url)
{
  /**
   * There exists no search part in the nntp spec; let's go around that
   */
  if (protocol() == "nntp")
  {
    TQString urlStr(_url);
    urlStr.replace(0,4, "imap4");
    *this = KBiffURL(urlStr);
    setProtocol("nntp");
  }
}

/**
 * BNF description of the syntax (see RFC1738, HTTP syntax)
 * ; HTTP
 *
 * httpurl        = "http://" hostport [ "/" hpath [ "?" search ]]
 * hpath          = hsegment *[ "/" hsegment ]
 * hsegment       = *[ uchar | ";" | ":" | "@" | "&" | "=" ]
 * search         = *[ uchar | ";" | ":" | "@" | "&" | "=" ]
 */
TQString KBiffURL::searchPar( const TQString & _parName ) const
{
  const char *_searchPart, *_searchPos, *_parVal;
  int n;

  // Set some initial values
  n = 0;
  _parVal = NULL;

  // Get the search part of the URL, i.e. the stuff after "?"
  TQString query_str(query());
  if (!query_str.isNull())
    query_str = query_str.remove(0,1);
  _searchPart = query_str.ascii();

  // Try to find the given parameter in the search part string
  if ((n = findPos( _searchPart, _parName )) < 0)
    return TQString::null;

  /*
   * Now, we know that the parameter name is found
   */

  // If no value is assigned, an empty string is returned
  if (_searchPart[n] != '=')
    return TQString::null;

  // Set the beginning of the parameter value string
  _parVal = &(_searchPart[n+1]);

  // Find the end of the assigned parameter value
  _searchPos = strpbrk( _parVal, ";:@&=" );

  // Return the assigned parameter value
  if (_searchPos == NULL)
    return TQString( _parVal );
  else
    return TQString( _parVal ).left(_searchPos - _parVal);
}

void KBiffURL::setSearchPar( const TQString & _parName, const TQString & _newParVal )
{
  TQString _newSearchPart;
  const char *_searchPart, *_searchPos, *_parVal;
  int index, len;

  // Get the search part of the URL, i.e. the stuff after "?"
  TQString query_str(query());

  if (!query_str.isNull())
    query_str = query_str.remove(0,1);
  _searchPart = query_str.ascii();

  // Try to find the given parameter in the search part string
  index = findPos( _searchPart, _parName );

  // If the parameter name is not found it is simply appended
  if (index < 0) 
  {
    if (query_str.length() > 0) 
    {
      _newSearchPart = query_str;
      _newSearchPart += "&";
    }
    _newSearchPart += _parName;
    _newSearchPart += "=";
    _newSearchPart += _newParVal;
  }
  else
  {
    _newSearchPart = _searchPart;

    // If no value is assigned, the new value is inserted
    if (_searchPart[index] != '=') 
    {
      _newSearchPart.insert( index, _newParVal );
      _newSearchPart.insert( index, '=' );
    }

    // Otherwise, the old value is replaced with the new one
    else
    {
      // Point to the first character of the assigned value
      index++;

      // Set the beginning of the parameter value string
      _parVal = &(_searchPart[index]);

      // Get the length of the old parameter value
      _searchPos = strpbrk( _parVal, ";:@&=" );

      if (_searchPos == NULL)
        len = strlen( _parVal );
      else
        len = _searchPos - _parVal;

      _newSearchPart.replace( index, len, _newParVal );
    }
  }

  setQuery( _newSearchPart );
}

int KBiffURL::findPos( const TQString & _searchPart, const TQString & _parName ) const
{
  const char *_searchPos;
  int n = -1;

  _searchPos = _searchPart.ascii();
  while (_searchPos != NULL)
  {
    _searchPos = strstr( _searchPos, _parName.ascii() );

    // If not found, a NULL string is returned
    if (_searchPos == NULL)
      return -1;

    // Find the index of the next character
    n = _searchPos - _searchPart.ascii() + strlen(_parName.ascii());

    // Stop searching if this is not a substring
    if ((_searchPos == _searchPart || _searchPos[-1] == '&') &&
        (_searchPart[n] == '0' || strchr(";:@&=", _searchPart[n]) != NULL))
      return n;

    _searchPos = &(_searchPart.ascii()[n+1]);
  }

  return -1;
}

TQString KBiffURL::pass() const
{
  return KURL::decode_string(KURL::pass());
}
