Files
mars-flaim/flaim/src/furl.cpp
dsandersoremutah c55dab446f Renamed version4 to flaim and version5 to xflaim
git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@7 0109f412-320b-0410-ab79-c3e0c5ffbbe6
2006-01-27 21:06:39 +00:00

406 lines
8.8 KiB
C++

//-------------------------------------------------------------------------
// Desc: URL parsing.
// Tabs: 3
//
// Copyright (c) 1998-2000,2002-2003,2005-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// 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, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id: furl.cpp 12329 2006-01-20 17:49:30 -0700 (Fri, 20 Jan 2006) ahodgkinson $
//-------------------------------------------------------------------------
#include "flaimsys.h"
#define FLAIM_PROTOCOL_NAME "x-flaim"
#define FLAIM_PROTOCOL_NAME_LEN 7
#define TCP_SUB_PROTOCOL_NAME ":tcp://"
#define TCP_SUB_PROTOCOL_NAME_LEN 7
#define STREAM_SUB_PROTOCOL_NAME ":stream://"
#define STREAM_SUB_PROTOCOL_NAME_LEN 10
#define NO_SUB_PROTOCOL_NAME "://"
#define NO_SUB_PROTOCOL_NAME_LEN 3
#define FLAIM_DEFAULT_PORT 1677
/****************************************************************************
Public: FUrl constructor, destructor
****************************************************************************/
FUrl::FUrl()
{
m_iPort = -1;
m_iSubProtocol = NO_SUB_PROTOCOL;
m_bRelative = FALSE;
m_pucAlloc = NULL;
m_pszHostName = NULL;
m_pszFileName = NULL;
m_uiAddrType = FLM_CS_NO_ADDR;
m_pszIPName = NULL;
m_ui32IPAddr = 0;
f_memset( m_pszAddr, 0, FLM_CS_MAX_ADDR_LEN);
}
FUrl::~FUrl()
{
Reset();
}
/****************************************************************************
Public: FUrl::Reset
Desc: Reset members of the URL - freeing memory, etc.
****************************************************************************/
void FUrl::Reset()
{
m_iPort = -1;
m_iSubProtocol = NO_SUB_PROTOCOL;
m_bRelative = FALSE;
f_free( &m_pucAlloc);
m_pszHostName = NULL;
m_pszFileName = NULL;
m_bLocal = FALSE;
f_free( (void **)&m_pszIPName);
m_ui32IPAddr = 0;
m_uiAddrType = FLM_CS_NO_ADDR;
f_memset( m_pszAddr, 0, FLM_CS_MAX_ADDR_LEN);
}
/****************************************************************************
Public: FUrl::SetUrl
Desc: Parse the string passed in and setup the members of the URL.
****************************************************************************/
RCODE FUrl::SetUrl(
const char * pszUrlStr)
{
RCODE rc = FERR_OK;
FLMUINT uiAllocLen;
char * pucTmp;
const char * pucCurrent;
const char * pszFileName = NULL;
const char * pszHostName = NULL;
FLMINT iHostNameLen = 0;
FLMINT iPort = -1;
FLMINT iSubProtocol = NO_SUB_PROTOCOL;
FLMBOOL bRelative = FALSE;
/* Clear out the current URL. */
Reset();
/*
See if the string begins with our protocol name. If not, assume that
it is a file name.
*/
if ((f_strncmp( pszUrlStr, FLAIM_PROTOCOL_NAME,
FLAIM_PROTOCOL_NAME_LEN) != 0) ||
((f_strncmp( pszUrlStr + FLAIM_PROTOCOL_NAME_LEN,
TCP_SUB_PROTOCOL_NAME,
TCP_SUB_PROTOCOL_NAME_LEN) != 0) &&
(f_strncmp( pszUrlStr + FLAIM_PROTOCOL_NAME_LEN,
STREAM_SUB_PROTOCOL_NAME,
STREAM_SUB_PROTOCOL_NAME_LEN) != 0) &&
(f_strncmp( pszUrlStr + FLAIM_PROTOCOL_NAME_LEN,
NO_SUB_PROTOCOL_NAME,
NO_SUB_PROTOCOL_NAME_LEN) != 0)))
{
bRelative = FALSE;
pszFileName = pszUrlStr;
m_bLocal = TRUE;
}
else
{
pucCurrent = pszUrlStr + FLAIM_PROTOCOL_NAME_LEN;
if( f_strncmp( pucCurrent, TCP_SUB_PROTOCOL_NAME,
TCP_SUB_PROTOCOL_NAME_LEN) == 0)
{
iSubProtocol = TCP_SUB_PROTOCOL;
pucCurrent += TCP_SUB_PROTOCOL_NAME_LEN;
}
else if( f_strncmp( pucCurrent, STREAM_SUB_PROTOCOL_NAME,
STREAM_SUB_PROTOCOL_NAME_LEN) == 0)
{
iSubProtocol = STREAM_SUB_PROTOCOL;
pucCurrent += STREAM_SUB_PROTOCOL_NAME_LEN;
m_uiAddrType = FLM_CS_STREAM_ADDR;
}
else
{
iSubProtocol = NO_SUB_PROTOCOL;
pucCurrent += NO_SUB_PROTOCOL_NAME_LEN;
}
/*
If the next character is NOT a slash, we have a host name
(or stream name) and optionally a port number
*/
if( *pucCurrent != '/')
{
FLMINT iAddrPos;
FLMINT iAddrSlot;
FLMUINT uiTmpVal;
const char * pucNamePos;
iPort = FLAIM_DEFAULT_PORT;
pszHostName = pucCurrent;
while( (*pucCurrent) && (*pucCurrent != '/') && (*pucCurrent != ':'))
{
iHostNameLen++;
pucCurrent++;
}
/*
It is invalid to have an empty host name
*/
if( !iHostNameLen)
{
rc = RC_SET( FERR_IO_INVALID_PATH);
goto Exit;
}
/*
If this is a URL that does not include a file path,
we are done
*/
if( !(*pucCurrent))
{
goto Done;
}
/* See if we got a colon. If so, extract the port number. */
if( *pucCurrent == ':')
{
iPort = 0;
/* Increment past colon. */
pucCurrent++;
/* Make sure we have at least one digit. */
if( (*pucCurrent < '0') || (*pucCurrent > '9'))
{
rc = RC_SET( FERR_IO_INVALID_PATH);
goto Exit;
}
/* Go until string termination or another backslash. */
while( (*pucCurrent) && (*pucCurrent != '/'))
{
if ((*pucCurrent < '0') || (*pucCurrent > '9'))
{
rc = RC_SET( FERR_IO_INVALID_PATH);
goto Exit;
}
iPort *= 10;
iPort += (FLMINT)(*pucCurrent - '0');
pucCurrent++;
}
}
if( iSubProtocol != STREAM_SUB_PROTOCOL)
{
m_uiAddrType = FLM_CS_IP_ADDR;
}
/*
See if the host name is an IP address. If it is an
address, extract it.
*/
/*
Dotted IP Address. The format of an IP address is
000.000.000.000 where each dot-separated value can vary
in length from 1 to 3 characters.
*/
iAddrSlot = 0;
uiTmpVal = 0;
pucNamePos = pszHostName;
for( iAddrPos = 0; iAddrPos < iHostNameLen; iAddrPos++)
{
switch( *pucNamePos)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
{
uiTmpVal *= 10;
uiTmpVal += (FLMUINT)(*pucNamePos - '0');
break;
}
case '.':
{
if( iAddrSlot >= 4)
{
rc = RC_SET( FERR_IO_INVALID_PATH);
goto Exit;
}
((FLMBYTE *)(&m_ui32IPAddr))[ iAddrSlot++] = (FLMBYTE)uiTmpVal;
uiTmpVal = 0;
break;
}
default:
{
// The buffer does not contain an address. Cause the
// loop to terminate.
iAddrPos = iHostNameLen;
iAddrSlot = 3;
continue;
}
}
pucNamePos++;
}
if( iAddrSlot != 3)
{
rc = RC_SET( FERR_IO_INVALID_PATH);
goto Exit;
}
/* By now we better be on another slash */
if( *pucCurrent != '/')
{
rc = RC_SET( FERR_IO_INVALID_PATH);
goto Exit;
}
}
/* Increment past slash. */
pucCurrent++;
/* See if there are any keywords. */
if( f_strnicmp( pucCurrent, "RELATIVE.", 9) == 0)
{
pucCurrent += 9;
/*
Better have specified a host name - RELATIVE is only valid when
talking to a server.
*/
if (!iHostNameLen)
{
rc = RC_SET( FERR_IO_INVALID_PATH);
goto Exit;
}
/*
Treat the rest of the string after the "RELATIVE."
as a relative file name.
*/
bRelative = TRUE;
pszFileName = pucCurrent;
}
else if( f_strnicmp( pucCurrent, "ABSOLUTE.", 9) == 0)
{
pucCurrent += 9;
/*
Treat the rest of the string after the "ABSOLUTE."
as an absolute file name.
*/
bRelative = FALSE;
pszFileName = pucCurrent;
}
else
{
/*
No keywords, so default case is to treat the rest of the
string as a relative file name.
*/
bRelative = TRUE;
pszFileName = pucCurrent;
}
}
/* Make one allocation for everything that is to be copied. */
Done:
uiAllocLen = 0;
if( pszFileName)
{
uiAllocLen += (FLMUINT)(f_strlen( pszFileName) + 1);
}
if (iHostNameLen)
{
uiAllocLen += (FLMUINT)(iHostNameLen + 1);
}
if (RC_BAD( rc = f_alloc( uiAllocLen, &m_pucAlloc)))
{
goto Exit;
}
m_iSubProtocol = iSubProtocol;
m_bRelative = bRelative;
pucTmp = m_pucAlloc;
m_iPort = iPort;
if (iHostNameLen)
{
f_memcpy( pucTmp, pszHostName, iHostNameLen);
pucTmp[ iHostNameLen] = 0;
m_pszHostName = pucTmp;
pucTmp += (iHostNameLen + 1);
if( iHostNameLen + 1 <= FLM_CS_MAX_ADDR_LEN)
{
f_strcpy( m_pszAddr, m_pszHostName);
}
else
{
rc = RC_SET( FERR_MEM);
goto Exit;
}
}
if( pszFileName)
{
f_strcpy( pucTmp, pszFileName);
m_pszFileName = pucTmp;
}
else
{
m_pszFileName = NULL;
}
Exit:
return( rc);
}