bug-commoncpp
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: New Class for the library


From: David Sugar
Subject: Re: New Class for the library
Date: Sun, 10 Feb 2002 15:39:26 -0500
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.4) Gecko/20010914

This is interesting. I tend to think url_string.h should itself just be in url.h so all url stuff is under a single header. Other than that, I think it may be possible to adopt this class into the project largely as is. There already is a string function for handing encoding/decoding of url escaped strings, although it operates on pure "char" arrays rather than on std::string. In structuring the Get() request with queries, this could be very useful.



arjan derk-jan paijralbe wrote:

Hi
A good library, so I've a new class for it.
It is a string class to handle urls's.
I've also add an entry for doxygen to doc global functions.

kind regards
  arjan


------------------------------------------------------------------------

// Copyright (C) 1999-2001 Open Source Telecom Corporation.
//
// 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.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other files
// to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name Common C++.  If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.

//*****************************************************************************
#include "url_string.h"
#include <cstdlib>
#include <stdlib.h>

#ifdef  CCXX_NAMESPACES
namespace ost {
#endif


//*****************************************************************************
static char *hex_char = "0123456789abcdef";

//*****************************************************************************
UrlString::UrlString( urlcode_t _urlcode )
         :string(), urlcode(_urlcode), check(1)
{
}

//*****************************************************************************
UrlString::UrlString( char *url, urlcode_t _urlcode )
         :string( url ), urlcode(_urlcode), check(1)
{
}

//*****************************************************************************
UrlString::UrlString( string &url, urlcode_t _urlcode )
         :string( url ), urlcode(_urlcode), check(1)
{
}

//*****************************************************************************
UrlString::UrlString( UrlString &url )
         :string( url ), urlcode(url.urlcode), check(1)
{
}

//*****************************************************************************
UrlString::UrlString( InetAddress &address, urlcode_t urlcode )
              :string(), urlcode(urlcode), check(1)
{
  SetUrl( address );
}

//*****************************************************************************
UrlString::~UrlString( void )
{

}

//*****************************************************************************
UrlString& UrlString::operator=( char *url )
{
  return assign( url );
}

//*****************************************************************************
UrlString& UrlString::operator=( UrlString &url )
{
  return assign( url );
}

//*****************************************************************************
UrlString& UrlString::operator=( string &url )
{
  return assign( url );
}

//*****************************************************************************
UrlString& UrlString::operator=( urlcode_t _urlcode )
{
  urlcode = _urlcode;
  return *this;
}

//*****************************************************************************
bool UrlString::operator==( UrlString &url )
{
  findpos();
  url.findpos();

  return !Cmp( (int)url_begin, url_end - url_begin,
                  url, (int)url.url_begin, url.url_end - url.url_begin ) &&
         !Cmp( (int)path_begin, path_end - path_begin,
               url, (int)url.path_begin, url.path_end - url.path_begin ) &&
                 (GetPort() == url.GetPort());
}


//*****************************************************************************
bool UrlString::operator>( UrlString &url )
{
  int result;
  findpos();
  url.findpos();

  result = Cmp( url_begin, url_end - url_begin,
                         url, url.url_begin, url.url_end - url.url_begin );
  if( result == 0 )
  {
     return (Cmp( path_begin, path_end - path_begin,
                url, url.path_begin, url.path_end - url.path_begin ) > 0 );
  }
  return (result > 0);
}

//*****************************************************************************
bool UrlString::operator<( UrlString &url )
{
  int result;
  findpos();
  url.findpos();

  result = Cmp( url_begin, url_end - url_begin,
                         url, url.url_begin, url.url_end - url.url_begin );
  if( result == 0 )
  {
     return (Cmp( path_begin, path_end - path_begin,
                url, url.path_begin, url.path_end - url.path_begin ) < 0 );
  }
  return (result < 0);
}


//*****************************************************************************
UrlString& UrlString::assign( char *url )
{
  check = 1;
  string::assign( url );
  return *this;
}

//*****************************************************************************
UrlString& UrlString::assign( UrlString &url )
{
  check = 1;
  string::assign( url );
  return *this;
}

//*****************************************************************************
UrlString& UrlString::assign( string &url )
{
  check = 1;
  string::assign( url );
  return *this;
}

//*****************************************************************************
char *UrlString::GetService( char *buffer, size_t size )
{
  findpos( );
  if( buffer && ( service_end < size ))
  {
     if( service_end > 0 )
     {
        copy( buffer, service_end, 0 );
        buffer[service_end] = '\0';
     }
     else
     {
        buffer[0] = '\0';
     }
     return buffer;
  }
  return NULL;
}

//*****************************************************************************
string UrlString::GetService( void )
{
  findpos( );
  if( service_end > 0 )
  {
     return string( *this, 0, service_end );
  }
  else
  {
     return string();
  }
}

//*****************************************************************************
void UrlString::SetService( char *service )
{
  if( service )
  {
     findpos( );

     if( service_end > 0 )
     {
        replace( 0, service_end, service );
     }
     else
     {
        insert( 0, "://" );
        insert( 0, service );
     }
     check = 1;
  }
}

//*****************************************************************************
void UrlString::SetService( UrlString &service )
{
  service.findpos( );
  findpos( );

  if( service.service_end > 0 )
  {
     if( service_end > 0 )
     {
        replace( 0, service_end, service, 0, service.service_end );
     }
     else
     {
        insert( 0, "://" );
        insert( 0, service, 0, service.service_end );
     }
     check = 1;
  }
}


//*****************************************************************************
char *UrlString::GetPath( char *buffer, size_t size )
{
  int copy_size;

  findpos( );
  copy_size = path_end - path_begin;

  if( buffer && ( size > copy_size ) && ( size > 2 ))
  {
     if( path_begin < path_end )
     {
        copy_size = UrlDecode((char*)string::c_str() + path_begin,
                                                    copy_size, buffer, size );
        if( copy_size >= 0 )
        {
           buffer[copy_size] = '\0';
        }
        else
        {
           return NULL;
        }
     }
     else
     {
        strcpy( buffer, "/" );
     }
     return buffer;
  }
  return NULL;
}

//*****************************************************************************
string UrlString::GetPath( void )
{
  findpos( );

  if( path_begin < path_end )
  {
     string temp;
     temp = string( *this, path_begin, path_end - path_begin );
     UrlDecode_s( temp );
     return temp;
  }
  else
  {
     return string( "/" );
  }
}

//*****************************************************************************
void UrlString::SetPath( char *path )
{
  if( path )
  {
     findpos( );

     if( path_begin < path_end )
     {
        if( *path != '/' )
        {
           path_begin++;
        }
        replace( path_begin, path_end - path_begin, path );
     }
     else
     {
        if( *path != '/' )
        {
           insert( path_begin, "/" );
           path_begin++;
        }
        insert( path_begin, path );
     }
     check = 1;
  }
}

//*****************************************************************************
void UrlString::SetPath( UrlString &path )
{
  unsigned int size, path_size;
  findpos( );
  path.findpos( );

  size = path_end - path_begin;
  path_size = path.path_end - path.path_begin;

  if( size > 0 )
  {
     if( path_size > 0)
     {
        replace( path_begin, size, path, path.path_begin, path_size );
     }
     else
     {
        replace( path_begin, size, "/" );
     }
  }
  else
  {
     if( path_size > 0)
     {
        insert( path_begin, path, path.path_begin, path_size );
     }
     else
     {
        insert( path_begin, "/" );
     }
  }
  check = 1;
}


//*****************************************************************************
char *UrlString::GetUrl( char *buffer, size_t size )
{
  unsigned int copy_size;

  findpos( );
  copy_size = url_end - url_begin;

  if( buffer && ( size > copy_size ) && size)
  {
     if( url_begin < url_end )
     {
        copy( buffer, copy_size, url_begin );
        buffer[copy_size] = '\0';
     }
     else
     {
        buffer[0] = '\0';
     }
     return buffer;
  }
  return NULL;
}

//*****************************************************************************
string UrlString::GetUrl( void )
{
  findpos( );
  if( url_begin < url_end )
  {
     return string( *this, url_begin, url_end - url_begin );
  }
  else
  {
     return string();
  }
}


//*****************************************************************************
void UrlString::SetUrl( char *url )
{
  if( url )
  {
     findpos( );

     if( url_begin < url_end )
     {
        replace( url_begin, url_end - url_begin, url );
     }
     else
     {
        insert( url_begin, url );
     }
     check = 1;
  }
}


//*****************************************************************************
void UrlString::SetUrl( UrlString &url )
{
  unsigned int size, url_size;
  findpos( );
  url.findpos( );

  size = url_end - url_begin;
  url_size = url.url_end - url.url_begin;

  findpos( );
  url.findpos( );

  if( url_size > 0 )
  {
     if( size > 0 )
     {
        replace( url_begin, size, url, url.url_begin, url_size );
     }
     else
     {
        insert( url_begin, url, url.url_begin, url_size );
     }
     check = 1;
  }
}

//*****************************************************************************
void UrlString::SetUrl( InetAddress &address )
{
  // A valid address ?
  if( address.isInetAddress() )
  {
     SetUrl( (char*)address.getHostname() );
  }
}



//*****************************************************************************
InetAddress &UrlString::GetAdresss( InetAddress &address )
{
  char *buffer;
  unsigned int copy_size;

  findpos( );

  copy_size = (url_end - url_begin)  + 1;

  if( url_begin < url_end )
  {
     buffer = new char[copy_size];

     copy( buffer, copy_size, url_begin );
     buffer[copy_size] = '\0';
     address = (const char*)buffer;

     delete[] buffer;
  }
  else
  {
     address = (unsigned long)0;
  }
  return address;
}


//*****************************************************************************
char *UrlString::GetUser( char *buffer, size_t size )
{
  unsigned int copy_size;

  findpos( );
  copy_size = path_end - path_begin;

  if( buffer && ( size > copy_size ) && ( size > 2 ))
  {
     if( user_begin < user_end )
     {
        copy( buffer, copy_size, user_begin );
        buffer[copy_size] = '\0';
     }
     else
     {
        buffer[0] = '\0';
     }
     return buffer;
  }
  return NULL;
}

//*****************************************************************************
string UrlString::GetUser( void )
{
  findpos( );
  if( user_begin < user_end )
  {
     return string( *this, user_begin, user_end - user_begin);
  }
  else
  {
     return string( );
  }
}

//*****************************************************************************
int UrlString::SetUser( char *user )
{
  if( user )
  {
     findpos( );

     // Only posible if there is a url.
     if( url_begin < url_end )
     {
        if( user_begin < user_end )
        {
           replace( user_begin, user_end - user_begin, user );
        }
        else
        {
           insert( user_begin, "@" );
           insert( user_begin, user );
        }
        check = 1;
        return 0;
     }
  }
  return -1;
}


//*****************************************************************************
int UrlString::SetUser( UrlString &user )
{
  unsigned int size, user_size;

  findpos( );
  user.findpos( );

  size =  user_end - user_begin;
  user_size=  user.user_end - user.user_begin;

  // Only posible if there is a url.
  if( url_begin < url_end )
  {
     if( user_size > 0 )
     {
        if( size > 0 )
        {
           replace( user_begin, size, user, user.user_begin, user_size );
        }
        else
        {
           insert( user_begin, user, user.user_begin, user_size + 1 );
        }
     }
     check = 1;
  }
}

//*****************************************************************************
void UrlString::EraseUser( void )
{
  findpos( );
  if( user_begin < user_end )
  {
     erase( user_begin, user_end + 1 );
  }
}

//*****************************************************************************
char *UrlString::GetQuery( char *buffer, size_t size )
{
  unsigned int copy_size;
  int end;

  findpos( );
  end = string::size();
  copy_size = end - path_end;

  if( buffer && ( size > copy_size ) && size )
  {
     if( path_end < end )
     {
        copy_size--;
        copy( buffer, copy_size, path_end + 1 );
        buffer[copy_size] = '\0';
     }
     else
     {
        buffer[0] = '\0';
     }
     return buffer;
  }
  return NULL;
}

//*****************************************************************************
string UrlString::GetQuery( void )
{
  int end;
  findpos( );

  end = size() - 1;
  if( path_end < end )
  {
     return string( *this, path_end + 1, end - path_end );
  }
  else
  {
     return string( );
  }
}

//*****************************************************************************
int UrlString::SetQuery( char *query )
{
  if( query && !prepeare_for_query( ) )
  {
     if( *query == '?' )
     {
        query++;
     }
     replace( path_end + 1, size() - path_end - 1, query );

     return 0;
  }
  return -1;
}


//*****************************************************************************
int UrlString::SetQuery( UrlString &query )
{
  unsigned int query_size;

  query.findpos( );
  query_size = query.size() - query.path_end;

  if( query_size > 0 )
  {
     if( !prepeare_for_query( ) )
     {
        replace( path_end, size() - path_end, query, query.path_end, query_size 
);
     }
     return 0;
  }
  return -1;
}

//*****************************************************************************
void UrlString::EraseQuery( void )
{
  int end;

  findpos( );

  end = size();

  if( path_end < end )
  {
     erase( path_end, end );
     check = 1;
  }
}

//*****************************************************************************
void UrlString::AddQuery( char* entry, char * value )
{
  char *buffer;
  int b_size, e_size, v_size = 0;

  if( !prepeare_for_query( ) && entry )
  {
     e_size = strlen( entry );
     b_size = e_size;
     if( value )
     {
        v_size = strlen( value );
     }
     if( e_size < v_size )
     {
        b_size = v_size;
     }
     b_size *= 3;
     buffer = new char[b_size];
     UrlEncode(entry, e_size, buffer, b_size );
     if( *rbegin() != '?' )
     {
        append("+");
     }
     append(buffer);
     if( value )
     {
        append("=");
        UrlEncode(value, v_size, buffer, b_size );
        append(buffer);
     }
     delete[] buffer;
  }
}

//*****************************************************************************
int UrlString::FirstQuery( char* entry, size_t e_size,
                                                char * value, size_t v_size )
{
  findpos( );
  if( path_end < size() )
  {
     query = path_end;
     return NextQuery( entry, e_size, value, v_size );
  }
  return -1;
}

//*****************************************************************************
int UrlString::NextQuery( char* entry, size_t e_size,
                                                char* value, size_t v_size )
{
  int entry_start, entry_end, value_start, value_end;
  char *start;
  findpos( );
  if( !next_query_pos( entry_start, entry_end, value_start, value_end ) )
  {
     start = (char*)string::c_str();
     if( entry && UrlDecode( start + entry_start,
                               entry_end - entry_start, entry, e_size ) >= 0 )
     {
        if( value && ( value_start < value_end ) &&
           ( UrlDecode( start + value_start,
                              value_end - value_start, value, v_size ) >= 0 ))
        {
           return 0;
        }
        else
        {
           *value = '\0';
           return 0;
        }
     }
  }
  return -1;

}


//*****************************************************************************
int UrlString::FirstQuery( string &entry, string &value )
{
  findpos( );
  if( path_end < size() )
  {
     query = path_end;
     return NextQuery( entry, value );
  }
  return -1;
}


//*****************************************************************************
int UrlString::NextQuery( string &entry, string &value )
{
  int entry_start, entry_end, value_start, value_end;
  findpos( );
  if( !next_query_pos( entry_start, entry_end, value_start, value_end ) )
  {
     entry.assign( *this, entry_start, entry_end - entry_start );
     value.assign( *this, value_start, value_end - value_start );
     UrlDecode_s( entry );
     UrlDecode_s( value );
     return 0;
  }
  return -1;
}

//*****************************************************************************
int UrlString::next_query_pos( int &entry_start, int &entry_end,
                              int &value_start, int &value_end )
{
  unsigned int end = size();
  if(( query < end ) && ( query >= path_end ) )
  {
     query++;
     entry_start = query;
     value_end = find_first_of("+?", entry_start);
     if ( value_end < 0 )
     {
        query = end;
        value_end = end;
     }
     else
     {
        query = value_end;
     }

     value_start = find( '=', entry_start );
if( (value_start < entry_start ) || (value_start > value_end )) {
        value_start = value_end;
        entry_end = value_end;
     }
     else
     {
        entry_end = value_start;
        value_start++;
     }
     return 0;
  }
  return -1;
}

//*****************************************************************************
int UrlString::prepeare_for_query( void )
{
  findpos( );

  // Only posible if there is a url.
  if( url_begin < url_end )
  {
     if( path_begin == path_end )
     {
        insert( path_begin, "/" );
        path_end++;
     }

     if( path_end == size() )
     {
        append( "?" );
     }
     return 0;
  }
  return -1;
}

//*****************************************************************************
int UrlString::IsLocalFile( void )
{
  findpos( );

  // Is there a url ?
  if( url_begin < url_end )
  {
     return 0;
  }
  return 1;
}

//*****************************************************************************
int UrlString::Setport( unsigned int port )
{
  char buffer[10];

  findpos( );

  // Only posible if there is a url
  if(( port <= 0xFFFF ) && ( url_begin < url_end ))
  {
     buffer[0] = ':';
     gcvt(port, 6, buffer + 1);
     replace( url_end, path_begin - url_end, buffer );
     check = 1;
     return 0;
  }
  return -1;
}
//*****************************************************************************
int UrlString::GetPort( void )
{
  int size;
  char buffer[6];

  findpos( );
  if( url_end < path_begin )
  {
     size = path_begin - url_end - 1;
     if( size <= 5 )
     {
        copy(buffer, size, url_end + 1 );
        buffer[size] = '\0';
        return atoi( buffer );
     }
  }
  if( service_end > 0 )
  {
     for( size = 0; size < service_end; size++ )
     {
        at(size) = tolower(at(size));
     }
     return service_to_port( );
  }
  return -1;
}

//*****************************************************************************
int UrlString::service_to_port( void )
{
  if( !Cmp(0, service_end, "http" ) )
  {
     return 80;
  }
  if( !Cmp(0, service_end, "ftp" ) )
  {
     return 21;
  }
  if( !Cmp(0, service_end, "smtp" ) )
  {
     return 25;
  }
  if( !Cmp(0, service_end, "pop3" ) )
  {
     return 110;
  }
  return -1;
}

//*****************************************************************************
void UrlString::findpos( void )
{
  int temp;
  if( check )
  {
     service_end = find( "//" );
     if( service_end < 0 )
     {
        service_end = 0;
        user_begin = service_end;
     }
     else
     {
        user_begin = service_end+2;
        service_end--;
     }

     path_begin = find( '/', user_begin );
     if( path_begin < 0 )
     {
        path_begin = size();
     }

     if( !service_end && path_begin && (at(path_begin-1) == ':' ))
     {
        temp = find( '.' );
        if(( temp < 0 ) || ( temp > path_begin ))
        {
           service_end = path_begin - 1;
           user_begin = service_end;
           user_end = user_begin;
        }
     }

     user_end = find( '@', user_begin );
     if( ( user_end < 0 ) || ( user_end > path_begin ) )
     {
        user_end = user_begin;
        url_begin = user_end;
     }
     else
     {
        url_begin = user_end + 1;
     }

     // find ipv6 adresses.
     temp = find( '[', url_begin );

     if( ( temp >= 0 ) && ( temp < path_begin ))
     {
        url_end = find( ']', temp );
        if( url_end < path_begin )
        {
           url_end++;
        }
        else
        {
           url_end = url_begin;
        }
     }
     else
     {
        url_end = find( ':', url_begin );
        if( (url_end < 0) || ( url_end > path_begin ))
        {
           url_end = path_begin;
        }
     }
     path_end = find( '?', path_begin );
     if( path_end < path_begin )
     {
        path_end = size();
     }
query = path_end; check = 0;
  }
}

//*****************************************************************************
const char * UrlString::c_str( void )
{
  return string::c_str();
}



//*****************************************************************************
void UrlString::PathEncode( void )
{
  findpos( );
  UrlEncode_s( *this, path_begin, path_end - path_begin );
  check = 1;
}





//*****************************************************************************
void UrlString::PathDecode( void )
{
  findpos( );
  UrlDecode_s( *this, path_begin, path_end - path_begin );
  check = 1;
}

//*****************************************************************************
int UrlString::Cmp( size_type pos1, size_type n1,
                               UrlString& str, size_type pos2, size_type n2)
{
  #ifdef __STRING_STL
     return compare( pos1, n1, str, pos2, n2);
  #else
     if( n1 == n2 )
     {
        return strncmp( (char*)string::c_str() + pos1,
                                 (char*)str.string::c_str() + pos2, n1 );
     }
     return -1;
  #endif
}

//*****************************************************************************
int UrlString::Cmp( size_type pos, size_type n, char *str )
{
  #ifdef __STRING_STL
     return compare( pos, n, str);
  #else
     return strncmp( (char*)string::c_str() + pos, str, n );
  #endif
}

//*****************************************************************************
ostream& operator<<(ostream& csStream, UrlString& csUrl)
{
  switch( csUrl.urlcode )
  {
     case URL_ENCODE : csUrl.PathEncode( );
       break;
     case URL_DECODE : csUrl.PathDecode( );
       break;
     case URL_CODE_AS_IS : ;
       break;
  }
  return operator<<( csStream, (string&) csUrl);
}


//*****************************************************************************
istream& operator>>(istream& csStream, UrlString& csUrl)
{
  operator>>( csStream, (string&) csUrl);

  csUrl.check = 1;

  switch( csUrl.urlcode )
  {
     case URL_ENCODE : csUrl.PathEncode( );
       break;
     case URL_DECODE : csUrl.PathDecode( );
       break;
     case URL_CODE_AS_IS : ;
       break;
  }
  return csStream;
}



//*****************************************************************************
void HexCharToInt( char hex, int &value )
{
  if( (hex >= '0') && (hex <= '9') )
  {
     value |= (hex - '0');
  }
  else
  if( (hex >= 'a') && (hex <= 'f') )
  {
     value |= (hex - 'a' + 10);
  }
  else
  if( (hex >= 'A') && (hex <= 'F') )
  {
     value |= (hex - 'A' + 10);
  }
  else
  {
     value = -1;
  }
}

//*****************************************************************************
int UrlEncode(char *source, size_t s_size, char *dest, size_t d_size )
{
  unsigned int cnt = 0;
  int c;

  if( source && dest && (s_size <= d_size) )
  {
     if( !s_size )
     {
        s_size = strlen( source );
     }

     while( s_size && *source && ( cnt < d_size ))
     {
        if( (( *source >= '0' ) && ( *source <= '9' )) ||
            (( *source >= 'a' ) && ( *source <= 'z' )) ||
            (( *source >= 'A' ) && ( *source <= 'Z' )) ||
             ( *source == '/' ) || ( *source == '.' )  ||
             ( *source == '_' )                           )
        {
           *dest = *source;
        }
        else
        {
           if( (cnt + 2) < d_size )
           {
              if( ( *source == '%' ) && ( s_size > 2 ))
              {
                 HexCharToInt( *(source+1), c = 0 );
                 c = (c << 4) & 0xF0;
                 HexCharToInt( *(source+2), c );
                 if( c >= 0 )
                 {
                    source += 2;
                    s_size -= 2;
                 }
                 else
                 {
                    c = '%';
                 }
              }
              else
              {
                 c = *source;
              }
              *dest = '%';
              dest++;
              *dest = hex_char[(unsigned char)c >> 4];
              dest++;
              *dest = hex_char[(unsigned char)c & 0x0F];
              cnt += 2;
           }
           else
           {
              return -1;
           }
        }
        source++;
        s_size--;

        dest++;
        cnt++;
     }
     if( cnt < d_size )
     {
        *dest = '\0';

        return cnt;
     }
  }
  return -1;
}


//*****************************************************************************
int UrlDecode(char *source, size_t s_size, char *dest, size_t d_size )
{
  unsigned int cnt = 0;
  int c;

  if( source && dest && (s_size <= d_size) )
  {
     if( !s_size )
     {
        s_size = strlen( source );
     }

     while( s_size && *source && ( cnt < d_size ))
     {
        if( *source == '%' )
        {
           source++;
           HexCharToInt( *(source), c = 0 );
           c = (c << 4) & 0xF0;
           HexCharToInt( *(source+1), c );
           if( c >= 0 )
           {
              *dest = (char)c;
              source += 2;
              s_size -=2;
           }
           else
           {
              *dest = '%';
              if( *source == '%' )
              {
                 source++;
              }
           }
        }
        else
        {
           *dest = *source;
           source++;
        }
        s_size--;

        dest++;

        cnt++;
     }
     if( cnt < d_size )
     {
        *dest = '\0';
     }
     return cnt;
  }
  return -1;
}

//*****************************************************************************
string &UrlDecode_s( string &str, size_t pos, size_t n )
{
  unsigned int size;
  char *buffer;

  size = str.size();
  if( pos < size )
  {
     if( !n || ((pos + n) > size ))
     {
        n = size - pos;
     }
     buffer = (char *)str.c_str() + pos;
     size = UrlDecode(buffer, n, buffer, n );
     str.erase( pos + size, n - size);
  }
  return str;
}

//*****************************************************************************
string &UrlEncode_s( string &str, size_t pos, size_t n )
{

  unsigned int size, b_size;
  char *buffer;

  size = str.size();
  if( pos < size )
  {
     if( !n || ((pos + n) > size ))
     {
        n = size - pos;
     }
     b_size = n*3;
     buffer = new char[b_size];
     size = UrlEncode((char *)str.c_str() + pos, n, buffer, b_size );
     str.replace( pos, n, buffer);
     delete[] buffer;
  }
  return str;
}


#ifdef  CCXX_NAMESPACES
}
#endif




------------------------------------------------------------------------

// Copyright (C) 1999-2001 Open Source Telecom Corporation.
//
// 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.
//
// As a special exception to the GNU General Public License, permission is
// granted for additional uses of the text contained in its release
// of Common C++.
//
// The exception is that, if you link the Common C++ library with other
// files to produce an executable, this does not by itself cause the
// resulting executable to be covered by the GNU General Public License.
// Your use of that executable is in no way restricted on account of
// linking the Common C++ library code into it.
//
// This exception does not however invalidate any other reasons why
// the executable file might be covered by the GNU General Public License.
//
// This exception applies only to the code released under the
// name Common C++.  If you copy code from other releases into a copy of
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way.  To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for Common C++, it is your
// choice whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.

//*****************************************************************************
#ifndef CCXX_URL_STRING_H
#define CCXX_URL_STRING_H

#ifndef CCXX_CONFIG_H_
#include <cc++/config.h>
#endif

#include "export.h"
#include "socket.h"
#include <string>
#include <iostream>


//*****************************************************************************
#ifdef  CCXX_NAMESPACES
namespace ost {
#endif

using namespace std;

//*****************************************************************************
/** @enum urlcode_t
   Used to deside if the string should be decoded or encoded.
   @see UrlString::urlcode
 */
enum urlcode_t { /// No modifications of the url.
                URL_CODE_AS_IS,
                /// Encode the url string, to send over a http stream
                URL_ENCODE,
                /// Decode the url string
                URL_DECODE };

typedef enum urlcode_t urlcode_t;


//*****************************************************************************
class CCXX_CLASS_EXPORT UrlString;


/// @see UrlString::operator<<
ostream & operator<<(ostream & csStream, const UrlString& csUrl);
/// @see UrlString::operator>>
istream & operator>>(istream & csStream, UrlString& csUrl);


//*****************************************************************************
/** @class UrlString "url_class.h"
   Set and get the parts of an url.
   The following examples are supported :        \n
   service://address@hidden:port/path?query+query      \n
   service://url:port/path?query=1+query+query=2 \n
   service://address@hidden/path                       \n
   service://url:port                            \n
   service://url                                 \n
   url:port/path                                 \n
   url                                           \n
   address@hidden                                      \n
   /path                                         \n
   service:/path                                 \n
   service:///path                               \n
   @author arjan.paijralbe
   @date   10-2-2002
*/
class UrlString : protected string
{
  public :

     /** Constructor of the class.
         This constructor creates an empty class.
         @param urlcode Sets the url coding for the stream operators.
       */
     UrlString( urlcode_t urlcode = URL_ENCODE );
     /** Constructor of the class.
         This constructor copy the url from the char buffer.
         @param url Pointer to a char buffer with an url
         @param urlcode Sets the url coding for the stream operators.
       */
     UrlString( char *url, urlcode_t urlcode = URL_ENCODE );
     /** Constructor of the class.
         This constructor copy the url from the string.
         @param url Reference to a string with an url
         @param urlcode Sets the url coding for the stream operators.
       */
     UrlString( string &url, urlcode_t urlcode = URL_ENCODE );
     /** Constructor of the class.
         This constructor copy the url from the UrlString.
         @param url Reference to a string with an url
       */
     UrlString( UrlString &url );

     /** Constructor of the class.
         This constructor takes the the url from address.
         @param address Contains the url.
         @param urlcode sets the url coding for the stream operators.
       */
     UrlString( InetAddress &address, urlcode_t urlcode = URL_ENCODE );

     /** Destructor of the class.
       */
     virtual ~UrlString( void );

     /// This operator assign a new url to the class.
     UrlString& operator=( char *url );
     /// This operator assign a new url to the class.
     UrlString& operator=( string &url );
     /// This operator assign a new url to the class.
     UrlString& operator=( UrlString &url );

     /** This operator set a new coding mode of the class.
         @see urlcode
       */
     UrlString& operator=( urlcode_t urlcode );

     /** This operator compares the url the path and the port of
         both classes for eaquality.
         The service and the query will be ignored.
       */
     bool operator==( UrlString &url );

     /** This operator compares the url the path both classes to find out
         witch one is bigger....
         The service the query and the port will be ignored.
       */
     bool operator>( UrlString &url );

     /** This operator compares the url the path both classes to find out
         witch one is smaller....
         The service the query and the port will be ignored.
       */
     bool operator<( UrlString &url );


     /// This methode assign a new url to the class.
     UrlString& assign( char *url );
     /// This methode assign a new url to the class.
     UrlString& assign( UrlString &url );
     /// This methode assign a new url to the class.
     UrlString& assign( string &url );

     /** This methode returns the specified service of the url.
         If there is no service specified the buffer will be empty.
         The service has no ':' char at the end!
         @param buffer In this buffer the service is been inserted.
         @param size Size of the buffer.
         @retval buffer The service is been copyed.
         @retval NULL Not enough space in the buffer.
       */
     char *GetService( char *buffer, size_t size );

     /** This methode returns the specified service of the url.
         If there is no service specified the buffer will be empty.
         The service has no ':' char at the end!
         @param str In this buffer the service is been inserted.
         @return str.
       */
     string GetService( void );

     /** This methode set the service of the url.
         The should no ':' char at the end!
         @param service Service to set.
       */
     void SetService( char *service );


     /** This methode get the service from the urlstring class and set it this 
class.
         @param service Service to set.
       */
     void SetService( UrlString &service );

     /** This methode returns the specified user of the url.
         If there is no user specified the buffer will be empty.
         @param buffer In this buffer the user is been inserted.
         @param size Size of the buffer.
         @retval buffer The user is been copyed.
         @retval NULL Not enough space in the buffer.

       */
     char *GetUser( char *buffer, size_t size );

     /** This methode returns the specified user of the url.
         If there is no user specified the buffer will be empty.
         @param str In this buffer the user is been inserted.
         @return str.
       */
     string GetUser( void );

     /** This methode set the user of the url.
         @param user User to set.

       */
     int SetUser( char *user );

     /** This methode set the user of the url.
         @param user User to set.

       */
     int SetUser( UrlString &user );


     /** This methode erase the user from the url.
       */
     void EraseUser( void );

     /** This methode returns the specified url.
         If there is no url specified the buffer will be empty.
         @param buffer In this buffer the url is been inserted.
         @param size Size of the buffer.
         @retval buffer The url is been copyed.
         @retval NULL Not enough space in the buffer.
       */
     char *GetUrl( char *buffer, size_t size );

     /** This methode returns the specified url.
         If there is no url specified the buffer will be empty.
         @param str In this buffer the url is been inserted.
         @return str.
       */
     string GetUrl( void );

     /** This methode set the url.
         @param url Url to set.
       */
     void SetUrl( char *url );

     /** This methode get the url from the urlstring class and set it to this 
class.
         @param url Url to set.
         @warning workes only if url contains an url!
       */
     void SetUrl( UrlString &url );

     /** This methode takes the url from the address if it is a valid adress.
         @param address Contains the address to the url.
         @see InetAddress::getHostname
       */
     void SetUrl( InetAddress &address );

     /** This methode insert the url to the InetAddress class.
         @see InetAddress::operator=
         @return address
       */
     InetAddress &GetAdresss( InetAddress &address );

     /** This methode returns the specified path of the url.
         If there is no path specified the buffer contains '/'.
         @param buffer In this buffer the path is been inserted.
         @param size Size of the buffer.
         @retval buffer The path is been copyed.
         @retval NULL Not enough space in the buffer.
       */
     char *GetPath( char *buffer, size_t size );

     /** This methode returns the specified path of the url.
         If there is no path specified the buffer contains '/'.
         @param str In this buffer the path is been inserted.
         @return str.
       */
     string GetPath( void );

     /** This methode set the path of the url.
         If the first char is not an '/' it will be added.
         @param path Path to set.
       */
     void SetPath( char *path );

     /** This methode takes the path from the urlstring class and add it to 
this class.
         @param path Path to set.
       */
     void SetPath( UrlString &path );

     /** This methode returns the specified query of the url.
         If there is no query specified the buffer will be empty.
         @param buffer In this buffer the query is been inserted.
         @param size Size of the buffer.
         @retval buffer The query is been copyed.
         @retval NULL Not enough space in the buffer.
       */
     char *GetQuery( char *buffer, size_t size );

     /** This methode returns the specified query of the url.
         If there is no query specified the buffer will be empty.
         @param str In this buffer the query is been inserted.
         @return str.
       */
     string GetQuery( void );

     /** This methode set the query of the url.
         If the first char is not an '/' it will be added.
         @param query Query to set.
       */
     int  SetQuery( char *query );


     /** This methode get the query from the urlstring class and set it to this 
class.
         If the first char is not an '/' it will be added.
         @param query Query to set.
       */
     int  SetQuery( UrlString &query );

     /// This methode erase the query from the url.
     void EraseQuery( void );

     /** This methode add's a new entry to the query.
         The entry and the value will first encoded and then added to the url.
         To seperate the entry's the '+' character is been used.
         @param entry Name of the entry.
         @arg entry = NULL No query will be added.
         @param value Value of the entry.
         @arg value = NULL only the entry will be added.
        */
     void AddQuery( char* entry, char * value );

     /** This methode get the first query entry and decode it.
         @param entry Buffer for the name of the entry.
         @param e_size Size of the entry buffer.
         @param value Buffer for the value of the entry.
         @param v_size Size of the value buffer.
         @retval 0 The first entry found.
         @retval -1 No entry found or size of the buffer is to small.
         @see NextQuery, AddQuery;
        */
     int FirstQuery( char* entry, size_t e_size, char * value, size_t v_size );

     /** This methode get the first query entry and decode it.
         @param entry Buffer for the name of the entry.
         @param value Buffer for the value of the entry.
         @retval 0 The first entry found.
         @retval -1 No entry found.
         @see NextQuery, AddQuery;
        */

     int FirstQuery( string &entry, string &value );

     /** This methode get the next query entry and decode it.
         @param entry Buffer for the name of the entry.
         @param e_size Size of the entry buffer.
         @param value Buffer for the value of the entry.
         @param v_size Size of the value buffer.
         @retval 0 The first entry found.
         @retval -1 No entry found or size of the buffer is to small.
         @see FirstQuery, AddQuery;
        */
     int NextQuery( char* entry, size_t e_size, char * value, size_t v_size );

     /** This methode get the next query entry and decode it.
         @param entry Buffer for the name of the entry.
         @param value Buffer for the value of the entry.
         @retval 0 The first entry found.
         @retval -1 No entry found.
         @see FirstQuery, AddQuery;
        */
     int NextQuery( string &entry, string &value );

     /** Set the port number.
         @warning only possible if a url is specified.
       */
     int Setport( unsigned int port );

     /**  This returns the specified port.
          If there is no port, the methode #service_to_port is been
          called to translate the servic to a port number.
          @retval 0..65535 specified port.
          @retval -1 no port specified.
        */
     int GetPort( void );

     /** Checks if there is a url specified.
         @retval 0 It has a url.
         @retval 1 There is no url, so it will be a local file.
       */
     int IsLocalFile( void );

     /** Decode the path of the string.
       */
     void PathDecode( void );


     /** Encode the path of the string.
       */
     void PathEncode( void );

     /** Get the string as zero terminated char buffer.
       */
     const char * c_str( void );

     /// Methode to stream the class.
     friend ostream& operator<<(ostream& csStream, UrlString& csUrl);
     /// Methode to get the url information from a stream.
     friend istream& operator>>(istream& csStream, UrlString& csUrl);

  protected :
     /// End position of the service.
     int service_end;
     /// begin position of the user.
     int user_begin;
     /// end position of the user.
     int user_end;
     /// begin position of the url.
     int url_begin;
     /// end position of the url.
     int url_end;
     /// begin position of the path.
     int path_begin;
     /// end position of the path.
     int path_end;
     /// start position of the last readed query entry.
     int query;

     /** Is been used with the operator<< and operator>> to decide if the
         path should be encoded or coded.
         @see urlcode_t
        */
     urlcode_t urlcode;

     /** Status of string modifications.
         @arg check == 0 string is not modified.
         @arg check != 0 string is modified, findpos should be called.
       */
     int check;

     /** scanns the structure of the url and is updating the position
         attributs of the class.
       */
     void findpos( void );

     /** Translate the service to a port number.
         Is been called by GetPort, if there is no port specified.
         @retval 21 if service = 'ftp'
         @retval 25 if service = 'smpt'
         @retval 80 if service = 'http'
         @retval -1 unknown service port.
       */
     virtual int service_to_port( void );

     /** get the positions of the next qery entry.
       */
     inline int next_query_pos( int &entry_start, int &entry_end,
                                int &value_start, int &value_end );

  private :
     // prepeats the string to add a querry.
     int prepeare_for_query( void );
     inline int Cmp( size_type pos1, size_type n1,
                           UrlString& str, size_type pos2, size_type n2);
     inline int Cmp( size_type pos, size_type n, char *str );
};

//*****************************************************************************
/** @defgroup global Global
*  Global Functions and attributs.
*/

/** Encode a string.
   @param source  string to encode.
   @param s_size  size of the encoded string.
   @arg   s_size = 0 takes the size of the source string.
   @arg   s_size > string size  it will takes the size of the source string
   @arg   s_size < string size  it will takes s_size.
   @param dest    buffer for the encoded string.
   @param d_size  size of the buffer ( has to be 3 * s_size )
   @retval 0 string is been encoded.
   @retval -1 not enough space in the destination buffer.
   @see #url_string.h
   @ingroup global
 */
int UrlEncode( char *source, size_t s_size, char *dest, size_t d_size );

/** Decode a string.
   @param source  string to decode.
   @param s_size  size of the decoded string.
   @arg   s_size = 0 takes the size of the source string.
   @arg   s_size > string size  it will takes the size of the source string
   @arg   s_size < string size  it will takes s_size.
   @param dest    buffer for the decoded string.
   @param d_size  size of the buffer ( has to be at minimum s_size )
   @retval 0 string is been encoded.
   @retval -1 not enough space in the destination buffer.
   @see #url_string.h
   @ingroup global
 */
int UrlDecode( char *source, size_t s_size, char *dest, size_t d_size );

/** Encode a string.
   @param str  string to encode.
   @param pos  start position to encode
   @param n    size to encode.
   @arg   n = 0 size from pos to end()
   @return reference to str.
   @see #url_string.h
   @ingroup global
 */
string &UrlEncode_s( string &str, size_t pos = 0, size_t n = 0 );

/** Decode a string.
   @param str  string to encode.
   @param pos  start position to encode
   @param n    size to encode.
   @arg   n = 0 size from pos to end()
   @return reference to str.
   @see #url_string.h
   @ingroup global
 */
string &UrlDecode_s( string &str, size_t pos = 0, size_t n = 0 );

#ifdef  CCXX_NAMESPACES
}
#endif

#endif









reply via email to

[Prev in Thread] Current Thread [Next in Thread]