//-----------------------------------------------------------------------------
// Copyright © 2003 - Philip Howard - All rights reserved
//
// 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.
//-----------------------------------------------------------------------------
// package	libh/string
// homepage	http://libh.slashusr.org/
//-----------------------------------------------------------------------------
// author	Philip Howard
// email	libh at ipal dot org
// homepage	http://phil.ipal.org/
//-----------------------------------------------------------------------------
// This file is best viewed using a fixed spaced font such as Courier
// and in a display at least 120 columns wide.
//-----------------------------------------------------------------------------

#include "string_lib.h"

__PROTO_BEGIN__
//-----------------------------------------------------------------------------
// function	str_split_url
//
// purpose	Split a string with a URL into multiple strings, storing
//		pointers to each component in the original buffer into
//		locations in the argument list as pointers.
//
// arguments	1 (char *) string and buffer space to split.
//		2 (char * *) store pointer to protocol here
//		3 (char * *) store pointer to user name here
//		4 (char * *) store pointer to password here
//		5 (char * *) store pointer to host name here
//		6 (char * *) store pointer to port number here
//		7 (char * *) store pointer to full path here
//		8 (char * *) store pointer to query string here
//
// returns	(int) -1 : error
//		(int)  0 : OK
//
// example	protocol://username:password@hostname:port/path?querystring
//
// note		The components are split within the given buffer.  If the
//		caller needs the original buffer, a duplicate should be made
//		before calling str_split_url().  If the buffer was allocated
//		with malloc() or similar, the caller can only free the space
//		using the original pointer at which time all the components
//		are freed.
//
// note		This splitter/parser does not handle malformed URLs well.
//		Some bad URLs may be handled as if good.
//-----------------------------------------------------------------------------
int
str_split_url (
    char *		arg_string
    ,
    char * *		arg_prot_p
    ,
    char * *		arg_user_p
    ,
    char * *		arg_pass_p
    ,
    char * *		arg_host_p
    ,
    char * *		arg_port_p
    ,
    char * *		arg_path_p
    ,
    char * *		arg_qstr_p
    )
__PROTO_END__
{
    char *	prot_p	;
    char *	user_p	;
    char *	pass_p	;
    char *	host_p	;
    char *	port_p	;
    char *	path_p	;
    char *	qstr_p	;
    char *	p1	;
    int		rc	;

    //-- What we do not see is left NULL.
    prot_p = NULL;
    user_p = NULL;
    pass_p = NULL;
    host_p = NULL;
    port_p = NULL;
    path_p = NULL;
    qstr_p = NULL;

    //-- Make sure we have something to parse.
    rc = -1;
    if ( ( p1 = arg_string ) ) {
	rc = 0;

	//-- Scan for "?" to split prot:host/path from query string.
	{
	    char * p2;
	    p2 = p1;
	    while ( * p2 && * p2 != '?' ) ++ p2;
	    if ( * p2 ) {
		* p2 = 0;
		qstr_p = p2 + 1;
	    }
	}

	//-- Scan for ":" or "/" to split protocol and host/path.
	{
	    char * p2;
	    p2 = p1;
	    while ( * p2 && * p2 != ':' && * p2 != '/' ) ++ p2;
	    if ( * p2 == ':' ) {
		prot_p = p1;
		* p2 = 0;
		p1 = ++ p2;
	    }
	}

	//-- If this is "//" then host is next.
	if ( p1[0] == '/' && p1[1] == '/' ) {
	    char * p2;
	    ++ p1;

	    //-- Shift host part to make room for terminator
	    //-- while scanning for "/" to split host and path.
	    p2 = p1;
	    {
		char * p3;
		p3 = p1;
		while ( * ++ p1 && * p1 != '/' ) {
		    * p3 = * p1;
		    p3 = p1;
		}
		* p3 = 0;
	    }

	    //-- Scan for "@" to split user:pass and host:port.
	    {
		char * p3;
		p3 = p2;
		while ( * p3 && * p3 != '@' ) ++ p3;
		if ( * p3 ) {
		    char * p4;
		    * p3 = 0;

		    //-- Scan for ":" to split user and pass.
		    user_p = p4 = p2;
		    while ( * p4 && * p4 != ':' ) ++ p4;
		    if ( * p4 == ':' ) {
			* p4 = 0;
			pass_p = p4 + 1;
		    }
		    p2 = p3 + 1;
		}
	    }

	    //-- Scan for ":" to split host and port.
	    {
		char * p3;
		host_p = p3 = p2;
		while ( * p3 && * p3 != ':' ) ++ p3;
		if ( * p3 ) {
		    * p3 = 0;
		    port_p = ++ p3;
		}
	    }

	}

	//-- What remains is the path and may have leading "/".
	path_p = p1;
    }

    if ( arg_prot_p ) * arg_prot_p = prot_p;
    if ( arg_user_p ) * arg_user_p = user_p;
    if ( arg_pass_p ) * arg_pass_p = pass_p;
    if ( arg_host_p ) * arg_host_p = host_p;
    if ( arg_port_p ) * arg_port_p = port_p;
    if ( arg_path_p ) * arg_path_p = path_p;
    if ( arg_qstr_p ) * arg_qstr_p = qstr_p;

    return rc;
}

