rugk/xenforo-threema-gateway

View on GitHub
src/library/ThreemaGateway/Handler/Settings.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php
/**
 * Uses the settings to provide some high-level functions.
 *
 * Please do not use this directly. Better use
 * {@link ThreemaGateway_Handler_PhpSdk->getSettings()}. If you want to use the
 * settings before initiating the SDK, you can use this class before, but please
 * pass an instance of it to {@link ThreemaGateway_Handler_PhpSdk} in this case.
 *
 * @package ThreemaGateway
 * @author rugk
 * @copyright Copyright (c) 2015-2016 rugk
 * @license MIT
 */

class ThreemaGateway_Handler_Settings
{
    /**
     * @var string $gatewayId Your own Threema Gateway ID
     */
    protected $gatewayId = '';

    /**
     * @var string $gatewaySecret Your own Threema Gateway secret
     */
    protected $gatewaySecret = '';

    /**
     * @var string $privateKey Your own private key
     */
    protected $privateKey = '';

    /**
     * @var string $privateKeyBase The unconverted private key from settings.
     */
    private $privateKeyBase = '';

    /**
     * @var string $publicKey the public key converted from the private key {@see $privateKey}
     */
    protected $publicKey = '';

    /**
     * Initiate settings.
     */
    public function __construct()
    {
        /** @var XenForo_Options $xenOptions */
        $xenOptions = XenForo_Application::getOptions();

        // get options (if not hard-coded)
        if (!$this->gatewayId) {
            $this->gatewayId = $xenOptions->threema_gateway_threema_id;
        }
        if (!$this->gatewaySecret) {
            $this->gatewaySecret = $xenOptions->threema_gateway_threema_id_secret;
        }
        if (!$this->privateKey) {
            if (!$this->privateKeyBase) {
                $this->privateKeyBase = $xenOptions->threema_gateway_privatekeyfile;
            }

            // vadility check & processing is later done when private key is actually requested
            // {@see convertPrivateKey()}
        }
    }

    /**
     * Checks whether the Gateway is basically set up.
     *
     * Note that this may not check all requirements (like installed libsodium
     * and so on).
     * In contrast to {@link isReady()} this only checks whether it is possible
     * to query the Threema Server for data, not whether sending/receiving
     * messages is actually possible.
     * This does not check any permissions! Use
     * {@link ThreemaGateway_Handler_Permissions->hasPermission()} for this
     * instead!
     *
     * @return bool
     */
    public function isAvaliable()
    {
        if (!$this->gatewayId ||
            !$this->gatewaySecret ||
            XenForo_Application::getOptions()->threema_gateway_e2e == ''
        ) {
            return false;
        }

        return true;
    }

    /**
     * Checks whether everything is comple, so sending and receiving messages
     * is (theoretically) possible.
     *
     * This includes {@link isAvaliable()} as a basic check.
     * This does not check any permissions! Use
     * {@link ThreemaGateway_Handler_Permissions->hasPermission()} for this
     * instead!
     *
     * @return bool
     */
    public function isReady()
    {
        // basic check
        if (!$this->isAvaliable()) {
            return false;
        }

        //check whether sending and receiving is possible
        if ($this->isEndToEnd()) {
            // fast check
            if (!$this->privateKey && !$this->privateKeyBase) {
                return false;
            }

            // get private key if necessary
            if (!$this->privateKey) {
                try {
                    $this->convertPrivateKey();
                } catch (Exception $e) {
                    // in case of an error, it is not ready
                    return false;
                }
            }

            // if the key is (still) invalid, return error
            if (!$this->isPrivateKey($this->privateKey)) {
                return false;
            }
        }

        return true;
    }

    /**
     * Checks whether sending uses the end-to-end encrypted mode.
     *
     * Note: When E2E mode is not used it is also not possible to receive
     * messages.
     *
     * @return bool
     */
    public function isEndToEnd()
    {
        return (XenForo_Application::getOptions()->threema_gateway_e2e == 'e2e');
    }

    /**
     * Checks whether the Gateway is running in debug mode.
     *
     * You may use this to show scary messages to the admins ;-) or to
     * conditionally disable functionality.
     *
     * @return bool
     */
    public function isDebug()
    {
        /** @var XenForo_Options $xenOptions */
        $xenOptions = XenForo_Application::getOptions();

        return (($xenOptions->threema_gateway_logreceivedmsgs['enabled'] ||
            $xenOptions->threema_gateway_allow_get_receive) &&
            XenForo_Application::debugMode());
    }

    /**
     * Returns the gateway ID.
     *
     * @return string
     */
    public function getId()
    {
        return $this->gatewayId;
    }

    /**
     * Returns the gateway secret.
     *
     * @return string
     */
    public function getSecret()
    {
        return $this->gatewaySecret;
    }

    /**
     * Returns the private key.
     *
     * @return string
     */
    public function getPrivateKey()
    {
        if (!$this->privateKey) {
            $this->convertPrivateKey();
        }

        return $this->privateKey;
    }

    /**
     * Returns the public key.
     *
     * @return string
     */
    public function getOwnPublicKey()
    {
        if (!$this->publicKey) {
            /** @var ThreemaGateway_Handler_Action_KeyConverter $keyConverter */
            $keyConverter    = new ThreemaGateway_Handler_Action_KeyConverter;
            $this->publicKey = $keyConverter->derivePublicKey($this->getPrivateKey());
        }

        return $this->publicKey;
    }

    /**
     * Checks and processes the private key. Throws an exception if something
     * is wrong.
     *
     * @throws XenForo_Exception
     */
    protected function convertPrivateKey()
    {
        // use raw key (undocumented, not recommend)
        if (ThreemaGateway_Helper_Key::check($this->privateKeyBase, 'private:')) {
            $this->privateKey = $this->privateKeyBase;
            return;
        }

        // find path of private key file
        if (!file_exists(__DIR__ . '/../' . $this->privateKeyBase)) {
            throw new XenForo_Exception(new XenForo_Phrase('threemagw_invalid_privatekey'));
        }

        // open file
        /** @var resource|false $fileres */
        $fileres = fopen(__DIR__ . '/../' . $this->privateKeyBase, 'r');

        // read content of private key file
        if (empty($fileres) || !is_resource($fileres)) {
            //error opening file
            throw new XenForo_Exception(new XenForo_Phrase('threemagw_invalid_keystorepath'));
        }

        $this->privateKey = fgets($fileres);
        fclose($fileres);
    }

    /**
     * Checks whether the string actually is a private key.
     *
     * @param  string $privateKey The string to check.
     * @return bool
     */
    protected function isPrivateKey($privateKey)
    {
        return ThreemaGateway_Helper_Key::check($privateKey, 'private:');
    }

    /**
     * Convert object to string.
     *
     * @return string
     */
    public function __toString()
    {
        return __CLASS__ . ' of ' . $this->gatewayId;
    }
}