diff --git a/src/calibre/__init__.py b/src/calibre/__init__.py index f105db8879..c3039794b8 100644 --- a/src/calibre/__init__.py +++ b/src/calibre/__init__.py @@ -543,9 +543,9 @@ def strftime(fmt, t=None): t[0] = replacement ans = None if iswindows: - if isinstance(fmt, unicode): - fmt = fmt.encode('mbcs', 'replace') - fmt = fmt.replace(b'%e', b'%#d') + if isinstance(fmt, bytes): + fmt = fmt.decode('mbcs', 'replace') + fmt = fmt.replace(u'%e', u'%#d') ans = plugins['winutil'][0].strftime(fmt, t) else: ans = time.strftime(fmt, t).decode(preferred_encoding, 'replace') diff --git a/src/calibre/utils/windows/winutil.c b/src/calibre/utils/windows/winutil.c index 567493bbe4..04b5e04f8c 100644 --- a/src/calibre/utils/windows/winutil.c +++ b/src/calibre/utils/windows/winutil.c @@ -300,84 +300,69 @@ winutil_strftime(PyObject *self, PyObject *args) { PyObject *tup = NULL; struct tm buf; - const char *_fmt; - size_t fmtlen, buflen; - wchar_t *outbuf = NULL, *fmt = NULL; + size_t buflen; + wchar_t *outbuf = NULL; + Py_UNICODE *fmt = NULL; + int fmtlen; size_t i; - memset((void *) &buf, '\0', sizeof(buf)); + memset((void *) &buf, 0, sizeof(buf)); - if (!PyArg_ParseTuple(args, "s|O:strftime", &_fmt, &tup)) - return NULL; - - if (mbstowcs_s(&fmtlen, NULL, 0, _fmt, strlen(_fmt)) != 0) { - PyErr_SetString(PyExc_ValueError, "Failed to convert fmt to wchar"); - return NULL; - } - fmt = (wchar_t *)PyMem_Malloc((fmtlen+2)*sizeof(wchar_t)); - if (fmt == NULL) return PyErr_NoMemory(); - if (mbstowcs_s(&fmtlen, fmt, fmtlen+2, _fmt, strlen(_fmt)) != 0) { - PyErr_SetString(PyExc_ValueError, "Failed to convert fmt to wchar"); - goto end; - } + if (!PyArg_ParseTuple(args, "u#|O:strftime", &fmt, &fmtlen, &tup)) return NULL; if (tup == NULL) { time_t tt = time(NULL); if(localtime_s(&buf, &tt) != 0) { PyErr_SetString(PyExc_ValueError, "Failed to get localtime()"); - goto end; + return NULL; } - } else if (!gettmarg(tup, &buf)) - goto end; + } else if (!gettmarg(tup, &buf)) return NULL; - if (buf.tm_mon == -1) - buf.tm_mon = 0; + if (buf.tm_mon == -1) buf.tm_mon = 0; else if (buf.tm_mon < 0 || buf.tm_mon > 11) { - PyErr_SetString(PyExc_ValueError, "month out of range"); - goto end; - } - if (buf.tm_mday == 0) - buf.tm_mday = 1; + PyErr_SetString(PyExc_ValueError, "month out of range"); + return NULL; + } + if (buf.tm_mday == 0) buf.tm_mday = 1; else if (buf.tm_mday < 0 || buf.tm_mday > 31) { - PyErr_SetString(PyExc_ValueError, "day of month out of range"); - goto end; - } - if (buf.tm_hour < 0 || buf.tm_hour > 23) { - PyErr_SetString(PyExc_ValueError, "hour out of range"); - goto end; - } - if (buf.tm_min < 0 || buf.tm_min > 59) { - PyErr_SetString(PyExc_ValueError, "minute out of range"); - goto end; - } - if (buf.tm_sec < 0 || buf.tm_sec > 61) { - PyErr_SetString(PyExc_ValueError, "seconds out of range"); - goto end; - } - /* tm_wday does not need checking of its upper-bound since taking - ``% 7`` in gettmarg() automatically restricts the range. */ - if (buf.tm_wday < 0) { - PyErr_SetString(PyExc_ValueError, "day of week out of range"); - goto end; - } - if (buf.tm_yday == -1) - buf.tm_yday = 0; + PyErr_SetString(PyExc_ValueError, "day of month out of range"); + return NULL; + } + if (buf.tm_hour < 0 || buf.tm_hour > 23) { + PyErr_SetString(PyExc_ValueError, "hour out of range"); + return NULL; + } + if (buf.tm_min < 0 || buf.tm_min > 59) { + PyErr_SetString(PyExc_ValueError, "minute out of range"); + return NULL; + } + if (buf.tm_sec < 0 || buf.tm_sec > 61) { + PyErr_SetString(PyExc_ValueError, "seconds out of range"); + return NULL; + } + /* tm_wday does not need checking of its upper-bound since taking + ``% 7`` in gettmarg() automatically restricts the range. */ + if (buf.tm_wday < 0) { + PyErr_SetString(PyExc_ValueError, "day of week out of range"); + return NULL; + } + if (buf.tm_yday == -1) buf.tm_yday = 0; else if (buf.tm_yday < 0 || buf.tm_yday > 365) { - PyErr_SetString(PyExc_ValueError, "day of year out of range"); - goto end; - } - if (buf.tm_isdst < -1 || buf.tm_isdst > 1) { - PyErr_SetString(PyExc_ValueError, - "daylight savings flag out of range"); - goto end; - } + PyErr_SetString(PyExc_ValueError, "day of year out of range"); + return NULL; + } + if (buf.tm_isdst < -1 || buf.tm_isdst > 1) { + PyErr_SetString(PyExc_ValueError, + "daylight savings flag out of range"); + return NULL; + } - for (i = 5*fmtlen; ; i += i) { + for (i = 5*(unsigned int)fmtlen; ; i += i) { outbuf = (wchar_t *)PyMem_Malloc(i*sizeof(wchar_t)); if (outbuf == NULL) { - PyErr_NoMemory(); goto end; + PyErr_NoMemory(); return NULL; } buflen = wcsftime(outbuf, i, fmt, &buf); - if (buflen > 0 || i >= 256 * fmtlen) { + if (buflen > 0 || i >= 256 * (unsigned int)fmtlen) { /* If the buffer is 256 times as long as the format, it's probably not failing for lack of room! More likely, the format yields an empty result, @@ -385,20 +370,17 @@ winutil_strftime(PyObject *self, PyObject *args) is unknown. */ PyObject *ret; ret = PyUnicode_FromWideChar(outbuf, buflen); - PyMem_Free(outbuf); PyMem_Free(fmt); + PyMem_Free(outbuf); return ret; } PyMem_Free(outbuf); -#if defined _MSC_VER && _MSC_VER >= 1400 && defined(__STDC_SECURE_LIB__) /* VisualStudio .NET 2005 does this properly */ if (buflen == 0 && errno == EINVAL) { PyErr_SetString(PyExc_ValueError, "Invalid format string"); - goto end; + return NULL; } -#endif } -end: - PyMem_Free(fmt); return NULL; + return NULL; }