diff options
author | dgp <dgp@users.sourceforge.net> | 2020-03-28 19:44:20 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2020-03-28 19:44:20 (GMT) |
commit | 11db05f8dcd356de0e5d2835681315a063c54532 (patch) | |
tree | 330c9c4d8a9787eac0814933dbf737491f2b11b0 /generic/tclBinary.c | |
parent | 5162052befd46c99fdf279db9b3f3ca39a989e2b (diff) | |
parent | 7a81cc7b2b6bb91af471e292b4199d1af61bf52b (diff) | |
download | tcl-11db05f8dcd356de0e5d2835681315a063c54532.zip tcl-11db05f8dcd356de0e5d2835681315a063c54532.tar.gz tcl-11db05f8dcd356de0e5d2835681315a063c54532.tar.bz2 |
merge 8.7
Diffstat (limited to 'generic/tclBinary.c')
-rw-r--r-- | generic/tclBinary.c | 68 |
1 files changed, 43 insertions, 25 deletions
diff --git a/generic/tclBinary.c b/generic/tclBinary.c index f12716d..51b6f53 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -2665,6 +2665,7 @@ BinaryDecodeHex( Tcl_SetObjResult(interp, Tcl_ObjPrintf( "invalid hexadecimal digit \"%c\" at position %d", c, (int) (data - datastart - 1))); + Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL); return TCL_ERROR; } @@ -2673,16 +2674,10 @@ BinaryDecodeHex( * * BinaryEncode64 -- * - * This implements a generic 6 bit binary encoding. Input is broken into - * 6 bit chunks and a lookup table passed in via clientData is used to - * turn these values into output characters. This is used to implement - * base64 binary encodings. + * This procedure implements the "binary encode base64" Tcl command. * * Results: - * Interp result set to an encoded byte array object - * - * Side effects: - * None + * The base64 encoded value prescribed by the input arguments. * *---------------------------------------------------------------------- */ @@ -2711,11 +2706,11 @@ BinaryEncode64( Tcl_Obj *const objv[]) { Tcl_Obj *resultObj; - unsigned char *data, *cursor, *limit; + unsigned char *data, *limit; int maxlen = 0; const char *wrapchar = "\n"; int wrapcharlen = 1; - int offset, i, index, size, outindex = 0, count = 0; + int offset, i, index, size, outindex = 0, count = 0, purewrap = 1; enum { OPT_MAXLEN, OPT_WRAPCHAR }; static const char *const optStrings[] = { "-maxlen", "-wrapchar", NULL }; @@ -2743,17 +2738,24 @@ BinaryEncode64( } break; case OPT_WRAPCHAR: - wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen); - if (wrapcharlen == 0) { - maxlen = 0; + wrapchar = (const char *)Tcl_GetBytesFromObj(NULL, + objv[i + 1], &wrapcharlen); + if (wrapchar == NULL) { + purewrap = 0; + wrapchar = TclGetStringFromObj(objv[i + 1], &wrapcharlen); } break; } } + if (wrapcharlen == 0) { + maxlen = 0; + } resultObj = Tcl_NewObj(); data = Tcl_GetByteArrayFromObj(objv[objc - 1], &count); if (count > 0) { + unsigned char *cursor = NULL; + size = (((count * 4) / 3) + 3) & ~3; /* ensure 4 byte chunks */ if (maxlen > 0 && size > maxlen) { int adjusted = size + (wrapcharlen * (size / maxlen)); @@ -2762,8 +2764,17 @@ BinaryEncode64( adjusted -= wrapcharlen; } size = adjusted; + + if (purewrap == 0) { + /* Wrapchar is (possibly) non-byte, so build result as + * general string, not bytearray */ + Tcl_SetObjLength(resultObj, size); + cursor = (unsigned char *) TclGetString(resultObj); + } + } + if (cursor == NULL) { + cursor = Tcl_SetByteArrayLength(resultObj, size); } - cursor = Tcl_SetByteArrayLength(resultObj, size); limit = cursor + size; for (offset = 0; offset < count; offset += 3) { unsigned char d[3] = {0, 0, 0}; @@ -3100,8 +3111,9 @@ BinaryDecode64( unsigned char *data, *datastart, *dataend, c = '\0'; unsigned char *begin = NULL; unsigned char *cursor = NULL; - int strict = 0; + int pure = 1, strict = 0; int i, index, size, cut = 0, count = 0; + Tcl_UniChar ch; enum { OPT_STRICT }; static const char *const optStrings[] = { "-strict", NULL }; @@ -3122,8 +3134,12 @@ BinaryDecode64( } TclNewObj(resultObj); - datastart = data = (unsigned char *) - TclGetStringFromObj(objv[objc - 1], &count); + data = Tcl_GetBytesFromObj(NULL, objv[objc - 1], &count); + if (data == NULL) { + pure = 0; + data = (unsigned char *) TclGetStringFromObj(objv[objc - 1], &count); + } + datastart = data; dataend = data + count; size = ((count + 3) & ~3) * 3 / 4; begin = cursor = Tcl_SetByteArrayLength(resultObj, size); @@ -3224,21 +3240,23 @@ BinaryDecode64( return TCL_OK; bad64: - { + if (pure) { + ch = c; + } else { /* The decoder is byte-oriented. If we saw a byte that's not a * valid member of the base64 alphabet, it could be the lead byte * of a multi-byte character. */ - Tcl_UniChar ch; /* Safe because we know data is NUL-terminated */ TclUtfToUniChar((const char *)(data - 1), &ch); - - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "invalid base64 character \"%c\" at position %d", ch, - (int) (data - datastart - 1))); - TclDecrRefCount(resultObj); - return TCL_ERROR; } + + Tcl_SetObjResult(interp, Tcl_ObjPrintf( + "invalid base64 character \"%c\" at position %d", ch, + (int) (data - datastart - 1))); + Tcl_SetErrorCode(interp, "TCL", "BINARY", "DECODE", "INVALID", NULL); + TclDecrRefCount(resultObj); + return TCL_ERROR; } /* |