[ Index ]
 

Code source de Drupal 5.3

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

/modules/color/ -> color.module (source)

   1  <?php
   2  // $Id: color.module,v 1.13.2.3 2007/10/16 07:02:40 drumm Exp $
   3  
   4  /**
   5   * Implementation of hook_help
   6   */
   7  function color_help($section) {
   8    switch ($section) {
   9      case 'admin/help#color':
  10        $output = '<p>'. t('Color module allows a site administrator to quickly and easily change the color scheme of the entire site. In order for color module to work however, a theme must be specifically designed to use the color changing features. The default theme, Garland, (as well as its fixed width counterpart, Minnelli) was designed to take advantage of these features. With color module, you can easily change the color of links, backgrounds, text, and more depending on which color module enabled theme you are using. Color module requires your <a href="@url">file download method</a> to be set to public.', array('@url' => url('admin/settings/file-system'))) .'</p>';
  11        $output .= '<p>'. t("It is important to remember that color module saves a modified copy of the theme's style.css file in the files directory, and includes it after the theme's original style.css. This means that if you make any manual changes to your theme's style.css file, you must save your color settings again, even if they haven't changed. This causes the color module generated version of style.css in the files directory to be recreated using the new version of the original file.") .'</p>';
  12        return $output;
  13    }
  14  }
  15  
  16  /**
  17   * Implementation of hook_form_alter().
  18   */
  19  function color_form_alter($form_id, &$form) {
  20    // Insert the color changer into the theme settings page.
  21    // TODO: Last condition in the following if disables color changer when private files are used this should be solved in a different way. See issue #92059.
  22    if ($form_id == 'system_theme_settings' && color_get_info(arg(4)) && function_exists('gd_info') && variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC) {
  23      $form['color'] = array(
  24        '#type' => 'fieldset',
  25        '#title' => t('Color scheme'),
  26        '#weight' => -1,
  27        '#attributes' => array('id' => 'color_scheme_form'),
  28        '#theme' => 'color_scheme_form',
  29      );
  30      $form['color'] += color_scheme_form(arg(4));
  31      $form['#submit']['color_scheme_form_submit'] = array();
  32    }
  33  
  34    // Use the generated screenshot in the theme list
  35    if ($form_id == 'system_theme_select_form' || $form_id == 'system_themes') {
  36      $themes = list_themes();
  37      foreach (element_children($form) as $theme) {
  38        if ($screenshot = variable_get('color_'. $theme .'_screenshot', NULL)) {
  39          if (isset($form[$theme]['screenshot'])) {
  40            $form[$theme]['screenshot']['#value'] = theme('image', $screenshot, '', '', array('class' => 'screenshot'), FALSE);
  41          }
  42        }
  43      }
  44    }
  45  }
  46  
  47  /**
  48   * Callback for the theme to alter the resources used.
  49   */
  50  function _color_page_alter(&$vars) {
  51    global $theme_key;
  52  
  53    // Override stylesheet
  54    $path = variable_get('color_'. $theme_key .'_stylesheet', NULL);
  55    if ($path) {
  56      $vars['css']['all']['theme'][$path] = TRUE;
  57      $vars['styles'] = drupal_get_css($vars['css']);
  58    }
  59  
  60    // Override logo
  61    $logo = variable_get('color_'. $theme_key .'_logo', NULL);
  62    if ($logo && $vars['logo'] && preg_match('!'. $theme_key .'/logo.png$!', $vars['logo'])) {
  63      $vars['logo'] = base_path() . $logo;
  64    }
  65  }
  66  
  67  /**
  68   * Retrieve the color.module info for a particular theme.
  69   */
  70  function color_get_info($theme) {
  71    $path = drupal_get_path('theme', $theme);
  72    $file = $path .'/color/color.inc';
  73    if ($path && file_exists($file)) {
  74      include $file;
  75      return $info;
  76    }
  77  }
  78  
  79  /**
  80   * Helper function to retrieve the color palette for a particular theme.
  81   */
  82  function color_get_palette($theme, $default = false) {
  83    // Fetch and expand default palette
  84    $fields = array('base', 'link', 'top', 'bottom', 'text');
  85    $info = color_get_info($theme);
  86    $keys = array_keys($info['schemes']);
  87    foreach (explode(',', array_shift($keys)) as $k => $scheme) {
  88      $palette[$fields[$k]] = $scheme;
  89    }
  90  
  91    // Load variable
  92    return $default ? $palette : variable_get('color_'. $theme .'_palette', $palette);
  93  }
  94  
  95  /**
  96   * Form callback. Returns the configuration form.
  97   */
  98  function color_scheme_form($theme) {
  99    $base = drupal_get_path('module', 'color');
 100    $info = color_get_info($theme);
 101  
 102    // Add Farbtastic color picker
 103    drupal_add_css('misc/farbtastic/farbtastic.css', 'module', 'all', FALSE);
 104    drupal_add_js('misc/farbtastic/farbtastic.js');
 105  
 106    // Add custom CSS/JS
 107    drupal_add_css($base .'/color.css', 'module', 'all', FALSE);
 108    drupal_add_js($base .'/color.js');
 109    drupal_add_js(array('color' => array(
 110      'reference' => color_get_palette($theme, true)
 111    )), 'setting');
 112  
 113    // See if we're using a predefined scheme
 114    $current = implode(',', variable_get('color_'. $theme .'_palette', array()));
 115    // Note: we use the original theme when the default scheme is chosen.
 116    $current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : '');
 117  
 118    // Add scheme selector
 119    $info['schemes'][''] = t('Custom');
 120    $form['scheme'] = array(
 121      '#type' => 'select',
 122      '#title' => t('Color set'),
 123      '#options' => $info['schemes'],
 124      '#default_value' => $current,
 125    );
 126  
 127    // Add palette fields
 128    $palette = color_get_palette($theme);
 129    $names = array(
 130      'base' => t('Base color'),
 131      'link' => t('Link color'),
 132      'top' => t('Header top'),
 133      'bottom' => t('Header bottom'),
 134      'text' => t('Text color')
 135    );
 136    $form['palette']['#tree'] = true;
 137    foreach ($palette as $name => $value) {
 138      $form['palette'][$name] = array(
 139        '#type' => 'textfield',
 140        '#title' => $names[$name],
 141        '#default_value' => $value,
 142        '#size' => 8,
 143      );
 144    }
 145    $form['theme'] = array('#type' => 'value', '#value' => arg(4));
 146    $form['info'] = array('#type' => 'value', '#value' => $info);
 147  
 148    return $form;
 149  }
 150  
 151  /**
 152   * Theme color form.
 153   */
 154  function theme_color_scheme_form($form) {
 155    // Include stylesheet
 156    $theme = $form['theme']['#value'];
 157    $info = $form['info']['#value'];
 158    $path = drupal_get_path('theme', $theme) .'/';
 159    drupal_add_css($path . $info['preview_css']);
 160  
 161    // Wrapper
 162    $output .= '<div class="color-form clear-block">';
 163  
 164    // Color schemes
 165    $output .= drupal_render($form['scheme']);
 166  
 167    // Palette
 168    $output .= '<div id="palette" class="clear-block">';
 169    foreach (element_children($form['palette']) as $name) {
 170      $output .= drupal_render($form['palette'][$name]);
 171    }
 172    $output .= '</div>';
 173  
 174    // Preview
 175    $output .= drupal_render($form);
 176    $output .= '<h2>'. t('Preview') .'</h2>';
 177    $output .= '<div id="preview"><div id="text"><h2>Lorem ipsum dolor</h2><p>Sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud <a href="#">exercitation ullamco</a> laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></div><div id="img" style="background-image: url('. base_path() . $path . $info['preview_image'] .')" alt=""></div></div>';
 178  
 179    // Close wrapper
 180    $output .= '</div>';
 181  
 182    return $output;
 183  }
 184  
 185  /**
 186   * Submit handler for color change form.
 187   */
 188  function color_scheme_form_submit($form_id, $values) {
 189    // Get theme coloring info
 190    if (!isset($values['info'])) {
 191      return;
 192    }
 193    $theme = $values['theme'];
 194    $info = $values['info'];
 195  
 196    // Resolve palette
 197    $palette = $values['palette'];
 198    if ($values['scheme'] != '') {
 199      $scheme = explode(',', $values['scheme']);
 200      foreach ($palette as $k => $color) {
 201        $palette[$k] = array_shift($scheme);
 202      }
 203    }
 204  
 205    // Make sure enough memory is available, if PHP's memory limit is compiled in.
 206    if (function_exists('memory_get_usage')) {
 207      // Fetch source image dimensions.
 208      $source = drupal_get_path('theme', $theme) .'/'. $info['base_image'];
 209      list($width, $height) = getimagesize($source);
 210  
 211      // We need at least a copy of the source and a target buffer of the same
 212      // size (both at 32bpp).
 213      $required = $width * $height * 8;
 214      $usage = memory_get_usage();
 215      $limit = parse_size(ini_get('memory_limit'));
 216      if ($usage + $required > $limit) {
 217        drupal_set_message(t('There is not enough memory available to PHP to change this theme\'s color scheme. You need at least %size more. Check the <a href="@url">PHP documentation</a> for more information.', array('%size' => format_size($usage + $required - $limit), '@url' => 'http://www.php.net/manual/en/ini.core.php#ini.sect.resource-limits')), 'error');
 218        return;
 219      }
 220    }
 221  
 222    // Delete old files
 223    foreach (variable_get('color_'. $theme .'_files', array()) as $file) {
 224      @unlink($file);
 225    }
 226    if ($file = dirname($file)) {
 227      @rmdir($file);
 228    }
 229  
 230    // Don't render the default colorscheme, use the standard theme instead.
 231    if (implode(',', color_get_palette($theme, true)) == implode(',', $palette)
 232      || $values['op'] == t('Reset to defaults')) {
 233      variable_del('color_'. $theme .'_palette');
 234      variable_del('color_'. $theme .'_stylesheet');
 235      variable_del('color_'. $theme .'_logo');
 236      variable_del('color_'. $theme .'_files');
 237      variable_del('color_'. $theme .'_screenshot');
 238      return;
 239    }
 240  
 241    // Prepare target locations for generated files
 242    $id = $theme .'-'. substr(md5(serialize($palette) . microtime()), 0, 8);
 243    $paths['color'] = file_directory_path() .'/color';
 244    $paths['target'] = $paths['color'] .'/'. $id;
 245    foreach ($paths as $path) {
 246      file_check_directory($path, FILE_CREATE_DIRECTORY);
 247    }
 248    $paths['target'] = $paths['target'] .'/';
 249    $paths['id'] = $id;
 250    $paths['source'] = drupal_get_path('theme', $theme) .'/';
 251    $paths['stylesheet'] = $paths['target'] .'style.css';
 252    $paths['files'] = $paths['map'] = array();
 253  
 254    // Save palette and stylesheet location
 255    variable_set('color_'. $theme .'_palette', $palette);
 256    variable_set('color_'. $theme .'_stylesheet', $paths['stylesheet']);
 257    variable_set('color_'. $theme .'_logo', $paths['target'] .'logo.png');
 258  
 259    // Copy over neutral images
 260    foreach ($info['copy'] as $file) {
 261      $base = basename($file);
 262      $source = $paths['source'] . $file;
 263      file_copy($source, $paths['target'] . $base);
 264      $paths['map'][$file] = $base;
 265      $paths['files'][] = $paths['target'] . $base;
 266    }
 267  
 268    // Render new images
 269    _color_render_images($theme, $info, $paths, $palette);
 270  
 271    // Rewrite stylesheet
 272    _color_rewrite_stylesheet($theme, $info, $paths, $palette);
 273  
 274    // Maintain list of files
 275    variable_set('color_'. $theme .'_files', $paths['files']);
 276  }
 277  
 278  /**
 279   * Rewrite the stylesheet to match the colors in the palette.
 280   */
 281  function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette) {
 282    // Load stylesheet
 283    $style = file_get_contents($paths['source'] .'style.css');
 284  
 285    // Prepare color conversion table
 286    $conversion = $palette;
 287    unset($conversion['base']);
 288    foreach ($conversion as $k => $v) {
 289      $conversion[$k] = drupal_strtolower($v);
 290    }
 291    $default = color_get_palette($theme, true);
 292  
 293    // Split off the "Don't touch" section of the stylesheet.
 294    list($style, $fixed) = explode("Color Module: Don't touch", $style);
 295  
 296    // Look for @import commands and insert the referenced stylesheets.
 297    $cwd = getcwd();
 298    chdir(drupal_get_path('theme', $theme));
 299    $style = preg_replace_callback('/@import\s*["\']([^"\']+)["\'];/', '_color_import_stylesheet', $style);
 300    chdir($cwd);
 301  
 302    // Find all colors in the stylesheet and the chunks in between.
 303    $style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE);
 304    $is_color = false;
 305    $output = '';
 306    $base = 'base';
 307  
 308    // Iterate over all parts
 309    foreach ($style as $chunk) {
 310      if ($is_color) {
 311        $chunk = drupal_strtolower($chunk);
 312        // Check if this is one of the colors in the default palette
 313        if ($key = array_search($chunk, $default)) {
 314          $chunk = $conversion[$key];
 315        }
 316        // Not a pre-set color. Extrapolate from the base.
 317        else {
 318          $chunk = _color_shift($palette[$base], $default[$base], $chunk, $info['blend_target']);
 319        }
 320      }
 321      else {
 322        // Determine the most suitable base color for the next color.
 323  
 324        // 'a' declarations. Use link.
 325        if (preg_match('@[^a-z0-9_-](a)[^a-z0-9_-][^/{]*{[^{]+$@i', $chunk)) {
 326          $base = 'link';
 327        }
 328        // 'color:' styles. Use text.
 329        else if (preg_match('/(?<!-)color[^{:]*:[^{#]*$/i', $chunk)) {
 330          $base = 'text';
 331        }
 332        // Reset back to base.
 333        else {
 334          $base = 'base';
 335        }
 336      }
 337      $output .= $chunk;
 338      $is_color = !$is_color;
 339    }
 340    // Append fixed colors segment
 341    $output .= $fixed;
 342  
 343    // Replace paths to images
 344    foreach ($paths['map'] as $before => $after) {
 345      $output = str_replace($before, $after, $output);
 346    }
 347  
 348    // Write new stylesheet
 349    $file = fopen($paths['stylesheet'], 'w+');
 350    fwrite($file, $output);
 351    fclose($file);
 352    $paths['files'][] = $paths['stylesheet'];
 353  
 354    // Set standard file permissions for webserver-generated files
 355    @chmod($paths['stylesheet'], 0664);
 356  }
 357  
 358  /**
 359   * Helper function for _color_rewrite_stylesheet.
 360   */
 361  function _color_import_stylesheet($matches) {
 362    return preg_replace('/url\(([\'"]?)(?![a-z]+:)/i', 'url(\1'. dirname($matches[1]) .'/', file_get_contents($matches[1]));
 363  }
 364  
 365  /**
 366   * Render images that match a given palette.
 367   */
 368  function _color_render_images($theme, &$info, &$paths, $palette) {
 369  
 370    // Prepare template image.
 371    $source = $paths['source'] .'/'. $info['base_image'];
 372    $source = imagecreatefrompng($source);
 373    $width = imagesx($source);
 374    $height = imagesy($source);
 375  
 376    // Prepare target buffer.
 377    $target = imagecreatetruecolor($width, $height);
 378    imagealphablending($target, true);
 379  
 380    // Fill regions of solid color.
 381    foreach ($info['fill'] as $color => $fill) {
 382      imagefilledrectangle($target, $fill[0], $fill[1], $fill[0] + $fill[2], $fill[1] + $fill[3], _color_gd($target, $palette[$color]));
 383    }
 384  
 385    // Render gradient.
 386    for ($y = 0; $y < $info['gradient'][3]; ++$y) {
 387      $color = _color_blend($target, $palette['top'], $palette['bottom'], $y / ($info['gradient'][3] - 1));
 388      imagefilledrectangle($target, $info['gradient'][0], $info['gradient'][1] + $y, $info['gradient'][2], $info['gradient'][1] + $y + 1, $color);
 389    }
 390  
 391    // Blend over template.
 392    imagecopy($target, $source, 0, 0, 0, 0, $width, $height);
 393  
 394    // Clean up template image.
 395    imagedestroy($source);
 396  
 397    // Cut out slices.
 398    foreach ($info['slices'] as $file => $coord) {
 399      list($x, $y, $width, $height) = $coord;
 400      $base = basename($file);
 401      $image = $paths['target'] . $base;
 402  
 403      // Cut out slice.
 404      if ($file == 'screenshot.png') {
 405        $slice = imagecreatetruecolor(150, 90);
 406        imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height);
 407        variable_set('color_'. $theme .'_screenshot', $image);
 408      }
 409      else {
 410        $slice = imagecreatetruecolor($width, $height);
 411        imagecopy($slice, $target, 0, 0, $x, $y, $width, $height);
 412      }
 413  
 414      // Save image.
 415      imagepng($slice, $image);
 416      imagedestroy($slice);
 417      $paths['files'][] = $image;
 418  
 419      // Set standard file permissions for webserver-generated files
 420      @chmod(realpath($image), 0664);
 421  
 422      // Build before/after map of image paths.
 423      $paths['map'][$file] = $base;
 424    }
 425  
 426    // Clean up target buffer.
 427    imagedestroy($target);
 428  }
 429  
 430  /**
 431   * Shift a given color, using a reference pair and a target blend color.
 432   *
 433   * Note: this function is significantly different from the JS version, as it
 434   * is written to match the blended images perfectly.
 435   *
 436   * Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction delta
 437   *              then (return == target + (given - target) * delta)
 438   *
 439   * Loose constraint: Preserve relative positions in saturation and luminance
 440   *                   space.
 441   */
 442  function _color_shift($given, $ref1, $ref2, $target) {
 443  
 444    // We assume that ref2 is a blend of ref1 and target and find
 445    // delta based on the length of the difference vectors:
 446  
 447    // delta = 1 - |ref2 - ref1| / |white - ref1|
 448    $target = _color_unpack($target, true);
 449    $ref1 = _color_unpack($ref1, true);
 450    $ref2 = _color_unpack($ref2, true);
 451    for ($i = 0; $i < 3; ++$i) {
 452      $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]);
 453      $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]);
 454    }
 455    $delta = ($denominator > 0) ? (1 - sqrt($numerator / $denominator)) : 0;
 456  
 457    // Calculate the color that ref2 would be if the assumption was true.
 458    for ($i = 0; $i < 3; ++$i) {
 459      $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta;
 460    }
 461  
 462    // If the assumption is not true, there is a difference between ref2 and ref3.
 463    // We measure this in HSL space. Notation: x' = hsl(x).
 464    $ref2 = _color_rgb2hsl($ref2);
 465    $ref3 = _color_rgb2hsl($ref3);
 466    for ($i = 0; $i < 3; ++$i) {
 467      $shift[$i] = $ref2[$i] - $ref3[$i];
 468    }
 469  
 470    // Take the given color, and blend it towards the target.
 471    $given = _color_unpack($given, true);
 472    for ($i = 0; $i < 3; ++$i) {
 473      $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta;
 474    }
 475  
 476    // Finally, we apply the extra shift in HSL space.
 477    // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0.
 478    $result = _color_rgb2hsl($result);
 479    for ($i = 0; $i < 3; ++$i) {
 480      $result[$i] = min(1, max(0, $result[$i] + $shift[$i]));
 481    }
 482    $result = _color_hsl2rgb($result);
 483  
 484    // Return hex color.
 485    return _color_pack($result, true);
 486  }
 487  
 488  /**
 489   * Convert a hex triplet into a GD color.
 490   */
 491  function _color_gd($img, $hex) {
 492    $c = array_merge(array($img), _color_unpack($hex));
 493    return call_user_func_array('imagecolorallocate', $c);
 494  }
 495  
 496  /**
 497   * Blend two hex colors and return the GD color.
 498   */
 499  function _color_blend($img, $hex1, $hex2, $alpha) {
 500    $in1 = _color_unpack($hex1);
 501    $in2 = _color_unpack($hex2);
 502    $out = array($img);
 503    for ($i = 0; $i < 3; ++$i) {
 504      $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha;
 505    }
 506    return call_user_func_array('imagecolorallocate', $out);
 507  }
 508  
 509  /**
 510   * Convert a hex color into an RGB triplet.
 511   */
 512  function _color_unpack($hex, $normalize = false) {
 513    if (strlen($hex) == 4) {
 514      $hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3];
 515    }
 516    $c = hexdec($hex);
 517    for ($i = 16; $i >= 0; $i -= 8) {
 518      $out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1);
 519    }
 520    return $out;
 521  }
 522  
 523  /**
 524   * Convert an RGB triplet to a hex color.
 525   */
 526  function _color_pack($rgb, $normalize = false) {
 527    foreach ($rgb as $k => $v) {
 528      $out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8));
 529    }
 530    return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
 531  }
 532  
 533  /**
 534   * Convert a HSL triplet into RGB
 535   */
 536  function _color_hsl2rgb($hsl) {
 537    $h = $hsl[0];
 538    $s = $hsl[1];
 539    $l = $hsl[2];
 540    $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s;
 541    $m1 = $l * 2 - $m2;
 542    return array(_color_hue2rgb($m1, $m2, $h + 0.33333),
 543                 _color_hue2rgb($m1, $m2, $h),
 544                 _color_hue2rgb($m1, $m2, $h - 0.33333));
 545  }
 546  
 547  /**
 548   * Helper function for _color_hsl2rgb().
 549   */
 550  function _color_hue2rgb($m1, $m2, $h) {
 551    $h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h);
 552    if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6;
 553    if ($h * 2 < 1) return $m2;
 554    if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6;
 555    return $m1;
 556  }
 557  
 558  /**
 559   * Convert an RGB triplet to HSL.
 560   */
 561  function _color_rgb2hsl($rgb) {
 562    $r = $rgb[0];
 563    $g = $rgb[1];
 564    $b = $rgb[2];
 565    $min = min($r, min($g, $b));
 566    $max = max($r, max($g, $b));
 567    $delta = $max - $min;
 568    $l = ($min + $max) / 2;
 569    $s = 0;
 570    if ($l > 0 && $l < 1) {
 571      $s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l));
 572    }
 573    $h = 0;
 574    if ($delta > 0) {
 575      if ($max == $r && $max != $g) $h += ($g - $b) / $delta;
 576      if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta);
 577      if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta);
 578      $h /= 6;
 579    }
 580    return array($h, $s, $l);
 581  }


Généré le : Fri Nov 30 16:20:15 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics