xmlsitemap.pages.inc 4.18 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
<?php
// $Id$

/**
 * @file
 * Page callbacks for the xmlsitemap module.
 *
 * @ingroup xmlsitemap
 */

/**
 * Output a sitemap page.
 *
 * @see xmlsitemap_file_transfer()
 */
function xmlsitemap_output_chunk($chunk = 0) {
  global $language;

  // @todo Remove this from the final version?
  if (isset($_GET['refresh']) && user_access('administer xmlsitemap')) {
    module_load_include('inc', 'xmlsitemap');
    xmlsitemap_generate($chunk, $language);
  }

  $file = xmlsitemap_get_chunk_file($chunk, $language);
  xmlsitemap_output_file($file);
}

/**
 * Output the contents of a file to the browser and check caching headers.
 */
function xmlsitemap_output_file($file, array $headers = array()) {
  if (!file_exists($file) || !is_readable($file)) {
    return drupal_not_found();
  }

  $mtime = filemtime($file);
  $last_modified = gmdate(DATE_RFC1123, $mtime);
  $etag = '"' . md5($last_modified) . '"';

  // See if the client has provided the required HTTP headers.
  $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE;
  $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE;
  if ($if_modified_since && $if_none_match && $if_none_match == $etag && $if_modified_since == $last_modified) {
    header('HTTP/1.1 304 Not Modified');
    // All 304 responses must send an etag if the 200 response for the same object contained an etag
    header('Etag: ' . $etag);
    exit;
  }

  $headers += array(
    'Content-type: text/xml; charset=utf-8',
    //'Content-length: ' . filesize($file),
    'Last-modified: ' . $last_modified,
    'Etag: ' . $etag,
    'Expires: ' . gmdate(DATE_RFC1123, $mtime + variable_get('xmlsitemap_minimum_lifetime', 0)),
    'Cache-Control: must-revalidate',
    'X-Robots-Tag: noindex, follow',
  );

  // Transfer the file as output.
  xmlsitemap_file_transfer($file, $headers);
}

/**
 * Modified version of file_transfer() that invokes hook_exit()s afterwards.
 *
 * @see file_transfer()
 */
function xmlsitemap_file_transfer($source, $headers) {
  if (ob_get_level()) {
    ob_end_clean();
  }

  foreach ($headers as $header) {
    // To prevent HTTP header injection, we delete new lines that are
    // not followed by a space or a tab.
    // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
    $header = preg_replace('/\r?\n(?!\t| )/', '', $header);
    drupal_set_header($header);
  }

  // Transfer file in 1024 byte chunks to save memory usage.
  if ($handle = fopen($source, 'rb')) {
    while (!feof($handle)) {
      print fread($handle, 1024);
    }
    fclose($handle);
  }
  else {
    drupal_not_found();
  }

  module_invoke_all('exit');
  exit();
}

/**
 * Output an XML transformation file for the sitemap XML.
 */
function xmlsitemap_output_xsl() {
  // Read the XSL content from the file.
  $module_path = drupal_get_path('module', 'xmlsitemap');
  $xsl_content = file_get_contents($module_path . '/xsl/xmlsitemap.xsl');

  // Make sure the strings in the XSL content are translated properly.
  $replacements = array(
    'Sitemap file' => t('Sitemap file'),
    'Generated by the <a href="http://drupal.org/project/xmlsitemap">Drupal XML sitemap module</a>.' => t('Generated by the <a href="@link-xmlsitemap">Drupal XML sitemap module</a>.', array('@link-xmlsitemap' => 'http://drupal.org/project/xmlsitemap')),
    'Number of sitemaps in this index' => t('Number of sitemaps in this index'),
    'Click on the table headers to change sorting.' => t('Click on the table headers to change sorting.'),
    'Sitemap URL' => t('Sitemap URL'),
    'Last modification date' => t('Last modification date'),
    'Number of URLs in this sitemap' => t('Number of URLs in this sitemap'),
    'URL location' => t('URL location'),
    'Change frequency' => t('Change frequency'),
    'Priority' => t('Priority'),
    '[xsl-css]' => base_path() . $module_path . '/xsl/xmlsitemap.xsl.css',
    '[xsl-js]' => base_path() . $module_path . '/xsl/xmlsitemap.xsl.js',
  );
  $xsl_content = strtr($xsl_content, $replacements);

  // Output the XSL content.
  drupal_set_header('Content-type: application/xml; charset=utf-8');
  drupal_set_header('X-Robots-Tag: noindex, follow');
  echo $xsl_content;
}