bug-commoncpp
[Top][All Lists]
Advanced

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

New Class for the library


From: arjan derk-jan paijralbe
Subject: New Class for the library
Date: Sun, 10 Feb 2002 16:36:53 +0100
User-agent: Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.6+) Gecko/20011130

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]