From: Arran Cudbard-Bell Date: Mon, 24 Oct 2011 11:20:39 +0000 (+0200) Subject: Add function to print VP values as JSON strings X-Git-Tag: release_3_0_0_beta0~548 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb608f5f9baf73d078212191e1c8441c8fc703b4;p=thirdparty%2Ffreeradius-server.git Add function to print VP values as JSON strings --- diff --git a/src/include/libradius.h b/src/include/libradius.h index fa438a0b0a0..0a2effdbfcc 100644 --- a/src/include/libradius.h +++ b/src/include/libradius.h @@ -256,6 +256,8 @@ size_t fr_print_string(const char *in, size_t inlen, char *out, size_t outlen); int vp_prints_value(char *out, size_t outlen, const VALUE_PAIR *vp, int delimitst); +int vp_prints_value_json(char *out, size_t outlen, + const VALUE_PAIR *vp); size_t vp_print_name(char *buffer, size_t bufsize, unsigned int attr, unsigned int vendor); int vp_prints(char *out, size_t outlen, const VALUE_PAIR *vp); diff --git a/src/lib/print.c b/src/lib/print.c index 20985282fea..a0d4498484c 100644 --- a/src/lib/print.c +++ b/src/lib/print.c @@ -362,6 +362,86 @@ int vp_prints_value(char * out, size_t outlen, const VALUE_PAIR *vp, int delimit return strlen(out); } +/* + * Almost identical to vp_prints_value, but escapes certain chars so the string + * may be used as a JSON value. + * + * Returns < 0 if the buffer may be (or have been) too small to write the encoded + * JSON value to. + */ +int vp_prints_value_json(char *buffer, size_t bufsize, const VALUE_PAIR *vp) +{ + int s = 0; + char *p = buffer; + const char *q; + + if (!vp->flags.has_tag) { + switch (vp->type) { + case PW_TYPE_INTEGER: + case PW_TYPE_BYTE: + case PW_TYPE_SHORT: + if (vp->flags.has_value) break; + + s = snprintf(buffer, bufsize, "%u", vp->vp_integer); + return ((unsigned) s == (bufsize - 1)) ? -1 : s; + case PW_TYPE_SIGNED: + s = snprintf(buffer, bufsize, "%d", vp->vp_signed); + return ((unsigned) s == (bufsize - 1)) ? -1 : s; + } + } + + if(bufsize < 3) return -1; + *p++ = '"'; + + switch (vp->type) { + case PW_TYPE_STRING: + for (q = vp->vp_strvalue; q < vp->vp_strvalue + vp->length; q++) { + s = bufsize - (p - buffer); + if (s < 3) return -1; + + if (*q == '"') { + *p++ = '\\'; + *p++ = '"'; + } else if (*q == '\\') { + *p++ = '\\'; + *p++ = '\\'; + } else if (*q == '/') { + *p++ = '\\'; + *p++ = '/'; + } else if (*q >= ' ') { + *p++ = *q; + } else { + *p++ = '\\'; + + if (*q == '\b') { + *p++ = 'b'; + } else if (*q == '\f') { + *p++ = 'f'; + } else if (*q == '\n') { + *p++ = 'n'; + } else if (*q == '\r') { + *p++ = 'r'; + } else if (*q == '\t'){ + *p++ = 't'; + } else { + if(s < 7) return -1; + *p += sprintf(p, "u%04X", *q); + } + } + } + break; + + default: + p += vp_prints_value(p, bufsize, vp, 0); + break; + } + + *p++ = '"'; + *p = '\0'; + + return p - buffer; +} + /* * This is a hack, and has to be kept in sync with tokens.h */