--- css_injector.module.old 2008-08-09 20:56:58.000000000 -0500 +++ css_injector.module 2009-04-17 13:30:56.176761200 -0500 @@ -96,7 +96,7 @@ function css_injector_theme() { * Implementation of hook_perm(). */ function css_injector_perm() { - return array('administer css injection'); + return array('administer css injection', 'edit css'); } /** @@ -126,6 +126,17 @@ function _css_injector_load_rule($crid = } } + +/** + * Helper function to load all CSS injection rule for a node. + */ +function _css_injector_load_node_rule($nid = NULL) { + $rules = array(); + $results = db_query("SELECT r.* FROM {css_injector_rule} r INNER JOIN {css_injector_node} n ON n.nid=%d AND n.crid=r.crid", $nid); + $rule = db_fetch_array($results); + return $rule; +} + /** * Helper function to delete an existing rule and its accompanying file. */ @@ -133,6 +144,7 @@ function _css_injector_delete_rule($crid if ($rule = _css_injector_load_rule($crid)) { file_delete(file_create_path($rule['file_path'])); db_query("DELETE FROM {css_injector_rule} WHERE crid = %d", $crid); + db_query("DELETE FROM {css_injector_node} WHERE crid = %d", $crid); } } @@ -164,3 +176,157 @@ function _css_injector_evaluate_rule($cs } return $page_match; } + + + +/** + * Implementation of hook_form_alter(). + */ +function css_injector_form_alter(&$form, $form_state, $form_id) { + if ($form_id == 'node_type_form') { + $form['css_injector'] = array( + '#type' => 'fieldset', + '#title' => t('CSS'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => 32 + ); + $form['css_injector']['css_injector_use'] = array( + '#type' => 'checkbox', + '#title' => t('Allow per-node CSS editing for this content type'), + '#default_value' => variable_get('css_injector_use_'. $form['#node_type']->type, FALSE), + '#description' => t("Only users with 'edit css' permission will see this fieldset") . '
' . t("Please note: Creative individuals can use CSS to execute code on a client's browser, by injecting JS snippets in place of images and so on. Treat the 'Administer CSS Injector' permission carefully, as you would any other sensitive administrative tool; allowing untrusted individuals to use it is a security risk.") . '' + + ); + } + elseif (isset($form['#node']) && $form['#node']->type .'_node_form' == $form_id && is_css_injector($form['#node'])) { + // Customize the redirect target and buttons of our own node forms. + $form['css_injector'] = array( + '#type' => 'fieldset', + '#title' => t('CSS'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + '#weight' => 32 + ); + $rule = _css_injector_load_node_rule($form['nid']['#value']); + $rule['css_text'] = file_get_contents($rule['file_path']); + + $form['css_injector']['css_injector_code'] = array( + '#type' => 'textarea', + '#title' => t('CSS Code'), + '#default_value' => $rule['css_text'], + '#description' => t("Do not include <style> tag"), + ); + $form['css_injector']['css_media'] = array( + '#type' => 'select', + '#title' => t('Media'), + '#description' => t(''), + '#options' => array('all' => t('All'), 'screen' => t('Screen'), 'print' => t('Print')), + '#default_value' => $rule['media'], + ); + $form['css_injector']['css_preprocess'] = array( + '#type' => 'checkbox', + '#title' => t('Preprocess CSS'), + '#description' => t(''), + '#default_value' => $rule['preprocess'], + ); + + $form['css_injector']['css_crid'] = array( + '#type' => 'hidden', + '#value' => $rule['crid'], + ); + $form['css_injector']['css_file_path'] = array( + '#type' => 'hidden', + '#value' => $rule['file_path'], + ); + } +} + +/** + * Implementation of hook_node_type(). + * Rename or delete the settings variable if a type changes. + */ +function css_injector_node_type($op, $info) { + switch ($op) { + case 'delete': + variable_del('css_injector_use_'. $info->type); + break; + case 'update': + if (!empty($info->old_type) && $info->old_type != $info->type) { + if (is_css_injector($info->old_type)) { + $settings = variable_get('content_profile_'. $info->old_type, array()); + variable_del('css_injector_use_'. $info->old_type); + variable_set('css_injector_use_'. $info->type, 1); + } + } + break; + } +} + +/* + * Determine if a given node has CSS injection. + * @param $type + * The node object or the node's type + */ +function is_css_injector($type) { + if (is_object($type)) { + $type = $type->type; + } + return variable_get('css_injector_use_'. $type, FALSE); +} + + +/** + * Implementation of hook_nodeapi(). + */ +function css_injector_nodeapi(&$node, $op, $a3 = NULL, $a4 = NULL) { + switch ($op) { + case 'delete': + $rid = db_fetch_object(db_query("SELECT * FROM {css_injector_node} WHERE nid=%d", $node->nid)); + _css_injector_delete_rule($rid->crid); + break; + case 'insert': + if (isset($node->css_injector_code) && user_access('edit css')) { + $rule = array( + 'title' => 'node-' . $node->nid, + 'rule_type' => 1, + 'rule_conditions' => 'node/' . $node->nid, + 'media' => $node->css_media, + 'preprocess' => $node->css_preprocess, + 'css_text' => $node->css_injector_code, + ); + drupal_write_record('css_injector_rule', $rule); + $directory = file_directory_path(); + $rule['file_path'] = file_create_path($directory .'/css_injector_'. $rule['crid'] .'.css'); + db_query('INSERT INTO {css_injector_node} (nid, crid) VALUES (%d, %d)', $node->nid, $rule['crid']); + drupal_write_record('css_injector_rule', $rule, array('crid')); + file_save_data($rule['css_text'], file_create_path($rule['file_path']), FILE_EXISTS_REPLACE); + _css_injector_load_rule(NULL, TRUE); + } + break; + case 'update': + if (isset($node->css_injector_code) && user_access('edit css')) { + $rule = array( + 'title' => 'node-' . $node->nid, + 'rule_type' => 1, + 'rule_conditions' => 'node/' . $node->nid, + 'media' => $node->css_media, + 'preprocess' => $node->css_preprocess, + 'css_text' => $node->css_injector_code, + ); + if (!$node->css_crid) { + drupal_write_record('css_injector_rule', $rule); + $directory = file_directory_path(); + $rule['file_path'] = file_create_path($directory .'/css_injector_'. $rule['crid'] .'.css'); + db_query('INSERT INTO {css_injector_node} (nid, crid) VALUES (%d, %d)', $node->nid, $rule['crid']); + } else { + $rule['crid'] = $node->css_crid; + $rule['file_path'] = $node->css_file_path; + } + drupal_write_record('css_injector_rule', $rule, array('crid')); + file_save_data($rule['css_text'], file_create_path($rule['file_path']), FILE_EXISTS_REPLACE); + _css_injector_load_rule(NULL, TRUE); + } + break; + } +}