# Copyright (C) 2018 Sony Interactive Entertainment Inc.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1.  Redistributions of source code must retain the above copyright
#     notice, this list of conditions and the following disclaimer.
# 2.  Redistributions in binary form must reproduce the above copyright
#     notice, this list of conditions and the following disclaimer in the
#     documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


import unittest

from webkitpy.common.system.pemfile import Pem, BadFormatError
from webkitpy.common.system.platforminfo import PlatformInfo


class PemFileTest(unittest.TestCase):
    """Test Pem file parsing"""
    def test_parse(self):
        pem = Pem(self.pem_contents)

        self.assertEqual(pem.private_key, self.private_key)
        self.assertEqual(pem.certificate, self.certificate)

        with self.assertRaises(KeyError):
            pem.csr

        with self.assertRaises(KeyError):
            pem.get("FOO BAR")

    def test_parse_crlf(self):
        pem = Pem(self.pem_contents.replace('\n', '\r\n'))

        self.assertEqual(pem.private_key, self.private_key)
        self.assertEqual(pem.certificate, self.certificate)

    def test_parse_cr(self):
        pem = Pem(self.pem_contents.replace('\n', '\r'))

        self.assertEqual(pem.private_key, self.private_key)
        self.assertEqual(pem.certificate, self.certificate)

    def test_parse_bad_format(self):
        with self.assertRaises(BadFormatError):
            # Partial contents raises format error
            Pem(trim("""-----BEGIN PRIVATE KEY-----
            MIICXQIBAAKBgQCmcXbusrr8zQr8snIb0OVQibVfgv7zPjh/5xdcrKOejJzp3epA
            AF4TITeFR9vzWIwkmkcRoY+IbQNhh7kefGUYD47bvVamJMtq5cGYVs0HngT+KTMa
            NGH/G44KkFIOaz/b5d/JNKONrlqwxqXS+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQAB
            """) + "\n")

        with self.assertRaises(BadFormatError):
            # No section content raises format error
            Pem("""HELLO WORLD
            HOW'S GOING????
            """)

    def test_parse_custom_content(self):
        pem = Pem(trim("""Hi, please take this.
        -----BEGIN FOOBAR-----
        HELLO/WORKD===
        -----END FOOBAR-----
        regards,
        kind of mail signature comes here
        """) + "\n")

        self.assertEqual(
            trim(pem.get("FOOBAR")),
            trim("""-----BEGIN FOOBAR-----
                    HELLO/WORKD===
                    -----END FOOBAR-----"""))

    def setUp(self):
        self.pem_contents = trim("""-----BEGIN PRIVATE KEY-----
        MIICXQIBAAKBgQCmcXbusrr8zQr8snIb0OVQibVfgv7zPjh/5xdcrKOejJzp3epA
        AF4TITeFR9vzWIwkmkcRoY+IbQNhh7kefGUYD47bvVamJMtq5cGYVs0HngT+KTMa
        NGH/G44KkFIOaz/b5d/JNKONrlqwxqXS+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQAB
        AoGBAIcDv4A9h6UOBv2ZGyspNvsv2erSblGOhXJrWO4aNNemJJspIp4sLiPCbDE3
        a1po17XRWBkbPz1hgL6axDXQnoeo++ebfrvRSed+Fys4+6SvuSrPOv6PmWTBT/Wa
        GpO+tv48JUNxC/Dy8ROixBXOViuIBEFq3NfVH4HU3+RG20NhAkEA1L3RAhdfPkLI
        82luSOYE3Eq44lICb/yZi+JEihwSeZTJKdZHwYD8KVCjOtjGrOmyEyvThrcIACQz
        JLEreVh33wJBAMhJm9pzJJNkIyBgiXA66FAwbhdDzSTPx0OBjoVWoj6u7jzGvIFT
        Cn1aiTBYzzsiMCaCx+W3e6pK/DcvHSwKrgkCQHZMcxwBmSHLC2lnmD8LQWqqVnLr
        fZV+VnfVw501DQT0uoP8NvygWBg1Uf9YKepfLXnBpidEQjup5ZKivnUEv+sCQA8N
        6VcMHI2vkyxV1T7ITrnoSf4ZrIu9yl56mHnRPzSy9VlAHt8hnMI7UeB+bGUndrMO
        VXQgzHzKUhbbxbePvfECQQDTtkOuhJyKDfHCxLDcwNpi+T6OWTEfCw/cq9ZWDbA7
        yCX81pQxfZkfMIS1YFIOGHovK0rMMTraCe+iDNYtVz/L
        -----END PRIVATE KEY-----
        -----BEGIN CERTIFICATE-----
        MIIB9zCCAWACCQDjWWTeC6BQvTANBgkqhkiG9w0BAQQFADBAMQswCQYDVQQGEwJB
        VTETMBEGA1UECBMKU29tZS1TdGF0ZTEcMBoGA1UEChMTV2ViS2l0IExheW91dCBU
        ZXN0czAeFw0wNzA3MTMxMjUxMzJaFw03MTA1MTMwNjIzMTZaMEAxCzAJBgNVBAYT
        AkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRwwGgYDVQQKExNXZWJLaXQgTGF5b3V0
        IFRlc3RzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmcXbusrr8zQr8snIb
        0OVQibVfgv7zPjh/5xdcrKOejJzp3epAAF4TITeFR9vzWIwkmkcRoY+IbQNhh7ke
        fGUYD47bvVamJMtq5cGYVs0HngT+KTMaNGH/G44KkFIOaz/b5d/JNKONrlqwxqXS
        +m6IY4l/E1Ff25ZjND5TaEvI1wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAAfbUbgD
        01O8DoZA02c1MUMbMHRPSb/qdok2pyWoCPa/BSaOIaNPePc8auPRbrS2XsVWSMft
        CTXiXmrK2Xx1+fJuZLAp0CUng4De4cDH5c8nvlocYmXo+1x53S9DfD0KPryjBRI7
        9LnJq2ysHAUawiqFXlwBag6mXawD8YjzcYat
        -----END CERTIFICATE-----
        """) + "\n"

        self.private_key = trim("""-----BEGIN PRIVATE KEY-----
        MIICXQIBAAKBgQCmcXbusrr8zQr8snIb0OVQibVfgv7zPjh/5xdcrKOejJzp3epA
        AF4TITeFR9vzWIwkmkcRoY+IbQNhh7kefGUYD47bvVamJMtq5cGYVs0HngT+KTMa
        NGH/G44KkFIOaz/b5d/JNKONrlqwxqXS+m6IY4l/E1Ff25ZjND5TaEvI1wIDAQAB
        AoGBAIcDv4A9h6UOBv2ZGyspNvsv2erSblGOhXJrWO4aNNemJJspIp4sLiPCbDE3
        a1po17XRWBkbPz1hgL6axDXQnoeo++ebfrvRSed+Fys4+6SvuSrPOv6PmWTBT/Wa
        GpO+tv48JUNxC/Dy8ROixBXOViuIBEFq3NfVH4HU3+RG20NhAkEA1L3RAhdfPkLI
        82luSOYE3Eq44lICb/yZi+JEihwSeZTJKdZHwYD8KVCjOtjGrOmyEyvThrcIACQz
        JLEreVh33wJBAMhJm9pzJJNkIyBgiXA66FAwbhdDzSTPx0OBjoVWoj6u7jzGvIFT
        Cn1aiTBYzzsiMCaCx+W3e6pK/DcvHSwKrgkCQHZMcxwBmSHLC2lnmD8LQWqqVnLr
        fZV+VnfVw501DQT0uoP8NvygWBg1Uf9YKepfLXnBpidEQjup5ZKivnUEv+sCQA8N
        6VcMHI2vkyxV1T7ITrnoSf4ZrIu9yl56mHnRPzSy9VlAHt8hnMI7UeB+bGUndrMO
        VXQgzHzKUhbbxbePvfECQQDTtkOuhJyKDfHCxLDcwNpi+T6OWTEfCw/cq9ZWDbA7
        yCX81pQxfZkfMIS1YFIOGHovK0rMMTraCe+iDNYtVz/L
        -----END PRIVATE KEY-----
        """) + "\n"

        self.certificate = trim("""-----BEGIN CERTIFICATE-----
        MIIB9zCCAWACCQDjWWTeC6BQvTANBgkqhkiG9w0BAQQFADBAMQswCQYDVQQGEwJB
        VTETMBEGA1UECBMKU29tZS1TdGF0ZTEcMBoGA1UEChMTV2ViS2l0IExheW91dCBU
        ZXN0czAeFw0wNzA3MTMxMjUxMzJaFw03MTA1MTMwNjIzMTZaMEAxCzAJBgNVBAYT
        AkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMRwwGgYDVQQKExNXZWJLaXQgTGF5b3V0
        IFRlc3RzMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmcXbusrr8zQr8snIb
        0OVQibVfgv7zPjh/5xdcrKOejJzp3epAAF4TITeFR9vzWIwkmkcRoY+IbQNhh7ke
        fGUYD47bvVamJMtq5cGYVs0HngT+KTMaNGH/G44KkFIOaz/b5d/JNKONrlqwxqXS
        +m6IY4l/E1Ff25ZjND5TaEvI1wIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAAfbUbgD
        01O8DoZA02c1MUMbMHRPSb/qdok2pyWoCPa/BSaOIaNPePc8auPRbrS2XsVWSMft
        CTXiXmrK2Xx1+fJuZLAp0CUng4De4cDH5c8nvlocYmXo+1x53S9DfD0KPryjBRI7
        9LnJq2ysHAUawiqFXlwBag6mXawD8YjzcYat
        -----END CERTIFICATE-----
        """) + "\n"


# Formal docstring indentation handling from PEP
# https://www.python.org/dev/peps/pep-0257/
def trim(docstring):
    if not docstring:
        return ''
    # Convert tabs to spaces (following the normal Python rules)
    # and split into a list of lines:
    lines = docstring.expandtabs().splitlines()
    # Determine minimum indentation (first line doesn't count):
    indent = PlatformInfo.MAX
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    # Remove indentation (first line is special):
    trimmed = [lines[0].strip()]
    if indent < PlatformInfo.MAX:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    # Strip off trailing and leading blank lines:
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    # Return a single string:
    return '\n'.join(trimmed)
