/[drupal]/contributions/modules/css/css.module
ViewVC logotype

Diff of /contributions/modules/css/css.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph | View Patch Patch

revision 1.3, Sun Nov 2 15:16:09 2008 UTC revision 1.4, Fri Dec 26 15:20:36 2008 UTC
# Line 1  Line 1 
1  <?php  <?php
2  // $Id: css.module,v 1.1.2.3 2006/05/15 18:39:51 fax8 Exp $  // $Id: $
3    
4  /**  /**
5   * @file   * @file
# Line 9  Line 9 
9   * @author Fabio Varesano <fvaresano at yahoo dot it>   * @author Fabio Varesano <fvaresano at yahoo dot it>
10   * @updated to Drupal 5 by Christopher Skauss <christopher skauss at gmail dot com>   * @updated to Drupal 5 by Christopher Skauss <christopher skauss at gmail dot com>
11   * @modified drupal 5 Version by Whispero   * @modified drupal 5 Version by Whispero
12     * @updated for Drupal 6 by Joshua Chan <josh at joshuachan dot ca>
13   *   *
14   * To store this extra information, we need an auxiliary database table.   * To store this extra information, we need an auxiliary database table.
15   *   *
# Line 36  function css_help($section) { Line 37  function css_help($section) {
37  /**  /**
38   * Implementation of hook_menu()   * Implementation of hook_menu()
39   */   */
40  function css_menu($may_cache) {  function css_menu() {
41    $items = array();    $items = array();
42    if ($may_cache) {    // defines the callback for getting the css file. we use
43      // defines the callback for getting the css file. we use    // css/get as path instead of only css to avoid that in some
44      // css/get as path instead of only css to avoid that in some    // installs users have yet a directory called css
45      // installs users have yet a directory called css    $items['css/get'] = array(
46      $items[] = array('path' => 'css/get', 'title' => t('css'),      'title' => 'css',
47                       'access' => user_access('access content'),      'path' => 'css/get',
48                       'type' => MENU_CALLBACK,      'page callback' => 'css_get',
49                       'callback' => 'css_get');      'access arguments' => array('access content'),
50    }      'type' => MENU_CALLBACK,
51      );
52    return $items;    return $items;
53  }  }
54    
# Line 60  function css_perm() { Line 62  function css_perm() {
62  /**  /**
63   * Implemenation of hook_form_alter()   * Implemenation of hook_form_alter()
64   */   */
65  function css_form_alter($form_id, &$form) {  function css_form_alter(&$form, $form_state, $form_id) {
66    //Add a text area to the form where users will put their csses rules.    //Add a text area to the form where users will put their csses rules.
67    if (user_access('create css for nodes') && variable_get('css__'.$form['#node']->type, FALSE)) {    if (user_access('create css for nodes') && variable_get('css__'.$form['#node']->type, FALSE)) {
68      if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {      if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
# Line 72  function css_form_alter($form_id, &$form Line 74  function css_form_alter($form_id, &$form
74            '#default_value' => $node->css_css,            '#default_value' => $node->css_css,
75            '#cols' => 60,            '#cols' => 60,
76            '#rows' => 10,            '#rows' => 10,
77            '#description' => t('Insert here the css rules for this node. You can use css defined for other nodes using @import "css/get/x" where x is the node identification number.'),            '#description' => t('Insert here the css rules for this node. You can use css defined for other nodes using <em>@import "?q=css/get/x";</em> where x is the identification number of the node which contains the css you want to use.'),
78            '#attributes' => NULL,            '#attributes' => NULL,
79            '#required' => FALSE,            '#required' => FALSE,
80        );        );
# Line 90  function css_form_alter($form_id, &$form Line 92  function css_form_alter($form_id, &$form
92    }    }
93  }  }
94    
   
95  /**  /**
96   * Implementation of hook_nodeapi().   * Implementation of hook_nodeapi().
97   */   */
98  function css_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {  function css_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
99    if (variable_get('css_'. $node->type, TRUE)) { // check that CSS editing is enabled for the given node type    static $prev_op = NULL;
100    
101      if (variable_get('css__'. $node->type, FALSE)) { // check that CSS editing is enabled for the given node type
102      switch ($op) {      switch ($op) {
103    
104        // Controls for valid input data        // Controls for valid input data
105        case 'validate':        case 'validate':
106          ;//do some input check here..          // Check for potentially malicious tags
107            $pattern = '~<\s*\/?\s*(style|script|meta)\s*.*?>~i';
108            if (preg_match($pattern, $node->css_css)) {
109              form_set_error('css_css', t('Please do not include any tags.'));
110            }
111          break;          break;
112    
113        // Now that the form has been properly completed, it is time to commit the new        // Now that the form has been properly completed, it is time to commit the new
114        // data to the database.        // data to the database.
115        case 'insert':        case 'insert':
116          db_query('INSERT INTO {css} (nid, css) VALUES (%d, "%s")', $node->nid, $node->css_css);          if (!empty($node->css_css)) {
117              db_query("INSERT INTO {css} (nid, css) VALUES (%d, '%s')", $node->nid, $node->css_css);
118            }
119          break;          break;
120    
121        // If the form was called to edit an existing node rather than create a new        // If the form was called to edit an existing node rather than create a new
122        // one, this operation gets called instead. We use a DELETE then INSERT rather        // one, this operation gets called instead. We use a DELETE then INSERT rather
123        // than an UPDATE just in case the rating didn't exist for some reason.        // than an UPDATE just in case the rating didn't exist for some reason.
124        case 'update':        case 'update':
125          db_query('DELETE FROM {css} WHERE nid = %d', $node->nid);          db_query("DELETE FROM {css} WHERE nid = %d", $node->nid);
126          db_query('INSERT INTO {css} (nid, css) VALUES (%d, "%s")', $node->nid, $node->css_css);          if (!empty($node->css_css)) {
127              db_query("INSERT INTO {css} (nid, css) VALUES (%d, '%s')", $node->nid, $node->css_css);
128            }
129          break;          break;
130    
131        // If the node is being deleted, we need this opportunity to clean up after        // If the node is being deleted, we need this opportunity to clean up after
# Line 134  function css_nodeapi(&$node, $op, $tease Line 145  function css_nodeapi(&$node, $op, $tease
145        // filters transform user-supplied content, whereas we are extending it with        // filters transform user-supplied content, whereas we are extending it with
146        // additional information.        // additional information.
147        case 'view':        case 'view':
148          theme('css_import', $node->nid);          if ($prev_op == 'validate') {
149              // 'validate' immediately followed by 'view' means this is a preview
150              if ($node->css_css) {
151                $css = '<style type="text/css" media="all"> '.
152                       css_sanitize($node->css_css, 'preview').
153                       ' </style>';
154                drupal_set_html_head($css, 'preview');
155              }
156            } else {
157              // Drupal 6 seems to check for the physical existence of CSS files
158              // before allowing them to be added. We have to include the virtual
159              // CSS file manually since it does not really exist.
160              if (!empty($node->css_css)) {
161                $link = url('css/get/'.$node->nid);
162                drupal_add_link(array(
163                  'type' => 'text/css',
164                  'rel' => 'stylesheet',
165                  'media' => 'all',
166                  'href' => $link,
167                ));
168              }
169            }
170          break;          break;
171      }      }
172    
173        $prev_op = $op; // used to determine Preview state
174    }    }
175  }  }
176    
177  /**  /**
178   * Return the css attached to the node   * Return the css attached to the node.
179   * Last-Modified header is set to let browsers cache the css.   * Last-Modified header is set to let browsers cache the css.
180   */   */
181  function css_get($nid = 0) {  function css_get($nid = 0) {
182    if (is_numeric($nid) && $nid > 0) {    if (is_numeric($nid) && $nid > 0) {
183      $object = db_fetch_object(db_query('SELECT css, changed FROM {css} c, {node} n WHERE n.nid = %d AND n.nid = c.nid', $nid));      $object = db_fetch_object(db_query('SELECT css, changed FROM {css} c, {node} n WHERE n.nid = %d AND n.nid = c.nid', $nid));
184      if($object) {      if ($object) {
185        $date = gmdate('D, d M Y H:i:s', $object->changed) .' GMT';        $date = gmdate('D, d M Y H:i:s', $object->changed) .' GMT';
186        header("Last-Modified: $date");        header("Last-Modified: $date");
187        drupal_set_header('Content-Type: text/css; charset=utf-8');        drupal_set_header('Content-Type: text/css; charset=utf-8');
188        print($object->css);        print(css_sanitize($object->css));
189      }      }
190    }    }
191  }  }
192    
193  /**  /**
194   * Adds @import for the css in the head tag of page   * Remove harmful code from CSS.
195   * We use a theme function for this to let themers able   */
196   * to customize the behaviour of importing.  function css_sanitize($css, $type = 'view') {
197   */    switch ($type) {
198  function theme_css_import($nid) {      case 'view':
199    // let's link the CSS file to the HTML:        // Are there any security vulnerabilites from external CSS files?
200    //   we use $path = '?q=css/get/' . $nid as without ?q= the hook would be called only when clean urls are enabled (mod_rewrite active)        break;
201    //   we use $type = theme as we want to be parsed after module rules, so that we can override module defined rules  
202    //   we use $preprocess = FALSE as we don't want to cache the CSS rules.      case 'preview':
203    drupal_add_css('?q=css/get/' . $nid, 'theme', 'all', FALSE);        // Catch potentially malicious code
204          $patterns = array(
205            '~<\s*(/?)\s*(style|script|meta)\s*>~i',
206          );
207          $css = preg_replace($patterns, '<$1FILTERED $2>', $css);
208          break;
209    
210        default:
211          $css = '';
212          break;
213      }
214    
215      return $css;
216  }  }

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

  ViewVC Help
Powered by ViewVC 1.1.2