<?php

/**
 * Lifestyle Webconsulting GmbH
 *
 * LICENSE: This Software is the property of Lifestyle Webconsulting GmbH (Aschaffenburg, Germany)
 * and is private by copyright law - it is NOT Freeware.
 *
 * Any unauthorized use of this software without a valid license
 * is a violation of the license agreement and will be prosecuted by
 * civil and criminal law.
 *
 * @copyright  2017 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 */

namespace Version2\Security;

use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Constants;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Credentials;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\FunctionalTestCase;
use Sso\WebserviceBundle\Tests\Functional\Services\Helper\Version2\Model\User;

/**
 * Class XmlBombTest
 *
 * @copyright  2017 Lifestyle Webconsulting GmbH
 * @link       http://www.life-style.de
 * @package Version2\Security
 */
class XmlBombTest extends FunctionalTestCase
{

    public function testXmlBomb()
    {
        $this->markTestSkipped('XML Bomb tests may destroy phpunittest. Skipping ...');

        $requestBody = '<?xml version="1.0"?>
<!DOCTYPE lolz [
    <!ENTITY lol "lol">
    <!ELEMENT lolz (#PCDATA)>
    <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
    <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
    <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
    <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
    <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
    <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
    <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
    <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
    <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<lolz>&lol9;</lolz>';

        $response = $this->sendPostRequest('User', 'Show', $requestBody);

        static::assertEquals(
            400,
            $response->getStatusCode());

        $xml = $response->getContent();

        // Value check
        $xmlSimple = simplexml_load_string($xml);

        static::assertTrue(isset($xmlSimple->Status),
            $this->fXml($requestBody, $xml, 'Global xml status code not found!')
        );

        static::assertEquals(
            Constants::STATUS_BAD_REQUEST,
            (string)$xmlSimple->Status,
            $this->fXml($requestBody, $xml, 'Global xml status code does not match!')
        );


        static::assertTrue(isset($xmlSimple->Date), $this->fXml($requestBody, $xml, 'Date not found!'));
        static::assertRegExp(
            Constants::REGEXP_DATE,
            (string)$xmlSimple->Date,
            $this->fXml($requestBody, $xml, 'Date format does not match!')
        );

    }

    public function testXmlSpy()
    {
        $this->markTestSkipped('XML Bomb tests may destroy phpunittest. Skipping ...');

        $faker = \Faker\Factory::create();
        $user = new User();
        $user->setEmail(Constants::PREFIX . $faker->email);
        $user->setUsername(Constants::PREFIX . $faker->userName);
        $user->setActive(true);
        $user->setFirstname($faker->firstName);
        $user->setLastname($faker->lastName);
        $user->setPassword($faker->password(8, 120) . '_Aa1');

        $this->testUser = $user;

        $requestBody = '<?xml version="1.0"?><!DOCTYPE SsoRequest [<!ENTITY harmless SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/apache2/apache2.conf">]>
<SsoRequest>' . (string)(new Credentials($this->configuration)) . '<User>
        <Add>
            <Value>
                <UserType>
                    <Email>' . $this->cdata($user->getEmail()) . '</Email>
                    <Username>' . $this->cdata($user->getUsername()) . '</Username>
                    <Firstname>' . $this->cdata($user->getFirstname()) . '</Firstname>
                    <Lastname>&harmless;</Lastname>
                    <Password>' . $this->cdata($user->getPassword()) . '</Password>
                    <Active>' . ($user->isActive() ? '1' : '0') . '</Active>
                    <AuthId>' . $this->cdata($user->getAuthId()) . '</AuthId>
                    <LdapSearchAttributes>' . $this->cdata($user->getLdapSearchAttributes()) . '</LdapSearchAttributes>
                    <LdapSearchValue>' . $this->cdata($user->getLdapSearchValue()) . '</LdapSearchValue>
                </UserType>
            </Value>
        </Add>
    </User>
</SsoRequest>';
        $response = $this->sendPostRequest('User', 'Add', $requestBody);
        static::assertEquals(400, $response->getStatusCode());

        $xml = $response->getContent();
        $xmlElement = $this->loadResponse($xml);

        $xmlExpectedElement = $this->loadXmlDomElement(__DIR__ . '/xml/xml-spy-response.xml', 'SsoResponse');
        static::assertEqualXMLStructure($xmlExpectedElement, $xmlElement, false, $this->fXml($requestBody, $xml, 'Xml structure check failed'));

        // Value check
        $xmlSimple = simplexml_load_string($xml);
        static::assertEquals(
            Constants::STATUS_BAD_REQUEST,
            (string)$xmlSimple->Status,
            $this->fXml($requestBody, $xml, 'Global xml status code does not match!')
        );

        static::assertRegExp(
            Constants::REGEXP_DATE,
            (string)$xmlSimple->Date,
            $this->fXml($requestBody, $xml, 'Date format does not match!')
        );

    }
}
