diff --git a/src/libCom/misc/epicsString.c b/src/libCom/misc/epicsString.c index 7db59b230..76a85fcbd 100644 --- a/src/libCom/misc/epicsString.c +++ b/src/libCom/misc/epicsString.c @@ -1,4 +1,5 @@ /*************************************************************************\ +* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie. * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as @@ -9,7 +10,7 @@ /* $Id$ */ /* Authors: Jun-ichi Odagiri, Marty Kraimer, Eric Norum, - * Mark Rivers, Andrew Johnson + * Mark Rivers, Andrew Johnson, Ralph Lange */ #include @@ -24,76 +25,149 @@ #include "cantProceed.h" #include "epicsString.h" +/* Deprecated: This may be insecure; use epicsStrnRawFromEscaped instead */ int dbTranslateEscape(char *to, const char *from) +{ + size_t big_enough = strlen(from)+1; + return epicsStrnRawFromEscaped(to, big_enough, from, big_enough); +} + +int epicsStrnRawFromEscaped(char *to, size_t outsize, const char *from, size_t inlen) { const char *pfrom = from; char *pto = to; char c; - int nto=0; + int nto=0, nfrom=0; - while( (c = *pfrom++ ) ){ - if(c=='\\') { - switch( *pfrom ){ - case 'a': pfrom++; *pto++ = '\a' ; nto++; break; - case 'b': pfrom++; *pto++ = '\b' ; nto++; break; - case 'f': pfrom++; *pto++ = '\f' ; nto++; break; - case 'n': pfrom++; *pto++ = '\n' ; nto++; break; - case 'r': pfrom++; *pto++ = '\r' ; nto++; break; - case 't': pfrom++; *pto++ = '\t' ; nto++; break; - case 'v': pfrom++; *pto++ = '\v' ; nto++; break; - case '\\': pfrom++; *pto++ = '\\' ; nto++; break; - case '\?': pfrom++; *pto++ = '\?' ; nto++; break; - case '\'': pfrom++; *pto++ = '\'' ; nto++; break; - case '\"': pfrom++; *pto++ = '\"' ; nto++; break; - case '0' :case '1' :case '2' :case '3' : - case '4' :case '5' :case '6' :case '7' : - { - int i; - char strval[4] = {0,0,0,0}; - unsigned int ival; - unsigned char *pchar; + while( (c = *pfrom++) && nto < outsize && nfrom < inlen){ + nfrom++; + if(c == '\\') { + if( nfrom >= inlen || *pfrom == '\0' ) break; + switch( *pfrom ){ + case 'a': pfrom++; nfrom++; *pto++ = '\a' ; nto++; break; + case 'b': pfrom++; nfrom++; *pto++ = '\b' ; nto++; break; + case 'f': pfrom++; nfrom++; *pto++ = '\f' ; nto++; break; + case 'n': pfrom++; nfrom++; *pto++ = '\n' ; nto++; break; + case 'r': pfrom++; nfrom++; *pto++ = '\r' ; nto++; break; + case 't': pfrom++; nfrom++; *pto++ = '\t' ; nto++; break; + case 'v': pfrom++; nfrom++; *pto++ = '\v' ; nto++; break; + case '\\': pfrom++; nfrom++; *pto++ = '\\' ; nto++; break; + case '\?': pfrom++; nfrom++; *pto++ = '\?' ; nto++; break; + case '\'': pfrom++; nfrom++; *pto++ = '\'' ; nto++; break; + case '\"': pfrom++; nfrom++; *pto++ = '\"' ; nto++; break; + case '0' :case '1' :case '2' :case '3' : + case '4' :case '5' :case '6' :case '7' : + { + int i; + char strval[4] = {0,0,0,0}; + unsigned int ival; + unsigned char *pchar; - for(i=0; i<3; i++) { - if((*pfrom < '0') || (*pfrom > '7')) break; - strval[i] = *pfrom++; - } - sscanf(strval,"%o",&ival); - pchar = (unsigned char *)(pto++); nto++; - *pchar = (unsigned char)(ival); + for(i=0; i<3; i++) { + if((*pfrom < '0') || (*pfrom > '7')) break; + strval[i] = *pfrom++; nfrom++; + } + sscanf(strval,"%o",&ival); + pchar = (unsigned char *)(pto++); nto++; + *pchar = (unsigned char)(ival); + } + break; + case 'x' : + { + int i; + char strval[3] = {0,0,0}; + unsigned int ival; + unsigned char *pchar; + + pfrom++; /*skip the x*/ + for(i=0; i<2; i++) { + if(!isxdigit((int)*pfrom)) break; + strval[i] = *pfrom++; nfrom++; + } + sscanf(strval,"%x",&ival); + pchar = (unsigned char *)(pto++); nto++; + *pchar = (unsigned char)(ival); + } + break; + default: + *pto++ = *pfrom++; nfrom++; nto++; } - break; - case 'x' : - { - int i; - char strval[3] = {0,0,0}; - unsigned int ival; - unsigned char *pchar; - - pfrom++; /*skip the x*/ - for(i=0; i<2; i++) { - if(!isxdigit((int)*pfrom)) break; - strval[i] = *pfrom++; - } - sscanf(strval,"%x",&ival); - pchar = (unsigned char *)(pto++); nto++; - *pchar = (unsigned char)(ival); - } - break; - default: - *pto++ = *pfrom++; - } } else { - *pto++ = c; nto++; + *pto++ = c; nto++; } } - *pto = '\0'; /*NOTE that nto does not have to be incremented*/ + *pto = '\0'; /* NOTE that nto does not have to be incremented */ return(nto); } +int epicsStrnEscapedFromRaw(char *outbuf, size_t outsize, const char *inbuf, size_t inlen) +{ + int maxout = outsize; + int nout = 0; + int len; + char *outpos = outbuf; + + while (inlen--) { + char c = *inbuf++; + switch (c) { + case '\a': len = epicsSnprintf(outpos, maxout, "\\a"); break; + case '\b': len = epicsSnprintf(outpos, maxout, "\\b"); break; + case '\f': len = epicsSnprintf(outpos, maxout, "\\f"); break; + case '\n': len = epicsSnprintf(outpos, maxout, "\\n"); break; + case '\r': len = epicsSnprintf(outpos, maxout, "\\r"); break; + case '\t': len = epicsSnprintf(outpos, maxout, "\\t"); break; + case '\v': len = epicsSnprintf(outpos, maxout, "\\v"); break; + case '\\': len = epicsSnprintf(outpos, maxout, "\\\\"); ; break; + /*? does not follow C convention because trigraphs no longer important*/ + case '\?': len = epicsSnprintf(outpos, maxout, "?"); break; + case '\'': len = epicsSnprintf(outpos, maxout, "\\'"); break; + case '\"': len = epicsSnprintf(outpos, maxout, "\\\""); break; + default: + if (isprint((int)c)) + len = epicsSnprintf(outpos, maxout, "%c", c); + else + len = epicsSnprintf(outpos, maxout, "\\%03o", (unsigned char)c); + break; + } + if(len<0) return -1; + nout += len; + if(nout < outsize) { + maxout -= len; + outpos += len; + } else { + outpos = outpos + maxout -1; + maxout = 1; + } + } + *outpos = '\0'; + return nout; +} + +size_t epicsStrnEscapedFromRawSize(const char *inbuf, size_t inlen) +{ + size_t nout = inlen; + + while (inlen--) { + char c = *inbuf++; + switch (c) { + case '\a': case '\b': case '\f': case '\n': + case '\r': case '\t': case '\v': case '\\': + case '\?': case '\'': case '\"': + inlen++; + break; + default: + if (!isprint((int)c)) + nout += 4; + break; + } + } + return nout; +} + int epicsStrCaseCmp(const char *s1, const char *s2) { int nexts1,nexts2; - + while(1) { /* vxWorks implementation expands argument more than once!!! */ nexts1 = toupper(*s1); @@ -111,7 +185,7 @@ int epicsStrnCaseCmp(const char *s1, const char *s2, int n) { size_t ind = 0; int nexts1,nexts2; - + while(1) { if(ind++ >= (size_t)n) break; /* vxWorks implementation expands argument more than once!!! */ @@ -161,49 +235,6 @@ int epicsStrPrintEscaped(FILE *fp, const char *s, int n) return nout; } -int epicsStrSnPrintEscaped(char *outbuf, int outsize, const char *inbuf, - int inlen) -{ - int maxout = outsize; - int nout = 0; - int len; - char *outpos = outbuf; - - while (inlen--) { - char c = *inbuf++; - switch (c) { - case '\a': len = epicsSnprintf(outpos, maxout, "\\a"); break; - case '\b': len = epicsSnprintf(outpos, maxout, "\\b"); break; - case '\f': len = epicsSnprintf(outpos, maxout, "\\f"); break; - case '\n': len = epicsSnprintf(outpos, maxout, "\\n"); break; - case '\r': len = epicsSnprintf(outpos, maxout, "\\r"); break; - case '\t': len = epicsSnprintf(outpos, maxout, "\\t"); break; - case '\v': len = epicsSnprintf(outpos, maxout, "\\v"); break; - case '\\': len = epicsSnprintf(outpos, maxout, "\\\\"); ; break; - /*? does not follow C convention because trigraphs no longer important*/ - case '\?': len = epicsSnprintf(outpos, maxout, "?"); break; - case '\'': len = epicsSnprintf(outpos, maxout, "\\'"); break; - case '\"': len = epicsSnprintf(outpos, maxout, "\\\""); break; - default: - if (isprint((int)c)) - len = epicsSnprintf(outpos, maxout, "%c", c); - else - len = epicsSnprintf(outpos, maxout, "\\%03o", (unsigned char)c); - break; - } - if(len<0) return -1; - nout += len; - if(nout < outsize) { - maxout -= len; - outpos += len; - } else { - outpos = outpos + maxout -1; - maxout = 1; - } - } - return nout; -} - int epicsStrGlobMatch(const char *str, const char *pattern) { const char *cp=NULL, *mp=NULL; diff --git a/src/libCom/misc/epicsString.h b/src/libCom/misc/epicsString.h index c1c2c2545..8cf9d26a0 100644 --- a/src/libCom/misc/epicsString.h +++ b/src/libCom/misc/epicsString.h @@ -1,4 +1,5 @@ /*************************************************************************\ +* Copyright (c) 2009 Helmholtz-Zentrum Berlin fuer Materialien und Energie. * Copyright (c) 2009 UChicago Argonne LLC, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as @@ -9,7 +10,7 @@ /* $Id$ */ /* Authors: Jun-ichi Odagiri, Marty Kraimer, Eric Norum, - * Mark Rivers, Andrew Johnson + * Mark Rivers, Andrew Johnson, Ralph Lange */ #ifndef INC_epicsString_H @@ -23,18 +24,23 @@ extern "C" { #endif -epicsShareFunc int dbTranslateEscape(char *s,const char *ct); -epicsShareFunc int epicsStrCaseCmp(const char *s1,const char *s2); -epicsShareFunc int epicsStrnCaseCmp(const char *s1,const char *s2, int n); +epicsShareFunc int epicsStrnRawFromEscaped(char *outbuf, size_t outsize, + const char *inbuf, size_t inlen); +epicsShareFunc int epicsStrnEscapedFromRaw(char *outbuf, size_t outsize, + const char *inbuf, size_t inlen); +epicsShareFunc size_t epicsStrnEscapedFromRawSize(const char *inbuf, size_t inlen); +epicsShareFunc int epicsStrCaseCmp(const char *s1, const char *s2); +epicsShareFunc int epicsStrnCaseCmp(const char *s1, const char *s2, int n); epicsShareFunc char * epicsStrDup(const char *s); epicsShareFunc int epicsStrPrintEscaped(FILE *fp, const char *s, int n); -epicsShareFunc int epicsStrSnPrintEscaped(char *outbuf, int outsize, - const char *inbuf, int inlen); +#define epicsStrSnPrintEscaped epicsStrnEscapedFromRaw epicsShareFunc int epicsStrGlobMatch(const char *str, const char *pattern); epicsShareFunc char * epicsStrtok_r(char *s, const char *delim, char **lasts); epicsShareFunc unsigned int epicsStrHash(const char *str, unsigned int seed); epicsShareFunc unsigned int epicsMemHash(const char *str, size_t length, - unsigned int seed); + unsigned int seed); +/* dbTranslateEscape is deprecated, use epicsStrnRawFromEscaped instead */ +epicsShareFunc int dbTranslateEscape(char *s, const char *ct); #ifdef __cplusplus }