[ Index ]

PHP Cross Reference of Moodle 1.9.3 [Build 15-Oct-2008]

title

Body

[close]

/lib/ -> rsslib.php (source)

   1  <?php  // $Id: rsslib.php,v 1.52.2.4 2008/09/16 08:55:43 moodler Exp $
   2         // This file contains all the common stuff to be used in RSS System
   3  
   4  //This function returns the icon (from theme) with the link to rss/file.php
   5  function rss_get_link($courseid, $userid, $modulename, $id, $tooltiptext='') {
   6  
   7      global $CFG, $USER;
   8  
   9      static $pixpath = '';
  10      static $rsspath = '';
  11  
  12      //In site course, if no logged (userid), use admin->id. Bug 2048.
  13      if ($courseid == SITEID and empty($userid)) {
  14          $admin = get_admin();
  15          $userid = $admin->id;
  16      }
  17  
  18      $rsspath = rss_get_url($courseid, $userid, $modulename, $id);
  19      $rsspix = $CFG->pixpath .'/i/rss.gif';
  20  
  21      return '<a href="'. $rsspath .'"><img src="'. $rsspix .'" title="'. strip_tags($tooltiptext) .'" alt="'.get_string('rss').'" /></a>';
  22  
  23  }
  24  
  25  //This function returns the URL for the RSS XML file.
  26  function rss_get_url($courseid, $userid, $modulename, $id) {
  27      global $CFG;
  28      require_once($CFG->libdir.'/filelib.php');
  29      return get_file_url($courseid.'/'.$userid.'/'.$modulename.'/'.$id.'/rss.xml', null, 'rssfile');
  30  }
  31  
  32  //This function prints the icon (from theme) with the link to rss/file.php
  33  function rss_print_link($courseid, $userid, $modulename, $id, $tooltiptext='') {
  34  
  35      print rss_get_link($courseid, $userid, $modulename, $id, $tooltiptext);
  36  
  37  }
  38  //This function iterates over each module in the server to see if
  39  //it supports generating rss feeds, searching for a MODULENAME_rss_feeds()
  40  //function and invoking it foreach activity as necessary
  41  function cron_rss_feeds () {
  42  
  43      global $CFG;
  44  
  45      $status = true;
  46  
  47      mtrace('    Generating rssfeeds...');
  48  
  49      //Check for required functions...
  50      if(!function_exists('utf8_encode')) {
  51          mtrace('        ERROR: You need to add XML support to your PHP installation!');
  52          return true;
  53      }
  54  
  55      if ($allmods = get_records('modules') ) {
  56          foreach ($allmods as $mod) {
  57              mtrace('        '.$mod->name.': ', '');
  58              $modname = $mod->name;
  59              $modfile = "$CFG->dirroot/mod/$modname/rsslib.php";
  60              //If file exists and we have selected to restore that type of module
  61              if (file_exists($modfile)) {
  62                  include_once($modfile);
  63                  $generaterssfeeds = $modname.'_rss_feeds';
  64                  if (function_exists($generaterssfeeds)) {
  65                      if ($status) {
  66                          mtrace('generating ', '');;
  67                          $status = $generaterssfeeds();
  68                          if (!empty($status)) {
  69                              mtrace('...OK');
  70                          } else {
  71                              mtrace('...FAILED');
  72                          }
  73                      } else {
  74                          mtrace('...SKIPPED (failed above)');
  75                      }
  76                  } else {
  77                      mtrace('...NOT SUPPORTED (function)');
  78                  }
  79              } else {
  80                  mtrace('...NOT SUPPORTED (file)');
  81              }
  82          }
  83      }
  84      mtrace('    Ending  rssfeeds...', '');
  85      if (!empty($status)) {
  86          mtrace('...OK');
  87      } else {
  88          mtrace('...FAILED');
  89      }
  90  
  91      return $status;
  92  }
  93  
  94  //This function saves to file the rss feed specified in the parameters
  95  function rss_save_file ($modname, $mod, $result) {
  96  
  97      global $CFG;
  98  
  99      $status = true;
 100  
 101      if (! $basedir = make_upload_directory ('rss/'. $modname)) {
 102          //Cannot be created, so error
 103          $status = false;
 104      }
 105  
 106      if ($status) {
 107          $file = rss_file_name($modname, $mod);
 108          $rss_file = fopen($file, "w");
 109          if ($rss_file) {
 110              $status = fwrite ($rss_file, $result);
 111              fclose($rss_file);
 112          } else {
 113              $status = false;
 114          }
 115      }
 116      return $status;
 117  }
 118  
 119  
 120  function rss_file_name($modname, $mod) {
 121      global $CFG;
 122  
 123      return "$CFG->dataroot/rss/$modname/$mod->id.xml";
 124  }
 125  
 126  //This function return all the common headers for every rss feed in the site
 127  function rss_standard_header($title = NULL, $link = NULL, $description = NULL) {
 128  
 129      global $CFG, $USER;
 130  
 131      static $pixpath = '';
 132  
 133      $status = true;
 134      $result = "";
 135  
 136      if (!$site = get_site()) {
 137          $status = false;
 138      }
 139  
 140      if ($status) {
 141  
 142          //Calculate title, link and description
 143          if (empty($title)) {
 144              $title = format_string($site->fullname);
 145          }
 146          if (empty($link)) {
 147              $link = $CFG->wwwroot;
 148          }
 149          if (empty($description)) {
 150              $description = $site->summary;
 151          }
 152  
 153          //xml headers
 154          $result .= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
 155          $result .= "<rss version=\"2.0\">\n";
 156  
 157          //open the channel
 158          $result .= rss_start_tag('channel', 1, true);
 159  
 160          //write channel info
 161          $result .= rss_full_tag('title', 2, false, strip_tags($title));
 162          $result .= rss_full_tag('link', 2, false, $link);
 163          $result .= rss_full_tag('description', 2, false, $description);
 164          $result .= rss_full_tag('generator', 2, false, 'Moodle');
 165          if (!empty($USER->lang)) {
 166              $result .= rss_full_tag('language', 2, false, substr($USER->lang,0,2));
 167          }
 168          $today = getdate();
 169          $result .= rss_full_tag('copyright', 2, false, '&#169; '. $today['year'] .' '. format_string($site->fullname));
 170          /*
 171         if (!empty($USER->email)) {
 172              $result .= rss_full_tag('managingEditor', 2, false, fullname($USER));
 173              $result .= rss_full_tag('webMaster', 2, false, fullname($USER));
 174          }
 175         */
 176  
 177          //write image info
 178          $rsspix = $CFG->pixpath."/i/rsssitelogo.gif";
 179  
 180          //write the info 
 181          $result .= rss_start_tag('image', 2, true);
 182          $result .= rss_full_tag('url', 3, false, $rsspix);
 183          $result .= rss_full_tag('title', 3, false, 'moodle');
 184          $result .= rss_full_tag('link', 3, false, $CFG->wwwroot);
 185          $result .= rss_full_tag('width', 3, false, '140');
 186          $result .= rss_full_tag('height', 3, false, '35');
 187          $result .= rss_end_tag('image', 2, true);
 188      }
 189  
 190      if (!$status) {
 191          return false;
 192      } else {
 193          return $result;
 194      }
 195  }
 196  
 197  //This function returns the rss XML code for every item passed in the array
 198  //item->title: The title of the item
 199  //item->author: The author of the item. Optional !!
 200  //item->pubdate: The pubdate of the item
 201  //item->link: The link url of the item
 202  //item->description: The content of the item
 203  function rss_add_items($items) {
 204  
 205      global $CFG;
 206  
 207      $result = '';
 208  
 209      if (!empty($items)) {
 210          foreach ($items as $item) {
 211              $result .= rss_start_tag('item',2,true);
 212              //Include the category if exists (some rss readers will use it to group items)
 213              if (isset($item->category)) {
 214                  $result .= rss_full_tag('category',3,false,$item->category);
 215              }
 216              $result .= rss_full_tag('title',3,false,strip_tags($item->title));
 217              $result .= rss_full_tag('link',3,false,$item->link);
 218              $result .= rss_add_enclosures($item);
 219              $result .= rss_full_tag('pubDate',3,false,gmdate('D, d M Y H:i:s',$item->pubdate).' GMT');  # MDL-12563
 220              //Include the author if exists 
 221              if (isset($item->author)) {
 222                  //$result .= rss_full_tag('author',3,false,$item->author);
 223                  //We put it in the description instead because it's more important 
 224                  //for moodle than most other feeds, and most rss software seems to ignore
 225                  //the author field ...
 226                  $item->description = get_string('byname','',$item->author).'. &nbsp;<p>'.$item->description.'</p>';
 227              }
 228              $result .= rss_full_tag('description',3,false,$item->description);
 229              $result .= rss_full_tag('guid',3,false,$item->link,array('isPermaLink' => 'true'));
 230              $result .= rss_end_tag('item',2,true);
 231  
 232          }
 233      } else {
 234          $result = false;
 235      }
 236      return $result;
 237  }
 238  
 239  //This function return all the common footers for every rss feed in the site
 240  function rss_standard_footer($title = NULL, $link = NULL, $description = NULL) {
 241  
 242      global $CFG, $USER;
 243  
 244      $status = true;
 245      $result = '';
 246  
 247      //Close the chanel
 248      $result .= rss_end_tag('channel', 1, true);
 249      ////Close the rss tag
 250      $result .= '</rss>';
 251  
 252      return $result;
 253  }
 254  
 255  //This function return an error xml file (string)
 256  //to be sent when a rss is required (file.php)
 257  //and something goes wrong
 258  function rss_geterrorxmlfile() {
 259  
 260      global $CFG;
 261  
 262      $return = '';
 263  
 264      //XML Header
 265      $return = rss_standard_header();
 266  
 267      //XML item
 268      if ($return) {
 269          $item = new object();
 270          $item->title = "RSS Error";
 271          $item->link = $CFG->wwwroot;
 272          $item->pubdate = time();
 273          $item->description = get_string("rsserror");
 274          $return .= rss_add_items(array($item));
 275      }
 276  
 277      //XML Footer
 278      if ($return) {
 279          $return .= rss_standard_footer();
 280      }
 281  
 282      return $return;
 283  }
 284  
 285  // ===== This function are used to write XML tags =========
 286  // [stronk7]: They are similar to the glossary export and backup generation
 287  // but I've replicated them here because they have some minor
 288  // diferences. Someday all they should go to a common place.
 289  
 290  //Return the xml start tag
 291  function rss_start_tag($tag,$level=0,$endline=false,$attributes=null) {
 292      if ($endline) {
 293         $endchar = "\n";
 294      } else {
 295         $endchar = "";
 296      }
 297      $attrstring = '';
 298      if (!empty($attributes) && is_array($attributes)) {
 299          foreach ($attributes as $key => $value) {
 300              $attrstring .= " ".$key."=\"".$value."\"";
 301          }
 302      }
 303      return str_repeat(" ",$level*2)."<".$tag.$attrstring.">".$endchar;
 304  }
 305  
 306  //Return the xml end tag
 307  function rss_end_tag($tag,$level=0,$endline=true) {
 308      if ($endline) {
 309         $endchar = "\n";
 310      } else {
 311         $endchar = "";
 312      }
 313      return str_repeat(" ",$level*2)."</".$tag.">".$endchar;
 314  }
 315  
 316  //Return the start tag, the contents and the end tag
 317  function rss_full_tag($tag,$level=0,$endline=true,$content,$attributes=null) {
 318      global $CFG;
 319      $st = rss_start_tag($tag,$level,$endline,$attributes);
 320      $co="";
 321      $co = preg_replace("/\r\n|\r/", "\n", htmlspecialchars($content));
 322      $et = rss_end_tag($tag,0,true);
 323  
 324      return $st.$co.$et;
 325  }
 326  
 327  //////////////////// LIBRARY FUNCTIONS FOR RSS_CLIENT BLOCK ////////////////
 328  
 329  //initialize default config vars for rss_client block if needed
 330  if (!isset($CFG->block_rss_client_submitters) ) {
 331      $CFG->block_rss_client_submitters = 1; //default to admin only
 332  }
 333  if (empty($CFG->block_rss_client_num_entries) ) {
 334      $CFG->block_rss_client_num_entries = 5; //default to 5 entries per block
 335  }
 336  if (!isset($CFG->block_rss_client_timeout) ) {
 337      $CFG->block_rss_client_timeout = 30; //default to 30 mins
 338  }
 339  
 340  // Defines for moodle's use of magpierss classes
 341  define('MAGPIE_DIR', $CFG->libdir.'/magpie/');
 342  define('MAGPIE_CACHE_DIR', $CFG->dataroot .'/cache/rsscache');
 343  define('MAGPIE_CACHE_ON', true); //might want to expose as an admin config option, but perhaps this is something that should truly just be on unless the code is tweaked
 344  define('MAGPIE_CACHE_FRESH_ONLY', false); //should be exposed as an admin config option
 345  define('MAGPIE_CACHE_AGE', $CFG->block_rss_client_timeout * 60);
 346  define('MAGPIE_DEBUG', $CFG->debug); // magpie, like moodle, takes an integer debug
 347  
 348  // defines for config var block_rss_client_submitters
 349  define('SUBMITTERS_ALL_ACCOUNT_HOLDERS', 0);
 350  define('SUBMITTERS_ADMIN_ONLY', 1);
 351  define('SUBMITTERS_ADMIN_AND_TEACHER', 2);
 352  
 353  /**
 354   * @param int $courseid The id of the course the user is currently viewing
 355   * @param int $userid We need this to know which feeds the user is allowed to manage
 356   * @param int $rssid If present the rss entry matching this id alone will be displayed
 357   *            as long as the user is allowed to manage this feed
 358   * @param object $context we need the context object to check what the user is allowed to do.
 359   */
 360  function rss_display_feeds($courseid, $userid, $rssid='', $context) {
 361      global $db, $USER, $CFG;
 362      global $blogid; //hackish, but if there is a blogid it would be good to preserve it
 363  
 364      require_once($CFG->libdir.'/tablelib.php');
 365  
 366      $select = '';
 367      $managesharedfeeds = has_capability('block/rss_client:manageanyfeeds', $context);
 368      $manageownfeeds = has_capability('block/rss_client:manageownfeeds', $context);
 369  
 370      if ($rssid != '') {
 371          $select = 'id = '.$rssid.' AND ';
 372      }
 373      if ($managesharedfeeds) {
 374          $select .= '(userid = '.$userid.' OR shared = 1)';
 375      } else if ($manageownfeeds) {
 376          $select .= 'userid = '.$userid;
 377      }
 378  
 379      $table = new flexible_table('rss-display-feeds');
 380  
 381      $table->define_columns(array('feed', 'actions'));
 382      $table->define_headers(array(get_string('feed', 'block_rss_client'), get_string('actions', 'moodle')));
 383  
 384      $table->set_attribute('cellspacing', '0');
 385      $table->set_attribute('id', 'rssfeeds');
 386      $table->set_attribute('class', 'generaltable generalbox');
 387      $table->column_class('feed', 'feed');
 388      $table->column_class('actions', 'actions');
 389  
 390      $table->setup();
 391  
 392      $feeds = get_records_select('block_rss_client', $select, sql_order_by_text('title'));
 393  
 394      if(!empty($feeds)) {
 395          foreach($feeds as $feed) {
 396  
 397              if (!empty($feed->preferredtitle)) {
 398                  $feedtitle = stripslashes_safe($feed->preferredtitle);
 399              } else {
 400                  $feedtitle =  stripslashes_safe($feed->title);
 401              }
 402  
 403              if ( ($feed->userid == $USER->id && $manageownfeeds)
 404                      || ($feed->shared && $managesharedfeeds) ) {
 405  
 406                  $feedicons = '<a href="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_action.php?id='. $courseid .'&amp;act=rssedit&amp;rssid='. $feed->id .'&amp;shared='.$feed->shared.'&amp;blogid='. $blogid .'">'.
 407                               '<img src="'. $CFG->pixpath .'/t/edit.gif" alt="'. get_string('edit').'" title="'. get_string('edit') .'" /></a>&nbsp;'.
 408  
 409                               '<a href="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_action.php?id='. $courseid .'&amp;act=delfeed&amp;rssid='. $feed->id.'&amp;shared='.$feed->shared.'blogid='. $blogid .'" 
 410                  onclick="return confirm(\''. get_string('deletefeedconfirm', 'block_rss_client') .'\');">'.
 411                               '<img src="'. $CFG->pixpath .'/t/delete.gif" alt="'. get_string('delete').'" title="'. get_string('delete') .'" /></a>';
 412              }
 413              else {
 414                  $feedicons = '';
 415              }
 416  
 417              $feedinfo = '
 418      <div class="title">
 419          <a href="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_action.php?id='. $courseid .'&amp;act=view&amp;rssid='.$feed->id .'&amp;blogid='. $blogid .'">
 420          '. $feedtitle .'</a>
 421      </div>
 422      <div class="url">
 423          <a href="'. $feed->url .'">'. $feed->url .'</a>
 424      </div>
 425      <div class="description">'.$feed->description.'</div>';
 426  
 427              $table->add_data(array($feedinfo, $feedicons));
 428          }
 429      }
 430  
 431      $table->print_html();
 432  }
 433  
 434  
 435  /**
 436   * Wrapper function for rss_get_form
 437   */
 438  function rss_print_form($act='none', $url='', $rssid='', $preferredtitle='', $shared=0, $courseid='', $context) {
 439      print rss_get_form($act, $url, $rssid, $preferredtitle, $shared, $courseid, $context);
 440  }
 441  
 442  
 443  /**
 444   * Prints or returns a form for managing rss feed entries.
 445   * @param string $act The current action. If "rssedit" then and "update" button is used, otherwise "add" is used.
 446   * @param string $url The url of the feed that is being updated or NULL
 447   * @param int $rssid The dataabse id of the feed that is being updated or NULL
 448   * @param string $preferredtitle The preferred title to display for this feed
 449   * @param int $shared Whether this feed is to be shared or not
 450   * @param int $courseid The id of the course that is currently being viewed if applicable
 451   * @param object $context The context that we will use to check for permissions
 452   * @return string Either the form is printed directly and nothing is returned or the form is returned as a string
 453   */
 454  function rss_get_form($act='none', $url='', $rssid='', $preferredtitle='', $shared=0, $courseid='', $context) {
 455      global $USER, $CFG, $_SERVER, $blockid, $blockaction;
 456      global $blogid; //hackish, but if there is a blogid it would be good to preserve it
 457      $stredit = get_string('edit');
 458      $stradd = get_string('add');
 459      $strupdatefeed = get_string('updatefeed', 'block_rss_client');
 460      $straddfeed = get_string('addfeed', 'block_rss_client');
 461  
 462      $returnstring = '';
 463  
 464      $returnstring .= '<form action="'. $CFG->wwwroot .'/blocks/rss_client/block_rss_client_action.php" method="post" id="block_rss">'."\n";
 465      print_location_comment(__FILE__,__LINE__);
 466      $returnstring .= '<div id="rss_table">'."\n";
 467      if ($act == 'rssedit') {
 468          $returnstring .= $strupdatefeed;
 469      } else {
 470          $returnstring .= $straddfeed;
 471      }
 472  
 473      $returnstring .= "\n".'<br /><input type="text" size="60" maxlength="256" name="url" value="';
 474      if ($act == 'rssedit') {
 475          $returnstring .= $url;
 476      }
 477  
 478      $returnstring .= '" />'."\n";
 479      $returnstring .= '<br />'. get_string('customtitlelabel', 'block_rss_client');
 480      $returnstring .= '<br /><input type="text" size="60" maxlength="128" name="preferredtitle" value="';
 481  
 482      if ($act == 'rssedit') {
 483          $returnstring .= $preferredtitle;
 484      }
 485  
 486      $returnstring .= '" />'."\n";
 487  
 488      if (has_capability('block/rss_client:createsharedfeeds', $context)) {
 489          $returnstring .= '<br /><input type="checkbox" name="shared" value="1" ';
 490          if ($shared) {
 491              $returnstring .= 'checked="checked" ';
 492          }
 493          $returnstring .= '/> ';
 494          $returnstring .= get_string('sharedfeed', 'block_rss_client');
 495          $returnstring .= '<br />'."\n";
 496      }
 497  
 498      $returnstring .= '<input type="hidden" name="act" value="';
 499  
 500      if ($act == 'rssedit') {
 501          $returnstring .= 'updfeed';
 502      } else {
 503          $returnstring .= 'addfeed';
 504      }
 505  
 506      $returnstring .= '" />'."\n";
 507      if ($act == 'rssedit') {
 508          $returnstring .= '<input type="hidden" name="rssid" value="'. $rssid .'" />'. "\n";
 509      }
 510  
 511      $returnstring .= '<input type="hidden" name="id" value="'. $courseid .'" />'."\n";
 512      $returnstring .= '<input type="hidden" name="blogid" value="'. $blogid .'" />'."\n";
 513      $returnstring .= '<input type="hidden" name="user" value="'. $USER->id .'" />'."\n";
 514      $returnstring .= '<br /><input type="submit" value="';
 515      $validatestring = "<a href=\"#\" onclick=\"window.open('http://feedvalidator.org/check.cgi?url='+getElementById('block_rss').elements['url'].value,'validate','width=640,height=480,scrollbars=yes,status=yes,resizable=yes');return true;\">". get_string('validatefeed', 'block_rss_client')."</a>";
 516  
 517      if ($act == 'rssedit') {
 518          $returnstring .= $stredit;
 519      } else {
 520          $returnstring .= $stradd;
 521      }
 522  
 523      $returnstring .= '" />&nbsp;'. $validatestring ."\n";
 524      // $returnstring .= '</div></form>'."\n"; // Avoiding nested forms... Ugly temporary hack #8922
 525      return $returnstring . print_location_comment(__FILE__, __LINE__, true);
 526  }
 527  
 528  
 529  /**
 530  * Adds RSS Media Enclosures for "podcasting" by examining links to media files,
 531  * and attachments which are media files. Please note that the RSS that is
 532  * produced cannot be strictly valid for the linked files, since we do not know
 533  * the files' sizes and cannot include them in the "length" attribute. At
 534  * present, the validity (and therefore the podcast working in most software)
 535  * can only be ensured for attachments, and not for links.
 536  * Note also that iTunes does some things very badly - one thing it does is
 537  * refuse to download ANY of your files if you're using "file.php?file=blah"
 538  * and can't use the more elegant "file.php/blah" slasharguments setting. It
 539  * stops after ".php" and assumes the files are not media files, despite what
 540  * is specified in the "type" attribute. Dodgy coding all round!
 541  *
 542  * @param    $item     object representing an RSS item
 543  * @return   string    RSS enclosure tags
 544  * @author   Hannes Gassert <hannes@mediagonal.ch>
 545  * @author   Dan Stowell
 546  */
 547  function rss_add_enclosures($item){
 548  
 549      global $CFG;
 550  
 551      $returnstring = '';
 552      $rss_text = $item->description;
 553  
 554      // list of media file extensions and their respective mime types
 555      include_once($CFG->libdir.'/filelib.php');
 556      $mediafiletypes = get_mimetypes_array();
 557  
 558      // regular expression (hopefully) matching all links to media files
 559      $medialinkpattern = '@href\s*=\s*(\'|")(\S+(' . implode('|', array_keys($mediafiletypes)) . '))\1@Usie';
 560  
 561      // take into account attachments (e.g. from forum) - with these, we are able to know the file size
 562      if (isset($item->attachments) && is_array($item->attachments)) {
 563          foreach ($item->attachments as $attachment){
 564              $extension = strtolower(substr($attachment->url, strrpos($attachment->url, '.')+1));
 565              if (isset($mediafiletypes[$extension]['type'])) {
 566                  $type = $mediafiletypes[$extension]['type'];
 567              } else {
 568                  $type = 'document/unknown';
 569              }
 570              $returnstring .= "\n<enclosure url=\"$attachment->url\" length=\"$attachment->length\" type=\"$type\" />\n";
 571          }
 572      }
 573  
 574      if (!preg_match_all($medialinkpattern, $rss_text, $matches)){
 575          return $returnstring;
 576      }
 577  
 578      // loop over matches of regular expression
 579      for ($i = 0; $i < count($matches[2]); $i++){
 580          $url = htmlspecialchars($matches[2][$i]);
 581          $extension = strtolower($matches[3][$i]);
 582          if (isset($mediafiletypes[$extension]['type'])) {
 583              $type = $mediafiletypes[$extension]['type'];
 584          } else {
 585              $type = 'document/unknown';
 586          }
 587  
 588          // the rss_*_tag functions can't deal with methods, unfortunately
 589          $returnstring .= "\n<enclosure url='$url' type='$type' />\n";
 590      }
 591  
 592      return $returnstring;
 593  }
 594  ?>


Generated: Wed Jan 14 11:33:29 2009 Cross-referenced by PHPXref 0.7