ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilCtrl.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2012 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
11 class ilCtrl
12 {
13  const IL_RTOKEN_NAME = 'rtoken';
14 
16  var $forward; // forward array
17  var $parent; // parent array (reverse forward)
18  var $save_parameter; // save parameter array
19  var $return; // return commmands
20  var $call_hist = array(); // calling history
21  var $debug = array();
22  var $calls = array();
23  var $rtoken = false;
24 
28  function ilCtrl()
29  {
30  global $ilBench;
31 
32  $this->bench =& $ilBench;
33 
34  // initialisation
35  $this->init();
36 
37  // this information should go to xml files one day
38  $this->stored_trees = array
39  ("ilrepositorygui", "ilpersonaldesktopgui",
40  "illmpresentationgui", "illmeditorgui",
41  "iladministrationgui");
42  }
43 
49  function debug($str)
50  {
51  $this->debug[] = $str;
52  }
53 
59  function getDebug()
60  {
61  return $this->debug;
62  }
63 
67  function init()
68  {
69  $this->transit = array();
70  $this->forward = array(); // forward array
71  $this->forwards = array(); // forward array
72  $this->parent = array(); // parent array (reverse forward)
73  $this->save_parameter = array(); // save parameter array
74  $this->parameter = array(); // save parameter array
75  $this->return = ""; // return commmands
76  $this->location = array();
77  $this->tab = array();
78  $this->current_node = 0;
79  $this->module_dir = "";
80  $this->service_dir = "";
81  $this->call_node = array();
82  $this->root_class = "";
83  }
84 
91  function callBaseClass()
92  {
93  global $ilDB;
94 
95  $baseClass = strtolower($_GET["baseClass"]);
96 
97  // get class information
98  $mc_set = $ilDB->query("SELECT * FROM module_class WHERE LOWER(class) = ".
99  $ilDB->quote($baseClass, "text"));
100  $mc_rec = $ilDB->fetchAssoc($mc_set);
101  $module = $mc_rec["module"];
102  $class = $mc_rec["class"];
103  $class_dir = $mc_rec["dir"];
104 
105  if ($module != "")
106  {
107  $m_set = $ilDB->query("SELECT * FROM il_component WHERE name = ".
108  $ilDB->quote($module, "text"));
109  $m_rec = $ilDB->fetchAssoc($m_set);
110  $this->module_dir = $m_rec["type"]."/".$m_rec["name"];
111  include_once $this->module_dir."/".$class_dir."/class.".$class.".php";
112  }
113  else // check whether class belongs to a service
114  {
115  $mc_set = $ilDB->query("SELECT * FROM service_class WHERE LOWER(class) = ".
116  $ilDB->quote($baseClass, "text"));
117  $mc_rec = $ilDB->fetchAssoc($mc_set);
118 
119  $service = $mc_rec["service"];
120  $class = $mc_rec["class"];
121  $class_dir = $mc_rec["dir"];
122 
123  if ($service == "")
124  {
125  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
126  throw new ilCtrlException("Could not find entry in modules.xml or services.xml for ".
127  $baseClass." <br/>".str_replace("&", "<br />&", htmlentities($_SERVER["REQUEST_URI"])));
128  }
129 
130  // get service information
131  $m_set = $ilDB->query("SELECT * FROM il_component WHERE name = ".
132  $ilDB->quote($service, "text"));
133  $m_rec = $ilDB->fetchAssoc($m_set);
134  $this->service_dir = $m_rec["type"]."/".$m_rec["name"];
135 
136  include_once $this->service_dir."/".$class_dir."/class.".$class.".php";;
137  }
138 
139  // forward processing to base class
140  $this->getCallStructure(strtolower($baseClass));
141  $base_class_gui =& new $class();
142  $this->forwardCommand($base_class_gui);
143  }
144 
148  function getModuleDir()
149  {
150  return $this->module_dir;
151  }
152 
162  function &forwardCommand(&$a_gui_object)
163  {
164  $class = strtolower(get_class($a_gui_object));
165 //echo "<br>class:".$class.":";
166  $nr = $this->getNodeIdForTargetClass($this->current_node, $class);
167  $nr = $nr["node_id"];
168  if ($nr != "")
169  {
170  $current_node = $this->current_node;
171 
172  $this->current_node = $nr;
173 
174  // always populate the call history
175  // it will only be displayed in DEVMODE but is needed for UI plugins, too
176  $this->call_hist[] = array("class" => get_class($a_gui_object),
177  "mode" => "execComm", "cmd" => $this->getCmd());
178 
179 //echo "<br>class:".get_class($a_gui_object).":";
180  $html = $a_gui_object->executeCommand();
181 
182  // reset current node
183  $this->current_node = $current_node;
184 
185  return $html;
186 
187  }
188 
189  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
190  throw new ilCtrlException("ERROR: Can't forward to class $class.");
191  }
192 
200  function &getHTML(&$a_gui_object)
201  {
202  $class = strtolower(get_class($a_gui_object));
203 
204  $nr = $this->getNodeIdForTargetClass($this->current_node, $class);
205  $nr = $nr["node_id"];
206  if ($nr != "")
207  {
208  $current_node = $this->current_node;
209 
210  // set current node to new gui class
211  $this->current_node = $nr;
212 
213  // always populate the call history
214  // it will only be displayed in DEVMODE but is needed for UI plugins, too
215  $this->call_hist[] = array("class" => get_class($a_gui_object),
216  "mode" => "getHtml", "cmd" => $this->getCmd());
217 
218  // get block
219  $html = $a_gui_object->getHTML();
220 
221  // reset current node
222  $this->current_node = $current_node;
223 
224  // return block
225  return $html;
226  }
227 
228  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
229  throw new ilCtrlException("ERROR: Can't getHTML from class $class.");
230 
231  }
232 
242  function setContext($a_obj_id, $a_obj_type, $a_sub_obj_id = 0, $a_sub_obj_type = "")
243  {
244  $this->context_obj_id = $a_obj_id;
245  $this->context_obj_type = $a_obj_type;
246  $this->context_sub_obj_id = $a_sub_obj_id;
247  $this->context_sub_obj_type = $a_sub_obj_type;
248  }
249 
255  public function getContextObjId()
256  {
257  return $this->context_obj_id;
258  }
259 
265  public function getContextObjType()
266  {
267  return $this->context_obj_type;
268  }
269 
275  public function getContextSubObjId()
276  {
277  return $this->context_sub_obj_id;
278  }
279 
285  public function getContextSubObjType()
286  {
287  return $this->context_sub_obj_type;
288  }
289 
308  private function getNodeIdForTargetClass($a_par_node, $a_class, $a_check = false)
309  {
310  $class = strtolower($a_class);
311  $this->readClassInfo($class);
312 
313  if ($a_par_node === 0 || $a_par_node == "")
314  {
315  return array("node_id" => $this->getCidForClass($class),
316  "base_class" => "");
317  }
318 
319  $this->readNodeInfo($a_par_node);
320 
321  $node_cid = $this->getCurrentCidOfNode($a_par_node);
322 
323  // target class is class of current node id
324  if ($class == $this->getClassForCid($node_cid))
325  {
326  return array("node_id" => $a_par_node,
327  "base_class" => "");
328  }
329 
330  // target class is child of current node id
331  if (isset($this->calls[$this->getClassForCid($node_cid)]) &&
332  is_array($this->calls[$this->getClassForCid($node_cid)]) &&
333  in_array($a_class, $this->calls[$this->getClassForCid($node_cid)]))
334  {
335  return array("node_id" => $a_par_node.":".$this->getCidForClass($class),
336  "base_class" => "");
337  }
338 
339  // target class is sibling
340  $par_cid = $this->getParentCidOfNode($a_par_node);
341  if ($par_cid != "")
342  {
343  if (is_array($this->calls[$this->getClassForCid($par_cid)]) &&
344  in_array($a_class, $this->calls[$this->getClassForCid($par_cid)]))
345  {
346  return array("node_id" =>
347  $this->removeLastCid($a_par_node).":".$this->getCidForClass($class),
348  "base_class" => "");
349  }
350  }
351 
352  // target class is parent
353  $temp_node = $this->removeLastCid($a_par_node);
354  while($temp_node != "")
355  {
356  $temp_cid = $this->getCurrentCidOfNode($temp_node);
357  if ($this->getClassForCid($temp_cid) == $a_class)
358  {
359  return array("node_id" => $temp_node,
360  "base_class" => "");
361  }
362  $temp_node = $this->removeLastCid($temp_node);
363  }
364 
365  // target class is another base class
366  $n_class = "";
367  if ($a_class != "")
368  {
369  global $ilDB;
370 
371  // get class information
372  $mc_set = $ilDB->query("SELECT * FROM module_class WHERE LOWER(class) = ".
373  $ilDB->quote($class, "text"));
374  $mc_rec = $ilDB->fetchAssoc($mc_set);
375  $n_class = strtolower($mc_rec["class"]);
376 
377  if ($n_class == "")
378  {
379  $mc_set = $ilDB->query("SELECT * FROM service_class WHERE LOWER(class) = ".
380  $ilDB->quote($class, "text"));
381  $mc_rec = $ilDB->fetchAssoc($mc_set);
382  $n_class = strtolower($mc_rec["class"]);
383  }
384 
385  if ($n_class != "")
386  {
387  $this->getCallStructure($n_class);
388  return array("node_id" => $this->getCidForClass($n_class),
389  "base_class" => $class);
390  }
391  }
392 
393  if ($a_check)
394  {
395  return false;
396  }
397 
398  // Please do NOT change these lines.
399  // Developers must be aware, if they use classes unknown to the controller
400  // otherwise certain problem will be extremely hard to track down...
401 
402 // echo "ERROR: Can't find target class $a_class for node $a_par_node ".
403 // "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].").<br>";
404  error_log( "ERROR: Can't find target class $a_class for node $a_par_node ".
405  "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].")");
406 
407  if (DEVMODE == 1)
408  {
409 // ilUtil::printBacktrace();
410  }
411 
412  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
413  throw new ilCtrlException("ERROR: Can't find target class $a_class for node $a_par_node ".
414  "(".$this->cid_class[$this->getParentCidOfNode($a_par_node)].").");
415  }
416 
423  function checkTargetClass($a_class)
424  {
425  if (!is_array($a_class))
426  {
427  $a_class = array($a_class);
428  }
429 
430  $nr = $this->current_node;
431  foreach ($a_class as $class)
432  {
433  $class = strtolower($class);
434 
435  if (!$this->getCidForClass($class, true))
436  {
437  return false;
438  }
439 
440  $nr = $this->getNodeIdForTargetClass($nr, $class, true);
441  $nr = $nr["node_id"];
442  if ($nr === false)
443  {
444  return false;
445  }
446  }
447  return true;
448  }
449 
455  function getCmdNode()
456  {
457  return $_GET["cmdNode"];
458  }
459 
467  function addLocation($a_title, $a_link, $a_target = "", $a_ref_id = 0)
468  {
469  $this->location[] = array("title" => $a_title,
470  "link" => $a_link, "target" => $a_target, "ref_id" => $a_ref_id);
471  }
472 
478  function getLocations()
479  {
480  return $this->location;
481  }
482 
491  function addTab($a_lang_var, $a_link, $a_cmd, $a_class)
492  {
493  $a_class = strtolower($a_class);
494 
495  $this->tab[] = array("lang_var" => $a_lang_var,
496  "link" => $a_link, "cmd" => $a_cmd, "class" => $a_class);
497  }
498 
504  function getTabs()
505  {
506  return $this->tab;
507  }
508 
515  function getCallHistory()
516  {
517  return $this->call_hist;
518  }
519 
536  function getCallStructure($a_class)
537  {
538  $this->readClassInfo($a_class);
539  }
540 
545 /* function storeCommonStructures()
546  {
547  global $ilDB;
548 
549  $ilDB->manipulate("DELETE FROM ctrl_structure");
550 
551  foreach ($this->stored_trees as $root_gui_class)
552  {
553  $this->call_node = array();
554  $this->forward = array();
555  $this->parent = array();
556  $this->readCallStructure($root_gui_class);
557  $ilDB->insert("ctrl_structure", array(
558  "root_class" => array("text", $root_gui_class),
559  "call_node" => array("text", serialize($this->call_node)),
560  "forward" => array("text", serialize($this->forward)),
561  "parent" => array("clob", serialize($this->parent))));
562  }
563  }
564 */
565 
569  function readCallStructure($a_class, $a_nr = 0, $a_parent = 0)
570  {
571  global $ilDB;
572 
573  $a_class = strtolower($a_class);
574 
575  $a_nr++;
576 
577  // determine call node structure
578  $this->call_node[$a_nr] = array("class" => $a_class, "parent" => $a_parent);
579 
580 //echo "<br>nr:$a_nr:class:$a_class:parent:$a_parent:";
581  $call_set = $ilDB->query("SELECT * FROM ctrl_calls WHERE parent = ".
582  $ilDB->quote(strtolower($a_class), "text").
583  " ORDER BY child", array("text"));
584  $a_parent = $a_nr;
585  while ($call_rec = $ilDB->fetchAssoc($call_set))
586  {
587  $a_nr = $this->readCallStructure($call_rec["child"], $a_nr, $a_parent);
588  $forw[] = $call_rec["child"];
589  }
590 
591  // determin forward and parent array
592  $this->forwards($a_class, $forw);
593 //echo "<br>forwards:".$a_class."<br>"; var_dump($forw);
594 
595  // determine root class
596  $this->root_class = $a_class;
597  return $a_nr;
598  }
599 
600 
607  private function forwards($a_from_class, $a_to_class)
608  {
609  $a_from_class = strtolower($a_from_class);
610 
611  if (is_array($a_to_class))
612  {
613  foreach($a_to_class as $to_class)
614  {
615  if ($a_from_class != "" && $to_class != "")
616  {
617  if (!is_array($this->forward[$a_from_class]) || !in_array(strtolower($to_class), $this->forward[$a_from_class]))
618  {
619  $this->forward[$a_from_class][] = strtolower($to_class);
620  }
621  if (!is_array($this->parent[strtolower($to_class)]) || !in_array($a_from_class, $this->parent[strtolower($to_class)]))
622  {
623  $this->parent[strtolower($to_class)][] = $a_from_class;
624  }
625  }
626  }
627  }
628  else
629  {
630  $to_class = $a_to_class;
631  if ($a_from_class != "" && $to_class != "")
632  {
633  if (!is_array($this->forward[$a_from_class]) || !in_array(strtolower($to_class), $this->forward[$a_from_class]))
634  {
635  $this->forward[$a_from_class][] = strtolower($to_class);
636  }
637  if (!is_array($this->parent[strtolower($to_class)]) || !in_array($a_from_class, $this->parent[strtolower($to_class)]))
638  {
639  $this->parent[strtolower($to_class)][] = $a_from_class;
640  }
641  }
642  }
643  }
644 
645 
665  public function saveParameter(&$a_obj, $a_parameter)
666  {
667  if (is_object($a_obj))
668  {
669  $this->saveParameterByClass(get_class($a_obj), $a_parameter);
670  }
671  }
672 
679  function saveParameterByClass($a_class, $a_parameter)
680  {
681  if (is_array($a_parameter))
682  {
683  foreach($a_parameter as $parameter)
684  {
685  $this->save_parameter[strtolower($a_class)][] = $parameter;
686  }
687  }
688  else
689  {
690  $this->save_parameter[strtolower($a_class)][] = $a_parameter;
691  }
692  }
693 
694 
717  public function setParameter(&$a_obj, $a_parameter, $a_value)
718  {
719  $this->parameter[strtolower(get_class($a_obj))][$a_parameter] = $a_value;
720  }
721 
722 
730  public function setParameterByClass($a_class, $a_parameter, $a_value)
731  {
732  $this->parameter[strtolower($a_class)][$a_parameter] = $a_value;
733  }
734 
735 
742  public function clearParameters(&$a_obj)
743  {
744  $this->clearParametersByClass(strtolower(get_class($a_obj)));
745  }
746 
753  public function clearParametersByClass($a_class)
754  {
755  $this->parameter[strtolower($a_class)] = array();
756  }
757 
766  function getNextClass()
767  {
768  $cmdNode = $this->getCmdNode();
769 //echo "<br>getNextClass (current node: ".$this->current_node."; cmd node: ".$cmdNode.") ";
770  if ($cmdNode == "")
771  {
772  return false;
773  }
774  else
775  {
776  if ($this->current_node == $cmdNode)
777  {
778 //echo "1:".$this->call_node[$cmdNode]["class"]."<br>";
779  //return $this->call_node[$cmdNode]["class"];
780  return "";
781  }
782  else
783  {
784  $path = $this->getPathNew($this->current_node, $cmdNode);
785 //var_dump($path);
786 //echo " - Next Node: ".$path[1];
787  $this->readCidInfo($this->getCurrentCidOfNode($path[1]));
788 //echo ":".$this->cid_class[$this->getCurrentCidOfNode($path[1])].":".$this->getCurrentCidOfNode($path[1]).":";
789  return $this->cid_class[$this->getCurrentCidOfNode($path[1])];
790  }
791  }
792  }
793 
800  function lookupClassPath($a_class_name)
801  {
802  global $ilDB;
803  $a_class_name = strtolower($a_class_name);
804 
805  $class_set = $ilDB->query("SELECT * FROM ctrl_classfile WHERE class = ".
806  $ilDB->quote($a_class_name, "text"));
807  $class_rec = $ilDB->fetchAssoc($class_set);
808 
809  if ($class_rec["plugin_path"] != "")
810  {
811  return $class_rec["plugin_path"]."/".$class_rec["filename"];
812  }
813  else
814  {
815  return $class_rec["filename"];
816  }
817  }
818 
827  function getClassForClasspath($a_class_path)
828  {
829  $path = pathinfo($a_class_path);
830  $file = $path["basename"];
831  $class = substr($file, 6, strlen($file) - 10);
832 
833  return $class;
834  }
835 
842  private function getPathNew($a_source_node, $a_target_node)
843  {
844 //if ($this->getCmdClass() == "ilmailfoldergui") echo "-".$a_source_node."-".$a_target_node."-";
845 //echo "-".$a_source_node."-".$a_target_node."-";
846 //echo "<br>:::$a_source_node:::";
847  if ($a_source_node == "1")
848  {
849  $a_source_node = "";
850  }
851  if (substr($a_target_node, 0, strlen($a_source_node)) != $a_source_node)
852  {
853  $failure = "ERROR: Path not found. Source:".$a_source_node.
854  ", Target:".$a_target_node;
855  if (DEVMODE == 1)
856  {
857  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
858  throw new ilCtrlException($failure);
859  }
860  $GLOBALS['ilLog']->write(__METHOD__.' '.$failure);
861  ilUtil::redirect('./ilias.php?baseClass=ilRepositoryGUI');
862  }
863 //echo "<br>:::$a_source_node:::";
864  $temp_node = $a_source_node;
865 
866  $path = array();
867  if ($a_source_node != "")
868  {
869  $path = array($a_source_node);
870  }
871 
872  $diffstart = ($a_source_node == "")
873  ? 0
874  : strlen($a_source_node) + 1;
875  $diff = substr($a_target_node, $diffstart);
876 //echo "=$diff=$diffstart=";
877  $diff_arr = explode(":", $diff);
878  foreach($diff_arr as $cid)
879  {
880  if ($temp_node != "")
881  {
882  $temp_node.= ":";
883  }
884  $temp_node.= $cid;
885  $path[] = $temp_node;
886  }
887 //if ($this->getCmdClass() == "ilmailfoldergui") var_dump($path);
888 //var_dump($path);
889  return $path;
890  }
891 
897  public function setTargetScript($a_target_script)
898  {
899  $this->target_script = $a_target_script;
900  }
901 
902 
908  public function getTargetScript()
909  {
910  return $this->target_script;
911  }
912 
913 
922  public function initBaseClass($a_base_class)
923  {
924  $_GET["baseClass"] = $a_base_class;
925  $_GET["cmd"] = "";
926  $_GET["cmdClass"] = "";
927  $_GET["cmdNode"] = "";
928  $this->init();
929  }
930 
938  public function getCmd($a_default_cmd = "", $a_safe_commands = "")
939  {
940  $cmd = "";
941  if (isset($_GET["cmd"]))
942  {
943  $cmd = $_GET["cmd"];
944  }
945  if($cmd == "post")
946  {
947  if (isset($_POST["cmd"]) && is_array($_POST["cmd"]))
948  {
949  reset($_POST["cmd"]);
950  }
951  $cmd = @key($_POST["cmd"]);
952 
953  // verify command
954  if ($this->verified_cmd != "")
955  {
956  return $this->verified_cmd;
957  }
958  else
959  {
960  if (!$this->verifyToken() &&
961  (!is_array($a_safe_commands) || !in_array($cmd, $a_safe_commands)))
962  {
963  return $a_default_cmd;
964  }
965  }
966 
967  $this->verified_cmd = $cmd;
968  if($cmd == "" && isset($_POST["table_top_cmd"])) // selected command in multi-list (table2)
969  {
970  $cmd = @key($_POST["table_top_cmd"]);
971  $this->verified_cmd = $cmd;
972  $_POST[$_POST["cmd_sv"][$cmd]] = $_POST[$_POST["cmd_sv"][$cmd]."_2"];
973  }
974  if($cmd == "" && isset($_POST["select_cmd2"])) // selected command in multi-list (table2)
975  {
976  if(isset($_POST["select_cmd_all2"]))
977  {
978  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"];
979  }
980  else
981  {
982  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"] = null;
983  }
984  $cmd = $_POST["selected_cmd2"];
985  $this->verified_cmd = $cmd;
986  }
987  if($cmd == "" && isset($_POST["select_cmd"])) // selected command in multi-list (table2)
988  {
989  if(isset($_POST["select_cmd_all"]))
990  {
991  $_POST["select_cmd_all2"] = $_POST["select_cmd_all"];
992  }
993  else
994  {
995  $_POST["select_cmd_all"] = $_POST["select_cmd_all2"] = null;
996  }
997  $cmd = $_POST["selected_cmd"];
998  $this->verified_cmd = $cmd;
999  }
1000  if($cmd == "")
1001  {
1002  $cmd = $_GET["fallbackCmd"];
1003  $this->verified_cmd = $cmd;
1004  }
1005  }
1006  if($cmd == "")
1007  {
1008  $cmd = $a_default_cmd;
1009  }
1010  return $cmd;
1011  }
1012 
1023  function setCmd($a_cmd)
1024  {
1025  $_GET["cmd"] = $a_cmd;
1026  }
1027 
1038  public function setCmdClass($a_cmd_class)
1039  {
1040  $a_cmd_class = strtolower($a_cmd_class);
1041  $nr = $this->getNodeIdForTargetClass($this->current_node, $a_cmd_class);
1042  $nr = $nr["node_id"];
1043  $_GET["cmdClass"] = $a_cmd_class;
1044  $_GET["cmdNode"] = $nr;
1045  }
1046 
1052  function getCmdClass()
1053  {
1054  return strtolower($_GET["cmdClass"]);
1055  }
1056 
1067  function getFormAction(&$a_gui_obj, $a_fallback_cmd = "", $a_anchor = "", $a_asynch = false,
1068  $xml_style = true)
1069  {
1070  $script = $this->getFormActionByClass(strtolower(get_class($a_gui_obj)),
1071  $a_fallback_cmd, $a_anchor, $a_asynch, $xml_style);
1072  return $script;
1073  }
1074 
1085  function getFormActionByClass($a_class, $a_fallback_cmd = "", $a_anchor = "", $a_asynch = false,
1086  $xml_style = true)
1087  {
1088  if(!is_array($a_class))
1089  {
1090  $a_class = strtolower($a_class);
1091  }
1092 
1093  $tok = $this->getRequestToken();
1094 
1095  if ($a_asynch)
1096  {
1097  $xml_style = false;
1098  }
1099 
1100  $script = $this->getLinkTargetByClass($a_class, "post", "", $a_asynch);
1101  if ($a_fallback_cmd != "")
1102  {
1103  $script = ilUtil::appendUrlParameterString($script, "fallbackCmd=".$a_fallback_cmd, $xml_style);
1104  }
1105  $script = ilUtil::appendUrlParameterString($script, self::IL_RTOKEN_NAME.'='.$this->getRequestToken(),
1106  $xml_style);
1107  if ($a_anchor != "")
1108  {
1109  $script = $script."#".$a_anchor;
1110  }
1111 
1112  return $script;
1113  }
1114 
1121  public function appendRequestTokenParameterString($a_url, $xml_style = true)
1122  {
1123  return ilUtil::appendUrlParameterString($a_url, self::IL_RTOKEN_NAME.'='.$this->getRequestToken(),
1124  $xml_style);
1125  }
1126 
1132  public function getRequestToken()
1133  {
1134  global $ilDB, $ilUser;
1135 
1136  if ($this->rtoken != "")
1137  {
1138  return $this->rtoken;
1139  }
1140  else
1141  {
1142  if (is_object($ilDB) && is_object($ilUser) && $ilUser->getId() > 0 &&
1143  $ilUser->getId() != ANONYMOUS_USER_ID)
1144  {
1145  $res = $ilDB->query("SELECT token FROM il_request_token WHERE user_id = ".
1146  $ilDB->quote($ilUser->getId(), "integer").
1147  " AND session_id = ".$ilDB->quote(session_id(), "text"));
1148  $rec = $ilDB->fetchAssoc($res);
1149 //echo session_id();
1150  if ($rec["token"] != "")
1151  {
1152  $this->rtoken = $rec["token"];
1153  return $rec["token"];
1154  }
1155 //echo "new rtoken, new entry for :".$ilUser->getId().":".session_id().":"; exit;
1156  $this->rtoken = md5(uniqid(rand(), true));
1157 
1158  // delete entries older than one and a half days
1159  if (rand(1, 200) == 2)
1160  {
1161  $dt = new ilDateTime(time(),IL_CAL_UNIX);
1162  $dt->increment(IL_CAL_DAY, -1);
1163  $dt->increment(IL_CAL_HOUR, -12);
1164  $dq = "DELETE FROM il_request_token WHERE ".
1165  " stamp < ".$ilDB->quote($dt->get(IL_CAL_DATETIME), "timestamp");
1166  $ilDB->manipulate($dq);
1167  }
1168 
1169  // IMPORTANT: Please do NOT try to move this implementation to a
1170  // session basis. This will fail due to framesets that are used
1171  // occasionally in ILIAS, e.g. in the chat, where multiple
1172  // forms are loaded in different frames.
1173  $ilDB->manipulate("INSERT INTO il_request_token (user_id, token, stamp, session_id) VALUES ".
1174  "(".
1175  $ilDB->quote($ilUser->getId(), "integer").",".
1176  $ilDB->quote($this->rtoken, "text").",".
1177  $ilDB->now().",".
1178  $ilDB->quote(session_id(), "text").")");
1179  return $this->rtoken;
1180  }
1181  //$this->rtoken = md5(uniqid(rand(), true));
1182  }
1183  return "";
1184  }
1185 
1191  private function verifyToken()
1192  {
1193  global $ilDB, $ilUser;
1194 
1195  if (is_object($ilUser) && is_object($ilDB) && $ilUser->getId() > 0 &&
1196  $ilUser->getId() != ANONYMOUS_USER_ID)
1197  {
1198  if ($_GET["rtoken"] == "")
1199  {
1200  #echo "ilCtrl::No Request Token Given!"; // for debugging, maybe changed later
1201  return false;
1202  }
1203 
1204  $set = $ilDB->query("SELECT * FROM il_request_token WHERE ".
1205  " user_id = ".$ilDB->quote($ilUser->getId(), "integer")." AND ".
1206  " token = ".$ilDB->quote($_GET[self::IL_RTOKEN_NAME]), "text");
1207  if ($ilDB->numRows($set) > 0)
1208  {
1209  // remove used token
1210  /*
1211  $ilDB->query("DELETE FROM il_request_token WHERE ".
1212  " user_id = ".$ilDB->quote($ilUser->getId())." AND ".
1213  " token = ".$ilDB->quote($_GET[self::IL_RTOKEN_NAME]));
1214  */
1215 
1216  // remove tokens from older sessions
1217  // if we do this immediately, working with multiple windows does not work:
1218  // - window one: open form (with token a)
1219  // - window two: open form (with token b)
1220  // - submit window one: a is verified, but b must not be deleted immediately, otherwise
1221  // - window two: submit results in invalid token
1222  // see also bug #13551
1223  $dt = new ilDateTime(time(),IL_CAL_UNIX);
1224  $dt->increment(IL_CAL_DAY, -1);
1225  $dt->increment(IL_CAL_HOUR, -12);
1226  $ilDB->manipulate("DELETE FROM il_request_token WHERE ".
1227  " user_id = ".$ilDB->quote($ilUser->getId(), "integer")." AND ".
1228  " session_id != ".$ilDB->quote(session_id(), "text")." AND ".
1229  " stamp < ".$ilDB->quote($dt->get(IL_CAL_DATETIME), "timestamp"));
1230  return true;
1231  }
1232  else
1233  {
1234  return false;
1235  }
1236 
1237  if ($_SESSION["rtokens"][$_GET[self::IL_RTOKEN_NAME]] != "")
1238  {
1239  // remove used token
1240  unset($_SESSION["rtokens"][$_GET[self::IL_RTOKEN_NAME]]);
1241 
1242  // remove old tokens
1243  if (count($_SESSION["rtokens"]) > 100)
1244  {
1245  $to_remove = array();
1246  $sec = 7200; // two hours
1247 
1248  foreach($_SESSION["rtokens"] as $tok => $time)
1249  {
1250  if (time() - $time > $sec)
1251  {
1252  $to_remove[] = $tok;
1253  }
1254  }
1255  foreach($to_remove as $tok)
1256  {
1257  unset($_SESSION["rtokens"][$tok]);
1258  }
1259  }
1260 
1261  return true;
1262  }
1263  return false;
1264  }
1265  else
1266  {
1267  return true; // do not verify, if user or db object is missing
1268  }
1269 
1270  return false;
1271  }
1272 
1280  public function redirect(&$a_gui_obj, $a_cmd = "", $a_anchor = "", $a_asynch = false)
1281  {
1282  global $ilBench;
1283 
1284  $script = $this->getLinkTargetByClass(strtolower(get_class($a_gui_obj)), $a_cmd,
1285  "", $a_asynch, false);
1286  if (is_object($ilBench))
1287  {
1288  $ilBench->save();
1289  }
1290  if ($a_anchor != "")
1291  {
1292  $script = $script."#".$a_anchor;
1293  }
1294  ilUtil::redirect($script);
1295  }
1296 
1297 
1304  public function redirectByClass($a_class, $a_cmd = "", $a_anchor = "", $a_asynch = false)
1305  {
1306  $script = $this->getLinkTargetByClass($a_class, $a_cmd, "", $a_asynch, false);
1307  if ($a_anchor != "")
1308  {
1309  $script = $script."#".$a_anchor;
1310  }
1311  ilUtil::redirect($script);
1312  }
1313 
1319  public function isAsynch()
1320  {
1321  if (isset($_GET["cmdMode"]) && $_GET["cmdMode"] == "asynch")
1322  {
1323  return true;
1324  }
1325  else
1326  {
1327  return false;
1328  }
1329  }
1330 
1331 
1343  function getLinkTarget(&$a_gui_obj, $a_cmd = "", $a_anchor = "", $a_asynch = false,
1344  $xml_style = true)
1345  {
1346  $script = $this->getLinkTargetByClass(strtolower(get_class($a_gui_obj)), $a_cmd, $a_anchor, $a_asynch,
1347  $xml_style);
1348  return $script;
1349  }
1350 
1351 
1363  function getLinkTargetByClass($a_class, $a_cmd = "", $a_anchor = "", $a_asynch = false,
1364  $xml_style = true)
1365  {
1366  if ($a_asynch)
1367  {
1368  $xml_style = false;
1369  }
1370 
1371  // note: $a_class may be an array
1372  //$a_class = strtolower($a_class);
1373 
1374 //echo "<br>getLinkTargetByClass";
1375  $script = $this->getTargetScript();
1376  $script = $this->getUrlParameters($a_class, $script, $a_cmd, $xml_style);
1377 
1378  if ($a_asynch)
1379  {
1380  //$amp = $xml_style
1381  // ? "&amp;"
1382  // : "&";
1383  $amp = "&";
1384  $script.= $amp."cmdMode=asynch";
1385  }
1386 
1387  if ($a_anchor != "")
1388  {
1389  $script = $script."#".$a_anchor;
1390  }
1391 
1392  return $script;
1393  }
1394 
1398  function setReturn(&$a_gui_obj, $a_cmd)
1399  {
1400  $script = $this->getTargetScript();
1401  $script = $this->getUrlParameters(strtolower(get_class($a_gui_obj)), $script, $a_cmd);
1402 //echo "<br>setReturn:".get_class($a_gui_obj).":".$script.":<br>";
1403  $this->return[strtolower(get_class($a_gui_obj))] = $script;
1404  }
1405 
1409  function setReturnByClass($a_class, $a_cmd)
1410  {
1411  // may not be an array!
1412  $a_class = strtolower($a_class);
1413 
1414  $script = $this->getTargetScript();
1415  $script = $this->getUrlParameters($a_class, $script, $a_cmd);
1416 //echo "<br>setReturn:".get_class($a_gui_obj).":".$script.":<br>";
1417  $this->return[strtolower($a_class)] = $script;
1418  }
1419 
1423  function returnToParent(&$a_gui_obj, $a_anchor = "")
1424  {
1425  $script = $this->getParentReturn($a_gui_obj);
1426 
1427  $script = ilUtil::appendUrlParameterString($script,
1428  "redirectSource=".strtolower(get_class($a_gui_obj)));
1429  $script = ilUtil::appendUrlParameterString($script,
1430  "cmdMode=".$_GET["cmdMode"]);
1431  if ($a_anchor != "")
1432  {
1433  $script = $script."#".$a_anchor;
1434  }
1435 
1436  ilUtil::redirect($script);
1437  }
1438 
1439 
1446  {
1447  return $_GET["redirectSource"];
1448  }
1449 
1453  function getParentReturn(&$a_gui_obj)
1454  {
1455  return $this->getParentReturnByClass(strtolower(get_class($a_gui_obj)));
1456  }
1457 
1458 
1462  function getParentReturnByClass($a_class)
1463  {
1464  $a_class = strtolower($a_class);
1465  $ret_class = $this->searchReturnClass($a_class);
1466 //echo ":$ret_class:";
1467  if($ret_class)
1468  {
1469 //echo ":".$this->return[$ret_class].":";
1470  return $this->return[$ret_class];
1471  }
1472  }
1473 
1480  function getReturnClass($a_class)
1481  {
1482  if (is_object($a_class))
1483  {
1484  $class = strtolower(get_class($a_class));
1485  }
1486  else
1487  {
1488  $class = strtolower($a_class);
1489  }
1490  return $this->searchReturnClass($class);
1491  }
1492 
1493 
1497  private function searchReturnClass($a_class)
1498  {
1499  $a_class = strtolower($a_class);
1500 
1501  $node = $this->getNodeIdForTargetClass($this->current_node, $a_class);
1502  $node = $node["node_id"];
1503  $n_arr = explode(":", $node);
1504  for($i = count($n_arr)-2; $i>=0; $i--)
1505  {
1506  if ($this->return[$this->getClassForCid($n_arr[$i])] != "")
1507  {
1508  return $this->getClassForCid($n_arr[$i]);
1509  }
1510  }
1511 
1512  return false;
1513  }
1514 
1518  public function getUrlParameters($a_class, $a_str, $a_cmd = "", $xml_style = false)
1519  {
1520  // note: $a_class may be an array!
1521  //$a_class = strtolower($a_class);
1522 
1523  $params = $this->getParameterArrayByClass($a_class, $a_cmd);
1524 
1525  foreach ($params as $par => $value)
1526  {
1527  if (strlen((string) $value))
1528  {
1529  $a_str = ilUtil::appendUrlParameterString($a_str, $par."=".$value, $xml_style);
1530  }
1531  }
1532 
1533  return $a_str;
1534  }
1535 
1539  public function getParameterArray(&$a_gui_obj, $a_cmd = "")
1540  {
1541  $par_arr = $this->getParameterArrayByClass(strtolower(get_class($a_gui_obj)), $a_cmd);
1542 
1543  return $par_arr;
1544  }
1545 
1553  public function getParameterArrayByClass($a_class, $a_cmd = "")
1554  {
1555  if ($a_class == "")
1556  {
1557  return array();
1558  }
1559 
1560  if (!is_array($a_class))
1561  {
1562  $a_class = array($a_class);
1563  }
1564 
1565  $nr = $this->current_node;
1566  foreach ($a_class as $class)
1567  {
1568  $class = strtolower($class);
1569  $nr = $this->getNodeIdForTargetClass($nr, $class);
1570  if ($nr["base_class"] != "")
1571  {
1572  $new_baseclass = $nr["base_class"];
1573  }
1574  $nr = $nr["node_id"];
1575  $target_class = $class;
1576  }
1577 
1578  $path = $this->getPathNew(1, $nr);
1579  $params = array();
1580 
1581  // append parameters of parent classes
1582  foreach($path as $node_id)
1583  {
1584  $class = ($node_id == "")
1585  ? strtolower($_GET["baseClass"])
1586  : $this->getClassForCid($this->getCurrentCidOfNode($node_id));
1587  if (isset($this->save_parameter[$class]) && is_array($this->save_parameter[$class]))
1588  {
1589  foreach($this->save_parameter[$class] as $par)
1590  {
1591  if (isset($_GET[$par]))
1592  {
1593  $params[$par] = $_GET[$par];
1594  }
1595  else if (isset($_POST[$par]))
1596  {
1597  $params[$par] = $_POST[$par];
1598  }
1599  }
1600  }
1601 
1602  if (isset($this->parameter[$class]) && is_array($this->parameter[$class]))
1603  {
1604  foreach($this->parameter[$class] as $par => $value)
1605  {
1606  $params[$par] = $value;
1607  }
1608  }
1609  }
1610 
1611  if ($a_cmd != "")
1612  {
1613  $params["cmd"] = $a_cmd;
1614  }
1615 
1616  $params["cmdClass"] = $target_class;
1617  $params["cmdNode"] = $nr;
1618  if($new_baseclass == "")
1619  {
1620  $params["baseClass"] = $_GET["baseClass"];
1621  }
1622  else
1623  {
1624  $params["baseClass"] = $new_baseclass;
1625  }
1626 
1627  return $params;
1628  }
1629 
1633  private function getCidForClass($a_class, $a_check = false)
1634  {
1635  if ($this->class_cid[$a_class] == "")
1636  {
1637  $this->readClassInfo($a_class);
1638  }
1639  if ($this->class_cid[$a_class] == "")
1640  {
1641  if ($a_check)
1642  {
1643  return false;
1644  }
1645  if (DEVMODE == 1)
1646  {
1647  $add = "<br><br>Please make sure your GUI class name ends with 'GUI' and that the filename is 'class.[YourClassName].php'. In exceptional cases you
1648  may solve the issue by putting an empty * @ilCtrl_Calls [YourClassName]: into your class header.".
1649  " In both cases you need to reload the control structure in the setup.";
1650  }
1651  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
1652  throw new ilCtrlException("Cannot find cid for class ".$a_class.".".$add);
1653  }
1654  return $this->class_cid[$a_class];
1655  }
1656 
1660  private function getClassForCid($a_cid)
1661  {
1662  if ($this->cid_class[$a_cid] == "")
1663  {
1664  $this->readCidInfo($a_cid);
1665  }
1666  if ($this->cid_class[$a_cid] == "")
1667  {
1668  include_once("./Services/UICore/exceptions/class.ilCtrlException.php");
1669  throw new ilCtrlException("Cannot find class for cid ".$a_cid.".");
1670  }
1671  return $this->cid_class[$a_cid];
1672  }
1673 
1679  private function readCidInfo($a_cid)
1680  {
1681  global $ilDB;
1682 
1683  if (isset($this->info_read_cid[$a_cid]))
1684  {
1685  return;
1686  }
1687  $set = $ilDB->query("SELECT * FROM ctrl_classfile ".
1688  " WHERE cid = ".$ilDB->quote($a_cid, "text")
1689  );
1690  if ($rec = $ilDB->fetchAssoc($set))
1691  {
1692  $this->cid_class[$a_cid] = $rec["class"];
1693  $this->class_cid[$rec["class"]] = $a_cid;
1694 
1695  $set = $ilDB->query("SELECT * FROM ctrl_calls ".
1696  " WHERE parent = ".$ilDB->quote($rec["class"], "text")
1697  );
1698  while ($rec2 = $ilDB->fetchAssoc($set))
1699  {
1700  if (!isset($this->calls[$rec["class"]]) || !is_array($this->calls[$rec["class"]]) || !in_array($rec2["child"], $this->calls[$rec["class"]]))
1701  {
1702  if ($rec2["child"] != "")
1703  {
1704  $this->calls[$rec["class"]][] = $rec2["child"];
1705  }
1706  }
1707  }
1708  $this->info_read_class[$rec["class"]] = true;
1709  }
1710 
1711  $this->info_read_cid[$a_cid] = true;
1712  }
1713 
1719  private function readNodeInfo($a_node)
1720  {
1721  $n_arr = explode(":", $a_node);
1722  foreach ($n_arr as $cid)
1723  {
1724  $this->readCidInfo($cid);
1725  }
1726  }
1727 
1733  private function readClassInfo($a_class)
1734  {
1735  global $ilDB;
1736 
1737  $a_class = strtolower($a_class);
1738  if (isset($this->info_read_class[$a_class]))
1739  {
1740  return;
1741  }
1742  $set = $ilDB->query("SELECT * FROM ctrl_classfile ".
1743  " WHERE class = ".$ilDB->quote($a_class, "text")
1744  );
1745  if ($rec = $ilDB->fetchAssoc($set))
1746  {
1747  $this->cid_class[$rec["cid"]] = $a_class;
1748  $this->class_cid[$a_class] = $rec["cid"];
1749  }
1750 
1751  $set = $ilDB->query("SELECT * FROM ctrl_calls ".
1752  " WHERE parent = ".$ilDB->quote($a_class, "text")
1753  );
1754  while ($rec = $ilDB->fetchAssoc($set))
1755  {
1756  if (!isset($this->calls[$a_class]) || !is_array($this->calls[$a_class]) || !in_array($rec["child"], $this->calls[$a_class]))
1757  {
1758  if ($rec["child"] != "")
1759  {
1760  $this->calls[$a_class][] = $rec["child"];
1761  }
1762  }
1763  }
1764 
1765  $this->info_read_class[$a_class] = true;
1766  $this->info_read_cid[$this->class_cid[$a_class]] = true;
1767  }
1768 
1772  private function getParentCidOfNode($a_node)
1773  {
1774  $n_arr = explode(":", $a_node);
1775  return $n_arr[count($n_arr) - 2];
1776  }
1777 
1781  private function removeLastCid($a_node)
1782  {
1783  $lpos = strrpos($a_node, ":");
1784  return substr($a_node, 0, $lpos);
1785  }
1786 
1790  private function getCurrentCidOfNode($a_node)
1791  {
1792  $n_arr = explode(":", $a_node);
1793  return $n_arr[count($n_arr) - 1];
1794  }
1795 
1802  function insertCtrlCalls($a_parent, $a_child, $a_comp_prefix)
1803  {
1804  global $ilDB;
1805 
1806  $a_parent = strtolower($a_parent);
1807  $a_child = strtolower($a_child);
1808  $a_comp_prefix = strtolower($a_comp_prefix);
1809 
1810  $set = $ilDB->query("SELECT * FROM ctrl_calls WHERE ".
1811  " parent = ".$ilDB->quote($a_parent, "text")." AND ".
1812  " child = ".$ilDB->quote($a_child, "text")." AND ".
1813  " comp_prefix = ".$ilDB->quote($a_comp_prefix, "text")
1814  );
1815  if ($rec = $ilDB->fetchAssoc($set))
1816  {
1817  return;
1818  }
1819  $ilDB->manipulate("INSERT INTO ctrl_calls ".
1820  "(parent, child, comp_prefix) VALUES (".
1821  $ilDB->quote($a_parent, "text").",".
1822  $ilDB->quote($a_child, "text").",".
1823  $ilDB->quote($a_comp_prefix, "text").
1824  ")");
1825  }
1826 
1827 }
1828 ?>