ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilSoapUtils.php
Go to the documentation of this file.
1 <?php
2  /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22  */
23 
24 
33 include_once './webservice/soap/classes/class.ilSoapAdministration.php';
34 
36 {
37  function ilSoapUtils()
38  {
40  }
41 
42  function ignoreUserAbort()
43  {
44  return ignore_user_abort(true);
45  }
46 
47  function disableSOAPCheck()
48  {
49  $this->soap_check = false;
50  }
51 
52  function sendMail($sid,$to,$cc,$bcc,$sender,$subject,$message,$attach)
53  {
54  $this->initAuth($sid);
55  $this->initIlias();
56 
57  if(!$this->__checkSession($sid))
58  {
59  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
60  }
61 
62 
63  global $ilLog;
64 
65  include_once 'Services/Mail/classes/class.ilMimeMail.php';
66 
67  $mmail = new ilMimeMail();
68  $mmail->autoCheck(false);
69  $mmail->From($sender);
70  $mmail->To(explode(',',$to));
71  $mmail->Subject($subject);
72  $mmail->Body($message);
73 
74  if($cc)
75  {
76  $mmail->Cc(explode(',',$cc));
77  }
78 
79  if($bcc)
80  {
81  $mmail->Bcc(explode(',',$bcc));
82  }
83  if($attach)
84  {
85  // mjansen: switched separator from "," to "#:#" because of mantis bug #6039
86  // for backward compatibility we have to check if the substring "#:#" exists as leading separator
87  // otherwise we should use ";"
88  if(strpos($attach, '#:#') === 0)
89  {
90  $attach = substr($attach, strlen('#:#'));
91  $attachments = explode('#:#', $attach);
92  }
93  else
94  {
95  $attachments = explode(',', $attach);
96  }
97 
98  foreach($attachments as $attachment)
99  {
100  $final_filename = null;
101  $filename = basename($attachment);
102  if(strlen($filename) > 0)
103  {
104  // #17740
105  $final_filename = preg_replace('/^(\d+?_)(.*)/', '$2', $filename);
106  }
107  $mmail->Attach($attachment, '', 'inline', $final_filename);
108  }
109  }
110 
111  $mmail->Send();
112  $ilLog->write('SOAP: sendMail(): '.$to.', '.$cc.', '.$bcc);
113 
114  return true;
115  }
116 
123  public function distributeMails($sid, $a_mail_xml)
124  {
125  $this->initAuth($sid);
126  $this->initIlias();
127 
128  if(!$this->__checkSession($sid))
129  {
130  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
131  }
132 
133  include_once 'Services/Mail/classes/class.ilMail.php';
134  include_once 'webservice/soap/classes/class.ilSoapMailXmlParser.php';
135 
136  $parser = new ilSoapMailXmlParser($a_mail_xml);
137  try
138  {
139  // Check if wellformed
140  libxml_use_internal_errors(true);
141  $ok = simplexml_load_string($a_mail_xml);
142  if(!$ok)
143  {
144  foreach(libxml_get_errors() as $err)
145  {
146  $error .= ($err->message.' ');
147  }
148  return $this->__raiseError($error, 'CLIENT');
149  }
150  $parser->start();
151  }
152  catch(InvalidArgumentException $e)
153  {
154  $GLOBALS['ilLog']->write(__METHOD__.' '.$e->getMessage());
155  return $this->__raiseError($e->getMessage(),'CLIENT');
156  }
157  catch(ilSaxParserException $e)
158  {
159  $GLOBALS['ilLog']->write(__METHOD__.' '.$e->getMessage());
160  return $this->__raiseError($e->getMessage(), 'CLIENT');
161  }
162 
163  $mails = $parser->getMails();
164 
165  global $ilUser;
166 
167  foreach($mails as $mail)
168  {
169  // Prepare attachments
170  include_once './Services/Mail/classes/class.ilFileDataMail.php';
171  $file = new ilFileDataMail($ilUser->getId());
172  foreach((array) $mail['attachments'] as $attachment)
173  {
174  // TODO: Error handling
175  $file->storeAsAttachment($attachment['name'], $attachment['content']);
176  $attachments[] = ilUtil::_sanitizeFilemame($attachment['name']);
177  }
178 
179  $mail_obj = new ilMail($ilUser->getId());
180  $mail_obj->setSaveInSentbox(true);
181  $mail_obj->saveAttachments((array) $attachments);
182  $mail_obj->sendMail(
183  implode(',',(array) $mail['to']),
184  implode(',',(array) $mail['cc']),
185  implode(',',(array) $mail['bcc']),
186  $mail['subject'],
187  implode("\n",$mail['body']),
188  (array) $attachments,
189  array($mail['type']),
190  (bool) $mail['usePlaceholders']
191  );
192 
193  // Finally unlink attachments
194  foreach((array) $attachments as $att)
195  {
196  $file->unlinkFile($att);
197  }
198  $mail_obj->savePostData(
199  $ilUser->getId(),
200  array(),
201  '',
202  '',
203  '',
204  '',
205  '',
206  '',
207  '',
208  ''
209  );
210  }
211  return true;
212  }
213 
214  function saveTempFileAsMediaObject($sid, $name, $tmp_name)
215  {
216  $this->initAuth($sid);
217  $this->initIlias();
218 
219  if(!$this->__checkSession($sid))
220  {
221  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
222  }
223 
224  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
225  return ilObjMediaObject::_saveTempFileAsMediaObject($name, $tmp_name);
226  }
227 
228  function getMobsOfObject($sid, $a_type, $a_id)
229  {
230  $this->initAuth($sid);
231  $this->initIlias();
232 
233  if(!$this->__checkSession($sid))
234  {
235  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
236  }
237 
238  include_once "./Services/MediaObjects/classes/class.ilObjMediaObject.php";
239  return ilObjMediaObject::_getMobsOfObject($a_type, $a_id);
240  }
241 
249  public function ilCloneDependencies($sid,$copy_identifier)
250  {
251  $this->initAuth($sid);
252  $this->initIlias();
253 
254  if(!$this->__checkSession($sid))
255  {
256  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
257  }
258 
259  global $ilLog,$ilUser;
260 
261  include_once('Services/CopyWizard/classes/class.ilCopyWizardOptions.php');
262  $cp_options = ilCopyWizardOptions::_getInstance($copy_identifier);
263 
264  // Check owner of copy procedure
265  if(!$cp_options->checkOwner($ilUser->getId()))
266  {
267  $ilLog->write(__METHOD__.': Permission check failed for user id: '.$ilUser->getId().', copy id: '.$copy_identifier);
268  return false;
269  }
270 
271  // Fetch first node
272  if(($node = $cp_options->fetchFirstDependenciesNode()) === false)
273  {
274  $cp_options->deleteAll();
275  $ilLog->write(__METHOD__.': Finished copy step 2. Copy completed');
276 
277  return true;
278  }
279 
280  // Check options of this node
281  $options = $cp_options->getOptions($node['child']);
282  $new_ref_id = 0;
283  switch($options['type'])
284  {
286  $ilLog->write(__METHOD__.': Omitting node: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
287  $this->callNextDependency($sid,$cp_options);
288  break;
289 
291  $ilLog->write(__METHOD__.': Nothing to do for node: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
292  $this->callNextDependency($sid,$cp_options);
293  break;
294 
296  $ilLog->write(__METHOD__.': Start cloning dependencies: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
297  $this->cloneDependencies($node,$cp_options);
298  $this->callNextDependency($sid,$cp_options);
299  break;
300 
301  default:
302  $ilLog->write(__METHOD__.': No valid action type given for node: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
303  $this->callNextDependency($sid,$cp_options);
304  break;
305  }
306  return true;
307  }
308 
317  public function ilClone($sid,$copy_identifier)
318  {
319  $this->initAuth($sid);
320  $this->initIlias();
321 
322  if(!$this->__checkSession($sid))
323  {
324  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
325  }
326 
327  global $ilLog,$ilUser;
328 
329  include_once('Services/CopyWizard/classes/class.ilCopyWizardOptions.php');
330  $cp_options = ilCopyWizardOptions::_getInstance($copy_identifier);
331 
332  // Check owner of copy procedure
333  if(!$cp_options->checkOwner($ilUser->getId()))
334  {
335  $ilLog->write(__METHOD__.': Permission check failed for user id: '.$ilUser->getId().', copy id: '.$copy_identifier);
336  return false;
337  }
338 
339 
340  // Fetch first node
341  if(($node = $cp_options->fetchFirstNode()) === false)
342  {
343  $ilLog->write(__METHOD__.': Finished copy step 1. Starting copying of object dependencies...');
344  return $this->ilCloneDependencies($sid,$copy_identifier);
345  }
346 
347  // Check options of this node
348  $options = $cp_options->getOptions($node['child']);
349 
350  $new_ref_id = 0;
351  switch($options['type'])
352  {
354  $ilLog->write(__METHOD__.': Omitting node: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
355  // set mapping to zero
356  $cp_options->appendMapping($node['child'],0);
357  $this->callNextNode($sid,$cp_options);
358  break;
359 
361  $ilLog->write(__METHOD__.': Start cloning node: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
362  $new_ref_id = $this->cloneNode($node,$cp_options);
363  $this->callNextNode($sid,$cp_options);
364  break;
365 
367  $ilLog->write(__METHOD__.': Start linking node: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
368  $new_ref_id = $this->linkNode($node,$cp_options);
369  $this->callNextNode($sid,$cp_options);
370  break;
371 
372  default:
373  $ilLog->write(__METHOD__.': No valid action type given for node: '.$node['obj_id'].', '.$node['title'].', '.$node['type']);
374  $this->callNextNode($sid,$cp_options);
375  break;
376 
377  }
378  return $new_ref_id;
379  }
380 
387  private function callNextNode($sid,$cp_options)
388  {
389  global $ilLog;
390 
391  $cp_options->dropFirstNode();
392 
393  if($cp_options->isSOAPEnabled())
394  {
395  // Start next soap call
396  include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php';
397  $soap_client = new ilSoapClient();
398  $soap_client->setResponseTimeout(1);
399  $soap_client->enableWSDL(true);
400  $soap_client->init();
401  $soap_client->call('ilClone',array($sid,$cp_options->getCopyId()));
402  }
403  else
404  {
405  $ilLog->write(__METHOD__.': Cannot call SOAP server');
406  $cp_options->read();
407  include_once('./webservice/soap/include/inc.soap_functions.php');
408  $res = ilSoapFunctions::ilClone($sid,$cp_options->getCopyId());
409  }
410  return true;
411  }
412 
413  private function callNextDependency($sid,$cp_options)
414  {
415  global $ilLog;
416 
417  $cp_options->dropFirstDependenciesNode();
418 
419  if($cp_options->isSOAPEnabled())
420  {
421  // Start next soap call
422  include_once 'Services/WebServices/SOAP/classes/class.ilSoapClient.php';
423  $soap_client = new ilSoapClient();
424  $soap_client->setResponseTimeout(1);
425  $soap_client->enableWSDL(true);
426  $soap_client->init();
427  $soap_client->call('ilCloneDependencies',array($sid,$cp_options->getCopyId()));
428  }
429  else
430  {
431  $ilLog->write(__METHOD__.': Cannot call SOAP server');
432  $cp_options->read();
433  include_once('./webservice/soap/include/inc.soap_functions.php');
434  $res = ilSoapFunctions::ilCloneDependencies($sid,$cp_options->getCopyId());
435  }
436  return true;
437  }
438 
446  private function cloneNode($node,$cp_options)
447  {
448  global $ilLog,$tree,$ilAccess,$rbacreview;
449 
450  #sleep(20);
451 
452  $source_id = $node['child'];
453  $parent_id = $node['parent'];
454  $options = $cp_options->getOptions($node['child']);
455  $mappings = $cp_options->getMappings();
456 
457  if(!$ilAccess->checkAccess('copy','',$node['child']))
458  {
459  $ilLog->write(__METHOD__.': No copy permission granted: '.$source_id.', '.$node['title'].', '.$node['type']);
460  return false;
461 
462  }
463  if(!isset($mappings[$parent_id]))
464  {
465  $ilLog->write(__METHOD__.': Omitting node '.$source_id.', '.$node['title'].', '.$node['type']. '. No target found.');
466  return true;
467  }
468  $target_id = $mappings[$parent_id];
469 
470  if(!$tree->isInTree($target_id))
471  {
472  $ilLog->write(__METHOD__.': Omitting node '.$source_id.', '.$node['title'].', '.$node['type']. '. Object has been deleted.');
473  return false;
474  }
475 
476  $orig = ilObjectFactory::getInstanceByRefId((int) $source_id);
477  $new_obj = $orig->cloneObject((int) $target_id,$cp_options->getCopyId());
478 
479  if(!is_object($new_obj))
480  {
481  $ilLog->write(__METHOD__.': Error copying '.$source_id.', '.$node['title'].', '.$node['type'].'. No target found.');
482  return false;
483  }
484 
485  // rbac log
486  include_once "Services/AccessControl/classes/class.ilRbacLog.php";
487  $rbac_log_roles = $rbacreview->getParentRoleIds($new_obj->getRefId(), false);
488  $rbac_log = ilRbacLog::gatherFaPa($new_obj->getRefId(), array_keys($rbac_log_roles), true);
489  ilRbacLog::add(ilRbacLog::COPY_OBJECT, $new_obj->getRefId(), $rbac_log, (int)$source_id);
490 
491  // Finally add new mapping entry
492  $cp_options->appendMapping($source_id,$new_obj->getRefId());
493  return $new_obj->getRefId();
494  }
495 
503  private function cloneDependencies($node,$cp_options)
504  {
505  global $ilLog;
506 
507  $source_id = $node['child'];
508  $mappings = $cp_options->getMappings();
509 
510  if(!isset($mappings[$source_id]))
511  {
512  $ilLog->write(__METHOD__.': Omitting node '.$source_id.', '.$node['title'].', '.$node['type']. '. No mapping found.');
513  return true;
514  }
515  $target_id = $mappings[$source_id];
516 
517  $orig = ilObjectFactory::getInstanceByRefId((int) $source_id);
518  $orig->cloneDependencies($target_id,$cp_options->getCopyId());
519  return true;
520  }
521 
529  private function linkNode($node,$cp_options)
530  {
531  global $ilLog,$ilAccess,$rbacreview;
532 
533  $source_id = $node['child'];
534  $parent_id = $node['parent'];
535  $options = $cp_options->getOptions($node['child']);
536  $mappings = $cp_options->getMappings();
537 
538  if(!$ilAccess->checkAccess('delete','',$node['child']))
539  {
540  $ilLog->write(__METHOD__.': No delete permission granted: '.$source_id.', '.$node['title'].', '.$node['type']);
541  return false;
542 
543  }
544  if(!isset($mappings[$parent_id]))
545  {
546  $ilLog->write(__METHOD__.': Omitting node '.$source_id.', '.$node['title'].', '.$node['type']. '. No target found.');
547  return true;
548  }
549  $target_id = $mappings[$parent_id];
550 
551  $orig = ilObjectFactory::getInstanceByRefId((int) $source_id);
552  $new_ref_id = $orig->createReference();
553  $orig->putInTree($target_id);
554  $orig->setPermissions($target_id);
555 
556  if(!($new_ref_id))
557  {
558  $ilLog->write(__METHOD__.': Error linking '.$source_id.', '.$node['title'].', '.$node['type'].'. No target found.');
559  return false;
560  }
561 
562  // rbac log
563  include_once "Services/AccessControl/classes/class.ilRbacLog.php";
564  $rbac_log_roles = $rbacreview->getParentRoleIds($new_ref_id, false);
565  $rbac_log = ilRbacLog::gatherFaPa($new_ref_id, array_keys($rbac_log_roles), true);
566  ilRbacLog::add(ilRbacLog::LINK_OBJECT, $new_ref_id, $rbac_log, (int)$source_id);
567 
568  // Finally add new mapping entry
569  $cp_options->appendMapping($source_id,$new_ref_id);
570  return $new_ref_id;
571  }
572 
579  static function validateXML ($xml) {
580  // validate to prevent wrong XMLs
581  $dom = @domxml_open_mem($xml, DOMXML_LOAD_VALIDATING, $error);
582  if ($error)
583  {
584  $msg = array();
585  if (is_array($error))
586  {
587  foreach ($error as $err) {
588  $msg []= "(".$err["line"].",".$err["col"]."): ".$err["errormessage"];
589  }
590  }
591  else
592  {
593  $msg[] = $error;
594  }
595  $msg = join("\n",$msg);
596  return $msg;
597  }
598  return true;
599  }
600 
601  public function handleECSTasks($sid,$a_server_id)
602  {
603  $this->initAuth($sid);
604  $this->initIlias();
605 
606  if(!$this->__checkSession($sid))
607  {
608  return $this->__raiseError($this->__getMessage(),$this->__getMessageCode());
609  }
610 
611  include_once('./Services/WebServices/ECS/classes/class.ilECSTaskScheduler.php');
612 
613  global $ilLog;
614 
615  $ilLog->write(__METHOD__.': Starting task execution...');
616  $scheduler = ilECSTaskScheduler::_getInstanceByServerId($a_server_id);
617  $scheduler->startTaskExecution();
618 
619  return true;
620  }
621 
634  public function deleteExpiredDualOptInUserObjects($sid, $usr_id)
635  {
636  $this->initAuth($sid);
637  $this->initIlias();
638 
639  // Session check not possible -> anonymous user is the trigger
640 
641  global $ilDB, $ilLog;
642 
643  $ilLog->write(__METHOD__.': Started deletion of inactive user objects with expired confirmation hash values (dual opt in) ...');
644 
645  require_once 'Services/Registration/classes/class.ilRegistrationSettings.php';
646  $oRegSettigs = new ilRegistrationSettings();
647 
648  $query = '';
649 
650  /*
651  * Fetch the current actuator user object first, because this user will try to perform very probably
652  * a new registration with the same login name in a few seconds ;-)
653  *
654  */
655  if((int)$usr_id > 0)
656  {
657  $query .= 'SELECT usr_id, create_date, reg_hash FROM usr_data '
658  . 'WHERE active = 0 '
659  . 'AND reg_hash IS NOT NULL '
660  . 'AND usr_id = '.$ilDB->quote($usr_id, 'integer').' ';
661  $query .= 'UNION ';
662  }
663 
664  $query .= 'SELECT usr_id, create_date, reg_hash FROM usr_data '
665  . 'WHERE active = 0 '
666  . 'AND reg_hash IS NOT NULL '
667  . 'AND usr_id != '.$ilDB->quote($usr_id, 'integer').' ';
668 
669  $res = $ilDB->query($query);
670 
671  $ilLog->write(__METHOD__.': '.$ilDB->numRows($res).' inactive user objects with confirmation hash values (dual opt in) found ...');
672 
673  /*
674  * mjansen: 15.12.2010:
675  * I perform the expiration check in php because of multi database support (mysql, postgresql).
676  * I did not find an oracle equivalent for mysql: UNIX_TIMESTAMP()
677  */
678 
679  $num_deleted_users = 0;
680  while($row = $ilDB->fetchAssoc($res))
681  {
682  if($row['usr_id'] == ANONYMOUS_USER_ID || $row['usr_id'] == SYSTEM_USER_ID) continue;
683  if(!strlen($row['reg_hash'])) continue;
684 
685  if((int)$oRegSettigs->getRegistrationHashLifetime() > 0 &&
686  $row['create_date'] != '' &&
687  time() - $oRegSettigs->getRegistrationHashLifetime() > strtotime($row['create_date']))
688  {
689  $user = ilObjectFactory::getInstanceByObjId($row['usr_id'], false);
690  if($user instanceof ilObjUser)
691  {
692  $ilLog->write(__METHOD__.': User '.$user->getLogin().' (obj_id: '.$user->getId().') will be deleted due to an expired registration hash ...');
693  $user->delete();
694  ++$num_deleted_users;
695  }
696  }
697  }
698 
699  $ilLog->write(__METHOD__.': '.$num_deleted_users.' inactive user objects with expired confirmation hash values (dual opt in) deleted ...');
700 
701  $ilLog->write(__METHOD__.': Finished deletion of inactive user objects with expired confirmation hash values (dual opt in) ...');
702 
703  return true;
704  }
705 }
706 ?>