xref: /plugin/farmer/helper.php (revision c66a21e9310e026fbbb84ac28904b906f052d2d5)
1bc461538SMichael Große<?php
2bc461538SMichael Große/**
3bc461538SMichael Große * DokuWiki Plugin farmer (Helper Component)
4bc461538SMichael Große *
5bc461538SMichael Große * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6bc461538SMichael Große * @author  Michael Große <grosse@cosmocode.de>
7bc461538SMichael Große */
8bc461538SMichael Große
9bc461538SMichael Große// must be run within Dokuwiki
10bc461538SMichael Großeif(!defined('DOKU_INC')) die();
11bc461538SMichael Große
12bc461538SMichael Großeclass helper_plugin_farmer extends DokuWiki_Plugin {
13bc461538SMichael Große
14fcbe16a4SMichael Große    private $allPlugins = array();
15fcbe16a4SMichael Große
16bc461538SMichael Große    /**
17bc461538SMichael Große     * Copy a file, or recursively copy a folder and its contents. Adapted for DokuWiki.
18bc461538SMichael Große     *
19bc461538SMichael Große     * @todo: needs tests
20bc461538SMichael Große     *
21bc461538SMichael Große     * @author      Aidan Lister <aidan@php.net>
22bc461538SMichael Große     * @author      Michael Große <grosse@cosmocode.de>
23bc461538SMichael Große     * @version     1.0.1
24bc461538SMichael Große     * @link        http://aidanlister.com/2004/04/recursively-copying-directories-in-php/
25bc461538SMichael Große     *
26bc461538SMichael Große     * @param       string $source       Source path
27bc461538SMichael Große     * @param       string $destination  Destination path
28bc461538SMichael Große     *
29bc461538SMichael Große     * @return      bool     Returns TRUE on success, FALSE on failure
30bc461538SMichael Große     */
31bc461538SMichael Große    function io_copyDir($source, $destination) {
32bc461538SMichael Große        if (is_link($source)) {
33bc461538SMichael Große            io_lock($destination);
34bc461538SMichael Große            $result=symlink(readlink($source), $destination);
35bc461538SMichael Große            io_unlock($destination);
36bc461538SMichael Große            return $result;
37bc461538SMichael Große        }
38bc461538SMichael Große
39bc461538SMichael Große        if (is_file($source)) {
40bc461538SMichael Große            io_lock($destination);
41bc461538SMichael Große            $result=copy($source, $destination);
42bc461538SMichael Große            io_unlock($destination);
43bc461538SMichael Große            return $result;
44bc461538SMichael Große        }
45bc461538SMichael Große
46bc461538SMichael Große        if (!is_dir($destination)) {
47bc461538SMichael Große            io_mkdir_p($destination);
48bc461538SMichael Große        }
49bc461538SMichael Große
50bc461538SMichael Große        $dir = dir($source);
51bc461538SMichael Große        while (false !== ($entry = $dir->read())) {
52bc461538SMichael Große            if ($entry == '.' || $entry == '..') {
53bc461538SMichael Große                continue;
54bc461538SMichael Große            }
55bc461538SMichael Große
56bc461538SMichael Große            // recurse into directories
57bc461538SMichael Große            $this->io_copyDir("$source/$entry", "$destination/$entry");
58bc461538SMichael Große        }
59bc461538SMichael Große
60bc461538SMichael Große        $dir->close();
61bc461538SMichael Große        return true;
62bc461538SMichael Große    }
63bc461538SMichael Große
6416bbfe4bSMichael Große    /**
6516bbfe4bSMichael Große     * get a list of all Plugins installed in the farmer wiki, regardless whether they are active or not.
6616bbfe4bSMichael Große     *
6716bbfe4bSMichael Große     * @return array
6816bbfe4bSMichael Große     */
690b96e6d7SMichael Große    public function getAllPlugins() {
700b96e6d7SMichael Große        $dir = dir(DOKU_PLUGIN);
710b96e6d7SMichael Große        $plugins = array();
720b96e6d7SMichael Große        while (false !== ($entry = $dir->read())) {
733949d8a1SMichael Große            if($entry == '.' || $entry == '..' || $entry == 'testing' || $entry == 'farmer') {
740b96e6d7SMichael Große                continue;
750b96e6d7SMichael Große            }
760b96e6d7SMichael Große            if (!is_dir(DOKU_PLUGIN ."/$entry")) {
770b96e6d7SMichael Große                continue;
780b96e6d7SMichael Große            }
790b96e6d7SMichael Große            $plugins[] = $entry;
800b96e6d7SMichael Große        }
816ec1ad8fSMichael Große        sort($plugins);
820b96e6d7SMichael Große        return $plugins;
830b96e6d7SMichael Große    }
840b96e6d7SMichael Große
8516bbfe4bSMichael Große    /**
8616bbfe4bSMichael Große     * List of all animals, i.e. directories within DOKU_FARMDIR without the template.
8716bbfe4bSMichael Große     *
8816bbfe4bSMichael Große     * @return array
8916bbfe4bSMichael Große     */
900b96e6d7SMichael Große    public function getAllAnimals() {
910b96e6d7SMichael Große        $animals = array();
920b96e6d7SMichael Große
930b96e6d7SMichael Große        $dir = dir(DOKU_FARMDIR);
940b96e6d7SMichael Große        while (false !== ($entry = $dir->read())) {
95a0fc814bSMichael Große            if ($entry == '.' || $entry == '..' || $entry == '_animal' || $entry == '.htaccess') {
96a0fc814bSMichael Große                continue;
97a0fc814bSMichael Große            }
98a0fc814bSMichael Große            if (!is_dir(DOKU_FARMDIR . $entry)) {
990b96e6d7SMichael Große                continue;
1000b96e6d7SMichael Große            }
1010b96e6d7SMichael Große            $animals[] = $entry;
1020b96e6d7SMichael Große        }
1030b96e6d7SMichael Große        $dir->close();
1040b96e6d7SMichael Große        return $animals;
1050b96e6d7SMichael Große    }
1060b96e6d7SMichael Große
10716bbfe4bSMichael Große    /**
10816bbfe4bSMichael Große     * Actiate a specific plugin in a specific animal
10916bbfe4bSMichael Große     *
11016bbfe4bSMichael Große     * @param string $plugin Name of the plugin to be activated
11116bbfe4bSMichael Große     * @param string $animal Directory of the animal within DOKU_FARMDIR
11216bbfe4bSMichael Große     */
113fcbe16a4SMichael Große    public function activatePlugin($plugin, $animal) {
114fcbe16a4SMichael Große        if (isset($this->allPlugins[$animal])) {
115fcbe16a4SMichael Große            $plugins = $this->allPlugins[$animal];
116fcbe16a4SMichael Große        } else {
117fcbe16a4SMichael Große            include(DOKU_FARMDIR . $animal . '/conf/plugins.local.php');
118fcbe16a4SMichael Große        }
119fcbe16a4SMichael Große        if (isset($plugins[$plugin]) && $plugins[$plugin] === 0) {
120fcbe16a4SMichael Große            unset($plugins[$plugin]);
121fcbe16a4SMichael Große            $this->writePluginConf($plugins, $animal);
122fcbe16a4SMichael Große        }
123fcbe16a4SMichael Große        $this->allPlugins[$animal] = $plugins;
124fcbe16a4SMichael Große    }
125fcbe16a4SMichael Große
126a0fc814bSMichael Große    /**
12716bbfe4bSMichael Große     * @param string $plugin Name of the plugin to be deactivated
12816bbfe4bSMichael Große     * @param string $animal Directory of the animal within DOKU_FARMDIR
129a0fc814bSMichael Große     */
130fcbe16a4SMichael Große    public function deactivatePlugin($plugin, $animal) {
131fcbe16a4SMichael Große        if (isset($this->allPlugins[$animal])) {
132fcbe16a4SMichael Große            $plugins = $this->allPlugins[$animal];
133fcbe16a4SMichael Große        } else {
134fcbe16a4SMichael Große            include(DOKU_FARMDIR . $animal . '/conf/plugins.local.php');
135fcbe16a4SMichael Große        }
136fcbe16a4SMichael Große        if (!isset($plugins[$plugin]) || $plugins[$plugin] !== 0) {
137fcbe16a4SMichael Große            $plugins[$plugin] = 0;
138fcbe16a4SMichael Große            $this->writePluginConf($plugins, $animal);
139fcbe16a4SMichael Große        }
140fcbe16a4SMichael Große        $this->allPlugins[$animal] = $plugins;
141fcbe16a4SMichael Große    }
142fcbe16a4SMichael Große
14316bbfe4bSMichael Große    /**
14416bbfe4bSMichael Große     * Write the list of (deactivated) plugins as plugin configuration of an animal to file
14516bbfe4bSMichael Große     *
14616bbfe4bSMichael Große     * @param array  $plugins associative array with the key being the plugin name and the value 0 or 1
14716bbfe4bSMichael Große     * @param string $animal  Directory of the animal within DOKU_FARMDIR
14816bbfe4bSMichael Große     */
149fcbe16a4SMichael Große    public function writePluginConf($plugins, $animal) {
150fcbe16a4SMichael Große        $pluginConf = '<?php' . "\n";
151fcbe16a4SMichael Große        foreach ($plugins as $plugin => $status) {
152fcbe16a4SMichael Große            $pluginConf .= '$plugins["' . $plugin  . '"] = ' . $status . ";\n";
153fcbe16a4SMichael Große        }
154fcbe16a4SMichael Große        io_saveFile(DOKU_FARMDIR . $animal . '/conf/plugins.local.php', $pluginConf);
155fcbe16a4SMichael Große        touch(DOKU_FARMDIR . $animal . '/conf/local.php');
156fcbe16a4SMichael Große    }
157fcbe16a4SMichael Große
15816bbfe4bSMichael Große    /**
15916bbfe4bSMichael Große     * Show a message for all errors which occured during form validation
16016bbfe4bSMichael Große     *
16116bbfe4bSMichael Große     * @param \dokuwiki\Form\Form $form        The form to which the errors should be added.
16216bbfe4bSMichael Große     * @param array               $errorArray  An associative array with the key being the name of the element at fault
16316bbfe4bSMichael Große     *                                         and the value being the associated error message.
16416bbfe4bSMichael Große     */
165a12b96c0SMichael Große    public function addErrorsToForm(\dokuwiki\Form\Form &$form, $errorArray) {
166628ea26fSMichael Große        foreach ($errorArray as $elementName => $errorMessage) {
167628ea26fSMichael Große            $offset = 0;
168628ea26fSMichael Große            msg($errorMessage, -1);
169628ea26fSMichael Große            while ($form->findPositionByAttribute('name',$elementName, $offset)) {
170628ea26fSMichael Große                $offset = $form->findPositionByAttribute('name',$elementName, $offset);
171628ea26fSMichael Große                $form->getElementAt($offset)->addClass('error');
172628ea26fSMichael Große                ++$offset;
173a12b96c0SMichael Große            }
174a12b96c0SMichael Große        }
175a12b96c0SMichael Große    }
176a12b96c0SMichael Große
17716bbfe4bSMichael Große    /**
17816bbfe4bSMichael Große     * @param string|null $page load adminpage $page, reload the current page if $page is ommited or null
17916bbfe4bSMichael Große     */
1804d120480SMichael Große    public function reloadAdminPage($page = null) {
1814d120480SMichael Große        global $ID;
1824d120480SMichael Große        $get = $_GET;
1834d120480SMichael Große        if(isset($get['id'])) unset($get['id']);
1844d120480SMichael Große        if ($page !== null ) {
1854d120480SMichael Große            $get['page'] = $page;
1864d120480SMichael Große        }
1874d120480SMichael Große        $self = wl($ID, $get, false, '&');
1884d120480SMichael Große        send_redirect($self);
1894d120480SMichael Große    }
1904d120480SMichael Große
19116bbfe4bSMichael Große    /**
19216bbfe4bSMichael Große     * Download and extract the animal template
19316bbfe4bSMichael Große     *
19416bbfe4bSMichael Große     * @param string $animalpath
19516bbfe4bSMichael Große     *
19616bbfe4bSMichael Große     * @throws \splitbrain\PHPArchive\ArchiveIOException
19716bbfe4bSMichael Große     */
19879435a6fSMichael Große    public function downloadTemplate($animalpath) {
19979435a6fSMichael Große        file_put_contents($animalpath . '/_animal.zip',fopen('https://www.dokuwiki.org/_media/dokuwiki_farm_animal.zip','r'));
200c9fd7b89SMichael Große        $zip = new splitbrain\PHPArchive\Zip();
20179435a6fSMichael Große        $zip->open($animalpath.'/_animal.zip');
202c9fd7b89SMichael Große        $zip->extract($animalpath);
20379435a6fSMichael Große        $zip->close();
20479435a6fSMichael Große        unlink($animalpath.'/_animal.zip');
20579435a6fSMichael Große    }
20679435a6fSMichael Große
207efa7af45SMichael Große    /**
208efa7af45SMichael Große     * recursive function to test wether a (non-existing) path points into an existint path
209efa7af45SMichael Große     *
210efa7af45SMichael Große     * @param $path string
211efa7af45SMichael Große     *
212efa7af45SMichael Große     * @param $container string has to exist
213efa7af45SMichael Große     *
214efa7af45SMichael Große     * @throws BadMethodCallException
215efa7af45SMichael Große     *
216efa7af45SMichael Große     * @return bool
217efa7af45SMichael Große     */
218efa7af45SMichael Große    public function isInPath ($path, $container) {
219efa7af45SMichael Große        if (!file_exists($container)) {
220efa7af45SMichael Große            throw new BadMethodCallException('The Container has to exist and be accessable by realpath().');
221efa7af45SMichael Große        }
222efa7af45SMichael Große        if (realpath($path) === false) {
223efa7af45SMichael Große            return $this->isInPath(dirname($path), $container);
224efa7af45SMichael Große        }
225efa7af45SMichael Große        if (strpos(realpath($path), realpath($container)) !== false) {
226efa7af45SMichael Große            return true;
227efa7af45SMichael Große        } else {
228efa7af45SMichael Große            return false;
229efa7af45SMichael Große        }
230efa7af45SMichael Große    }
231efa7af45SMichael Große
232d9ec4524SMichael Große    /**
23316bbfe4bSMichael Große     * Check if the farm is correctly configured for this farmer plugin
23416bbfe4bSMichael Große     *
235d9ec4524SMichael Große     * @return bool
236d9ec4524SMichael Große     */
237d9ec4524SMichael Große    public function checkFarmSetup () {
238d9ec4524SMichael Große        if(defined('DOKU_FARMDIR') && defined('DOKU_FARMTYPE')) {
239d9ec4524SMichael Große            if (DOKU_FARMTYPE == 'subdomain') {
240d9ec4524SMichael Große                return true;
241d9ec4524SMichael Große            } elseif (DOKU_FARMTYPE == 'htaccess') {
242d9ec4524SMichael Große                return defined('DOKU_FARMRELDIR');
243d9ec4524SMichael Große            } else {
244d9ec4524SMichael Große                return false;
245d9ec4524SMichael Große            }
246d9ec4524SMichael Große        }
247d9ec4524SMichael Große        return false;
248d9ec4524SMichael Große    }
249d9ec4524SMichael Große
25080ef674eSMichael Große    /**
25180ef674eSMichael Große     * The subdomain must contain at least two dots
25280ef674eSMichael Große     *
25380ef674eSMichael Große     * @link http://stackoverflow.com/questions/17986371/regular-expression-to-validate-fqdn-in-c-sharp-and-javascript
25480ef674eSMichael Große     *
25580ef674eSMichael Große     * @param string $subdomain
25680ef674eSMichael Große     *
25780ef674eSMichael Große     * @return bool
25880ef674eSMichael Große     */
25980ef674eSMichael Große    public function validateSubdomain ($subdomain) {
26080ef674eSMichael Große        return preg_match("/^(?=.{1,254}$)((?=[a-z0-9-]{1,63}\.)(xn--+)?[a-z0-9]+(-[a-z0-9]+)*\.){2,}[a-z]{2,63}$/i",$subdomain) === 1;
26180ef674eSMichael Große    }
26280ef674eSMichael Große
263909f2ff6SMichael Große    /**
264909f2ff6SMichael Große     * @param string $animalname
265909f2ff6SMichael Große     *
266909f2ff6SMichael Große     * @return bool
267909f2ff6SMichael Große     */
268909f2ff6SMichael Große    public function validateAnimalName ($animalname) {
269909f2ff6SMichael Große        return preg_match("/^[a-z0-9]+(-[a-z0-9]+)*$/i",$animalname) === 1;
270909f2ff6SMichael Große    }
271909f2ff6SMichael Große
272*c66a21e9SMichael Große    /**
273*c66a21e9SMichael Große     * @return string
274*c66a21e9SMichael Große     */
275*c66a21e9SMichael Große    public function getUserLine($currentAdmin) {
276*c66a21e9SMichael Große        $masterUsers = file_get_contents(DOKU_CONF . 'users.auth.php');
277*c66a21e9SMichael Große        $masterUsers = ltrim(strstr($masterUsers, "\n" . $currentAdmin . ":"));
278*c66a21e9SMichael Große        $newAdmin = substr($masterUsers, 0, strpos($masterUsers, "\n") + 1);
279*c66a21e9SMichael Große        return $newAdmin;
280*c66a21e9SMichael Große    }
281*c66a21e9SMichael Große
282bc461538SMichael Große}
283