ILIAS  Release_3_10_x_branch Revision 61812
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilLinkChecker.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 
33 {
34  var $db = null;
35  var $log_messages = array();
36  var $invalid_links = array();
37 
38  var $validate_all = true;
39  var $mail_status = false;
40  var $page_id = 0;
41 
42 
43  function ilLinkChecker(&$db,$a_validate_all = true)
44  {
45  global $ilDB;
46 
47  define('DEBUG',1);
48  define('SOCKET_TIMEOUT',5);
49 
50  $this->db =& $db;
51 
52  // SET GLOBAL DB HANDLER FOR STATIC METHODS OTHER CLASSES
53  $ilDB =& $db;
54 
55  $this->validate_all = $a_validate_all;
56  }
57 
58  function setCheckPeriod($a_period)
59  {
60  $this->period = $a_period;
61  }
62  function getCheckPeriod()
63  {
64  return $this->period;
65  }
66 
67  function setMailStatus($a_status)
68  {
69  $this->mail_status = (bool) $a_status;
70  }
71  function getMailStatus()
72  {
73  return (bool) $this->mail_status;
74  }
75 
76  function __setType($a_type)
77  {
78  $this->type = $a_type;
79  }
80  function __getType()
81  {
82  return $this->type;
83  }
84 
85  function setObjId($a_page_id)
86  {
87  return $this->page_id = $a_page_id;
88  }
89  function getObjId()
90  {
91  return $this->page_id;
92  }
93 
94  function getValidateAll()
95  {
96  return $this->validate_all ? true : false;
97  }
98 
99  function getLogMessages()
100  {
101  return $this->log_messages ? $this->log_messages : array();
102  }
103 
104  function getInvalidLinks()
105  {
106  return $this->invalid_links ? $this->invalid_links : array();
107  }
108 
110  {
111  global $ilDB;
112 
113  $query = "SELECT * FROM link_check ".
114  "WHERE obj_id = ".$ilDB->quote($this->getObjId())." ";
115 
116  $res = $this->db->query($query);
117  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
118  {
119  $invalid[] = array('page_id' => $row->page_id,
120  'url' => $row->url);
121  }
122 
123  return $invalid ? $invalid : array();
124  }
125 
127  {
128  global $ilDB;
129 
130  if($this->getValidateAll())
131  {
132  $query = "SELECT MAX(last_check) as last_check FROM link_check ";
133  }
134  else
135  {
136  $query = "SELECT MAX(last_check) as last_check FROM link_check ".
137  "WHERE obj_id = ".$ilDB->quote($this->getObjId())." ";
138  }
139  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
140 
141  return $row->last_check ? $row->last_check : 0;
142  }
143 
145  {
146  $pages = array();
147 
148  $this->__setType('webr');
149  $this->__clearLogMessages();
150  $this->__clearInvalidLinks();
151  $this->__appendLogMessage('LinkChecker: Start checkLinks()');
152 
153  if(count($invalid = $this->__validateLinks($this->__getWebResourceLinks())))
154  {
155  foreach($invalid as $invalid_item)
156  {
157  $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
158  $this->__appendInvalidLink($invalid_item);
159  }
160  }
161 
162  $this->__appendLogMessage('LinkChecker: End checkLinks()');
163  $this->__saveInDB();
164 
165  $this->__sendMail();
166 
167  return $this->getInvalidLinks();
168  }
169 
170  function checkLinks()
171  {
172  global $ilDB;
173 
174  $pages = array();
175 
176  $this->__setType('lm');
177  $this->__clearLogMessages();
178  $this->__clearInvalidLinks();
179  $this->__appendLogMessage('LinkChecker: Start checkLinks()');
180 
181  if(!$this->getValidateAll() and !$this->getObjId())
182  {
183  echo "ilLinkChecker::checkLinks() No Page id given";
184 
185  return false;
186  }
187  elseif(!$this->getValidateAll() and $this->getObjId())
188  {
189  $query = "SELECT * FROM page_object ".
190  "WHERE parent_id = ".$ilDB->quote($this->getObjId())." ".
191  "AND parent_type = 'lm'";
192 
193  $res = $this->db->query($query);
194  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
195  {
196  $pages[] = array('page_id' => $row->page_id,
197  'content' => $row->content,
198  'type' => $row->parent_type);
199  }
200  }
201  elseif($this->getValidateAll())
202  {
203  $query = "SELECT * FROM page_object ".
204  "WHERE parent_type = 'lm'";
205 
206  $res = $this->db->query($query);
207  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
208  {
209  $pages[] = array('page_id' => $row->page_id,
210  'content' => $row->content,
211  'type' => $row->parent_type);
212  }
213  }
214 
215  // VALIDATE
216  foreach($pages as $page)
217  {
218  if(count($invalid = $this->__validateLinks($this->__getLinks($page))))
219  {
220  foreach($invalid as $invalid_item)
221  {
222  $this->__appendLogMessage('LinkChecker: found invalid link: '.$invalid_item['complete']);
223  $this->__appendInvalidLink($invalid_item);
224  }
225  }
226  }
227 
228  $this->__appendLogMessage('LinkChecker: End checkLinks()');
229  $this->__saveInDB();
230 
231  $this->__sendMail();
232 
233  return $this->getInvalidLinks();
234  }
235 
236  function checkPear()
237  {
238  if(!@include_once('HTTP/Request.php'))
239  {
240  return false;
241  }
242  return true;
243  }
244 
245 
246  // PRIVATE
247  function __txt($language,$key,$module = 'common')
248  {
249  global $ilDB;
250 
251  $query = "SELECT value FROM lng_data ".
252  "WHERE module = ".$ilDB->quote($module)." ".
253  "AND identifier = ".$ilDB->quote($key)." ".
254  "AND lang_key = ".$ilDB->quote($language)."";
255 
256  $res = $this->db->query($query);
257  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
258  {
259  $value = $row->value;
260  }
261  if(!$value)
262  {
263  $query = "SELECT value FROM lng_data ".
264  "WHERE module = ".$ilDB->quote($module)." ".
265  "AND identifier = ".$ilDB->quote($key)." ".
266  "AND lang_key = 'en'";
267 
268  $res = $this->db->query($query);
269  while($row = $res->fetchRow(DB_FETCHMODE_OBJECT))
270  {
271  $value = $row->value;
272  }
273  }
274  return $value ? $value : '-'.$key.'-';
275  }
276 
277  function __fetchUserData($a_usr_id)
278  {
279  global $ilDB;
280 
281  $query = "SELECT email FROM usr_data WHERE usr_id = ".$ilDB->quote($a_usr_id)."";
282 
283  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
284 
285  $data['email'] = $row->email;
286 
287  $query = "SELECT * FROM usr_pref ".
288  "WHERE usr_id = ".$ilDB->quote($a_usr_id)." ".
289  "AND keyword = 'language'";
290 
291  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
292 
293  $data['lang'] = $row->value;
294 
295  return $data;
296  }
297 
298  function __getTitle($a_lm_obj_id)
299  {
300  global $ilDB;
301 
302  $query = "SELECT title FROM object_data ".
303  "WHERE obj_id = ".$ilDB->quote($a_lm_obj_id)." ";
304 
305  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
306 
307  return $row->title;
308  }
309 
310  function __sendMail()
311  {
312  global $ilUser;
313 
314 
315  if(!count($notify = $this->__getNotifyLinks()))
316  {
317  // Nothing to do
318  return true;
319  }
320  if(!$this->getMailStatus())
321  {
322  return true;
323  }
324 
325  include_once './classes/class.ilLinkCheckNotify.php';
326 
327  foreach(ilLinkCheckNotify::_getAllNotifiers($this->db) as $usr_id => $obj_ids)
328  {
329  if(!is_object($tmp_user =& ilObjectFactory::getInstanceByObjId($usr_id,false)))
330  {
331  $this->__appendLogMessage('LinkChecker: Cannot find user with id: '.$usr_id);
332  continue;
333  }
334 
335  $counter = 0;
336  foreach($obj_ids as $obj_id)
337  {
338  if(!isset($notify[$obj_id]))
339  {
340  continue;
341  }
342  ++$counter;
343 
344  switch($this->__getType())
345  {
346  case 'webr':
347  $body .= $this->__txt($tmp_user->getLanguage(),'obj_webr');
348  break;
349 
350  case 'lm':
351  default:
352  $body .= $this->__txt($tmp_user->getLanguage(),'lo');
353  break;
354  }
355 
356  $body .= ': ';
357  $body .= $this->__getTitle($obj_id)."\r\n";
358 
359  // Print all invalid
360  foreach($notify[$obj_id] as $data)
361  {
362  $body .= $data['url']."\r\n";
363  }
364  $body .= "\r\n";
365  }
366  if($counter)
367  {
368  include_once "Services/Mail/classes/class.ilFormatMail.php";
369 
370  $umail = new ilFormatMail($tmp_user->getId());
371  $subject = $this->__txt($tmp_user->getLanguage(),'link_check_subject');
372 
373  $umail->sendMail($tmp_user->getLogin(),"","",$subject,$body,array(),array("normal"));
374  $this->__appendLogMessage('LinkChecker: Sent mail to '.$tmp_user->getEmail());
375  }
376 
377  }
378 
379 
380  }
381 
382  function __getNotifyLinks()
383  {
384  return $this->notify ? $this->notify : array();
385  }
386 
387 
389  {
390  $this->invalid_links = array();
391  }
392  function __appendInvalidLink($a_link)
393  {
394  $this->invalid_links[] = $a_link;
395  }
396 
397 
398  function __appendLogMessage($a_string)
399  {
400  $this->log_messages[] = $a_string;
401  }
403  {
404  return $this->log_messages = array();
405  }
406 
407  function __getLinks($a_page)
408  {
409  $matches = array();
410 
411  $pattern_complete = '/<ExtLink Href="([^"]*)">/';
412  if(preg_match_all($pattern_complete,$a_page['content'],$matches))
413  {
414  for($i = 0;$i < count($matches[0]); ++$i)
415  {
416  $url_data = @parse_url($matches[1][$i]);
417  // continue if mailto link
418  if($url_data['scheme'] == 'mailto')
419  {
420  continue;
421  }
422 
423  // PUH, HTTP_REQUEST needs a beginning http://
424  if(!$url_data['scheme'])
425  {
426  $matches[1][$i] = 'http://'.$matches[1][$i];
427  }
428 
429  $lm_id = $this->__getObjIdByPageId($a_page['page_id']);
430  $link[] = array('page_id' => $a_page['page_id'],
431  'obj_id' => $lm_id,
432  'type' => $a_page['type'],
433  'complete' => $matches[1][$i],
434  'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
435  'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
436  }
437  }
438 
439  return $link ? $link : array();
440  }
441 
443  {
444  include_once 'Modules/WebResource/classes/class.ilLinkResourceItems.php';
445 
446  $link_res_obj = new ilLinkResourceItems($this->getObjId());
447 
448  foreach($check_links = $link_res_obj->getCheckItems($this->getCheckPeriod()) as $item_data)
449  {
450  $url_data = @parse_url($item_data['target']);
451 
452  // PUH, HTTP_REQUEST needs a beginning http://
453  if(!$url_data['scheme'])
454  {
455  $item_data['target'] = 'http://'.$item_data['target'];
456  }
457 
458  $link[] = array('page_id' => $item_data['link_id'],
459  'obj_id' => $this->getObjId(),
460  'type' => 'webr',
461  'complete' => $item_data['target'],
462  'scheme' => isset($url_data['scheme']) ? $url_data['scheme'] : 'http',
463  'host' => isset($url_data['host']) ? $url_data['host'] : $url_data['path']);
464  }
465  return $link ? $link : array();
466  }
467 
468 
469 
470  function __validateLinks($a_links)
471  {
472  if(!@include_once('HTTP/Request.php'))
473  {
474  $this->__appendLogMessage('LinkChecker: Pear HTTP_Request is not installed. Aborting');
475 
476  return array();
477  }
478 
479  foreach($a_links as $link)
480  {
481  if(gethostbyname($link['host']) == $link['host'])
482  {
483  $invalid[] = $link;
484  continue;
485  }
486 
487  if($link['scheme'] !== 'http' and $link['scheme'] !== 'https')
488  {
489  continue;
490  }
491  $req =& new HTTP_Request($link['complete']);
492  $req->sendRequest();
493 
494  switch($req->getResponseCode())
495  {
496  // EVERYTHING OK
497  case '200':
498  // In the moment 301 will be handled as ok
499  case '301':
500  case '302':
501  break;
502 
503  default:
504  $link['http_status_code'] = $req->getResponseCode();
505  $invalid[] = $link;
506  break;
507  }
508  }
509  return $invalid ? $invalid : array();
510  }
511 
512  function __getObjIdByPageId($a_page_id)
513  {
514  $query = "SELECT lm_id FROM lm_data ".
515  "WHERE obj_id = '".$a_page_id."'";
516 
517  $row = $this->db->getRow($query,DB_FETCHMODE_OBJECT);
518 
519  return $row->lm_id ? $row->lm_id : 0;
520  }
521 
522  function __isInvalid($a_page_id, $a_url)
523  {
524  foreach($this->getInvalidLinks() as $link)
525  {
526  if($link['page_id'] == $a_page_id and
527  substr($link['complete'],0,255) == $a_url)
528  {
529  return true;
530  }
531  }
532  return false;
533  }
534 
535  function __saveInDB()
536  {
537  global $ilDB;
538 
539  if($this->getMailStatus())
540  {
541  $this->__checkNotify();
542  }
543  $this->__clearDBData();
544 
545 
546  foreach($this->getInvalidLinks() as $link)
547  {
548 
549  $query = "INSERT INTO link_check ".
550  "SET page_id = ".$ilDB->quote($link['page_id']).", ".
551  "obj_id = ".$ilDB->quote($link['obj_id']).", ".
552  "url = ".$ilDB->quote((substr($link['complete'],0,255))).", ".
553  "parent_type = ".$ilDB->quote(($link['type'])).", ".
554  "http_status_code = ".$ilDB->quote(($link['http_status_code'])).", ".
555  "last_check = '".time()."'";
556 
557 
558  $res = $this->db->query($query);
559  }
560 
561  // delete old values
562 
563  }
564 
565  function __checkNotify()
566  {
567  global $ilDB;
568 
569  foreach($this->getInvalidLinks() as $link)
570  {
571  $query = "SELECT * FROM link_check ".
572  "WHERE page_id = ".$ilDB->quote($link['page_id'])." ".
573  "AND url = ".$ilDB->quote((substr($link['complete'],0,255)))." ";
574  $res = $this->db->query($query);
575 
576  if(!$res->numRows())
577  {
578  $this->notify["$link[obj_id]"][] = array('page_id' => $link['page_id'],
579  'url' => $link['complete']);
580  }
581  }
582  }
583 
584 
585  function __clearDBData()
586  {
587  global $ilDB;
588 
589  if($this->getValidateAll())
590  {
591  $query = "DELETE FROM link_check";
592  }
593  else
594  {
595  $query = "DELETE FROM link_check ".
596  "WHERE obj_id = ".$ilDB->quote($this->getObjId())." ";
597  }
598 
599  $this->db->query($query);
600 
601  return true;
602  }
603 }
604 ?>