ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilLinkChecker.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3
13{
14 var $db = null;
15 var $log_messages = array();
16 var $invalid_links = array();
17
18 var $validate_all = true;
19 var $mail_status = false;
20 var $page_id = 0;
21
22
23 function ilLinkChecker(&$db,$a_validate_all = true)
24 {
25 global $ilDB;
26
27 define('DEBUG',1);
28 define('SOCKET_TIMEOUT',5);
29
30 $this->db =& $db;
31
32 // SET GLOBAL DB HANDLER FOR STATIC METHODS OTHER CLASSES
33 $ilDB =& $db;
34
35 $this->validate_all = $a_validate_all;
36 }
37
38 function setCheckPeriod($a_period)
39 {
40 $this->period = $a_period;
41 }
42 function getCheckPeriod()
43 {
44 return $this->period;
45 }
46
47 function setMailStatus($a_status)
48 {
49 $this->mail_status = (bool) $a_status;
50 }
51 function getMailStatus()
52 {
53 return (bool) $this->mail_status;
54 }
55
56 function __setType($a_type)
57 {
58 $this->type = $a_type;
59 }
60 function __getType()
61 {
62 return $this->type;
63 }
64
65 function setObjId($a_page_id)
66 {
67 return $this->page_id = $a_page_id;
68 }
69 function getObjId()
70 {
71 return $this->page_id;
72 }
73
74 function getValidateAll()
75 {
76 return $this->validate_all ? true : false;
77 }
78
79 function getLogMessages()
80 {
81 return $this->log_messages ? $this->log_messages : array();
82 }
83
84 function getInvalidLinks()
85 {
86 return $this->invalid_links ? $this->invalid_links : array();
87 }
88
90 {
91 global $ilDB;
92
93 $query = "SELECT * FROM link_check ".
94 "WHERE obj_id = ".$ilDB->quote($this->getObjId(),'integer')." ";
95
96 $res = $this->db->query($query);
97 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
98 {
99 $invalid[] = array('page_id' => $row->page_id,
100 'url' => $row->url);
101 }
102
103 return $invalid ? $invalid : array();
104 }
105
107 {
108 global $ilDB;
109
110 if($this->getValidateAll())
111 {
112 $query = "SELECT MAX(last_check) last_check FROM link_check ";
113 }
114 else
115 {
116 $query = "SELECT MAX(last_check) last_check FROM link_check ".
117 "WHERE obj_id = ".$ilDB->quote($this->getObjId(),'integer')." ";
118 }
119 $res = $ilDB->query($query);
120 $row = $ilDB->fetchObject($res);
121
122 return $row->last_check ? $row->last_check : 0;
123 }
124
126 {
127 $pages = array();
128
129 $this->__setType('webr');
130 $this->__clearLogMessages();
131 $this->__clearInvalidLinks();
132 $this->__appendLogMessage('LinkChecker: Start checkLinks()');
133
134 if(count($invalid = $this->__validateLinks($this->__getWebResourceLinks())))
135 {
136 foreach($invalid as $invalid_item)
137 {
138 $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
139 $this->__appendInvalidLink($invalid_item);
140 }
141 }
142
143 $this->__appendLogMessage('LinkChecker: End checkLinks()');
144 $this->__saveInDB();
145
146 $this->__sendMail();
147
148 return $this->getInvalidLinks();
149 }
150
151 function checkLinks()
152 {
153 global $ilDB;
154
155 $pages = array();
156
157 $this->__setType('lm');
158 $this->__clearLogMessages();
159 $this->__clearInvalidLinks();
160 $this->__appendLogMessage('LinkChecker: Start checkLinks()');
161
162 if(!$this->getValidateAll() and !$this->getObjId())
163 {
164 echo "ilLinkChecker::checkLinks() No Page id given";
165
166 return false;
167 }
168 elseif(!$this->getValidateAll() and $this->getObjId())
169 {
170 $query = "SELECT * FROM page_object ".
171 "WHERE parent_id = ".$ilDB->quote($this->getObjId())." ".
172 "AND parent_type = 'lm'";
173
174 $res = $this->db->query($query);
175 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
176 {
177 $pages[] = array('page_id' => $row->page_id,
178 'content' => $row->content,
179 'type' => $row->parent_type);
180 }
181 }
182 elseif($this->getValidateAll())
183 {
184 $query = "SELECT * FROM page_object ".
185 "WHERE parent_type = 'lm'";
186
187 $res = $this->db->query($query);
188 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
189 {
190 $pages[] = array('page_id' => $row->page_id,
191 'content' => $row->content,
192 'type' => $row->parent_type);
193 }
194 }
195
196 // VALIDATE
197 foreach($pages as $page)
198 {
199 if(count($invalid = $this->__validateLinks($this->__getLinks($page))))
200 {
201 foreach($invalid as $invalid_item)
202 {
203 $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
204 $this->__appendInvalidLink($invalid_item);
205 }
206 }
207 }
208
209 $this->__appendLogMessage('LinkChecker: End checkLinks()');
210 $this->__saveInDB();
211
212 $this->__sendMail();
213
214 return $this->getInvalidLinks();
215 }
216
217 function checkPear()
218 {
219 if(!@include_once('HTTP/Request.php'))
220 {
221 return false;
222 }
223 return true;
224 }
225
226
227 // PRIVATE
228 function __txt($language,$key,$module = 'common')
229 {
230 global $ilDB;
231
232 include_once './Services/Language/classes/class.ilLanguage.php';
233 return ilLanguage::_lookupEntry($language, $module, $key);
234 }
235
236 function __fetchUserData($a_usr_id)
237 {
238 global $ilDB;
239
240 $query = "SELECT email FROM usr_data WHERE usr_id = ".$ilDB->quote($a_usr_id)."";
241
242 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
243
244 $data['email'] = $row->email;
245
246 $set = $ilDB->query("SELECT * FROM usr_pref ".
247 "WHERE usr_id = ".$ilDB->quote($a_usr_id, "integer")." ".
248 "AND keyword = ".$ilDB->quote('language', "text"));
249
250 $row = $ilDB->fetchObject($set);
251
252 $data['lang'] = $row->value;
253
254 return $data;
255 }
256
257 function __getTitle($a_lm_obj_id)
258 {
259 global $ilDB;
260
261 $query = "SELECT title FROM object_data ".
262 "WHERE obj_id = ".$ilDB->quote($a_lm_obj_id ,'integer')." ";
263
264 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
265
266 return $row->title;
267 }
268
269 function __sendMail()
270 {
271 global $ilUser;
272
273
274 if(!count($notify = $this->__getNotifyLinks()))
275 {
276 // Nothing to do
277 return true;
278 }
279 if(!$this->getMailStatus())
280 {
281 return true;
282 }
283
284 include_once './Services/LinkChecker/classes/class.ilLinkCheckNotify.php';
285 $body = "";
286 $obj_name = "";
287
288 foreach(ilLinkCheckNotify::_getAllNotifiers($this->db) as $usr_id => $obj_ids)
289 {
290 if(!is_object($tmp_user =& ilObjectFactory::getInstanceByObjId($usr_id,false)))
291 {
292 $this->__appendLogMessage('LinkChecker: Cannot find user with id: '.$usr_id);
293 continue;
294 }
295
296 $counter = 0;
297 foreach($obj_ids as $obj_id)
298 {
299 if(!isset($notify[$obj_id]))
300 {
301 continue;
302 }
303 ++$counter;
304
305 switch($this->__getType())
306 {
307 case 'webr':
308 $obj_name = $this->__txt($tmp_user->getLanguage(),'obj_webr');
309 break;
310 case 'lm':
311 default:
312 $obj_name = $this->__txt($tmp_user->getLanguage(),'lo');
313 break;
314 }
315 $body .= $obj_name.': '.$this->__getTitle($obj_id)."\r\n";
316 $body .= $this->__txt($tmp_user->getLanguage(),'link_check_perma_link', "mail"). ": " .
317 $this->createPermanentLink($obj_id, $usr_id, $this->__getType())." \r\n";
318 $body .= $this->__txt($tmp_user->getLanguage(),"link_check_affected_links", "mail"). ":\r\n";
319
320 // Print all invalid
321 foreach($notify[$obj_id] as $data)
322 {
323 $body .= $data['url']."\r\n";
324 }
325 $body .= "\r\n";
326 }
327 if($counter)
328 {
329 include_once "./Services/Notification/classes/class.ilSystemNotification.php";
330 $ntf = new ilSystemNotification();
331 $ntf->setLangModules(array("mail", "common"));
332 $ntf->setSubjectLangId("link_check_subject");
333 $ntf->setIntroductionLangId("link_check_introduction");
334 $ntf->setReasonLangId("link_check_reason");
335 $ntf->addAdditionalInfo("additional_info", $body,true);
336 $ntf->sendMail(array($tmp_user->getId()));
337
338 $this->__appendLogMessage('LinkChecker: Sent mail to '.$tmp_user->getEmail());
339 }
340 $body = "";
341 }
342 }
343
351 protected function createPermanentLink($a_obj_id, $a_usr_id, $a_obj_type)
352 {
353 global $ilAccess;
354 $ref_ids = ilObject::_getAllReferences($a_obj_id);
355 $ref_id = null;
356
357 foreach((array) $ref_ids as $id)
358 {
359 if($ilAccess->checkAccessOfUser($a_usr_id, "read", "", $id, $a_obj_type, $a_obj_id))
360 {
361 $ref_id = $id;
362 }
363 }
364
365 if($ref_id === null)
366 {
367 return false;
368 }
369
370 include_once './Services/Link/classes/class.ilLink.php';
371 return ilLink::_getLink($ref_id, $a_obj_type);
372 }
373
375 {
376 return $this->notify ? $this->notify : array();
377 }
378
379
381 {
382 $this->invalid_links = array();
383 }
384 function __appendInvalidLink($a_link)
385 {
386 $this->invalid_links[] = $a_link;
387 }
388
389
390 function __appendLogMessage($a_string)
391 {
392 $this->log_messages[] = $a_string;
393 }
395 {
396 return $this->log_messages = array();
397 }
398
399 function __getLinks($a_page)
400 {
401 $matches = array();
402
403 $pattern_complete = '/<ExtLink Href="([^"]*)">/';
404 if(preg_match_all($pattern_complete,$a_page['content'],$matches))
405 {
406 for($i = 0;$i < count($matches[0]); ++$i)
407 {
408 $url_data = @parse_url($matches[1][$i]);
409 // continue if mailto link
410 if($url_data['scheme'] == 'mailto')
411 {
412 continue;
413 }
414
415 // PUH, HTTP_REQUEST needs a beginning http://
416 if(!$url_data['scheme'])
417 {
418 $matches[1][$i] = 'http://'.$matches[1][$i];
419 }
420
421 $lm_id = $this->__getObjIdByPageId($a_page['page_id']);
422 $link[] = array('page_id' => $a_page['page_id'],
423 'obj_id' => $lm_id,
424 'type' => $a_page['type'],
425 'complete' => $matches[1][$i],
426 'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
427 'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
428 }
429 }
430
431 return $link ? $link : array();
432 }
433
435 {
436 global $objDefinition;
437
438 include_once 'Modules/WebResource/classes/class.ilLinkResourceItems.php';
439
440 $link_res_obj = new ilLinkResourceItems($this->getObjId());
441
442 foreach($check_links = $link_res_obj->getCheckItems($this->getCheckPeriod()) as $item_data)
443 {
444 // #10091 - internal
445 if(strpos($item_data['target'], '|'))
446 {
447 $parts = explode('|', $item_data['target']);
448 if(sizeof($parts) == 2 &&
449 is_numeric($parts[1]) &&
450 $objDefinition->isAllowedInRepository($parts[0]))
451 {
452 $link[] = array('page_id' => $item_data['link_id'],
453 'obj_id' => $this->getObjId(),
454 'type' => 'webr',
455 'complete' => $item_data['target'],
456 'scheme' => 'internal',
457 'obj_type' => $parts[0],
458 'ref_id' => $parts[1]);
459 continue;
460 }
461 }
462
463 // external
464 $url_data = @parse_url($item_data['target']);
465
466 // PUH, HTTP_REQUEST needs a beginning http://
467 if(!$url_data['scheme'])
468 {
469 $item_data['target'] = 'http://'.$item_data['target'];
470 }
471
472 $link[] = array('page_id' => $item_data['link_id'],
473 'obj_id' => $this->getObjId(),
474 'type' => 'webr',
475 'complete' => $item_data['target'],
476 'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
477 'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
478 }
479 return $link ? $link : array();
480 }
481
482
483
484 function __validateLinks($a_links)
485 {
486 global $tree;
487
488 if(!@include_once('HTTP/Request.php'))
489 {
490 $this->__appendLogMessage('LinkChecker: Pear HTTP_Request is not installed. Aborting');
491
492 return array();
493 }
494
495 foreach($a_links as $link)
496 {
497 // #10091 - internal
498 if($link['scheme'] == 'internal')
499 {
500 $obj_id = ilObject::_lookupObjId($link['ref_id']);
501 if(!$obj_id ||
502 ilObject::_lookupType($obj_id) != $link['obj_type'] ||
503 $tree->isDeleted($link['ref_id']))
504 {
505 $invalid[] = $link;
506 }
507 }
508 // external
509 else
510 {
511 if(gethostbyname($link['host']) == $link['host'])
512 {
513 $invalid[] = $link;
514 continue;
515 }
516
517 if($link['scheme'] !== 'http' and $link['scheme'] !== 'https')
518 {
519 continue;
520 }
521
522 require_once './Services/Http/classes/class.ilProxySettings.php';
523
524 if(ilProxySettings::_getInstance()->isActive())
525 {
526 $options = array('proxy_host' => ilProxySettings::_getInstance()->getHost(),
527 'proxy_port' => ilProxySettings::_getInstance()->getPort());
528 }
529 else
530 {
531 $options = array();
532 }
533
534 $req = new HTTP_Request($link['complete'], $options);
535 $req->sendRequest();
536
537 switch($req->getResponseCode())
538 {
539 // EVERYTHING OK
540 case '200':
541 // In the moment 301 will be handled as ok
542 case '301':
543 case '302':
544 break;
545
546 default:
547 $link['http_status_code'] = $req->getResponseCode();
548 $invalid[] = $link;
549 break;
550 }
551 }
552 }
553 return $invalid ? $invalid : array();
554 }
555
556 function __getObjIdByPageId($a_page_id)
557 {
558 $query = "SELECT lm_id FROM lm_data ".
559 "WHERE obj_id = '".$a_page_id."'";
560
561 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
562
563 return $row->lm_id ? $row->lm_id : 0;
564 }
565
566 function __isInvalid($a_page_id, $a_url)
567 {
568 foreach($this->getInvalidLinks() as $link)
569 {
570 if($link['page_id'] == $a_page_id and
571 substr($link['complete'],0,255) == $a_url)
572 {
573 return true;
574 }
575 }
576 return false;
577 }
578
579 function __saveInDB()
580 {
581 global $ilDB;
582
583 if($this->getMailStatus())
584 {
585 $this->__checkNotify();
586 }
587 $this->__clearDBData();
588
589
590 foreach($this->getInvalidLinks() as $link)
591 {
592 $query = "INSERT INTO link_check (obj_id,page_id,url,parent_type,http_status_code,last_check) ".
593 "VALUES ( ".
594 $ilDB->quote($link['obj_id'],'integer').", ".
595 $ilDB->quote($link['page_id'],'integer').", ".
596 $ilDB->quote(substr($link['complete'],0,255),'text').", ".
597 $ilDB->quote($link['type'],'text').", ".
598 $ilDB->quote($link['http_status_code'] ? $link['http_status_code'] : 0,'integer').", ".
599 $ilDB->quote(time(),'integer')." ".
600 ")";
601 $res = $ilDB->manipulate($query);
602 }
603 }
604
605 function __checkNotify()
606 {
607 global $ilDB;
608
609 foreach($this->getInvalidLinks() as $link)
610 {
611 $query = "SELECT * FROM link_check ".
612 "WHERE page_id = ".$ilDB->quote($link['page_id'],'integer')." ".
613 "AND url = ".$ilDB->quote(substr($link['complete'],0,255),'text')." ";
614 $res = $ilDB->query($query);
615
616 if(!$res->numRows())
617 {
618 $this->notify[$link["obj_id"]][] = array('page_id' => $link['page_id'],
619 'url' => $link['complete']);
620 }
621 }
622 }
623
624
625 function __clearDBData()
626 {
627 global $ilDB;
628
629 if($this->getValidateAll())
630 {
631 $query = "DELETE FROM link_check";
632 }
633 else
634 {
635 $query = "DELETE FROM link_check ".
636 "WHERE obj_id = ".$ilDB->quote($this->getObjId(),'integer');
637 }
638 $res = $ilDB->manipulate($query);
639
640 return true;
641 }
642}
643?>
const DB_FETCHMODE_OBJECT
Definition: class.ilDB.php:11
static _lookupEntry($a_lang_key, $a_mod, $a_id)
class for checking external links in page objects Normally used in Cron jobs, but should be extensibl...
__fetchUserData($a_usr_id)
setCheckPeriod($a_period)
setObjId($a_page_id)
__txt($language, $key, $module='common')
__getObjIdByPageId($a_page_id)
ilLinkChecker(&$db, $a_validate_all=true)
__isInvalid($a_page_id, $a_url)
createPermanentLink($a_obj_id, $a_usr_id, $a_obj_type)
creates a permanent link
__getTitle($a_lm_obj_id)
setMailStatus($a_status)
__appendInvalidLink($a_link)
__appendLogMessage($a_string)
Class ilObjLinkResourceGUI.
getInstanceByObjId($a_obj_id, $stop_on_error=true)
get an instance of an Ilias object by object id
static _lookupObjId($a_id)
static _getAllReferences($a_id)
get all reference ids of object
static _lookupType($a_id, $a_reference=false)
lookup object type
static _getInstance()
Getter for unique instance.
Wrapper classes for system notifications.
$data
$ref_id
Definition: sahs_server.php:39
global $ilDB
if(!is_array($argv)) $options
global $ilUser
Definition: imgupload.php:15