/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "secutil.h"
#include "nss.h"

unsigned char binary_line[64 * 1024];

int
main(int argc, const char** argv)
{
    int skip_count = 0;
    int bytes_read;
    char line[133];

    if (argc > 1) {
        skip_count = atoi(argv[1]);
    }
    if (argc > 2 || skip_count < 0) {
        printf("Usage: %s [ skip_columns ] \n", argv[0]);
        return 1;
    }

    NSS_NoDB_Init(NULL);

    while (fgets(line, 132, stdin) && (bytes_read = strlen(line)) > 0) {
        int bytes_written;
        char* found;
        char* in = line + skip_count;
        int left = bytes_read - skip_count;
        int is_cert;
        int is_serial;
        int is_name;
        int is_hash;
        int use_pp = 0;
        int out = 0;
        SECItem der = { siBuffer, NULL, 0 };

        line[bytes_read] = 0;
        if (bytes_read <= skip_count)
            continue;
        fwrite(in, 1, left, stdout);
        found = strstr(in, "MULTILINE_OCTAL");
        if (!found)
            continue;
        fflush(stdout);

        is_cert = (NULL != strstr(in, "CKA_VALUE"));
        is_serial = (NULL != strstr(in, "CKA_SERIAL_NUMBER"));
        is_name = (NULL != strstr(in, "CKA_ISSUER")) ||
                  (NULL != strstr(in, "CKA_SUBJECT"));
        is_hash = (NULL != strstr(in, "_HASH"));
        while (fgets(line, 132, stdin) &&
               (bytes_read = strlen(line)) > 0) {
            in = line + skip_count;
            left = bytes_read - skip_count;

            if ((left >= 3) && !strncmp(in, "END", 3))
                break;
            while (left >= 4) {
                if (in[0] == '\\' && isdigit((unsigned char)in[1]) &&
                    isdigit((unsigned char)in[2]) &&
                    isdigit((unsigned char)in[3])) {
                    left -= 4;
                    binary_line[out++] = ((in[1] - '0') << 6) |
                                         ((in[2] - '0') << 3) |
                                         (in[3] - '0');
                    in += 4;
                } else
                    break;
            }
        }
        der.data = binary_line;
        der.len = out;
        if (is_cert)
            SECU_PrintSignedData(stdout, &der, "Certificate", 0,
                                 SECU_PrintCertificate);
        else if (is_name)
            SECU_PrintDERName(stdout, &der, "Name", 0);
        else if (is_serial) {
            if (out > 2 && binary_line[0] == 2 &&
                out == 2 + binary_line[1]) {
                der.data += 2;
                der.len -= 2;
                SECU_PrintInteger(stdout, &der, "DER Serial Number", 0);
            } else
                SECU_PrintInteger(stdout, &der, "Raw Serial Number", 0);
        } else if (is_hash)
            SECU_PrintAsHex(stdout, &der, "Hash", 0);
        else
            SECU_PrintBuf(stdout, "Other", binary_line, out);
    }
    NSS_Shutdown();
    return 0;
}
