/***************************************************************************/ /* */ /* 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; }