1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4/**
5* Client Management
6*
7* @author Sascha Hofmann <shofmann@databay.de>
8* @author Alex Killing <alex.killing@gmx.de>
9* @version $Id$
10*
11*/
12class ilClient
13{
14    public $id;					// client_id (md5 hash)
15    public $dir;					// directory name in ilias/clients/
16    public $name;					// installation name
17    public $db_exists = false;		// db exists?
18    public $db_installed = false;	// db installed?
19
20    public $client_defaults;		// default settings
21    public $status;				// contains status infos about setup process (todo: move function to this class)
22    public $setup_ok = false;		// if client setup was finished at least once, this is set to true
23    public $nic_status;			// contains received data of ILIAS-NIC server when registering
24    /**
25     * @var string
26     */
27    public $error = '';
28    /**
29     * @var ilDBInterface
30     */
31    public $db;
32    /**
33     * @var ilIniFile
34     */
35    public $ini;
36
37    /**
38     * @var ilDbSetup|null
39     */
40    protected $db_setup = null;
41
42
43    /**
44     * ilClient constructor.
45     *
46     * @param $a_client_id
47     * @param $a_db_connections
48     */
49    public function __construct($a_client_id, $a_db_connections)
50    {
51        if ($a_client_id) {
52            $this->id = $a_client_id;
53            $this->ini_file_path = ILIAS_ABSOLUTE_PATH . "/" . ILIAS_WEB_DIR . "/" . $this->getId() . "/client.ini.php";
54        }
55
56        $this->db_connections = $a_db_connections;
57
58        // set path default.ini
59        $this->client_defaults = ILIAS_ABSOLUTE_PATH . "/setup/client.master.ini.php";
60    }
61
62
63    /**
64     * @param bool $cached
65     * @return \ilDbSetup
66     */
67    public function getDBSetup($cached = true)
68    {
69        require_once('./setup/classes/class.ilDbSetup.php');
70
71        if ($cached) {
72            if (is_null($this->db_setup)) {
73                $this->db_setup = \ilDbSetup::getNewInstanceForClient($this);
74            }
75            return $this->db_setup;
76        }
77
78
79        return \ilDbSetup::getNewInstanceForClient($this);
80    }
81
82    /**
83    * init client
84    * load client.ini and set some constants
85    * @return	boolean
86    */
87    public function init()
88    {
89        $this->ini = new ilIniFile($this->ini_file_path);
90
91        // load defaults only if no client.ini was found
92        if (!@file_exists($this->ini_file_path)) {
93            //echo "<br>A-".$this->ini_file_path."-";
94            $this->ini->GROUPS = parse_ini_file($this->client_defaults, true);
95
96            return false;
97        }
98
99        // read client.ini
100        if (!$this->ini->read()) {
101            $this->error = get_class($this) . ": " . $this->ini->getError();
102
103            return false;
104        }
105
106        // only for ilias main
107        define("CLIENT_WEB_DIR", ILIAS_ABSOLUTE_PATH . "/" . ILIAS_WEB_DIR . "/" . $this->getId());
108        define("CLIENT_DATA_DIR", ILIAS_DATA_DIR . "/" . $this->getId());
109        define("DEVMODE", $this->ini->readVariable('system', 'DEVMODE'));
110        define("ROOT_FOLDER_ID", $this->ini->readVariable('system', 'ROOT_FOLDER_ID'));
111        define("SYSTEM_FOLDER_ID", $this->ini->readVariable('system', 'SYSTEM_FOLDER_ID'));
112        define("ROLE_FOLDER_ID", $this->ini->readVariable('system', 'ROLE_FOLDER_ID'));
113        define("ANONYMOUS_USER_ID", 13);
114        define("ANONYMOUS_ROLE_ID", 14);
115        define("SYSTEM_USER_ID", 6);
116        define("SYSTEM_ROLE_ID", 2);
117
118        $this->db_exists = $this->getDBSetup()->isConnectable();
119        $this->getDBSetup()->provideGlobalDB();
120        if ($this->db_exists) {
121            $this->db_installed = $this->getDBSetup()->isDatabaseInstalled();
122        }
123
124        return true;
125    }
126
127
128    public function provideGlobalDB()
129    {
130        $this->getDBSetup()->provideGlobalDB();
131    }
132
133
134    public function revokeGlobalDB()
135    {
136        $this->getDBSetup()->provideGlobalDB();
137    }
138
139    /**
140    * get client id
141    * @return	string	client id
142    */
143    public function getId()
144    {
145        return $this->id;
146    }
147
148    /**
149    * set client id
150    * @param	string	client id
151    */
152    public function setId($a_client_id)
153    {
154        $this->id = $a_client_id;
155        $this->webspace_dir = ILIAS_ABSOLUTE_PATH . "/" . ILIAS_WEB_DIR . "/" . $this->id;
156    }
157
158    /**
159    * get client name
160    * @return	string	client name
161    */
162    public function getName()
163    {
164        return $this->ini->readVariable("client", "name");
165    }
166
167    /**
168    * set client name
169    * @param	string	client name
170    */
171    public function setName($a_str)
172    {
173        $this->ini->setVariable("client", "name", $a_str);
174    }
175
176    /**
177    * get client description
178    * @return	string	client description
179    */
180    public function getDescription()
181    {
182        return $this->ini->readVariable("client", "description");
183    }
184
185    /**
186    * set client description
187    * @param	string	client description
188    */
189    public function setDescription($a_str)
190    {
191        $this->ini->setVariable("client", "description", $a_str);
192    }
193
194    /**
195    * get mysql version
196    */
197    /*	function getMySQLVersion()
198        {
199            return mysql_get_server_info();
200        }*/
201
202    /**
203    * Get DB object
204    */
205    public function getDB()
206    {
207        return $this->db;
208    }
209
210    /**
211    * connect to client database
212    * @return	boolean	true on success
213    */
214    public function connect()
215    {
216        // check parameters
217        // To support oracle tnsnames.ora dbname is not required
218        if (!$this->getdbHost() || !$this->getdbUser()) {
219            $this->error = "empty_fields";
220
221            return false;
222        }
223
224        include_once("./Services/Database/classes/class.ilDBWrapperFactory.php");
225        $this->db = ilDBWrapperFactory::getWrapper($this->getdbType());
226        $this->db->setDBUser($this->getdbUser());
227        $this->db->setDBPort($this->getdbPort());
228        $this->db->setDBPassword($this->getdbPass());
229        $this->db->setDBHost($this->getdbHost());
230        $this->db->setDBName($this->getdbName());
231        $con = $this->db->connect(true);
232
233        if (!$con) {
234            $this->error = "Database connection failed.";
235            return false;
236        }
237        $GLOBALS["ilDB"] = $this->db;
238
239        if ($GLOBALS["DIC"]->offsetExists("ilDB")) {
240            $GLOBALS["DIC"]->offsetUnset("ilDB");
241        }
242
243        $GLOBALS["DIC"]["ilDB"] = function ($c) {
244            return $GLOBALS["ilDB"];
245        };
246
247        $this->db_exists = true;
248        return true;
249    }
250
251    /**
252    * check if client db is installed
253    * @param	object	db object
254    * @return	boolean	true if installed
255    */
256    public function isInstalledDB(&$a_db)
257    {
258        if (method_exists($a_db, 'loadModule')) {
259            $a_db->loadModule('Manager');
260        }
261        if (!$tables = $a_db->listTables()) {
262            return false;
263        }
264
265        // check existence of some basic tables from ilias3 to determine if ilias3 is already installed in given database
266        if (in_array("object_data", $tables) and in_array("object_reference", $tables) and in_array("usr_data", $tables) and in_array("rbac_ua", $tables)) {
267            $this->db_installed = true;
268            return true;
269        }
270        $this->db_installed = false;
271        return false;
272    }
273
274    /**
275    * set the dsn and dsn_host
276    */
277    public function setDSN()
278    {
279        switch ($this->getDbType()) {
280            case "postgres":
281                $db_port_str = "";
282                if (trim($this->getdbPort()) != "") {
283                    $db_port_str = ":" . $this->getdbPort();
284                }
285                $this->dsn_host = "pgsql://" . $this->getdbUser() . ":" . $this->getdbPass() . "@" . $this->getdbHost() . $db_port_str;
286                $this->dsn = "pgsql://" . $this->getdbUser() . ":" . $this->getdbPass() . "@" . $this->getdbHost() . $db_port_str . "/" . $this->getdbName();
287                break;
288
289            case "mysql":
290            case "innodb":
291            default:
292                $db_port_str = "";
293                if (trim($this->getdbPort()) != "") {
294                    $db_port_str = ":" . $this->getdbPort();
295                }
296                $this->dsn_host = "mysql://" . $this->getdbUser() . ":" . $this->getdbPass() . "@" . $this->getdbHost() . $db_port_str;
297                $this->dsn = "mysql://" . $this->getdbUser() . ":" . $this->getdbPass() . "@" . $this->getdbHost() . $db_port_str . "/" . $this->getdbName();
298                break;
299        }
300    }
301
302    /**
303    * set the host
304    * @param	string
305    */
306    public function setDbHost($a_str)
307    {
308        $this->ini->setVariable("db", "host", $a_str);
309    }
310
311    /**
312    * get db host
313    * @return	string	db host
314    *
315    */
316    public function getDbHost()
317    {
318        return $this->ini->readVariable("db", "host");
319    }
320
321    /**
322    * set the name of database
323    * @param	string
324    */
325    public function setDbName($a_str)
326    {
327        $this->ini->setVariable("db", "name", $a_str);
328    }
329
330    /**
331    * get name of database
332    * @return	string	name of database
333    */
334    public function getDbName()
335    {
336        return $this->ini->readVariable("db", "name");
337    }
338
339    /**
340    * set db user
341    * @param	string	db user
342    */
343    public function setDbUser($a_str)
344    {
345        $this->ini->setVariable("db", "user", $a_str);
346    }
347
348    /**
349    * get db user
350    * @return	string	db user
351    */
352    public function getDbUser()
353    {
354        return $this->ini->readVariable("db", "user");
355    }
356
357    /**
358    * get db port
359    * @return	string	db port
360    */
361    public function getDbPort()
362    {
363        return $this->ini->readVariable("db", "port");
364    }
365
366    /**
367    * set db port
368    * @param	string
369    */
370    public function setDbPort($a_str)
371    {
372        $this->ini->setVariable("db", "port", $a_str);
373    }
374
375    /**
376    * set db password
377    * @param	string
378    */
379    public function setDbPass($a_str)
380    {
381        $this->ini->setVariable("db", "pass", $a_str);
382    }
383
384    /**
385    * get db password
386    * @return	string	db password
387    */
388    public function getDbPass()
389    {
390        return $this->ini->readVariable("db", "pass");
391    }
392
393    /**
394    * set the slave active
395    * @param int
396    */
397    public function setDbSlaveActive($a_act)
398    {
399        $this->ini->setVariable("db", "slave_active", (int) $a_act);
400    }
401
402    /**
403    * get slave active
404    * @return int active
405    *
406    */
407    public function getDbSlaveActive()
408    {
409        return (int) $this->ini->readVariable("db", "slave_active");
410    }
411
412    /**
413    * set the slave host
414    * @param	string
415    */
416    public function setDbSlaveHost($a_str)
417    {
418        $this->ini->setVariable("db", "slave_host", $a_str);
419    }
420
421    /**
422    * get db slave host
423    * @return	string	db host
424    *
425    */
426    public function getDbSlaveHost()
427    {
428        return $this->ini->readVariable("db", "slave_host");
429    }
430
431    /**
432    * set the name of slave database
433    * @param	string
434    */
435    public function setDbSlaveName($a_str)
436    {
437        $this->ini->setVariable("db", "slave_name", $a_str);
438    }
439
440    /**
441    * get name of slave database
442    * @return	string	name of database
443    */
444    public function getDbSlaveName()
445    {
446        return $this->ini->readVariable("db", "slave_name");
447    }
448
449    /**
450    * set slave db user
451    * @param	string	db user
452    */
453    public function setDbSlaveUser($a_str)
454    {
455        $this->ini->setVariable("db", "slave_user", $a_str);
456    }
457
458    /**
459    * get slave db user
460    * @return	string	db user
461    */
462    public function getDbSlaveUser()
463    {
464        return $this->ini->readVariable("db", "slave_user");
465    }
466
467    /**
468    * get slave db port
469    * @return	string	db port
470    */
471    public function getDbSlavePort()
472    {
473        return $this->ini->readVariable("db", "slave_port");
474    }
475
476    /**
477    * set slave db port
478    * @param	string
479    */
480    public function setDbSlavePort($a_str)
481    {
482        $this->ini->setVariable("db", "slave_port", $a_str);
483    }
484
485    /**
486    * set slave db password
487    * @param	string
488    */
489    public function setDbSlavePass($a_str)
490    {
491        $this->ini->setVariable("db", "slave_pass", $a_str);
492    }
493
494    /**
495    * get slave db password
496    * @return	string	db password
497    */
498    public function getDbSlavePass()
499    {
500        return $this->ini->readVariable("db", "slave_pass");
501    }
502
503    /**
504    * set the type of database
505    * @param	string
506    */
507    public function setDbType($a_str)
508    {
509        $this->ini->setVariable("db", "type", $a_str);
510    }
511
512    /**
513    * get type of database
514    * @return	string	name of database
515    */
516    public function getDbType()
517    {
518        $val = $this->ini->readVariable("db", "type");
519        if ($val == "") {
520            return "mysql";
521        } else {
522            return $val;
523        }
524    }
525
526    /**
527    * get client datadir path
528    * @return	string	client datadir path
529    */
530    public function getDataDir()
531    {
532        return ILIAS_DATA_DIR . "/" . $this->getId();
533    }
534
535    /**
536    * get client webspacedir path
537    * @return 	string	clietn webspacedir path
538    */
539    public function getWebspaceDir()
540    {
541        return ILIAS_ABSOLUTE_PATH . "/" . ILIAS_WEB_DIR . "/" . $this->getId();
542    }
543
544
545    /**
546    * check database connection with database name
547    * @return	boolean
548    */
549    public function checkDatabaseExists($a_keep_connection = false)
550    {
551        return $this->getDBSetup()->isConnectable();
552
553        //try to connect to database
554        $db = $this->db_connections->connectDB($this->dsn);
555        if (MDB2::isError($db)) {
556            return false;
557        }
558
559        if (!$this->isInstalledDB($db)) {
560            return false;
561        }
562
563        // #10633
564        if ($a_keep_connection) {
565            $GLOBALS["ilDB"] = $this->db;
566            $GLOBALS["DIC"]["ilDB"] = function ($c) {
567                return $GLOBALS["ilDB"];
568            };
569        }
570
571        return true;
572    }
573
574    public function reconnect()
575    {
576        $this->connect();
577    }
578
579
580    /**
581     * read one value from settings table
582     *
583     * @access    public
584     * @param    string    keyword
585     * @return    string    value
586     */
587    public function getSetting($a_keyword)
588    {
589        global $ilDB;
590        if (!$this->getDBSetup()->isDatabaseInstalled() || !$ilDB) {
591            return false;
592        }
593        include_once './Services/Administration/classes/class.ilSetting.php';
594        $set = new ilSetting("common", true);
595
596        return $set->get($a_keyword);
597    }
598
599    /**
600    * read all values from settings table
601    * @access	public
602    * @return	array	keyword/value pairs
603    */
604    public function getAllSettings()
605    {
606        include_once './Services/Administration/classes/class.ilSetting.php';
607        $set = new ilSetting("common", true);
608        return $set->getAll();
609    }
610
611    /**
612    * write one value to settings table
613    * @access	public
614    * @param	string		keyword
615    * @param	string		value
616    * @return	boolean		true on success
617    */
618    public function setSetting($a_key, $a_val)
619    {
620        include_once './Services/Administration/classes/class.ilSetting.php';
621        $set = new ilSetting("common", true);
622        $set->set($a_key, $a_val);
623    }
624
625    /**
626    * @param	string	url to ilias nic server
627    * @return	string	url with required parameters
628    */
629    public function getURLStringForNIC($a_nic_url)
630    {
631        $settings = $this->getAllSettings();
632
633        $inst_id = (empty($settings["inst_id"])) ? "0" : $settings["inst_id"];
634
635        // send host information to ilias-nic
636        //#18132: removed ipadr, server_port, server_software, institution, contact_title, contact_position,
637        // contact_institution, contact_street, contact_pcode, contact_city, contact_country, contact_phone
638        $url = $a_nic_url .
639                "?cmd=getid" .
640                "&inst_id=" . rawurlencode($inst_id) .
641                "&hostname=" . rawurlencode($_SERVER["SERVER_NAME"]) .
642                "&inst_name=" . rawurlencode($this->ini->readVariable("client", "name")) .
643                "&inst_info=" . rawurlencode($this->ini->readVariable("client", "description")) .
644                "&http_path=" . rawurlencode(ILIAS_HTTP_PATH) .
645                "&contact_firstname=" . rawurlencode($settings["admin_firstname"]) .
646                "&contact_lastname=" . rawurlencode($settings["admin_lastname"]) .
647                "&contact_email=" . rawurlencode($settings["admin_email"]) .
648                "&nic_key=" . rawurlencode($this->getNICkey());
649
650        return $url;
651    }
652
653    /**
654    * Connect to ILIAS-NIC
655    *
656    * This function establishes a HTTP connection to the ILIAS Network
657    * Information Center (NIC) in order to update the ILIAS-NIC host
658    * database and - in case of a newly installed system - obtain an
659    * installation id at first connection.
660    * This function my be put into a dedicated include file as soon
661    * as there are more functions concerning the interconnection of
662    * ILIAS hosts
663    *
664    * @param	void
665    * @return	string/array	$ret	error message or data array
666    */
667    public function updateNIC($a_nic_url)
668    {
669        $max_redirects = 5;
670        $socket_timeout = 5;
671
672        require_once(__DIR__ . "/../../Services/WebServices/Curl/classes/class.ilCurlConnection.php");
673        if (!ilCurlConnection::_isCurlExtensionLoaded()) {
674            $this->setError("CURL-extension not loaded.");
675            return false;
676        }
677
678        $url = $this->getURLStringForNIC($a_nic_url);
679        $req = new ilCurlConnection($url);
680        $req->init();
681
682        $settings = $this->getAllSettings();
683        if ((bool) $settings['proxy_status'] && strlen($settings['proxy_host']) && strlen($settings['proxy_port'])) {
684            $req->setOpt(CURLOPT_HTTPPROXYTUNNEL, true);
685            $req->setOpt(CURLOPT_PROXY, $settings["proxy_host"]);
686            $req->setOpt(CURLOPT_PROXYPORT, $settings["proxy_port"]);
687        }
688
689        $req->setOpt(CURLOPT_HEADER, 1);
690        $req->setOpt(CURLOPT_RETURNTRANSFER, 1);
691        $req->setOpt(CURLOPT_CONNECTTIMEOUT, $socket_timeout);
692        $req->setOpt(CURLOPT_MAXREDIRS, $max_redirects);
693        $response = $req->exec();
694
695        $req->parseResponse($response);
696        $response_body = $req->getResponseBody();
697
698        $info = $req->getInfo();
699        if ($info["http_code"] != "200") {
700            $this->setError("Could not connect to NIC-Server at '" . $url . "'");
701            return false;
702        }
703
704        $this->nic_status = explode("\n", $response_body);
705
706        ilLoggerFactory::getLogger('setup')->dump($this->nic_status);
707
708        return true;
709    }
710
711    /**
712    * set nic_key
713    * generate nic_key if nic_key field in cust table is empty.
714    * the nic_key is used for authentication update requests sent
715    * to the ILIAS-NIC server.
716    * @access	public
717    * @return	boolean
718    */
719    public function setNICkey()
720    {
721        mt_srand((double) microtime() * 1000000);
722        $nic_key = md5(str_replace(".", "", $_SERVER["SERVER_ADDR"]) +
723                    mt_rand(100000, 999999));
724
725        $this->setSetting("nic_key", $nic_key);
726
727        $this->nic_key = $nic_key;
728
729        return true;
730    }
731
732    /**
733    * get nic_key
734    * @access	public
735    * @return	string	nic_key
736    */
737    public function getNICkey()
738    {
739        $this->nic_key = $this->getSetting("nic_key");
740
741        if (empty($this->nic_key)) {
742            $this->setNICkey();
743        }
744
745        return $this->nic_key;
746    }
747
748    public function getDefaultLanguage()
749    {
750        return $this->getSetting("language");
751    }
752
753    public function setDefaultLanguage($a_lang_key)
754    {
755        $this->setSetting("language", $a_lang_key);
756        $this->ini->setVariable("language", "default", $a_lang_key);
757        $this->ini->write();
758
759        return true;
760    }
761
762
763    /**
764     * get error message and clear error var
765     *
766     * @return    string    error message
767     */
768    public function getError()
769    {
770        $error = $this->error;
771        $this->error = "";
772
773        return $error;
774    }
775
776
777    /**
778     * @param $error_message
779     */
780    public function setError($error_message)
781    {
782        $this->error = $error_message;
783    }
784
785    /**
786    * delete client
787    * @param	boolean	remove ini if true
788    * @param	boolean	remove db if true
789    * @param	boolean remove files if true
790    * @return	array	confirmation messages
791    *
792    */
793    public function delete($a_ini = true, $a_db = false, $a_files = false)
794    {
795        if ($a_ini === true and file_exists(ILIAS_ABSOLUTE_PATH . "/" . ILIAS_WEB_DIR . "/" . $this->getId() . "/client.ini.php")) {
796            unlink(CLIENT_WEB_DIR . "/client.ini.php");
797            $msg[] = "ini_deleted";
798        }
799
800        if ($a_db === true and $this->db_exists) {
801            $this->db->query("DROP DATABASE " . $this->getDbName());
802            $msg[] = "db_deleted";
803        }
804
805        if ($a_files === true and file_exists(CLIENT_WEB_DIR) and is_dir(CLIENT_WEB_DIR)) {
806            // rmdir();
807            ilUtil::delDir(CLIENT_WEB_DIR);
808            ilUtil::delDir(CLIENT_DATA_DIR);
809            $msg[] = "files_deleted";
810        }
811
812        return $msg;
813    }
814
815    /**
816    * create a new client and its subdirectories
817    * @return	boolean	true on success
818    */
819    public function create()
820    {
821        //var_dump($this->getDataDir());exit;
822        // create base data dir
823        if (!ilUtil::makeDir($this->getDataDir())) {
824            $this->error = "could_not_create_base_data_dir :" . $this->getDataDir();
825            return false;
826        }
827
828        // create sub dirs in base data dir
829        if (!ilUtil::makeDir($this->getDataDir() . "/mail")) {
830            $this->error = "could_not_create_mail_data_dir :" . $this->getDataDir() . "/mail";
831            return false;
832        }
833
834        if (!ilUtil::makeDir($this->getDataDir() . "/lm_data")) {
835            $this->error = "could_not_create_lm_data_dir :" . $this->getDataDir() . "/lm_data";
836            return false;
837        }
838
839        if (!ilUtil::makeDir($this->getDataDir() . "/forum")) {
840            $this->error = "could_not_create_forum_data_dir :" . $this->getDataDir() . "/forum";
841            return false;
842        }
843
844        if (!ilUtil::makeDir($this->getDataDir() . "/files")) {
845            $this->error = "could_not_create_files_data_dir :" . $this->getDataDir() . "/files";
846            return false;
847        }
848
849        // create base webspace dir
850        if (!ilUtil::makeDir($this->getWebspaceDir())) {
851            $this->error = "could_not_create_base_webspace_dir :" . $this->getWebspaceDir();
852            return false;
853        }
854
855        // create sub dirs in base webspace dir
856        if (!ilUtil::makeDir($this->getWebspaceDir() . "/lm_data")) {
857            $this->error = "could_not_create_lm_webspace_dir :" . $this->getWebspaceDir() . "/lm_data";
858            return false;
859        }
860
861        if (!ilUtil::makeDir($this->getWebspaceDir() . "/usr_images")) {
862            $this->error = "could_not_create_usr_images_webspace_dir :" . $this->getWebspaceDir() . "/usr_images";
863            return false;
864        }
865
866        if (!ilUtil::makeDir($this->getWebspaceDir() . "/mobs")) {
867            $this->error = "could_not_create_mobs_webspace_dir :" . $this->getWebspaceDir() . "/mobs";
868            return false;
869        }
870
871        if (!ilUtil::makeDir($this->getWebspaceDir() . "/css")) {
872            $this->error = "could_not_create_css_webspace_dir :" . $this->getWebspaceDir() . "/css";
873            return false;
874        }
875
876        // write client ini
877        if (!$this->ini->write()) {
878            $this->error = get_class($this) . ": " . $this->ini->getError();
879            return false;
880        }
881
882        return true;
883    }
884
885    /**
886     * write init
887     *
888     * @param
889     * @return
890     */
891    public function writeIni()
892    {
893        $this->ini->write();
894    }
895} // END class.ilClient
896