PyUnicode_GET_SIZE(obj)); } return PyUnicode_FromEncodedObject(obj, NULL, "strict");} PyObject *PyUnicode_FromEncodedObject(register PyObject *obj, const char *encoding, const char *errors){ const char *s = NULL; Py_ssize_t len; PyObject *v; if (obj == NULL) { PyErr_BadInternalCall(); return NULL; } #if 0 /* For b/w compatibility we also accept Unicode objects provided that no encodings is given and then redirect to PyObject_Unicode() which then applies the additional logic for Unicode subclasses. NOTE: This API should really only be used for object which represent *encoded* Unicode ! */ if (PyUnicode_Check(obj)) { if (encoding) { PyErr_SetString(PyExc_TypeError, "decoding Unicode is not supported"); return NULL; } return PyObject_Unicode(obj); }#else if (PyUnicode_Check(obj)) { PyErr_SetString(PyExc_TypeError, "decoding Unicode is not supported"); return NULL; }#endif /* Coerce object */ if (PyString_Check(obj)) { s = PyString_AS_STRING(obj); len = PyString_GET_SIZE(obj); } else if (PyObject_AsCharBuffer(obj, &s, &len)) { /* Overwrite the error message with something more useful in case of a TypeError. */ if (PyErr_ExceptionMatches(PyExc_TypeError)) PyErr_Format(PyExc_TypeError, "coercing to Unicode: need string or buffer, " "%.80s found", obj->ob_type->tp_name); goto onError; } /* Convert to Unicode */ if (len == 0) { Py_INCREF(unicode_empty); v = (PyObject *)unicode_empty; } else v = PyUnicode_Decode(s, len, encoding, errors); return v; onError: return NULL;} PyObject *PyUnicode_Decode(const char *s, Py_ssize_t size, const char *encoding, const char *errors){ PyObject *buffer = NULL, *unicode; if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Shortcuts for common default encodings */ if (strcmp(encoding, "utf-8") == 0) return PyUnicode_DecodeUTF8(s, size, errors); else if (strcmp(encoding, "latin-1") == 0) return PyUnicode_DecodeLatin1(s, size, errors);#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) else if (strcmp(encoding, "mbcs") == 0) return PyUnicode_DecodeMBCS(s, size, errors);#endif else if (strcmp(encoding, "ascii") == 0) return PyUnicode_DecodeASCII(s, size, errors); /* Decode via the codec registry */ buffer = PyBuffer_FromMemory((void *)s, size); if (buffer == NULL) goto onError; unicode = PyCodec_Decode(buffer, encoding, errors); if (unicode == NULL) goto onError; if (!PyUnicode_Check(unicode)) { PyErr_Format(PyExc_TypeError, "decoder did not return an unicode object (type=%.400s)", unicode->ob_type->tp_name); Py_DECREF(unicode); goto onError; } Py_DECREF(buffer); return unicode; onError: Py_XDECREF(buffer); return NULL;} PyObject *PyUnicode_AsDecodedObject(PyObject *unicode, const char *encoding, const char *errors){ PyObject *v; if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Decode via the codec registry */ v = PyCodec_Decode(unicode, encoding, errors); if (v == NULL) goto onError; return v; onError: return NULL;} PyObject *PyUnicode_Encode(const Py_UNICODE *s, Py_ssize_t size, const char *encoding, const char *errors){ PyObject *v, *unicode; unicode = PyUnicode_FromUnicode(s, size); if (unicode == NULL) return NULL; v = PyUnicode_AsEncodedString(unicode, encoding, errors); Py_DECREF(unicode); return v;} PyObject *PyUnicode_AsEncodedObject(PyObject *unicode, const char *encoding, const char *errors){ PyObject *v; if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Encode via the codec registry */ v = PyCodec_Encode(unicode, encoding, errors); if (v == NULL) goto onError; return v; onError: return NULL;} PyObject *PyUnicode_AsEncodedString(PyObject *unicode, const char *encoding, const char *errors){ PyObject *v; if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Shortcuts for common default encodings */ if (errors == NULL) { if (strcmp(encoding, "utf-8") == 0) return PyUnicode_AsUTF8String(unicode); else if (strcmp(encoding, "latin-1") == 0) return PyUnicode_AsLatin1String(unicode);#if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) else if (strcmp(encoding, "mbcs") == 0) return PyUnicode_AsMBCSString(unicode);#endif else if (strcmp(encoding, "ascii") == 0) return PyUnicode_AsASCIIString(unicode); } /* Encode via the codec registry */ v = PyCodec_Encode(unicode, encoding, errors); if (v == NULL) goto onError; if (!PyString_Check(v)) { PyErr_Format(PyExc_TypeError, "encoder did not return a string object (type=%.400s)", v->ob_type->tp_name); Py_DECREF(v); goto onError; } return v; onError: return NULL;} PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode, const char *errors){ PyObject *v = ((PyUnicodeObject *)unicode)->defenc; if (v) return v; v = PyUnicode_AsEncodedString(unicode, NULL, errors); if (v && errors == NULL) ((PyUnicodeObject *)unicode)->defenc = v; return v;} Py_UNICODE *PyUnicode_AsUnicode(PyObject *unicode){ if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } return PyUnicode_AS_UNICODE(unicode); onError: return NULL;} Py_ssize_t PyUnicode_GetSize(PyObject *unicode){ if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } return PyUnicode_GET_SIZE(unicode); onError: return -1;} const char *PyUnicode_GetDefaultEncoding(void){ return unicode_default_encoding;} int PyUnicode_SetDefaultEncoding(const char *encoding){ PyObject *v; /* Make sure the encoding is valid. As side effect, this also loads the encoding into the codec registry cache. */ v = _PyCodec_Lookup(encoding); if (v == NULL) goto onError; Py_DECREF(v); strncpy(unicode_default_encoding, encoding, sizeof(unicode_default_encoding)); return 0; onError: return -1;} /* error handling callback helper: build arguments, call the callback and check the arguments, if no exception occurred, copy the replacement to the output and adjust various state variables. return 0 on success, -1 on error*/ staticint unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler, const char *encoding, const char *reason, const char *input, Py_ssize_t insize, Py_ssize_t *startinpos, Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, PyObject **output, Py_ssize_t *outpos, Py_UNICODE **outptr){ static char *argparse = "O!n;decoding error handler must return (unicode, int) tuple"; PyObject *restuple = NULL; PyObject *repunicode = NULL; Py_ssize_t outsize = PyUnicode_GET_SIZE(*output); Py_ssize_t requiredsize; Py_ssize_t newpos; Py_UNICODE *repptr; Py_ssize_t repsize; int res = -1; if (*errorHandler == NULL) { *errorHandler = PyCodec_LookupError(errors); if (*errorHandler == NULL) goto onError; } if (*exceptionObject == NULL) { *exceptionObject = PyUnicodeDecodeError_Create( encoding, input, insize, *startinpos, *endinpos, reason); if (*exceptionObject == NULL) goto onError; } else { if (PyUnicodeDecodeError_SetStart(*exceptionObject, *startinpos)) goto onError; if (PyUnicodeDecodeError_SetEnd(*exceptionObject, *endinpos)) goto onError; if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason)) goto onError; } restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL); if (restuple == NULL) goto onError; if (!PyTuple_Check(restuple)) { PyErr_Format(PyExc_TypeError, &argparse[4]); goto onError; } if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos)) goto onError; if (newpos<0) newpos = insize+newpos; if (newpos<0 || newpos>insize) { PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", newpos); goto onError; } /* need more space? (at least enough for what we have+the replacement+the rest of the string (starting at the new input position), so we won't have to check space when there are no errors in the rest of the string) */ repptr = PyUnicode_AS_UNICODE(repunicode); repsize = PyUnicode_GET_SIZE(repunicode); requiredsize = *outpos + repsize + insize-newpos; if (requiredsize > outsize) { if (requiredsize<2*outsize) requiredsize = 2*outsize; if (PyUnicode_Resize(output, requiredsize) < 0) goto onError; *outptr = PyUnicode_AS_UNICODE(*output) + *outpos; } *endinpos = newpos; *inptr = input + newpos; Py_UNICODE_COPY(*outptr, repptr, repsize); *outptr += repsize; *outpos += repsize; /* we made it! */ res = 0; onError: Py_XDECREF(restuple); return res;} /* --- UTF-7 Codec -------------------------------------------------------- */ /* see RFC2152 for details */ staticchar utf7_special[128] = { /* indicate whether a UTF-7 character is special i.e. cannot be directly encoded: 0 - not special 1 - special 2 - whitespace (optional) 3 - RFC2152 Set O (optional) */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, }; /* Note: The comparison (c) <= 0 is a trick to work-around gcc warnings about the comparison always being false; since utf7_special[0] is 1, we can safely make that one comparison true */ #define SPECIAL(c, encodeO, encodeWS) \ ((c) > 127 || (c) <= 0 || utf7_special[(c)] == 1 || \ (encodeWS && (utf7_special[(c)] == 2)) || \ (encodeO && (utf7_special[(c)] == 3))) #define B64(n) \ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f])#define B64CHAR(c) \ (isalnum(c) || (c) == '+' || (c) == '/')#define UB64(c) \ ((c) == '+' ? 62 : (c) == '/' ? 63 : (c) >= 'a' ? \ (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4 ) #define ENCODE(out, ch, bits) \ while (bits >= 6) { \ *out++ = B64(ch >> (bits-6)); \ bits -= 6; \ } #define DECODE(out, ch, bits, surrogate) \ while (bits >= 16) { \ Py_UNICODE outCh = (Py_UNICODE) ((ch >> (bits-16)) & 0xffff); \ bits -= 16; \ if (surrogate) { \ /* We have already generated an error for the high surrogate \ so let's not bother seeing if the low surrogate is correct or not */ \ surrogate = 0; \ } else if (0xDC00 <= outCh && outCh <= 0xDFFF) { \ /* This is a surrogate pair. Unfortunately we can't represent \ it in a 16-bit character */ \ surrogate = 1; \ errmsg = "code pairs are not supported"; \ goto utf7Error; \ } else { \ *out++ = outCh; \ } \ } PyObject *PyUnicode_DecodeUTF7(const char *s, Py_ssize_t size, const char *errors){ const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; Py_ssize_t outpos; const char *e; PyUnicodeObject *unicode; Py_UNICODE *p; const char *errmsg = ""; int inShift = 0; unsigned int bitsleft = 0; unsigned long charsleft = 0; int surrogate = 0; PyObject *errorHandler = NULL; PyObject *exc = NULL; unicode = _PyUnicode_New(size); if (!unicode) return NULL; if (size == 0) return (PyObject *)unicode; p = unicode->str; e = s + size; while (s < e) { Py_UNICODE ch; restart: ch = *s; if (inShift) { if ((ch == '-') || !B64CHAR(ch)) { inShift = 0; s++; /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate); if (bitsleft >= 6) { /* The shift sequence has a partial character in it. If bitsleft < 6 then we could just classify it as padding but that is not the case here */ errmsg = "partial character in shift sequence"; goto utf7Error; } /* According to RFC2152 the remaining bits should be zero. We choose to signal an error/insert a replacement character here so indicate the potential of a misencoded character. */ /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */ if (bitsleft && charsleft << (sizeof(charsleft) * 8 - bitsleft)) { errmsg = "non-zero padding bits in shift sequence"; goto utf7Error; } if (ch == '-') { if ((s < e) && (*(s) == '-')) {Lines 501–1000 of 8067. Previous lines Load more
PyUnicode_GET_SIZE(obj)); } return PyUnicode_FromEncodedObject(obj, NULL, "strict"); } PyObject *PyUnicode_FromEncodedObject(register PyObject *obj, const char *encoding, const char *errors) { const char *s = NULL; Py_ssize_t len; PyObject *v; if (obj == NULL) { PyErr_BadInternalCall(); return NULL; } #if 0 /* For b/w compatibility we also accept Unicode objects provided that no encodings is given and then redirect to PyObject_Unicode() which then applies the additional logic for Unicode subclasses. NOTE: This API should really only be used for object which represent *encoded* Unicode ! */ if (PyUnicode_Check(obj)) { if (encoding) { PyErr_SetString(PyExc_TypeError, "decoding Unicode is not supported"); return NULL; } return PyObject_Unicode(obj); } #else if (PyUnicode_Check(obj)) { PyErr_SetString(PyExc_TypeError, "decoding Unicode is not supported"); return NULL; } #endif /* Coerce object */ if (PyString_Check(obj)) { s = PyString_AS_STRING(obj); len = PyString_GET_SIZE(obj); } else if (PyObject_AsCharBuffer(obj, &s, &len)) { /* Overwrite the error message with something more useful in case of a TypeError. */ if (PyErr_ExceptionMatches(PyExc_TypeError)) PyErr_Format(PyExc_TypeError, "coercing to Unicode: need string or buffer, " "%.80s found", obj->ob_type->tp_name); goto onError; } /* Convert to Unicode */ if (len == 0) { Py_INCREF(unicode_empty); v = (PyObject *)unicode_empty; } else v = PyUnicode_Decode(s, len, encoding, errors); return v; onError: return NULL; } PyObject *PyUnicode_Decode(const char *s, Py_ssize_t size, const char *encoding, const char *errors) { PyObject *buffer = NULL, *unicode; if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Shortcuts for common default encodings */ if (strcmp(encoding, "utf-8") == 0) return PyUnicode_DecodeUTF8(s, size, errors); else if (strcmp(encoding, "latin-1") == 0) return PyUnicode_DecodeLatin1(s, size, errors); #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) else if (strcmp(encoding, "mbcs") == 0) return PyUnicode_DecodeMBCS(s, size, errors); #endif else if (strcmp(encoding, "ascii") == 0) return PyUnicode_DecodeASCII(s, size, errors); /* Decode via the codec registry */ buffer = PyBuffer_FromMemory((void *)s, size); if (buffer == NULL) goto onError; unicode = PyCodec_Decode(buffer, encoding, errors); if (unicode == NULL) goto onError; if (!PyUnicode_Check(unicode)) { PyErr_Format(PyExc_TypeError, "decoder did not return an unicode object (type=%.400s)", unicode->ob_type->tp_name); Py_DECREF(unicode); goto onError; } Py_DECREF(buffer); return unicode; onError: Py_XDECREF(buffer); return NULL; } PyObject *PyUnicode_AsDecodedObject(PyObject *unicode, const char *encoding, const char *errors) { PyObject *v; if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Decode via the codec registry */ v = PyCodec_Decode(unicode, encoding, errors); if (v == NULL) goto onError; return v; onError: return NULL; } PyObject *PyUnicode_Encode(const Py_UNICODE *s, Py_ssize_t size, const char *encoding, const char *errors) { PyObject *v, *unicode; unicode = PyUnicode_FromUnicode(s, size); if (unicode == NULL) return NULL; v = PyUnicode_AsEncodedString(unicode, encoding, errors); Py_DECREF(unicode); return v; } PyObject *PyUnicode_AsEncodedObject(PyObject *unicode, const char *encoding, const char *errors) { PyObject *v; if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Encode via the codec registry */ v = PyCodec_Encode(unicode, encoding, errors); if (v == NULL) goto onError; return v; onError: return NULL; } PyObject *PyUnicode_AsEncodedString(PyObject *unicode, const char *encoding, const char *errors) { PyObject *v; if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } if (encoding == NULL) encoding = PyUnicode_GetDefaultEncoding(); /* Shortcuts for common default encodings */ if (errors == NULL) { if (strcmp(encoding, "utf-8") == 0) return PyUnicode_AsUTF8String(unicode); else if (strcmp(encoding, "latin-1") == 0) return PyUnicode_AsLatin1String(unicode); #if defined(MS_WINDOWS) && defined(HAVE_USABLE_WCHAR_T) else if (strcmp(encoding, "mbcs") == 0) return PyUnicode_AsMBCSString(unicode); #endif else if (strcmp(encoding, "ascii") == 0) return PyUnicode_AsASCIIString(unicode); } /* Encode via the codec registry */ v = PyCodec_Encode(unicode, encoding, errors); if (v == NULL) goto onError; if (!PyString_Check(v)) { PyErr_Format(PyExc_TypeError, "encoder did not return a string object (type=%.400s)", v->ob_type->tp_name); Py_DECREF(v); goto onError; } return v; onError: return NULL; } PyObject *_PyUnicode_AsDefaultEncodedString(PyObject *unicode, const char *errors) { PyObject *v = ((PyUnicodeObject *)unicode)->defenc; if (v) return v; v = PyUnicode_AsEncodedString(unicode, NULL, errors); if (v && errors == NULL) ((PyUnicodeObject *)unicode)->defenc = v; return v; } Py_UNICODE *PyUnicode_AsUnicode(PyObject *unicode) { if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } return PyUnicode_AS_UNICODE(unicode); onError: return NULL; } Py_ssize_t PyUnicode_GetSize(PyObject *unicode) { if (!PyUnicode_Check(unicode)) { PyErr_BadArgument(); goto onError; } return PyUnicode_GET_SIZE(unicode); onError: return -1; } const char *PyUnicode_GetDefaultEncoding(void) { return unicode_default_encoding; } int PyUnicode_SetDefaultEncoding(const char *encoding) { PyObject *v; /* Make sure the encoding is valid. As side effect, this also loads the encoding into the codec registry cache. */ v = _PyCodec_Lookup(encoding); if (v == NULL) goto onError; Py_DECREF(v); strncpy(unicode_default_encoding, encoding, sizeof(unicode_default_encoding)); return 0; onError: return -1; } /* error handling callback helper: build arguments, call the callback and check the arguments, if no exception occurred, copy the replacement to the output and adjust various state variables. return 0 on success, -1 on error */ static int unicode_decode_call_errorhandler(const char *errors, PyObject **errorHandler, const char *encoding, const char *reason, const char *input, Py_ssize_t insize, Py_ssize_t *startinpos, Py_ssize_t *endinpos, PyObject **exceptionObject, const char **inptr, PyObject **output, Py_ssize_t *outpos, Py_UNICODE **outptr) { static char *argparse = "O!n;decoding error handler must return (unicode, int) tuple"; PyObject *restuple = NULL; PyObject *repunicode = NULL; Py_ssize_t outsize = PyUnicode_GET_SIZE(*output); Py_ssize_t requiredsize; Py_ssize_t newpos; Py_UNICODE *repptr; Py_ssize_t repsize; int res = -1; if (*errorHandler == NULL) { *errorHandler = PyCodec_LookupError(errors); if (*errorHandler == NULL) goto onError; } if (*exceptionObject == NULL) { *exceptionObject = PyUnicodeDecodeError_Create( encoding, input, insize, *startinpos, *endinpos, reason); if (*exceptionObject == NULL) goto onError; } else { if (PyUnicodeDecodeError_SetStart(*exceptionObject, *startinpos)) goto onError; if (PyUnicodeDecodeError_SetEnd(*exceptionObject, *endinpos)) goto onError; if (PyUnicodeDecodeError_SetReason(*exceptionObject, reason)) goto onError; } restuple = PyObject_CallFunctionObjArgs(*errorHandler, *exceptionObject, NULL); if (restuple == NULL) goto onError; if (!PyTuple_Check(restuple)) { PyErr_Format(PyExc_TypeError, &argparse[4]); goto onError; } if (!PyArg_ParseTuple(restuple, argparse, &PyUnicode_Type, &repunicode, &newpos)) goto onError; if (newpos<0) newpos = insize+newpos; if (newpos<0 || newpos>insize) { PyErr_Format(PyExc_IndexError, "position %zd from error handler out of bounds", newpos); goto onError; } /* need more space? (at least enough for what we have+the replacement+the rest of the string (starting at the new input position), so we won't have to check space when there are no errors in the rest of the string) */ repptr = PyUnicode_AS_UNICODE(repunicode); repsize = PyUnicode_GET_SIZE(repunicode); requiredsize = *outpos + repsize + insize-newpos; if (requiredsize > outsize) { if (requiredsize<2*outsize) requiredsize = 2*outsize; if (PyUnicode_Resize(output, requiredsize) < 0) goto onError; *outptr = PyUnicode_AS_UNICODE(*output) + *outpos; } *endinpos = newpos; *inptr = input + newpos; Py_UNICODE_COPY(*outptr, repptr, repsize); *outptr += repsize; *outpos += repsize; /* we made it! */ res = 0; onError: Py_XDECREF(restuple); return res; } /* --- UTF-7 Codec -------------------------------------------------------- */ /* see RFC2152 for details */ static char utf7_special[128] = { /* indicate whether a UTF-7 character is special i.e. cannot be directly encoded: 0 - not special 1 - special 2 - whitespace (optional) 3 - RFC2152 Set O (optional) */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 3, 3, 3, 3, 3, 0, 0, 0, 3, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 1, 1, }; /* Note: The comparison (c) <= 0 is a trick to work-around gcc warnings about the comparison always being false; since utf7_special[0] is 1, we can safely make that one comparison true */ #define SPECIAL(c, encodeO, encodeWS) \ ((c) > 127 || (c) <= 0 || utf7_special[(c)] == 1 || \ (encodeWS && (utf7_special[(c)] == 2)) || \ (encodeO && (utf7_special[(c)] == 3))) #define B64(n) \ ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[(n) & 0x3f]) #define B64CHAR(c) \ (isalnum(c) || (c) == '+' || (c) == '/') #define UB64(c) \ ((c) == '+' ? 62 : (c) == '/' ? 63 : (c) >= 'a' ? \ (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4 ) #define ENCODE(out, ch, bits) \ while (bits >= 6) { \ *out++ = B64(ch >> (bits-6)); \ bits -= 6; \ } #define DECODE(out, ch, bits, surrogate) \ while (bits >= 16) { \ Py_UNICODE outCh = (Py_UNICODE) ((ch >> (bits-16)) & 0xffff); \ bits -= 16; \ if (surrogate) { \ /* We have already generated an error for the high surrogate \ so let's not bother seeing if the low surrogate is correct or not */ \ surrogate = 0; \ } else if (0xDC00 <= outCh && outCh <= 0xDFFF) { \ /* This is a surrogate pair. Unfortunately we can't represent \ it in a 16-bit character */ \ surrogate = 1; \ errmsg = "code pairs are not supported"; \ goto utf7Error; \ } else { \ *out++ = outCh; \ } \ } PyObject *PyUnicode_DecodeUTF7(const char *s, Py_ssize_t size, const char *errors) { const char *starts = s; Py_ssize_t startinpos; Py_ssize_t endinpos; Py_ssize_t outpos; const char *e; PyUnicodeObject *unicode; Py_UNICODE *p; const char *errmsg = ""; int inShift = 0; unsigned int bitsleft = 0; unsigned long charsleft = 0; int surrogate = 0; PyObject *errorHandler = NULL; PyObject *exc = NULL; unicode = _PyUnicode_New(size); if (!unicode) return NULL; if (size == 0) return (PyObject *)unicode; p = unicode->str; e = s + size; while (s < e) { Py_UNICODE ch; restart: ch = *s; if (inShift) { if ((ch == '-') || !B64CHAR(ch)) { inShift = 0; s++; /* p, charsleft, bitsleft, surrogate = */ DECODE(p, charsleft, bitsleft, surrogate); if (bitsleft >= 6) { /* The shift sequence has a partial character in it. If bitsleft < 6 then we could just classify it as padding but that is not the case here */ errmsg = "partial character in shift sequence"; goto utf7Error; } /* According to RFC2152 the remaining bits should be zero. We choose to signal an error/insert a replacement character here so indicate the potential of a misencoded character. */ /* On x86, a << b == a << (b%32) so make sure that bitsleft != 0 */ if (bitsleft && charsleft << (sizeof(charsleft) * 8 - bitsleft)) { errmsg = "non-zero padding bits in shift sequence"; goto utf7Error; } if (ch == '-') { if ((s < e) && (*(s) == '-')) {