fis-gtm/sr_port/lke_getki.c

164 lines
4.8 KiB
C

/****************************************************************
* *
* Copyright 2006, 2013 Fidelity Information Services, Inc *
* *
* This source code contains the intellectual property *
* of its copyright holder(s), and is made available *
* under a license. If you do not know the terms of *
* the license, please stop and do not read further. *
* *
****************************************************************/
#include "mdef.h"
#include "gtm_string.h"
#include "lke_getcli.h"
#include "gtm_ctype.h" /* Needed for TOUPPER() */
/* This routine performs the necessary transformation of the LOCK keys passed in
* from the CLI layer and produces a canonical formatted key. This routine
*
* validates if the key is indeed in the correct syntax.
*
* adds quotes to the string subscripts (which were removed by the CLI
* layer on UNIX)
*
* removes the redundant quotes in the key (which were passed intact by
* CLI layer on VMS).
*
*/
int lke_getki(char* src, int srclen, char* outbuff)
{
char *inptr, *nextptr, *intop, *outptr, *tmpptr;
mval subsc = DEFINE_MVAL_STRING(MV_STR, 0, 0, 0, NULL, 0, 0);
char one_lockbuf[MAX_ZWR_KEY_SZ + 1], *one_char;
char *valid_char = "HAR"; /* This is used for validating characters following $ZCH and $C */
if (srclen > 1 && '"' == src[0] && '"' == src[srclen - 1])
{
outptr = one_lockbuf;
for (inptr = ++src, intop = src + srclen - 2; inptr < intop; *outptr++ = *inptr++)
{
if ('"' == *inptr && (++inptr >= intop || *inptr != '"'))
return -1; /* invalid (unescaped) quote within a quoted key */
}
src = one_lockbuf;
srclen = (int)(outptr - one_lockbuf);
}
inptr = memchr(src, '(', srclen);
if (NULL == inptr)
{
memcpy(outbuff, src, srclen);
return srclen;
}
++inptr;
outptr = outbuff;
memcpy(outptr, src, inptr - src);
outptr += inptr - src;
for (intop = src + srclen; inptr < intop; inptr = nextptr)
{
if (')' == *inptr) /* Catches incomplete lists or string concatenations */
return -1;
else if ('$' == *inptr)
{ /* the entire subscript is within $C() or $ZCH */
*outptr++ = '$';
inptr++;
if (('z' == *inptr) || ('Z' == *inptr))
{ /* Very likely $ZCHAR() */
*outptr++ = 'Z';
inptr++;
}
if (('c' == *inptr) || ('C' == *inptr))
{
*outptr++ = 'C';
inptr++;
if (('Z' == *(outptr - 2)) && (('h' == *inptr) || ('H' == *inptr)))
{
*outptr++ ='H';
inptr++;
one_char = valid_char + 1;
}
else
one_char = valid_char;
/* Validate/skip letters following C so that we allow C, CH, CHA, CHAR */
while (('\0' != *one_char) && ('(' != *inptr))
if (TOUPPER(*inptr++) != *one_char++)
return -1;
if ('(' != *inptr)
return -1;
} else /* We don't support anything other than $C() or $ZCH in locks */
return -1;
nextptr = memchr(inptr, ')', intop - inptr);
if (NULL == nextptr)
return -1;
++nextptr;
memcpy(outptr, inptr, nextptr - inptr);
outptr += nextptr - inptr;
} else
{
if ('"' == *inptr) /* Is this a quoted string? */
{ /*Process character by character because '_' or ',' can be used within the quotes. */
for (nextptr = inptr + 1; nextptr < intop; nextptr++)
if ('"' == *nextptr && (nextptr + 1 < intop))
{
nextptr++;
if ('"' != *nextptr)
/* This is not a two double-quote so terminate. */
break;
}
} else
{ /* Fast-forward to the next separator */
nextptr = memchr(inptr, '_', intop - inptr);
if (NULL == nextptr)
{ /* Not a string concatineated with $C() or $ZCH() */
nextptr = memchr(inptr, ',', intop - inptr);
if (NULL == nextptr)
nextptr = intop - 1;
}
}
if (intop - 1 == nextptr)
{ /* If it reached to the end, it had better closed the paran */
if (')' != *nextptr)
return -1;
}
else if ((',' != *nextptr) && ('_' != *nextptr))
/* If we are not at the end, it must be a separator*/
return -1;
subsc.str.len = INTCAST(nextptr - inptr);
subsc.str.addr = inptr;
if (val_iscan(&subsc))
{
memcpy(outptr, subsc.str.addr, subsc.str.len);
outptr += subsc.str.len;
} else
{
if (nextptr - 1 > inptr && '"' == *inptr && '"' == *(nextptr - 1))
{ /* The string is already enclosed by a pair of quotes */
memcpy(outptr, inptr, nextptr - inptr);
outptr += nextptr - inptr;
inptr += nextptr - inptr;
} else
{ /* unquoted string: add quotes */
*outptr++ = '"';
for (tmpptr = inptr; tmpptr < nextptr; ++tmpptr)
{
*outptr++ = *tmpptr;
if ('"' == *tmpptr)
*outptr++ = '"';
if ('_' == *tmpptr)
{
*--outptr;
nextptr = tmpptr;
}
}
*outptr++ = '"';
}
}
}
if ((',' != *nextptr) && (')' != *nextptr) && ('_' != *nextptr))
return -1;
*outptr++ = *nextptr++;
}
return (int)(outptr - outbuff);
}