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