00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00032 class ilLinkChecker
00033 {
00034 var $db = null;
00035 var $log_messages = array();
00036 var $invalid_links = array();
00037
00038 var $validate_all = true;
00039 var $mail_status = false;
00040 var $page_id = 0;
00041
00042
00043 function ilLinkChecker(&$db,$a_validate_all = true)
00044 {
00045 global $ilDB;
00046
00047 define('DEBUG',1);
00048 define('SOCKET_TIMEOUT',5);
00049
00050 $this->db =& $db;
00051
00052
00053 $ilDB =& $db;
00054
00055 $this->validate_all = $a_validate_all;
00056 }
00057
00058 function setCheckPeriod($a_period)
00059 {
00060 $this->period = $a_period;
00061 }
00062 function getCheckPeriod()
00063 {
00064 return $this->period;
00065 }
00066
00067 function setMailStatus($a_status)
00068 {
00069 $this->mail_status = (bool) $a_status;
00070 }
00071 function getMailStatus()
00072 {
00073 return (bool) $this->mail_status;
00074 }
00075
00076 function __setType($a_type)
00077 {
00078 $this->type = $a_type;
00079 }
00080 function __getType()
00081 {
00082 return $this->type;
00083 }
00084
00085 function setObjId($a_page_id)
00086 {
00087 return $this->page_id = $a_page_id;
00088 }
00089 function getObjId()
00090 {
00091 return $this->page_id;
00092 }
00093
00094 function getValidateAll()
00095 {
00096 return $this->validate_all ? true : false;
00097 }
00098
00099 function getLogMessages()
00100 {
00101 return $this->log_messages ? $this->log_messages : array();
00102 }
00103
00104 function getInvalidLinks()
00105 {
00106 return $this->invalid_links ? $this->invalid_links : array();
00107 }
00108
00109 function getInvalidLinksFromDB()
00110 {
00111 global $ilDB;
00112
00113 $query = "SELECT * FROM link_check ".
00114 "WHERE obj_id = ".$ilDB->quote($this->getObjId())." ";
00115
00116 $res = $this->db->query($query);
00117 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00118 {
00119 $invalid[] = array('page_id' => $row->page_id,
00120 'url' => $row->url);
00121 }
00122
00123 return $invalid ? $invalid : array();
00124 }
00125
00126 function getLastCheckTimestamp()
00127 {
00128 global $ilDB;
00129
00130 if($this->getValidateAll())
00131 {
00132 $query = "SELECT MAX(last_check) as last_check FROM link_check ";
00133 }
00134 else
00135 {
00136 $query = "SELECT MAX(last_check) as last_check FROM link_check ".
00137 "WHERE obj_id = ".$ilDB->quote($this->getObjId())." ";
00138 }
00139 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00140
00141 return $row->last_check ? $row->last_check : 0;
00142 }
00143
00144 function checkWebResourceLinks()
00145 {
00146 $pages = array();
00147
00148 $this->__setType('webr');
00149 $this->__clearLogMessages();
00150 $this->__clearInvalidLinks();
00151 $this->__appendLogMessage('LinkChecker: Start checkLinks()');
00152
00153 if(count($invalid = $this->__validateLinks($this->__getWebResourceLinks())))
00154 {
00155 foreach($invalid as $invalid_item)
00156 {
00157 $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
00158 $this->__appendInvalidLink($invalid_item);
00159 }
00160 }
00161
00162 $this->__appendLogMessage('LinkChecker: End checkLinks()');
00163 $this->__saveInDB();
00164
00165 $this->__sendMail();
00166
00167 return $this->getInvalidLinks();
00168 }
00169
00170 function checkLinks()
00171 {
00172 global $ilDB;
00173
00174 $pages = array();
00175
00176 $this->__setType('lm');
00177 $this->__clearLogMessages();
00178 $this->__clearInvalidLinks();
00179 $this->__appendLogMessage('LinkChecker: Start checkLinks()');
00180
00181 if(!$this->getValidateAll() and !$this->getObjId())
00182 {
00183 echo "ilLinkChecker::checkLinks() No Page id given";
00184
00185 return false;
00186 }
00187 elseif(!$this->getValidateAll() and $this->getObjId())
00188 {
00189 $query = "SELECT * FROM page_object ".
00190 "WHERE parent_id = ".$ilDB->quote($this->getObjId())." ".
00191 "AND parent_type = 'lm'";
00192
00193 $res = $this->db->query($query);
00194 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00195 {
00196 $pages[] = array('page_id' => $row->page_id,
00197 'content' => $row->content,
00198 'type' => $row->parent_type);
00199 }
00200 }
00201 elseif($this->getValidateAll())
00202 {
00203 $query = "SELECT * FROM page_object ".
00204 "WHERE parent_type = 'lm'";
00205
00206 $res = $this->db->query($query);
00207 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00208 {
00209 $pages[] = array('page_id' => $row->page_id,
00210 'content' => $row->content,
00211 'type' => $row->parent_type);
00212 }
00213 }
00214
00215
00216 foreach($pages as $page)
00217 {
00218 if(count($invalid = $this->__validateLinks($this->__getLinks($page))))
00219 {
00220 foreach($invalid as $invalid_item)
00221 {
00222 $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
00223 $this->__appendInvalidLink($invalid_item);
00224 }
00225 }
00226 }
00227
00228 $this->__appendLogMessage('LinkChecker: End checkLinks()');
00229 $this->__saveInDB();
00230
00231 $this->__sendMail();
00232
00233 return $this->getInvalidLinks();
00234 }
00235
00236 function checkPear()
00237 {
00238 if(!@include_once('HTTP/Request.php'))
00239 {
00240 return false;
00241 }
00242 return true;
00243 }
00244
00245
00246
00247 function __txt($language,$key,$module = 'common')
00248 {
00249 global $ilDB;
00250
00251 $query = "SELECT value FROM lng_data ".
00252 "WHERE module = ".$ilDB->quote($module)." ".
00253 "AND identifier = ".$ilDB->quote($key)." ".
00254 "AND lang_key = ".$ilDB->quote($language)."";
00255
00256 $res = $this->db->query($query);
00257 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00258 {
00259 $value = $row->value;
00260 }
00261 if(!$value)
00262 {
00263 $query = "SELECT value FROM lng_data ".
00264 "WHERE module = ".$ilDB->quote($module)." ".
00265 "AND identifier = ".$ilDB->quote($key)." ".
00266 "AND lang_key = 'en'";
00267
00268 $res = $this->db->query($query);
00269 while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
00270 {
00271 $value = $row->value;
00272 }
00273 }
00274 return $value ? $value : '-'.$key.'-';
00275 }
00276
00277 function __fetchUserData($a_usr_id)
00278 {
00279 global $ilDB;
00280
00281 $query = "SELECT email FROM usr_data WHERE usr_id = ".$ilDB->quote($a_usr_id)."";
00282
00283 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00284
00285 $data['email'] = $row->email;
00286
00287 $query = "SELECT * FROM usr_pref ".
00288 "WHERE usr_id = ".$ilDB->quote($a_usr_id)." ".
00289 "AND keyword = 'language'";
00290
00291 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00292
00293 $data['lang'] = $row->value;
00294
00295 return $data;
00296 }
00297
00298 function __getTitle($a_lm_obj_id)
00299 {
00300 global $ilDB;
00301
00302 $query = "SELECT title FROM object_data ".
00303 "WHERE obj_id = ".$ilDB->quote($a_lm_obj_id)." ";
00304
00305 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00306
00307 return $row->title;
00308 }
00309
00310 function __sendMail()
00311 {
00312 global $ilUser;
00313
00314
00315 if(!count($notify = $this->__getNotifyLinks()))
00316 {
00317
00318 return true;
00319 }
00320 if(!$this->getMailStatus())
00321 {
00322 return true;
00323 }
00324
00325 include_once './classes/class.ilLinkCheckNotify.php';
00326
00327 foreach(ilLinkCheckNotify::_getAllNotifiers($this->db) as $usr_id => $obj_ids)
00328 {
00329 if(!is_object($tmp_user =& ilObjectFactory::getInstanceByObjId($usr_id,false)))
00330 {
00331 $this->__appendLogMessage('LinkChecker: Cannot find user with id: '.$usr_id);
00332 continue;
00333 }
00334
00335 $counter = 0;
00336 foreach($obj_ids as $obj_id)
00337 {
00338 if(!isset($notify[$obj_id]))
00339 {
00340 continue;
00341 }
00342 ++$counter;
00343
00344 switch($this->__getType())
00345 {
00346 case 'webr':
00347 $body .= $this->__txt($tmp_user->getLanguage(),'obj_webr');
00348 break;
00349
00350 case 'lm':
00351 default:
00352 $body .= $this->__txt($tmp_user->getLanguage(),'lo');
00353 break;
00354 }
00355
00356 $body .= ': ';
00357 $body .= $this->__getTitle($obj_id)."\r\n";
00358
00359
00360 foreach($notify[$obj_id] as $data)
00361 {
00362 $body .= $data['url']."\r\n";
00363 }
00364 $body .= "\r\n";
00365 }
00366 if($counter)
00367 {
00368 include_once "Services/Mail/classes/class.ilFormatMail.php";
00369
00370 $umail = new ilFormatMail($tmp_user->getId());
00371 $subject = $this->__txt($tmp_user->getLanguage(),'link_check_subject');
00372
00373 $umail->sendMail($tmp_user->getLogin(),"","",$subject,$body,array(),array("normal"));
00374 $this->__appendLogMessage('LinkChecker: Sent mail to '.$tmp_user->getEmail());
00375 }
00376
00377 }
00378
00379
00380 }
00381
00382 function __getNotifyLinks()
00383 {
00384 return $this->notify ? $this->notify : array();
00385 }
00386
00387
00388 function __clearInvalidLinks()
00389 {
00390 $this->invalid_links = array();
00391 }
00392 function __appendInvalidLink($a_link)
00393 {
00394 $this->invalid_links[] = $a_link;
00395 }
00396
00397
00398 function __appendLogMessage($a_string)
00399 {
00400 $this->log_messages[] = $a_string;
00401 }
00402 function __clearLogMessages()
00403 {
00404 return $this->log_messages = array();
00405 }
00406
00407 function __getLinks($a_page)
00408 {
00409 $matches = array();
00410
00411 $pattern_complete = '/<ExtLink Href="([^"]*)">/';
00412 if(preg_match_all($pattern_complete,$a_page['content'],$matches))
00413 {
00414 for($i = 0;$i < count($matches[0]); ++$i)
00415 {
00416 $url_data = @parse_url($matches[1][$i]);
00417
00418 if($url_data['scheme'] == 'mailto')
00419 {
00420 continue;
00421 }
00422
00423
00424 if(!$url_data['scheme'])
00425 {
00426 $matches[1][$i] = 'http://'.$matches[1][$i];
00427 }
00428
00429 $lm_id = $this->__getObjIdByPageId($a_page['page_id']);
00430 $link[] = array('page_id' => $a_page['page_id'],
00431 'obj_id' => $lm_id,
00432 'type' => $a_page['type'],
00433 'complete' => $matches[1][$i],
00434 'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
00435 'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
00436 }
00437 }
00438
00439 return $link ? $link : array();
00440 }
00441
00442 function __getWebResourceLinks()
00443 {
00444 include_once 'Modules/WebResource/classes/class.ilLinkResourceItems.php';
00445
00446 $link_res_obj = new ilLinkResourceItems($this->getObjId());
00447
00448 foreach($check_links = $link_res_obj->getCheckItems($this->getCheckPeriod()) as $item_data)
00449 {
00450 $url_data = @parse_url($item_data['target']);
00451
00452
00453 if(!$url_data['scheme'])
00454 {
00455 $item_data['target'] = 'http://'.$item_data['target'];
00456 }
00457
00458 $link[] = array('page_id' => $item_data['link_id'],
00459 'obj_id' => $this->getObjId(),
00460 'type' => 'webr',
00461 'complete' => $item_data['target'],
00462 'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
00463 'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
00464 }
00465 return $link ? $link : array();
00466 }
00467
00468
00469
00470 function __validateLinks($a_links)
00471 {
00472 if(!@include_once('HTTP/Request.php'))
00473 {
00474 $this->__appendLogMessage('LinkChecker: Pear HTTP_Request is not installed. Aborting');
00475
00476 return array();
00477 }
00478
00479 foreach($a_links as $link)
00480 {
00481 if(gethostbyname($link['host']) == $link['host'])
00482 {
00483 $invalid[] = $link;
00484 continue;
00485 }
00486
00487 if($link['scheme'] !== 'http' and $link['scheme'] !== 'https')
00488 {
00489 continue;
00490 }
00491 $req =& new HTTP_Request($link['complete']);
00492 $req->sendRequest();
00493
00494 switch($req->getResponseCode())
00495 {
00496
00497 case '200':
00498
00499 case '301':
00500 case '302':
00501 break;
00502
00503 default:
00504 $link['http_status_code'] = $req->getResponseCode();
00505 $invalid[] = $link;
00506 break;
00507 }
00508 }
00509 return $invalid ? $invalid : array();
00510 }
00511
00512 function __getObjIdByPageId($a_page_id)
00513 {
00514 $query = "SELECT lm_id FROM lm_data ".
00515 "WHERE obj_id = '".$a_page_id."'";
00516
00517 $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
00518
00519 return $row->lm_id ? $row->lm_id : 0;
00520 }
00521
00522 function __isInvalid($a_page_id, $a_url)
00523 {
00524 foreach($this->getInvalidLinks() as $link)
00525 {
00526 if($link['page_id'] == $a_page_id and
00527 substr($link['complete'],0,255) == $a_url)
00528 {
00529 return true;
00530 }
00531 }
00532 return false;
00533 }
00534
00535 function __saveInDB()
00536 {
00537 global $ilDB;
00538
00539 if($this->getMailStatus())
00540 {
00541 $this->__checkNotify();
00542 }
00543 $this->__clearDBData();
00544
00545
00546 foreach($this->getInvalidLinks() as $link)
00547 {
00548
00549 $query = "INSERT INTO link_check ".
00550 "SET page_id = ".$ilDB->quote($link['page_id']).", ".
00551 "obj_id = ".$ilDB->quote($link['obj_id']).", ".
00552 "url = ".$ilDB->quote((substr($link['complete'],0,255))).", ".
00553 "parent_type = ".$ilDB->quote(($link['type'])).", ".
00554 "http_status_code = ".$ilDB->quote(($link['http_status_code'])).", ".
00555 "last_check = '".time()."'";
00556
00557
00558 $res = $this->db->query($query);
00559 }
00560
00561
00562
00563 }
00564
00565 function __checkNotify()
00566 {
00567 global $ilDB;
00568
00569 foreach($this->getInvalidLinks() as $link)
00570 {
00571 $query = "SELECT * FROM link_check ".
00572 "WHERE page_id = ".$ilDB->quote($link['page_id'])." ".
00573 "AND url = ".$ilDB->quote((substr($link['complete'],0,255)))." ";
00574 $res = $this->db->query($query);
00575
00576 if(!$res->numRows())
00577 {
00578 $this->notify["$link[obj_id]"][] = array('page_id' => $link['page_id'],
00579 'url' => $link['complete']);
00580 }
00581 }
00582 }
00583
00584
00585 function __clearDBData()
00586 {
00587 global $ilDB;
00588
00589 if($this->getValidateAll())
00590 {
00591 $query = "DELETE FROM link_check";
00592 }
00593 else
00594 {
00595 $query = "DELETE FROM link_check ".
00596 "WHERE obj_id = ".$ilDB->quote($this->getObjId())." ";
00597 }
00598
00599 $this->db->query($query);
00600
00601 return true;
00602 }
00603 }
00604 ?>