<?php

/**
 *
 * @see XenForo_ControllerAdmin_AddOn
 */
class Waindigo_InstallUpgrade_Extend_XenForo_ControllerAdmin_AddOn extends XFCP_Waindigo_InstallUpgrade_Extend_XenForo_ControllerAdmin_AddOn
{

    /**
     *
     * @see XenForo_ControllerAdmin_AddOn::actionIndex()
     */
    public function actionIndex()
    {
        $response = parent::actionIndex();
        
        if ($response instanceof XenForo_ControllerResponse_View) {
            $addOnModel = $this->_getAddOnModel();
            
            $response->params['addOns'] = $addOnModel->prepareAddOns($response->params['addOns']);
        }
        
        return $response;
    }

    /**
     *
     * @see XenForo_ControllerAdmin_AddOn::actionAdd()
     */
    public function actionAdd()
    {
        $response = parent::actionAdd();
        
        if ($response instanceof XenForo_ControllerResponse_View) {
            $xenOptions = XenForo_Application::get('options');
            if ($xenOptions->waindigo_installUpgrade_defaultVersions) {
                $response->params['addOn']['version_string'] = '1.0.0';
                $response->params['addOn']['version_id'] = XenForo_Application::$time;
            }
            if ($xenOptions->waindigo_installUpgrade_defaultWaindigoInstall) {
                $response->params['addOn']['install_callback_class'] = 'Waindigo_Install';
                $response->params['addOn']['install_callback_method'] = 'install';
                $response->params['addOn']['uninstall_callback_class'] = 'Waindigo_Install';
                $response->params['addOn']['uninstall_callback_method'] = 'uninstall';
            }
        }
        
        return $response;
    }

    /**
     *
     * @see XenForo_ControllerAdmin_AddOn::actionDelete()
     */
    public function actionDelete()
    {
        if ($this->isConfirmedPost()) {
            $addOnIds = $this->_input->filterSingle('addon_ids', XenForo_Input::ARRAY_SIMPLE);
            
            if ($addOnIds) {
                foreach ($addOnIds as $addOnId) {
                    $this->_request->setParam('addon_id', $addOnId);
                    
                    $response = parent::actionDelete();
                    
                    if ($response instanceof XenForo_ControllerResponse_View) {
                        break;
                    }
                }
            }
        }
        
        if (!isset($response)) {
            $response = parent::actionDelete();
        }
        
        return $response;
    }

    /**
     *
     * @see XenForo_ControllerAdmin_AddOn::actionInstall()
     */
    public function actionInstall()
    {
        $GLOBALS['XenForo_ControllerAdmin_AddOn'] = $this;
        
        if ($this->_request->isPost()) {
            $addOnIds = $this->_input->filterSingle('addon_ids', XenForo_Input::ARRAY_SIMPLE);
            
            if ($addOnIds) {
                $addOnIds = $this->_input->filterSingle('addon_ids', XenForo_Input::ARRAY_SIMPLE);
                
                $serverFiles = $this->_input->filterSingle('server_files', XenForo_Input::ARRAY_SIMPLE);
                
                foreach ($addOnIds as $addOnId) {
                    if (empty($serverFiles[$addOnId])) {
                        continue;
                    }
                    $this->_request->clearParams();
                    $this->_request->setParam('server_file', $serverFiles[$addOnId]);
                    
                    $response = parent::actionInstall();
                    
                    if ($response instanceof XenForo_ControllerResponse_View) {
                        break;
                    }
                }
            } else {
                $this->_checkForChoices();
                $this->_checkForTitle();
                $this->_checkForUrl();
                $this->_checkForDirectory();
                
                if (isset($_FILES['upload_file'])) {
                    $files = $_FILES['upload_file'];
                    if (!is_array($files['name'])) {
                        return parent::actionInstall();
                    }
                    foreach ($files['name'] as $key => $filename) {
                        $filesArrayKeys = array_keys($files);
                        $_FILES['upload_file'] = array();
                        foreach ($filesArrayKeys as $filesArrayKey) {
                            $_FILES['upload_file'][$filesArrayKey] = $files[$filesArrayKey][$key];
                        }
                        
                        $response = parent::actionInstall();
                        
                        if ($response instanceof XenForo_ControllerResponse_View) {
                            break;
                        }
                    }
                }
            }
        }
        
        if (!isset($response)) {
            $response = parent::actionInstall();
        }
        
        return $response;
    }

    /**
     *
     * @see XenForo_ControllerAdmin_AddOn::actionUpgrade()
     */
    public function actionUpgrade()
    {
        $GLOBALS['XenForo_ControllerAdmin_AddOn'] = $this;
        
        if ($this->_request->isPost()) {
            $addOnIds = $this->_input->filterSingle('addon_ids', XenForo_Input::ARRAY_SIMPLE);
            
            if ($addOnIds) {
                $addOns = $this->_getAddOnModel()->getAllAddOns();
                
                foreach ($addOnIds as $addOnId) {
                    if (!empty($addOns[$addOnId])) {
                        $addOn = $addOns[$addOnId];
                        
                        $this->_request->clearParams();
                        $this->_request->setParam('addon_id', $addOnId);
                        $this->_request->setParam('server_file', $addOn['install_upgrade_filename']);
                        
                        $this->_checkForUrl();
                        
                        $response = parent::actionUpgrade();
                        
                        if ($response instanceof XenForo_ControllerResponse_View) {
                            break;
                        }
                    }
                }
            } else {
                $this->_checkForChoices();
                $this->_checkForUrl();
                
                if (isset($_FILES['upload_file'])) {
                    $files = $_FILES['upload_file'];
                    foreach ($files['name'] as $key => $filename) {
                        $filesArrayKeys = array_keys($files);
                        $_FILES['upload_file'] = array();
                        foreach ($filesArrayKeys as $filesArrayKey) {
                            $_FILES['upload_file'][$filesArrayKey] = $files[$filesArrayKey][$key];
                        }
                        
                        $response = parent::actionUpgrade();
                        
                        if ($response instanceof XenForo_ControllerResponse_View) {
                            break;
                        }
                    }
                }
            }
        }
        
        if (!isset($response)) {
            $response = parent::actionUpgrade();
        }
        
        return $response;
    }

    public function actionInstallMultiple()
    {
        $serverFile = $this->_input->filterSingle('server_file', XenForo_Input::STRING);
        
        if (!$serverFile || !is_dir($serverFile)) {
            return $this->responseNoPermission();
        }
        
        /* @var $helper Waindigo_InstallUpgrade_ControllerHelper_Multiple */
        $helper = $this->getHelper('Waindigo_InstallUpgrade_ControllerHelper_Multiple');
        
        $directoryAddOns = $helper->getAddOnsFromDirectory($serverFile);
        
        $addOns = $this->_getAddOnModel()->getAllAddOns();
        
        $viewParams = array(
            'addOns' => $addOns,
            'directoryAddOns' => $directoryAddOns
        );
        
        return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_InstallMultiple', 
            'waindigo_install_addons_multiple_installupgrade', $viewParams);
    }

    public function actionOutdated()
    {
        $addOnModel = $this->_getAddOnModel();
        $addOns = $addOnModel->getAllAddOns();
        
        $installUpgradeModel = $this->_getInstallUpgradeModel();
        $checked = $installUpgradeModel->checkForAddOnUpdates($addOns, $errorString);
        
        $xenOptions = XenForo_Application::get('options');
        
        foreach ($addOns as $addOnId => $addOn) {
            if ($xenOptions->waindigo_installUpgrade_outdatedEnabledOnly && !$addOn['active']) {
                unset($addOns[$addOnId]);
            }
            if (!$addOn['install_upgrade_updated']) {
                unset($addOns[$addOnId]);
            }
        }
        
        $addOns = $addOnModel->prepareAddOns($addOns);
        
        $broadcast = XenForo_Application::getSimpleCacheData('installUpgradeBroadcast');
        
        if ($broadcast) {
            $formatter = XenForo_BbCode_Formatter_Base::create('Waindigo_InstallUpgrade_BbCode_Formatter_Broadcast');
            $parser = XenForo_BbCode_Parser::create($formatter);
            
            $broadcast['message'] = $parser->render($broadcast['message']);
        }
        
        $viewParams = array(
            'addOns' => $addOns,
            
            'errorString' => $errorString,
            'broadcast' => $broadcast
        );
        
        return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_Outdated', 
            'waindigo_outdated_addons_installupgrade', $viewParams);
    }

    /**
     *
     * @return XenForo_ControllerResponse_Abstract
     */
    public function actionEditUrl()
    {
        $addOnId = $this->_input->filterSingle('addon_id', XenForo_Input::STRING);
        $addOn = $this->_getAddOnOrError($addOnId);
        
        $viewParams = array(
            'addOn' => $addOn
        );
        
        return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_EditUrl', 
            'waindigo_addon_edit_url_installupgrade', $viewParams);
    }

    /**
     *
     * @return XenForo_ControllerResponse_Abstract
     */
    public function actionSaveUrl()
    {
        $this->_assertPostOnly();
        
        $addOnId = $this->_input->filterSingle('addon_id', XenForo_Input::STRING);
        $addOn = $this->_getAddOnOrError($addOnId);
        
        $dwInput = $this->_input->filter(
            array(
                'install_upgrade_filename' => XenForo_Input::STRING
            ));
        
        $dw = XenForo_DataWriter::create('XenForo_DataWriter_AddOn');
        $dw->setExistingData($addOn);
        $dw->bulkSet($dwInput);
        $dw->save();
        
        return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, 
            XenForo_Link::buildAdminLink('add-ons/outdated') . $this->getLastHash($addOnId));
    }

    /**
     *
     * @return XenForo_ControllerResponse_Abstract
     */
    public function actionDismissBroadcast()
    {
        $redirect = $this->getDynamicRedirect(XenForo_Link::buildAdminLink('index'));
        
        $installUpgradeBroadcast = XenForo_Application::getSimpleCacheData('installUpgradeBroadcast');
        
        if (empty($installUpgradeBroadcast)) {
            return $this->responseNoPermission();
        }
        
        if (!empty($installUpgradeBroadcast['dismiss'])) {
            return $this->responseNoPermission();
        }
        
        $xenOptions = XenForo_Application::get('options');
        
        if (!empty($installUpgradeBroadcast['class']) && !$xenOptions->waindigo_installUpgrade_overrideNoDismiss) {
            $classes = explode(' ', $installUpgradeBroadcast['class']);
            if (in_array('noDismiss', $classes)) {
                return $this->responseNoPermission();
            }
        }
        
        if ($this->isConfirmedPost()) {
            $installUpgradeBroadcast['dismiss'] = true;
            
            XenForo_Application::setSimpleCacheData('installUpgradeBroadcast', $installUpgradeBroadcast);
            
            return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, $redirect);
        } else {
            return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_DismissBroadcast', 
                'waindigo_broadcast_dismiss_installupgrade');
        }
    }

    protected function _checkForChoices()
    {
        $choices = $this->_input->filterSingle('choice', XenForo_Input::ARRAY_SIMPLE);
        if (!empty($choices)) {
            $viewParams = array(
                'addOnId' => $this->_input->filterSingle('addon_id', XenForo_Input::STRING),
                'choices' => $choices
            );
            throw ($this->responseException(
                $this->responseView('Waindigo_InstallUpgrade_ViewPublic_AddOn_ChooseXml', 
                    'waindigo_choose_xml_addon_installupgrade', $viewParams)));
        }
    }

    protected function _checkForTitle()
    {
        /* @var $helper Waindigo_InstallUpgrade_ControllerHelper_InstallUpgrade */
        $helper = $this->getHelper('Waindigo_InstallUpgrade_ControllerHelper_InstallUpgrade');
        $helper->checkForTitle();
    }

    protected function _checkForUrl()
    {
        /* @var $helper Waindigo_InstallUpgrade_ControllerHelper_InstallUpgrade */
        $helper = $this->getHelper('Waindigo_InstallUpgrade_ControllerHelper_InstallUpgrade');
        $helper->checkForUrl();
    }

    protected function _checkForDirectory()
    {
        /* @var $helper Waindigo_InstallUpgrade_ControllerHelper_InstallUpgrade */
        $helper = $this->getHelper('Waindigo_InstallUpgrade_ControllerHelper_InstallUpgrade');
        $helper->checkForDirectory();
    }

    public function actionRebuildCaches()
    {
        XenForo_Application::get('options')->set('waindigo_installUpgrade_noAddOnCacheRebuild', false);
        
        $caches = $this->_getAddOnModel()->rebuildAddOnCaches();
        
        if (XenForo_Application::$versionId < 1020000) {
            return XenForo_CacheRebuilder_Abstract::getRebuilderResponse($this, $caches, 
                XenForo_Link::buildAdminLink('add-ons'));
        }
        
        return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, 
            $this->getDynamicRedirect(XenForo_Link::buildAdminLink('add-ons'), true));
    }

    public function actionRebuild()
    {
        $xenOptions = XenForo_Application::get('options');
        
        $addOnId = $this->_input->filterSingle('addon_id', XenForo_Input::STRING);
        Waindigo_Install::install(array(), array(
            'addon_id' => $addOnId
        ));
        
        if ($xenOptions->waindigo_installUpgrade_cachesOnRebuild) {
            $caches = $this->_getAddOnModel()->rebuildAddOnCaches();
            
            return XenForo_CacheRebuilder_Abstract::getRebuilderResponse($this, $caches, 
                XenForo_Link::buildAdminLink('add-ons'));
        } else {
            return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, 
                $this->getDynamicRedirect(XenForo_Link::buildAdminLink('add-ons'), true));
        }
    }

    public function actionDownload()
    {
        $this->assertDebugMode();
        
        $addOnId = $this->_input->filterSingle('addon_id', XenForo_Input::STRING);
        $addOn = $this->_getAddOnModel()->getAddOnById($addOnId);
        if (!$addOn) {
            $addOn = array(
                'addon_id' => $addOnId
            );
        }
        
        if ($this->isConfirmedPost()) { // download add-on
            $versionString = $this->_input->filterSingle('version_string', XenForo_Input::STRING);
            $noCopyright = false;
            if (XenForo_Application::getOptions()->waindigo_installUpgrade_copyrightVisibility) {
                $noCopyright = $this->_input->filterSingle('no_copyright', XenForo_Input::UINT);
            }
            $GLOBALS['XenForo_ControllerAdmin_AddOn'] = $this;
            $zipFile = $this->_getAddOnModel()->prepareAddOnForDownload($addOn, $versionString, $noCopyright);
            
            $addOn['version_string'] = $versionString;
            
            $this->_routeMatch->setResponseType('raw');
            
            $viewParams = array(
                'addOn' => $addOn,
                'zipFile' => $zipFile
            );
            
            return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_Download', '', $viewParams);
        } else {
            if (!isset($addOn['title'])) {
                $addOnXML = new SimpleXMLElement(
                    file_get_contents(
                        XenForo_Application::getInstance()->getRootDir() . '/install/data/addon-' . $addOn['addon_id'] .
                             '.xml'));
                $addOn['title'] = (string) $addOnXML->attributes()->title;
                $addOn['version_string'] = (string) $addOnXML->attributes()->version_string;
            }
            $viewParams = array(
                'addOn' => $addOn
            );
            
            return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_Download', 
                'waindigo_addon_download_installupgrade', $viewParams);
        }
    }

    public function actionStoredCredentials()
    {
        $this->assertAdminPermission('installUpgradeCreds');
        
        $installUpgradeModel = $this->_getInstallUpgradeModel();
        
        $credentials = $installUpgradeModel->getAllCredentials();
        
        $input = $this->_input->filter(
            array(
                'login_id' => XenForo_Input::UINT,
                'edit' => XenForo_Input::UINT
            ));
        
        $viewParams = array(
            'storedCredentials' => $credentials,
            'canEncrypt' => $installUpgradeModel->canEncrypt(false),
            'token' => XenForo_Helper_Cookie::getCookie('install_credentials_token')
        );
        
        return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_StoredCredentials', 
            'waindigo_addon_stored_credentials_installupgrade', $viewParams);
    }

    public function actionStoredCredentialsEdit()
    {
        $this->assertAdminPermission('installUpgradeCreds');
        
        $installUpgradeModel = $this->_getInstallUpgradeModel();
        
        $input = $this->_input->filter(
            array(
                'login_id' => XenForo_Input::UINT,
                'username' => XenForo_Input::STRING,
                'password' => XenForo_Input::STRING,
                'host' => XenForo_Input::STRING,
                'path' => XenForo_Input::STRING
            ));
        
        if ($input['login_id']) {
            $credential = $installUpgradeModel->getCredentialById($input['login_id']);
        }
        
        if (!empty($credential)) {
            if ($input['username']) {
                $credential['username'] = $input['username'];
            }
            if ($input['password']) {
                $credential['password'] = $input['password'];
            }
        } elseif ($input['host']) {
            unset($input['login_id']);
            if (!$input['path']) {
                $input['path'] = '/';
            }
            $credential = $installUpgradeModel->getCredentialByHostAndPath($input['host'], $input['path']);
            if (!$credential) {
                $credential = $input;
            }
        } else {
            $credential = $input;
        }
        
        $credential = $installUpgradeModel->prepareCredential($credential);
        
        $viewParams = array(
            'credential' => $credential,
            'canEncrypt' => $installUpgradeModel->canEncrypt()
        );
        
        return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_StoredCredentials_Edit', 
            'waindigo_addon_stored_cred_edit_installupgrade', $viewParams);
    }

    public function actionStoredCredentialsSave()
    {
        $this->assertAdminPermission('installUpgradeCreds');
        
        $this->_assertPostOnly();
        
        $installUpgradeModel = $this->_getInstallUpgradeModel();
        
        $input = $this->_input->filter(
            array(
                'username' => XenForo_Input::STRING,
                'password' => XenForo_Input::STRING,
                'host' => XenForo_Input::STRING,
                'path' => XenForo_Input::STRING,
                'encrypt' => XenForo_Input::UINT
            ));
        
        $installUpgradeModel->addCredentials($input['username'], $input['password'], $input['host'], $input['path'], 
            $input['encrypt']);
        
        if ($input['host'] == 'waindigo.org' && $input['path'] == '/') {
            /* @var $addOnModel XenForo_Model_AddOn */
            $addOnModel = $this->_getAddOnModel();
            $addOns = $addOnModel->getAllAddOns();
            $installUpgradeModel->checkForAddOnUpdates($addOns);
        }
        
        return $this->responseRedirect(XenForo_ControllerResponse_Redirect::RESOURCE_UPDATED, 
            XenForo_Link::buildAdminLink('add-ons/stored-credentials'));
    }

    /**
     * Deletes stored credentials.
     *
     * @return XenForo_ControllerResponse_Abstract
     */
    public function actionStoredCredentialsDelete()
    {
        $this->assertAdminPermission('installUpgradeCreds');
        
        $installUpgradeModel = $this->_getInstallUpgradeModel();
        
        $loginId = $this->_input->filterSingle('login_id', XenForo_Input::UINT);
        $credential = $installUpgradeModel->getCredentialById($loginId);
        
        if (!$credential) {
            return $this->responseNoPermission();
        }
        
        if ($this->isConfirmedPost()) {
            $installUpgradeModel->deleteCredentials($loginId);
            
            if ($credential['host'] == 'waindigo.org' && $credential['path'] == '/') {
                /* @var $addOnModel XenForo_Model_AddOn */
                $addOnModel = $this->_getAddOnModel();
                $addOns = $addOnModel->getAllAddOns();
                $installUpgradeModel->checkForAddOnUpdates($addOns);
            }
            
            return $this->responseRedirect(XenForo_ControllerResponse_Redirect::SUCCESS, 
                XenForo_Link::buildAdminLink('add-ons/stored-credentials'));
        } else {
            $viewParams = array(
                'credential' => $credential
            );
            
            return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_StoredCredentials_Delete', 
                'waindigo_addon_stored_cred_delete_installupgrade', $viewParams);
        }
    }

    /**
     * Searches for a filename by the left-most prefix of a name (for
     * auto-complete).
     *
     * @return XenForo_ControllerResponse_Abstract
     */
    public function actionSearchFilename()
    {
        $q = ltrim(
            $this->_input->filterSingle('q', XenForo_Input::STRING, 
                array(
                    'noTrim' => true
                )));
        
        $results = array();
        
        if ($q !== '') {
            if (is_dir($q)) {
                $path = $q;
                $q = '';
            } else {
                $pathInfo = pathinfo($q);
                if (is_dir($pathInfo['dirname'])) {
                    $path = $pathInfo['dirname'];
                    $q = $pathInfo['basename'];
                } else {
                    $path = '';
                }
            }
            
            if ($path) {
                if ($path == '.') {
                    $path = '';
                } else {
                    $path = rtrim($path, '/\\') . DIRECTORY_SEPARATOR;
                }
                
                $dir = XenForo_Application::getInstance()->getRootDir() . DIRECTORY_SEPARATOR . $path;
                
                if (is_dir($dir)) {
                    $handle = opendir($dir);
                    
                    $possibleExtensions = array(
                        'kml',
                        'rar',
                        'xml',
                        'zip'
                    );
                    
                    while (false !== ($file = readdir($handle))) {
                        if ($file != "." && $file != "..") {
                            $pathInfo = pathinfo($file);
                            $result = '';
                            if (!$q) {
                                $result = $path . $file;
                            } elseif (preg_match('#^(' . preg_quote($q) . ')#i', $file)) {
                                $result = $path . $file;
                            }
                            if ($result && (empty($pathInfo['extension']) ||
                                 in_array(strtolower($pathInfo['extension']), $possibleExtensions))) {
                                $results[] = $result;
                            }
                        }
                        if (count($results) >= 5) {
                            break;
                        }
                    }
                    
                    if (count($results) == 1) {
                        $result = reset($results) . DIRECTORY_SEPARATOR;
                        
                        $dir = XenForo_Application::getInstance()->getRootDir() . DIRECTORY_SEPARATOR . $result;
                        
                        if (is_dir($dir)) {
                            try {
                                $handle = opendir($dir);
                                
                                while (false !== ($file = readdir($handle))) {
                                    if ($file != "." && $file != "..") {
                                        $pathInfo = pathinfo($file);
                                        if (empty($pathInfo['extension']) ||
                                             in_array(strtolower($pathInfo['extension']), $possibleExtensions)) {
                                            $results[] = $result . $file;
                                        }
                                    }
                                    if (count($results) >= 5) {
                                        break;
                                    }
                                }
                            } catch (Exception $e) {
                            }
                        }
                    }
                }
            }
            
            if (!$results) {
                try {
                    $client = Waindigo_InstallUpgrade_Helper_Http::getClient('https://waindigo.org/resources/find.json');
                    $client->setParameterGet('q', $q);
                    $response = $response = $client->request('GET');
                    $body = json_decode($response->getBody(), true);
                    $results = $body['results'];
                } catch (Exception $e) {
                    // do nothing
                }
            }
        }
        
        $viewParams = array(
            'results' => $results
        );
        
        return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_SearchFilename', '', $viewParams);
    }

    public function responseNoPermissionExternal(array $viewParams = array())
    {
        $addOnId = $this->_input->filterSingle('addon_id', XenForo_Input::STRING);
        if ($addOnId) {
            $viewParams['addOn'] = array(
                'addon_id' => $addOnId
            );
        }
        
        return $this->responseView('Waindigo_InstallUpgrade_ViewAdmin_AddOn_Login', 
            'waindigo_addon_login_installupgrade', $viewParams);
    }

    /**
     * Gets the install & upgrade model object.
     *
     * @return Waindigo_InstallUpgrade_Model_InstallUpgrade
     */
    protected function _getInstallUpgradeModel()
    {
        return $this->getModelFromCache('Waindigo_InstallUpgrade_Model_InstallUpgrade');
    }
}