summaryrefslogtreecommitdiff
path: root/src/sexp.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2002-01-31 08:06:14 +0000
committerWerner Koch <wk@gnupg.org>2002-01-31 08:06:14 +0000
commit7d7ed402d9fc0f09ed2ab327e7a6fb6dc18cc9ac (patch)
tree53d0412649b38b903fb2cc1c336d49931be763b8 /src/sexp.c
parent0bcbc7ba80d41c8197cb1eee60c13801b276f99c (diff)
downloadlibgcrypt-7d7ed402d9fc0f09ed2ab327e7a6fb6dc18cc9ac.tar.gz
* sexp.c (suitable_encoding,convert_to_hex,convert_to_string)
(convert_to_token): New. (gcry_sexp_sprint): Better formatting of advanced encoding, does now insert LFs and escapes all unprintable characters.
Diffstat (limited to 'src/sexp.c')
-rw-r--r--src/sexp.c304
1 files changed, 252 insertions, 52 deletions
diff --git a/src/sexp.c b/src/sexp.c
index 085ebc96..9b0dda7a 100644
--- a/src/sexp.c
+++ b/src/sexp.c
@@ -45,12 +45,16 @@ struct gcry_sexp {
#define ST_CLOSE 4
#define digitp(p) (*(p) >= '0' && *(p) <= '9')
+#define alphap(a) ( (*(a) >= 'A' && *(a) <= 'Z') \
+ || (*(a) >= 'a' && *(a) <= 'z'))
#define hexdigitp(a) (digitp (a) \
|| (*(a) >= 'A' && *(a) <= 'F') \
|| (*(a) >= 'a' && *(a) <= 'f'))
/* the atoi macros assume that the buffer has only valid digits */
#define atoi_1(p) (*(p) - '0' )
+#define TOKEN_SPECIALS "-./_:*+="
+
#if 0
static void
@@ -1025,6 +1029,123 @@ gcry_sexp_sscan( GCRY_SEXP *retsexp, size_t *erroff,
return sexp_sscan( retsexp, erroff, buffer, length, dummy_arg_ptr, 0 );
}
+
+/* Figure out a suitable encoding for BUFFER of LENGTH.
+ Returns: 0 = Binary
+ 1 = String possible
+ 2 = Token possible
+*/
+static int
+suitable_encoding (const unsigned char *buffer, size_t length)
+{
+ const unsigned char *s;
+ int maybe_token = 1;
+
+ if (!length)
+ return 1;
+
+ for (s=buffer; length; s++, length--)
+ {
+ if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0))
+ && !strchr ("\b\t\v\n\f\r\"\'\\", *s))
+ return 0; /*binary*/
+ if ( maybe_token
+ && !alphap (s) && !digitp (s) && !strchr (TOKEN_SPECIALS, *s))
+ maybe_token = 0;
+ }
+ s = buffer;
+ if ( maybe_token && !digitp (s) )
+ return 2;
+ return 1;
+}
+
+
+static int
+convert_to_hex (const unsigned char *src, size_t len, unsigned char *dest)
+{
+ int i;
+
+ if (dest)
+ {
+ *dest++ = '#';
+ for (i=0; i < len; i++, dest += 2 )
+ sprintf (dest, "%02X", src[i]);
+ *dest++ = '#';
+ }
+ return len*2+2;
+}
+
+static int
+convert_to_string (const unsigned char *s, size_t len, unsigned char *dest)
+{
+ if (dest)
+ {
+ unsigned char *p = dest;
+ *p++ = '\"';
+ for (; len; len--, s++ )
+ {
+ switch (*s)
+ {
+ case '\b': *p++ = '\\'; *p++ = 'b'; break;
+ case '\t': *p++ = '\\'; *p++ = 't'; break;
+ case '\v': *p++ = '\\'; *p++ = 'v'; break;
+ case '\n': *p++ = '\\'; *p++ = 'n'; break;
+ case '\f': *p++ = '\\'; *p++ = 'f'; break;
+ case '\r': *p++ = '\\'; *p++ = 'r'; break;
+ case '\"': *p++ = '\\'; *p++ = '\"'; break;
+ case '\'': *p++ = '\\'; *p++ = '\''; break;
+ case '\\': *p++ = '\\'; *p++ = '\\'; break;
+ default:
+ if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
+ {
+ sprintf (p, "\\x%02x", *s);
+ p += 4;
+ }
+ else
+ *p++ = *s;
+ }
+ }
+ *p++ = '\"';
+ return p - dest;
+ }
+ else
+ {
+ int count = 2;
+ for (; len; len--, s++ )
+ {
+ switch (*s)
+ {
+ case '\b':
+ case '\t':
+ case '\v':
+ case '\n':
+ case '\f':
+ case '\r':
+ case '\"':
+ case '\'':
+ case '\\': count += 2; break;
+ default:
+ if ( (*s < 0x20 || (*s >= 0x7f && *s <= 0xa0)))
+ count += 4;
+ else
+ count++;
+ }
+ }
+ return count;
+ }
+}
+
+
+
+static int
+convert_to_token (const unsigned char *src, size_t len, unsigned char *dest)
+{
+ if (dest)
+ memcpy (dest, src, len);
+ return len;
+}
+
+
/****************
* Print SEXP to buffer using the MODE. Returns the length of the
* SEXP in buffer or 0 if the buffer is too short (We have at least an
@@ -1035,65 +1156,144 @@ size_t
gcry_sexp_sprint( const GCRY_SEXP list, int mode,
char *buffer, size_t maxlength )
{
- static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
- const byte *s;
- char *d;
- DATALEN n;
- char numbuf[20];
- size_t len = 0;
-
- s = list? list->d : empty;
- d = buffer;
- while ( *s != ST_STOP ) {
- switch ( *s ) {
- case ST_OPEN:
- s++;
- len++;
- if ( buffer ) {
- if ( len >= maxlength )
- return 0;
- *d++ = '(';
+ static byte empty[3] = { ST_OPEN, ST_CLOSE, ST_STOP };
+ const byte *s;
+ char *d;
+ DATALEN n;
+ char numbuf[20];
+ size_t len = 0;
+ int i, indent = 0;
+
+ s = list? list->d : empty;
+ d = buffer;
+ while ( *s != ST_STOP )
+ {
+ switch ( *s )
+ {
+ case ST_OPEN:
+ s++;
+ if ( mode != GCRYSEXP_FMT_CANON )
+ {
+ if (indent)
+ len++;
+ len += indent;
+ }
+ len++;
+ if ( buffer )
+ {
+ if ( len >= maxlength )
+ return 0;
+ if ( mode != GCRYSEXP_FMT_CANON )
+ {
+ if (indent)
+ *d++ = '\n';
+ for (i=0; i < indent; i++)
+ *d++ = ' ';
+ }
+ *d++ = '(';
}
- break;
- case ST_CLOSE:
- s++;
- len++;
- if ( mode != GCRYSEXP_FMT_CANON )
- len++;
- if ( buffer ) {
- if ( len >= maxlength )
- return 0;
- *d++ = ')';
- if ( mode != GCRYSEXP_FMT_CANON )
- *d++ = '\n';
+ indent++;
+ break;
+ case ST_CLOSE:
+ s++;
+ len++;
+ if ( buffer )
+ {
+ if ( len >= maxlength )
+ return 0;
+ *d++ = ')';
}
- break;
- case ST_DATA:
- s++;
- memcpy ( &n, s, sizeof n ); s += sizeof n;
- sprintf (numbuf, "%u:", (unsigned int)n );
- len += strlen (numbuf) + n;
- if ( buffer ) {
- if ( len >= maxlength )
+ indent--;
+ if (*s != ST_OPEN && *s != ST_STOP && mode != GCRYSEXP_FMT_CANON)
+ {
+ len++;
+ len += indent;
+ if (buffer)
+ {
+ if (len >= maxlength)
+ return 0;
+ *d++ = '\n';
+ for (i=0; i < indent; i++)
+ *d++ = ' ';
+ }
+ }
+ break;
+ case ST_DATA:
+ s++;
+ memcpy ( &n, s, sizeof n ); s += sizeof n;
+ if (mode == GCRYSEXP_FMT_ADVANCED)
+ {
+ int type;
+ size_t nn;
+
+ switch ( (type=suitable_encoding (s, n)))
+ {
+ case 1: nn = convert_to_string (s, n, NULL); break;
+ case 2: nn = convert_to_token (s, n, NULL); break;
+ default: nn = convert_to_hex (s, n, NULL); break;
+ }
+ len += nn;
+ if (buffer)
+ {
+ if (len >= maxlength)
+ return 0;
+ switch (type)
+ {
+ case 1: convert_to_string (s, n, d); break;
+ case 2: convert_to_token (s, n, d); break;
+ default: convert_to_hex (s, n, d); break;
+ }
+ d += nn;
+ }
+ if (s[n] != ST_CLOSE)
+ {
+ len++;
+ if (buffer)
+ {
+ if (len >= maxlength)
+ return 0;
+ *d++ = ' ';
+ }
+ }
+ }
+ else
+ {
+ sprintf (numbuf, "%u:", (unsigned int)n );
+ len += strlen (numbuf) + n;
+ if ( buffer )
+ {
+ if ( len >= maxlength )
return 0;
- d = stpcpy ( d, numbuf );
- memcpy ( d, s, n ); d += n;
- }
- s += n;
- break;
- default:
- BUG ();
+ d = stpcpy ( d, numbuf );
+ memcpy ( d, s, n ); d += n;
+ }
+ }
+ s += n;
+ break;
+ default:
+ BUG ();
}
}
- if (buffer) {
- if ( len >= maxlength )
- return 0;
- *d++ = 0; /* for convenience we make a C string */
+ if ( mode != GCRYSEXP_FMT_CANON )
+ {
+ len++;
+ if (buffer)
+ {
+ if ( len >= maxlength )
+ return 0;
+ *d++ = '\n';
+ }
+ }
+ if (buffer)
+ {
+ if ( len >= maxlength )
+ return 0;
+ *d++ = 0; /* for convenience we make a C string */
}
- else
- len++; /* we need one byte more for this */
+ else
+ len++; /* we need one byte more for this */
- return len;
+ return len;
}