You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
423 lines
20 KiB
423 lines
20 KiB
4 years ago
|
/***************************************************************************/
|
||
|
/* */
|
||
|
/* Project: OpenSLP - OpenSource implementation of Service Location */
|
||
|
/* Protocol Version 2 */
|
||
|
/* */
|
||
|
/* File: slplib_parse.c */
|
||
|
/* */
|
||
|
/* Abstract: Implementation for SLPParseSrvUrl(), SLPEscape(), */
|
||
|
/* SLPUnescape() and SLPFree() calls. */
|
||
|
/* */
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* Please submit patches to http://www.openslp.org */
|
||
|
/* */
|
||
|
/*-------------------------------------------------------------------------*/
|
||
|
/* */
|
||
|
/* Copyright (C) 2000 Caldera Systems, Inc */
|
||
|
/* All rights reserved. */
|
||
|
/* */
|
||
|
/* Redistribution and use in source and binary forms, with or without */
|
||
|
/* modification, are permitted provided that the following conditions are */
|
||
|
/* met: */
|
||
|
/* */
|
||
|
/* Redistributions of source code must retain the above copyright */
|
||
|
/* notice, this list of conditions and the following disclaimer. */
|
||
|
/* */
|
||
|
/* Redistributions in binary form must reproduce the above copyright */
|
||
|
/* notice, this list of conditions and the following disclaimer in */
|
||
|
/* the documentation and/or other materials provided with the */
|
||
|
/* distribution. */
|
||
|
/* */
|
||
|
/* Neither the name of Caldera Systems nor the names of its */
|
||
|
/* contributors may be used to endorse or promote products derived */
|
||
|
/* from this software without specific prior written permission. */
|
||
|
/* */
|
||
|
/* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
|
||
|
/* `AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
|
||
|
/* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
|
||
|
/* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE CALDERA */
|
||
|
/* SYSTEMS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
|
||
|
/* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
|
||
|
/* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
|
||
|
/* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
|
||
|
/* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
|
||
|
/* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
|
||
|
/* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
|
||
|
/* */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
#include "slp.h"
|
||
|
#include "libslp.h"
|
||
|
|
||
|
#ifdef _WIN32 /* on Win32 strncasecmp is named strnicmp, but behaves the same */
|
||
|
#define strncasecmp(String1, String2, Num) strnicmp(String1, String2, Num)
|
||
|
#endif
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
void SLPAPI SLPFree(void* pvMem)
|
||
|
/* */
|
||
|
/* Frees memory returned from SLPParseSrvURL(), SLPFindScopes(), */
|
||
|
/* SLPEscape(), and SLPUnescape(). */
|
||
|
/* */
|
||
|
/* pvMem A pointer to the storage allocated by the SLPParseSrvURL(), */
|
||
|
/* SLPEscape(), SLPUnescape(), or SLPFindScopes() function. */
|
||
|
/* Ignored if NULL. */
|
||
|
/*=========================================================================*/
|
||
|
{
|
||
|
if(pvMem)
|
||
|
{
|
||
|
xfree(pvMem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
SLPError SLPAPI SLPParseSrvURL(const char *pcSrvURL,
|
||
|
SLPSrvURL** ppSrvURL)
|
||
|
/* */
|
||
|
/* Parses the URL passed in as the argument into a service URL structure */
|
||
|
/* and returns it in the ppSrvURL pointer. If a parse error occurs, */
|
||
|
/* returns SLP_PARSE_ERROR. The input buffer pcSrvURL is destructively */
|
||
|
/* modified during the parse and used to fill in the fields of the */
|
||
|
/* return structure. The structure returned in ppSrvURL should be freed */
|
||
|
/* with SLPFreeURL(). If the URL has no service part, the s_pcSrvPart */
|
||
|
/* string is the empty string, "", i.e. not NULL. If pcSrvURL is not a */
|
||
|
/* service: URL, then the s_pcSrvType field in the returned data */
|
||
|
/* structure is the URL's scheme, which might not be the same as the */
|
||
|
/* service type under which the URL was registered. If the transport is */
|
||
|
/* IP, the s_pcTransport field is the empty string. If the transport is */
|
||
|
/* not IP or there is no port number, the s_iPort field is zero. */
|
||
|
/* */
|
||
|
/* pcSrvURL A pointer to a character buffer containing the null terminated */
|
||
|
/* URL string to parse. */
|
||
|
/* */
|
||
|
/* ppSrvURL A pointer to a pointer for the SLPSrvURL structure to receive */
|
||
|
/* the parsed URL. The memory should be freed by a call to */
|
||
|
/* SLPFree() when no longer needed. */
|
||
|
/* */
|
||
|
/* Returns: If no error occurs, the return value is SLP_OK. Otherwise, the */
|
||
|
/* appropriate error code is returned. */
|
||
|
/*=========================================================================*/
|
||
|
{
|
||
|
int result = SLPParseSrvUrl(strlen(pcSrvURL),
|
||
|
pcSrvURL,
|
||
|
(SLPParsedSrvUrl**) ppSrvURL);
|
||
|
switch(result)
|
||
|
{
|
||
|
case ENOMEM:
|
||
|
return SLP_MEMORY_ALLOC_FAILED;
|
||
|
case EINVAL:
|
||
|
return SLP_PARSE_ERROR;
|
||
|
}
|
||
|
|
||
|
return SLP_OK;
|
||
|
}
|
||
|
|
||
|
#define ATTRIBUTE_RESERVE_STRING "(),\\!<=>~"
|
||
|
#define ATTRIBUTE_BAD_TAG "\r\n\t_"
|
||
|
#define ESCAPE_CHARACTER '\\'
|
||
|
#define ESCAPE_CHARACTER_STRING "\\"
|
||
|
/*=========================================================================*/
|
||
|
SLPError SLPAPI SLPEscape(const char* pcInbuf,
|
||
|
char** ppcOutBuf,
|
||
|
SLPBoolean isTag)
|
||
|
/* */
|
||
|
/* Process the input string in pcInbuf and escape any SLP reserved */
|
||
|
/* characters. If the isTag parameter is SLPTrue, then look for bad tag */
|
||
|
/* characters and signal an error if any are found by returning the */
|
||
|
/* SLP_PARSE_ERROR code. The results are put into a buffer allocated by */
|
||
|
/* the API library and returned in the ppcOutBuf parameter. This buffer */
|
||
|
/* should be deallocated using SLPFree() when the memory is no longer */
|
||
|
/* needed. */
|
||
|
/* */
|
||
|
/* pcInbuf Pointer to he input buffer to process for escape */
|
||
|
/* characters. */
|
||
|
/* */
|
||
|
/* ppcOutBuf Pointer to a pointer for the output buffer with the SLP */
|
||
|
/* reserved characters escaped. Must be freed using */
|
||
|
/* SLPFree()when the memory is no longer needed. */
|
||
|
/* */
|
||
|
/* isTag When true, the input buffer is checked for bad tag */
|
||
|
/* characters. */
|
||
|
/* */
|
||
|
/* Returns: Return SLP_PARSE_ERROR if any characters are bad tag */
|
||
|
/* characters and the isTag flag is true, otherwise SLP_OK, */
|
||
|
/* or the appropriate error code if another error occurs. */
|
||
|
/*=========================================================================*/
|
||
|
{
|
||
|
char *current_inbuf, *current_outBuf;
|
||
|
int amount_of_escape_characters;
|
||
|
char hex_digit;
|
||
|
|
||
|
/* Ensure that the parameters are good. */
|
||
|
if((pcInbuf == NULL) || ((isTag != SLP_TRUE) && (isTag != SLP_FALSE)))
|
||
|
return(SLP_PARAMETER_BAD);
|
||
|
|
||
|
/*
|
||
|
* Loop thru the string, counting the number of reserved characters
|
||
|
* and checking for bad tags when required. This is also used to
|
||
|
* calculate the size of the new string to create.
|
||
|
* ASSUME: that pcInbuf is a NULL terminated string.
|
||
|
*/
|
||
|
current_inbuf = (char *) pcInbuf;
|
||
|
amount_of_escape_characters = 0;
|
||
|
|
||
|
while(*current_inbuf != '\0')
|
||
|
{
|
||
|
/* Ensure that there are no bad tags when it is a tag. */
|
||
|
if((isTag) && strchr(ATTRIBUTE_BAD_TAG, *current_inbuf))
|
||
|
return(SLP_PARSE_ERROR);
|
||
|
|
||
|
if((strchr(ATTRIBUTE_RESERVE_STRING, *current_inbuf)) ||
|
||
|
((*current_inbuf >= 0x00) && (*current_inbuf <= 0x1F)) ||
|
||
|
(*current_inbuf == 0x7F)
|
||
|
)
|
||
|
amount_of_escape_characters++;
|
||
|
|
||
|
current_inbuf++;
|
||
|
} /* End While. */
|
||
|
|
||
|
/* Allocate the string. */
|
||
|
*ppcOutBuf = (char *) xmalloc(
|
||
|
sizeof(char) *
|
||
|
(strlen(pcInbuf) + (amount_of_escape_characters * 2) + 1));
|
||
|
|
||
|
if(ppcOutBuf == NULL)
|
||
|
return(SLP_MEMORY_ALLOC_FAILED);
|
||
|
|
||
|
/*
|
||
|
* Go over it, again. Replace each of the escape characters with their
|
||
|
* \hex equivalent.
|
||
|
*/
|
||
|
current_inbuf = (char *) pcInbuf;
|
||
|
current_outBuf = *ppcOutBuf;
|
||
|
while(*current_inbuf != '\0')
|
||
|
{
|
||
|
/* Check to see if it is an escape character. */
|
||
|
if((strchr(ATTRIBUTE_RESERVE_STRING, *current_inbuf)) ||
|
||
|
((*current_inbuf >= 0x00) && (*current_inbuf <= 0x1F)) ||
|
||
|
(*current_inbuf == 0x7F)
|
||
|
)
|
||
|
{
|
||
|
/* Insert the escape character. */
|
||
|
*current_outBuf = ESCAPE_CHARACTER;
|
||
|
current_outBuf++;
|
||
|
|
||
|
/* Do the first digit. */
|
||
|
hex_digit = (*current_inbuf & 0xF0)/0x0F;
|
||
|
if((hex_digit >= 0) && (hex_digit <= 9))
|
||
|
*current_outBuf = hex_digit + '0';
|
||
|
else
|
||
|
*current_outBuf = hex_digit + 'A' - 0x0A;
|
||
|
|
||
|
current_outBuf++;
|
||
|
|
||
|
/* Do the last digit. */
|
||
|
hex_digit = *current_inbuf & 0x0F;
|
||
|
if((hex_digit >= 0) && (hex_digit <= 9))
|
||
|
*current_outBuf = hex_digit + '0';
|
||
|
else
|
||
|
*current_outBuf = hex_digit + 'A' - 0x0A;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*current_outBuf = *current_inbuf;
|
||
|
} /* End If, Else. */
|
||
|
|
||
|
current_outBuf += sizeof(char);
|
||
|
current_inbuf += sizeof(char);
|
||
|
} /* End While. */
|
||
|
|
||
|
/* Make sure that the string is properly terminated. */
|
||
|
*current_outBuf = '\0';
|
||
|
|
||
|
return(SLP_OK);
|
||
|
}
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
SLPError SLPAPI SLPUnescape(const char* pcInbuf,
|
||
|
char** ppcOutBuf,
|
||
|
SLPBoolean isTag)
|
||
|
/* */
|
||
|
/* Process the input string in pcInbuf and unescape any SLP reserved */
|
||
|
/* characters. If the isTag parameter is SLPTrue, then look for bad tag */
|
||
|
/* characters and signal an error if any are found with the */
|
||
|
/* SLP_PARSE_ERROR code. No transformation is performed if the input */
|
||
|
/* string is an opaque. The results are put into a buffer allocated by */
|
||
|
/* the API library and returned in the ppcOutBuf parameter. This buffer */
|
||
|
/* should be deallocated using SLPFree() when the memory is no longer */
|
||
|
/* needed. */
|
||
|
/* */
|
||
|
/* pcInbuf Pointer to he input buffer to process for escape */
|
||
|
/* characters. */
|
||
|
/* */
|
||
|
/* ppcOutBuf Pointer to a pointer for the output buffer with the SLP */
|
||
|
/* reserved characters escaped. Must be freed using */
|
||
|
/* SLPFree() when the memory is no longer needed. */
|
||
|
/* */
|
||
|
/* isTag When true, the input buffer is checked for bad tag */
|
||
|
/* characters. */
|
||
|
/* */
|
||
|
/* Returns: Return SLP_PARSE_ERROR if any characters are bad tag */
|
||
|
/* characters and the isTag flag is true, otherwise SLP_OK, */
|
||
|
/* or the appropriate error code if another error occurs. */
|
||
|
/*=========================================================================*/
|
||
|
{
|
||
|
int output_buffer_size;
|
||
|
char *current_Inbuf, *current_OutBuf;
|
||
|
char escaped_digit[2];
|
||
|
|
||
|
/* Ensure that the parameters are good. */
|
||
|
if((pcInbuf == NULL) || ((isTag != SLP_TRUE) && (isTag != SLP_FALSE)))
|
||
|
return(SLP_PARAMETER_BAD);
|
||
|
|
||
|
/*
|
||
|
* Loop thru the string, counting the number of escape characters
|
||
|
* and checking for bad tags when required. This is also used to
|
||
|
* calculate the size of the new string to create.
|
||
|
* ASSUME: that pcInbuf is a NULL terminated string.
|
||
|
*/
|
||
|
current_Inbuf = (char *) pcInbuf;
|
||
|
output_buffer_size = strlen(pcInbuf);
|
||
|
|
||
|
while(*current_Inbuf != '\0')
|
||
|
{
|
||
|
/* Ensure that there are no bad tags when it is a tag. */
|
||
|
if((isTag) && strchr(ATTRIBUTE_BAD_TAG, *current_Inbuf))
|
||
|
return(SLP_PARSE_ERROR);
|
||
|
|
||
|
if(strchr(ESCAPE_CHARACTER_STRING, *current_Inbuf))
|
||
|
output_buffer_size-=2;
|
||
|
|
||
|
current_Inbuf++;
|
||
|
} /* End While. */
|
||
|
|
||
|
/* Allocate the string. */
|
||
|
*ppcOutBuf = (char *) xmalloc((sizeof(char) * output_buffer_size) + 1);
|
||
|
|
||
|
if(ppcOutBuf == NULL)
|
||
|
return(SLP_MEMORY_ALLOC_FAILED);
|
||
|
|
||
|
current_Inbuf = (char *) pcInbuf;
|
||
|
current_OutBuf = *ppcOutBuf;
|
||
|
|
||
|
while(*current_Inbuf != '\0')
|
||
|
{
|
||
|
/* Check to see if it is an escape character. */
|
||
|
if(strchr(ESCAPE_CHARACTER_STRING, *current_Inbuf))
|
||
|
{
|
||
|
/* Insert the real character based on the escaped character. */
|
||
|
escaped_digit[0] = *(current_Inbuf + sizeof(char));
|
||
|
escaped_digit[1] = *(current_Inbuf + (sizeof(char) * 2));
|
||
|
|
||
|
if((escaped_digit[0] >= 'A') && (escaped_digit[0] <= 'F'))
|
||
|
escaped_digit[0] = escaped_digit[0] - 'A' + 0x0A;
|
||
|
else if((escaped_digit[0] >= '0') && (escaped_digit[0] <= '9'))
|
||
|
escaped_digit[0] = escaped_digit[0] - '0';
|
||
|
else
|
||
|
return(SLP_PARSE_ERROR);
|
||
|
|
||
|
if((escaped_digit[1] >= 'A') && (escaped_digit[1] <= 'F'))
|
||
|
escaped_digit[1] = escaped_digit[1] - 'A' + 0x0A;
|
||
|
else if((escaped_digit[1] >= '0') && (escaped_digit[1] <= '9'))
|
||
|
escaped_digit[1] = escaped_digit[1] - '0';
|
||
|
else
|
||
|
return(SLP_PARSE_ERROR);
|
||
|
|
||
|
*current_OutBuf = escaped_digit[1] + (escaped_digit[0] * 0x10);
|
||
|
current_Inbuf = (char *) current_Inbuf + (sizeof(char) * 2);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*current_OutBuf = *current_Inbuf;
|
||
|
} /* End If, Else. */
|
||
|
|
||
|
/* Move to the next character. */
|
||
|
current_OutBuf++;
|
||
|
current_Inbuf++;
|
||
|
} /* End While. */
|
||
|
|
||
|
/* Make sure we terminate the string properly. */
|
||
|
*current_OutBuf = '\0';
|
||
|
|
||
|
return(SLP_OK);
|
||
|
}
|
||
|
|
||
|
|
||
|
/*=========================================================================*/
|
||
|
SLPError SLPAPI SLPParseAttrs(const char* pcAttrList,
|
||
|
const char *pcAttrId,
|
||
|
char** ppcAttrVal)
|
||
|
/* */
|
||
|
/* Used to get individual attribute values from an attribute string that */
|
||
|
/* is passed to the SLPAttrCallback */
|
||
|
/* */
|
||
|
/* pcAttrList (IN) A character buffer containing a comma separated, null */
|
||
|
/* terminated list of attribute id/value assignments, in */
|
||
|
/* SLP wire format; i.e. "(attr-id=attr-value-list)" */
|
||
|
/* */
|
||
|
/* pcAttrId (IN) The string indicating which attribute value to return. */
|
||
|
/* MUST not be null. MUST not be the empty string (""). */
|
||
|
/* */
|
||
|
/* ppcAttrVal (IN) A pointer to a pointer to the buffer to receive */
|
||
|
/* attribute value. The memory should be freed by a call */
|
||
|
/* to SLPFree() when no longer needed. */
|
||
|
/* */
|
||
|
/* Returns: Returns SLP_PARSE_ERROR if an attribute of the specified id */
|
||
|
/* was not found otherwise SLP_OK */
|
||
|
/*=========================================================================*/
|
||
|
{
|
||
|
const char* slider1;
|
||
|
const char* slider2;
|
||
|
int attridlen;
|
||
|
|
||
|
/* Check for bad parameters */
|
||
|
if(pcAttrList == 0 ||
|
||
|
pcAttrId == 0 ||
|
||
|
ppcAttrVal == 0)
|
||
|
{
|
||
|
return SLP_PARAMETER_BAD;
|
||
|
}
|
||
|
|
||
|
attridlen = strlen(pcAttrId);
|
||
|
slider1 = pcAttrList;
|
||
|
while(1)
|
||
|
{
|
||
|
while(*slider1 != '(')
|
||
|
{
|
||
|
if(*slider1 == 0)
|
||
|
{
|
||
|
return SLP_PARSE_ERROR;
|
||
|
}
|
||
|
slider1++;
|
||
|
}
|
||
|
slider1++;
|
||
|
slider2=slider1;
|
||
|
|
||
|
while(*slider2 && *slider2 != '=' && *slider2 !=')') slider2++;
|
||
|
|
||
|
if(attridlen == slider2-slider1 &&
|
||
|
strncasecmp(slider1, pcAttrId, slider2 - slider1) == 0)
|
||
|
{
|
||
|
/* found the attribute id */
|
||
|
slider1 = slider2;
|
||
|
if(*slider1 == '=') slider1++;
|
||
|
while(*slider2 && *slider2 !=')') slider2++;
|
||
|
|
||
|
*ppcAttrVal = (char*)xmalloc((slider2 - slider1) + 1);
|
||
|
if(*ppcAttrVal == 0)
|
||
|
{
|
||
|
return SLP_MEMORY_ALLOC_FAILED;
|
||
|
}
|
||
|
|
||
|
memcpy(*ppcAttrVal,slider1,slider2-slider1);
|
||
|
(*ppcAttrVal)[slider2-slider1] = 0;
|
||
|
|
||
|
return SLP_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* attrid does not exist */
|
||
|
return SLP_PARSE_ERROR;
|
||
|
}
|