int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
{
    char *str;
    ASN1_TIME atm;
    long offset;
    char buff1[24], buff2[24], *p;
    int i, j, remaining;
    p = buff1;
    remaining = ctm->length;
    str = (char *)ctm->data;
    if (ctm->type == V_ASN1_UTCTIME) {
        int min_length = sizeof("YYMMDDHHMMZ") - 1;
        int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
        if (remaining < min_length || remaining > max_length)
            return 0;
        memcpy(p, str, 10);
        p += 10;
        str += 10;
        remaining -= 10;
    } else {
        int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
        int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
        if (remaining < min_length || remaining > max_length)
            return 0;
        memcpy(p, str, 12);
        p += 12;
        str += 12;
        remaining -= 12;
    }
    if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
        *(p++) = '0';
        *(p++) = '0';
    } else {
        if (remaining < 2)
            return 0;
        *(p++) = *(str++);
        *(p++) = *(str++);
        remaining -= 2;
        if (remaining && *str == '.') {
            str++;
            remaining--;
            for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
                if (*str < '0' || *str > '9')
                    break;
            }
        }
    }
    *(p++) = 'Z';
    *(p++) = '\0';
    if (!remaining)
        return 0;
    if (*str == 'Z') {
        if (remaining != 1)
            return 0;
        offset = 0;
    } else {
        if ((*str != '+') && (*str != '-'))
            return 0;
        if (remaining != 5)
            return 0;
        if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
            str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
            return 0;
        offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
        offset += (str[3] - '0') * 10 + (str[4] - '0');
        if (*str == '-')
            offset = -offset;
    }
    atm.type = ctm->type;
    atm.flags = 0;
    atm.length = sizeof(buff2);
    atm.data = (unsigned char *)buff2;
    if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
        return 0;
    if (ctm->type == V_ASN1_UTCTIME) {
        i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
        if (i < 50)
            i += 100;
        j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
        if (j < 50)
            j += 100;
        if (i < j)
            return -1;
        if (i > j)
            return 1;
    }
    i = strcmp(buff1, buff2);
    if (i == 0)
        return -1;
    else
        return i;
}
['int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)\n{\n    char *str;\n    ASN1_TIME atm;\n    long offset;\n    char buff1[24], buff2[24], *p;\n    int i, j, remaining;\n    p = buff1;\n    remaining = ctm->length;\n    str = (char *)ctm->data;\n    if (ctm->type == V_ASN1_UTCTIME) {\n        int min_length = sizeof("YYMMDDHHMMZ") - 1;\n        int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;\n        if (remaining < min_length || remaining > max_length)\n            return 0;\n        memcpy(p, str, 10);\n        p += 10;\n        str += 10;\n        remaining -= 10;\n    } else {\n        int min_length = sizeof("YYYYMMDDHHMMZ") - 1;\n        int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;\n        if (remaining < min_length || remaining > max_length)\n            return 0;\n        memcpy(p, str, 12);\n        p += 12;\n        str += 12;\n        remaining -= 12;\n    }\n    if ((*str == \'Z\') || (*str == \'-\') || (*str == \'+\')) {\n        *(p++) = \'0\';\n        *(p++) = \'0\';\n    } else {\n        if (remaining < 2)\n            return 0;\n        *(p++) = *(str++);\n        *(p++) = *(str++);\n        remaining -= 2;\n        if (remaining && *str == \'.\') {\n            str++;\n            remaining--;\n            for (i = 0; i < 3 && remaining; i++, str++, remaining--) {\n                if (*str < \'0\' || *str > \'9\')\n                    break;\n            }\n        }\n    }\n    *(p++) = \'Z\';\n    *(p++) = \'\\0\';\n    if (!remaining)\n        return 0;\n    if (*str == \'Z\') {\n        if (remaining != 1)\n            return 0;\n        offset = 0;\n    } else {\n        if ((*str != \'+\') && (*str != \'-\'))\n            return 0;\n        if (remaining != 5)\n            return 0;\n        if (str[1] < \'0\' || str[1] > \'9\' || str[2] < \'0\' || str[2] > \'9\' ||\n            str[3] < \'0\' || str[3] > \'9\' || str[4] < \'0\' || str[4] > \'9\')\n            return 0;\n        offset = ((str[1] - \'0\') * 10 + (str[2] - \'0\')) * 60;\n        offset += (str[3] - \'0\') * 10 + (str[4] - \'0\');\n        if (*str == \'-\')\n            offset = -offset;\n    }\n    atm.type = ctm->type;\n    atm.flags = 0;\n    atm.length = sizeof(buff2);\n    atm.data = (unsigned char *)buff2;\n    if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)\n        return 0;\n    if (ctm->type == V_ASN1_UTCTIME) {\n        i = (buff1[0] - \'0\') * 10 + (buff1[1] - \'0\');\n        if (i < 50)\n            i += 100;\n        j = (buff2[0] - \'0\') * 10 + (buff2[1] - \'0\');\n        if (j < 50)\n            j += 100;\n        if (i < j)\n            return -1;\n        if (i > j)\n            return 1;\n    }\n    i = strcmp(buff1, buff2);\n    if (i == 0)\n        return -1;\n    else\n        return i;\n}']