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