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

Contents of /contributions/modules/htmLawed/htmLawed.module

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


Revision 1.11 - (show annotations) (download) (as text)
Mon Mar 23 02:47:33 2009 UTC (8 months ago) by patnaik
Branch: MAIN
CVS Tags: HEAD
Changes since 1.10: +101 -74 lines
File MIME type: text/x-php
Many changes so it works in the March 20 D7 dev release
1 <?php
2 // $Id: htmLawed.module,v 1.8.2.2 2008/07/03 01:28:14 patnaik Exp $
3
4 // Drupal 7 htmLawed module
5 // GPL v3 license
6 // Copyright Santosh Patnaik, MD, PhD
7 // Since May 2008
8
9 /*
10 * The module_comment hook is used for 'save' for 'Comment'
11 * Calls _htmLawed_process() to filter data before it is stored
12 * As this is for 'save', we don't care that there will be no filtering if node's content-type-settings are unavailable
13 * Other filtering in htmLawed_node_rss_item(), htmLawed_node_presave(), htmLawed_filter() and htmLawed_nodeapi()
14 */
15 function htmLawed_comment(&$comment, $op) {
16 $config = 0;
17 if($op == 'insert' or $op == 'update') {
18 $node_format = $comment['format'];
19 $filters = array_keys(filter_list_format($node_format));
20 if(in_array('htmLawed/0', $filters) and !empty($comment['comment'])) {
21 // Check setting
22 $setting = variable_get('htmLawed_format_'. $node_format, 0);
23 if(!is_array($setting)) {
24 return;
25 }
26 $def_setting = isset($setting['htmLawedDef']['Comment']) ? $setting['htmLawedDef']['Comment'] : array('config'=>"'safe'=>1, 'elements'=>'a, em, strong, cite, code, ol, ul, li, dl, dt, dd', 'deny_attribute'=>'id, style'",'spec'=>'');
27 $node_type = db_fetch_object(db_query('SELECT type AS type FROM {node} WHERE nid = %d', $comment['nid']))->type;
28 $setting = isset($setting[$node_type]['Comment']) ? $setting[$node_type]['Comment'] : array();
29 if(!empty($setting['save'])) {
30 $setting = !empty($setting['default']) ? $def_setting : $setting;
31 eval('$config = array('. $setting['config']. ');');
32 // Filter & save this way as hook_comment is unfortunately called AFTER database insertion
33 if(is_array($config)) {
34 // Preserve PHP code
35 $htmLawed_hook_parameter = (in_array('php/0', $filters) && strpos($comment['comment'], '<?') !== FALSE) ? 'save_php' : 0;
36 db_query("UPDATE {comments} SET comment = '%s' WHERE cid = %d", _htmLawed_process($comment['comment'], $config, $setting['spec'], $htmLawed_hook_parameter), $comment['cid']);
37 }
38 }
39 }
40 }
41 }
42
43 /*
44 * Delete settings for extinct input formats
45 * Also see htmLawed_uninstall() in htmLawed.install, and htmLawed_node_type()
46 */
47 function htmLawed_cron() {
48 $setting_rows = db_query("SELECT name AS name FROM {variable} WHERE name LIKE 'htmLawed_format_%'");
49 while($row = db_fetch_object($setting_rows)) {
50 $format = substr($row->name, 16);
51 if(db_fetch_object(db_query('SELECT COUNT(name) AS count FROM {filter_format} WHERE format = %d', $format))->count < 1) {
52 variable_del('htmLawed_format_'. $format);
53 drupal_set_message(t('Variable %htmLawed_format_num storing specific htmLawed settings for a non-existing text format was deleted from the database.', array('%htmLawed_format_num' => "htmLawed_format_$format")));
54 }
55 }
56 }
57
58 /*
59 * The module_filter hook; for 'show'
60 * Other filtering in htmLawed_node_rss_item(), htmLawed_node_presave(), htmLawed_comment() and htmLawed_nodeapi()
61 */
62 function htmLawed_filter($op, $delta = 0, $format = -1, $text = '') {
63 switch ($op) {
64 case 'list':
65 return array(0 => t('htmLawed (X)HTML filter/purifier'));
66 case 'no cache':
67 return FALSE;
68 case 'description':
69 return t('Restrict HTML markup as well as make content more secure, and standards- and admin-compliant.');
70 case 'prepare':
71 return $text;
72 case 'process':
73 // htmLawed_help() should use similar logic
74 $setting = variable_get('htmLawed_format_'. $format, 0);
75 if(!is_array($setting)){
76 return $text;
77 }
78
79 $node_id = $node_type = NULL;
80 $for = 'Other';
81 // Comment
82 if(arg(0) == 'comment') {
83 $for = 'Comment';
84 if(arg(1) == 'reply') {
85 $node_id = arg(2);
86 }
87 elseif(arg(1) == 'edit') {
88 $comment_id = arg(2);
89 $node_id = db_fetch_object(db_query('SELECT nid AS nid FROM {comments} WHERE cid = %d', $comment_id))->nid;
90 }
91 }
92 // Body, extra fields because of CCK, etc.
93 elseif(arg(0) == 'node') {
94 $for = 'Body';
95 if(arg(1) == 'add') {
96 $node_type = arg(2);
97 }
98 elseif(is_numeric(arg(1))) {
99 $node_id = arg(1);
100 }
101 }
102
103 // Content-type
104 if($node_id) {
105 $node_type = db_fetch_object(db_query('SELECT type AS type FROM {node} WHERE nid = %d', $node_id))->type;
106 }
107
108 // Right settings
109 $def_setting = isset($setting['htmLawedDef'][$for]) ? $setting['htmLawedDef'][$for] : array('show'=>1, 'config'=>"'safe'=>1, 'elements'=>'a, em, strong, cite, code, ol, ul, li, dl, dt, dd', 'deny_attribute'=>'id, style'",'spec'=>'');
110 if($node_type) {
111 $setting = isset($setting[$node_type][$for]) ? $setting[$node_type][$for] : $def_setting;
112 }
113 else {
114 $setting = $def_setting;
115 }
116
117 if(!empty($setting['show'])) {
118 $config = 0;
119 $setting = !empty($setting['default']) ? $def_setting : $setting;
120 // Filter by calling _htmLawed_process
121 eval('$config = array('. $setting['config']. ');');
122 if(!is_array($config)) {
123 return $text;
124 }
125 return _htmLawed_process($text, $config, $setting['spec']);
126 }
127
128 return $text;
129 break;
130
131 // Shows sub-forms on the pages for configuring input formats; _htmLawed_store_setting() will save the submitted data
132 case 'settings':
133 // Same key as in htmLawed_perm()
134 if(!user_access('administer htmLawed (X)HTML filter/purifier')) {
135 break;
136 }
137
138 // Default & content-type-specific settings to pre-fill sub-forms
139 $content_types = array();
140 $content_types['htmLawedDef'] = t('Default');
141 $content_types += node_get_types('names');
142
143 $help = l(t('(?)'), 'admin/help/htmLawed', array('title'=>t('help')));
144 $subform_count = 0;
145
146 $setting = variable_get('htmLawed_format_'. $format, array());
147
148 $form['htmLawed'] = array(
149 '#type' => 'fieldset',
150 '#title' => t('htmLawed (X)HTML filter/purifier'),
151 '#collapsible' => TRUE,
152 );
153
154 foreach($content_types as $k=>$v) {
155 // Default values
156 if(!isset($setting[$k]) or !is_array($setting[$k])) {
157 foreach(array('Body', 'Comment', 'Other', 'RSS') as $for) {
158 if($for == 'Other' and $k != 'htmLawedDef') {
159 continue;
160 }
161 $val[$for] = array('config'=>"'safe'=>1, 'elements'=>'a, em, strong, cite, code, ol, ul, li, dl, dt, dd". ($for == 'RSS' ? ', br, p' : ''). "', 'deny_attribute'=>'id, style'", 'spec'=>'', 'help'=>'Tags allowed: a, em, strong, cite, code, ol, ul, li, dl, dt, dd'. ($for == 'RSS' ? ', br, p' : ''));
162 if($k != 'htmLawedDef') {
163 if($for != 'RSS') {
164 $val[$for]['save'] = 0;
165 $val[$for]['show'] = 1;
166 }
167 else {
168 $val[$for]['show'] = 0;
169 }
170 $val[$for]['default'] = 1;
171 }
172 elseif($for == 'Other') {
173 $val[$for]['show'] = 1;
174 }
175 }
176 $setting[$k] = $val;
177 }
178
179 $my_k = 'htmLawed_'. $k;
180
181 $form['htmLawed'][$my_k] = array(
182 '#type' => 'fieldset',
183 '#title' => $v,
184 '#collapsible' => TRUE,
185 '#collapsed' => !$subform_count ? FALSE : TRUE,
186 '#description' => !$subform_count ? t('Generic settings; content-type-specific values can be set <a href="!below">further below</a>.', array('!below'=>'#htmLawed_specific_point')). '<a id="htmLawed_default_point"></a> <small>'. "$help</small>" : NULL,
187 );
188
189 foreach(array('Body', 'Comment', 'Other', 'RSS') as $for) {
190 if($for == 'Other' and $k != 'htmLawedDef') {
191 continue;
192 }
193
194 $my_for = $my_k. '_'. $for;
195
196 $form['htmLawed'][$my_k][$my_for] = array(
197 '#type' => 'fieldset',
198 '#title' => t(($for == 'RSS' ? 'Teaser' : $for)),
199 '#collapsible' => TRUE,
200 '#collapsed' => TRUE,
201 '#theme' => 'htmLawed_tabled_subform',
202 );
203
204 if($k != 'htmLawedDef') {
205 $form['htmLawed'][$my_k][$my_for][$my_for. '_guide'] = array(
206 '#type' => 'markup',
207 '#value' => '<p><small>'. t('For content-type %type, ', array('%type'=>$v)). ($for == 'Body' ? t('for main body') : ($for == 'RSS' ? t('for teasers and newsfeed items; the filtering will be additional to any done for <em>Body</em>') : t('for any user comment'))). " $help</small></p>",
208 );
209 $form['htmLawed'][$my_k][$my_for][$my_for. '_show'] = array(
210 '#type' => 'checkbox',
211 '#title' => t('Enable'),
212 '#default_value' => $setting[$k][$for]['show'],
213 '#description' => t('Filter content during page-display'),
214 );
215 if($for != 'RSS') {
216 $form['htmLawed'][$my_k][$my_for][$my_for. '_save'] = array(
217 '#type' => 'checkbox',
218 '#title' => t('Enable for <em>save</em>'),
219 '#default_value' => $setting[$k][$for]['save'],
220 '#description' => t('Filter submitted content before saving'),
221 );
222 }
223 $form['htmLawed'][$my_k][$my_for][$my_for. '_default'] = array(
224 '#type' => 'checkbox',
225 '#title' => t('Use the <a href="!default">Default</a> values', array('!default'=>'#htmLawed_default_point')),
226 '#default_value' => $setting[$k][$for]['default'],
227 '#description' => t('For <em>Config.</em>, <em>Help</em> and <em>Spec.</em>'),
228 );
229 }
230 else {
231 $form['htmLawed'][$my_k][$my_for][$my_for. '_guide'] = array(
232 '#type' => 'markup',
233 '#value' => '<p><small>'. t('Default settings for <em>Config.</em>, <em>Help</em> and <em>Spec.</em> for use with ', array('%type'=>$v)). ($for == 'Body' ? t('main body') : ($for == 'RSS' ? t('teasers and newsfeed items; the filtering will be additional to any done for <em>Body</em>') : ($for == 'Other' ? t('other cases not based on content-type (like a <em>header</em> field seen with the <em>Views</em> module. There are obviously no content-type-specific settings.') : t('any user comment')))). " $help</small></p>",
234 );
235 if($for == 'Other') {
236 $form['htmLawed'][$my_k][$my_for][$my_for. '_show'] = array(
237 '#type' => 'checkbox',
238 '#title' => t('Enable'),
239 '#default_value' => $setting[$k][$for]['show'],
240 '#description' => t('Filter content before showing'),
241 );
242 }
243 }
244
245 $form['htmLawed'][$my_k][$my_for][$my_for. '_config'] = array(
246 '#type' => 'textarea',
247 '#rows' => '3',
248 '#title' => t('Config.'),
249 '#default_value' => $setting[$k][$for]['config'],
250 '#description' => t('Comma-separated, quoted key-value pairs'),
251 );
252 $form['htmLawed'][$my_k][$my_for][$my_for. '_spec'] = array(
253 '#type' => 'textarea',
254 '#rows' => '3',
255 '#title' => t('Spec.'),
256 '#default_value' => $setting[$k][$for]['spec'],
257 '#description' => t('Optional'),
258 );
259 $form['htmLawed'][$my_k][$my_for][$my_for. '_help'] = array(
260 '#type' => 'textarea',
261 '#rows' => '3',
262 '#title' => t('Help'),
263 '#default_value' => $setting[$k][$for]['help'],
264 '#description' => t('Tips for users'),
265 );
266 } // End inner foreach
267
268 if(!$subform_count) {
269 $form['htmLawed']['htmLawed_content_specific_point'] = array(
270 '#type' => 'markup',
271 '#value' => '<div class="description">'. t('Set values per content-type below. Generic default values are set <a href="!above">above</a>.', array('!above'=>'#htmLawed_default_point')). '<a id="htmLawed_specific_point"></a> <small>'. "$help</small></div>",
272 );
273 }
274 ++$subform_count;
275 } // End outer foreach
276
277 $form['#submit'][] = '_htmLawed_store_setting'; // Drupal 6 diff.
278 $form['#submit'] = array_reverse($form['#submit']);
279 return $form;
280 break;
281
282 default:
283 return $text;
284 break;
285 }
286 }
287
288 /*
289 * Display tips indicating htmLawed settings (elements allowed, etc.)
290 */
291 function htmLawed_filter_tips($delta, $format, $long = FALSE) {
292 // Content-type unknown
293 $basic_out = t('Information indicating specific htmLawed (X)HTML filter/purifier settings in effect will be shown where appropriate.');
294 $setting = variable_get('htmLawed_format_'. $format, 0);
295 if(arg(2) == 'filter') { // Drupal 7 diff
296 if($setting) {
297 return $basic_out;
298 }
299 return t('For htmLawed to be active with this text format, it needs to be configured and the configuration <em>saved</em>. <a href="!conf" title="!tip">Configure now?</a>', array('!conf'=>url('admin/settings/filter/'. arg(3). '/configure'), '!tip'=>'proceed to configuration form')); // Drupal 7 diff
300 }
301 if(!$setting) {
302 return $basic_out;
303 }
304
305 if(!$long) {
306 $node_id = $node_type = NULL;
307 $for = 'Other';
308 // Comment
309 if(arg(0) == 'comment') {
310 $for = 'Comment';
311 if(arg(1) == 'reply') {
312 $node_id = arg(2);
313 }
314 elseif(arg(1) == 'edit') {
315 $comment_id = arg(2);
316 $node_id = db_fetch_object(db_query('SELECT nid AS nid FROM {comments} WHERE cid = %d', $comment_id))->nid;
317 }
318 }
319 // Body, extra fields because of CCK, etc.
320 elseif(arg(0) == 'node') {
321 $for = 'Body';
322 if(arg(1) == 'add') {
323 $node_type = arg(2);
324 }
325 elseif(is_numeric(arg(1))) {
326 $node_id = arg(1);
327 }
328 }
329 // Admin configuring an extra field, because of modules like CCK
330 elseif(arg(0) == 'admin' and arg(1) == 'content' and arg(2) == 'types') {
331 $for = 'Body';
332 $node_type = arg(3);
333 }
334
335 // Content-type
336 if($node_id) {
337 $node_type = db_fetch_object(db_query('SELECT type AS type FROM {node} WHERE nid = %d', $node_id))->type;
338 }
339
340 // Right settings
341 $def_setting = isset($setting['htmLawedDef'][$for]) ? $setting['htmLawedDef'][$for] : array('show'=>1, 'save'=>0, 'help'=>'Tags allowed: a, em, strong, cite, code, ol, ul, li, dl, dt, dd');
342 if($node_type) {
343 $setting = isset($setting[$node_type][$for]) ? $setting[$node_type][$for] : $def_setting;
344 }
345 else {
346 $setting = $def_setting;
347 }
348
349 if(!empty($setting['show']) or !empty($setting['save'])) {
350 $setting = !empty($setting['default']) ? $def_setting : $setting;
351 return $setting['help'];
352 }
353
354 return;
355 }
356
357 // Long tips: Content-type always unknown
358 return t('HTML markup is restricted using the <a href="http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/index.php">htmLawed</a> filter to make input text more secure, and standards- and admin-compliant. More details about the restrictions in effect (that may vary from one content-type to another) may be available elsewhere, such as in the text of the input format filter-tips and on the input format configuration forms.') .
359 (!user_access('administer htmLawed (X)HTML filter/purifier') ? '' : ' ' . t('For information on configuring htmLawed, visit the htmLawed !help section.', array('!help' => l(t('help'), 'admin/help/htmLawed'))));
360 }
361
362 /*
363 * Help page on module usage
364 */
365 function htmLawed_help($path, $arg) { // Drupal 6 diff.
366 switch ($path) {
367 case 'admin/help#htmLawed':
368 case 'admin/content/htmLawed':
369 $module_path = drupal_get_path('module', 'htmLawed');
370 include_once "$module_path/htmLawed/htmLawed.php"; // For version number
371 global $base_url;
372 return '<div>'. t('The htmLawed (X)HTML filter/purifier module restricts HTML markup in content as well as makes it more secure, and standards- and admin-compliant using the <a href="http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/index.php">htmLawed</a> (version !version) PHP software. Copies of the htmLawed <a href="!doc">documentation</a> and the module <a href="!readme">readme</a> files should be available on your site. A <a href="!handbook">handbook</a> detailing htmLawed module usage may be available on the Drupal website.', array('!doc' => $base_url. '/'. $module_path . '/htmLawed/htmLawed_README.htm', '!readme' => $base_url. '/'. $module_path . '/readme.txt', '!handbook'=>'http://drupal.org/search/apachesolr_search/htmlawed?filters=type%3abook', '!version' => hl_version())) . '<br /><br />' .
373
374 t('This module can be used to have the htmLawed-filtering configured differently for different text formats and content-types as well as for comments, teasers (like RSS newsfeed items), and other special content. ') . '<br /><br /><hr /><br />' .
375
376 t('To <strong>enable</strong> htmLawed per text format, visit the <em>!text_formats</em> section and choose to <em>configure</em> a text format that needs to include htmLawed-filtering. In the subsequently-displayed form, enable the htmLawed filter.', array('!text_formats' => l(t('Text formats'), 'admin/settings/filter'))) . '<blockquote><div>' . t('Because htmLawed does the task of the Drupal <em>HTML filter</em>, that filter can be disabled. Actions like <em>Correct broken HTML</em> that are used to balance or properly nest HTML tags can also be disabled. Unlike the Drupal filter, htmLawed can also be used to restrict HTML attributes and URL protocols, balance tags, etc., and that too in a content-type- and case-specific manner. Depending on the types of filters the text format uses, you may need to re-arrange the filters using the <em>rearrange</em> link on the form -- htmLawed would usually be the last filter to be run.') . '<br /><br />' .
377
378 t('If a filter that relies on the &lt;, &gt; or &amp; character (such as Drupal <em>PHP evaluator</em>) is being used with the input format, then that filter should run before htmLawed. Further, if that filter generates HTML markup, then htmLawed should be configured appropriately to permit such markup.'). '</div></blockquote>' .
379
380 t('The <strong>customization</strong> of htmLawed is dictated by two parameters, <em>Config.</em> and <em>Spec.</em>. Setting specific htmLawed filter settings involves setting values for the two parameters in the htmLawed settings form. To get to the settings form, use the <em>Configure</em> link for a text format for which htmLawed has been enabled. On the settings form, a sub-form, <em>Default</em>, can be used to set the default values to be used for any content-type. Content (node)-type-specific sub-forms allow you to over-ride the default values as well as to choose to use (or disable) htmLawed.') . '<br /><br />' .
381
382 t('The <em>Config.</em> form-field is filled with comma-separated, quoted, key-value pairs like <code>"safe"=>1, "element"=>"a, em, strong"</code> (these are interpreted as PHP array elements). The <em>Spec.</em> field is an optional string of text... see htmLawed <a href="!doc">documentation</a> for more. Content of the <em>Help</em> field will be used as a note to inform users or yourself about the filter, such as what tags are allowed.', array('!doc' => $base_url. '/'. $module_path . '/htmLawed/htmLawed_README.htm')) . '<blockquote><div>' .
383
384 t('The form-fields are pre-filled the first time htmLawed is being configured for a text format. The values allow the <em>a, em, strong, cite, code, ol, ul, li, dl, dt</em> and <em>dd</em> HTML tags, deny the <em>id</em> and <em>style</em> attributes, and any unsafe markup (such as the scriptable <em>onclick</em> attribute). These same values may be used during the filtering process if the specific or default settings cannot be found. Note that emptying a <em>Config.</em> field does not mean that the default setting will be used.') . '</div></blockquote>' .
385
386 t('Individualized settings can be applied for <em>Body</em>, <em>Comment</em> and <em>Teaser</em>: the first refers to the main content; the second to user comments for the main content; and, the third, to the teasers (like RSS newsfeed items) generated from the main content. You may have a need for a fourth case, <em>Other</em>, if you use modules like <em>Views</em> that create extra input fields (like <em>Header</em>) that are not content (node)-type-specific. Content-type-specific settings for <em>Other</em> are obviously not possible') . '<br /><br />' .
387
388 t('For <em>Body</em> and <em>Comment</em>, enabling the filter for <em>save</em> can be used to filter input before storage in the database (core Drupal does not filter submissions; filtering is done dynamically when content is displayed on as web-pages), but you have to check if that affects the functioning of filters (other than the Drupal <em>PHP evaluator</em>) that rely on the &lt;, &gt; or &amp; character. For <em>Teaser</em>, the htmLawed filtering is done at the end of all other filtering, including any prior htmLawed filtering because of <em>Body</em>, and the default settings will allow the <em>br</em> and <em>p</em> tags as well.') . '<br /><br /><hr /><br />' .
389
390 t('To control user <strong>permissions</strong> for editing of the htmLawed settings, !htmlawed_user_perm.', array('!htmlawed_user_perm' => l(t('visit the permissions page'), 'admin/user/permissions'))) . ' Ideally, only the main administrator would have the permission.<br /><br />' .
391
392 t('Content-type-specific htmLawed settings are <strong>deleted</strong> when a type is deleted. However, text-format-specific htmLawed settings are not automatically deleted when a format is deleted; you have to <em>!run_cron_manually</em> to get rid of the no-more-needed settings. Disabling htmLawed for a text format will not delete the associated settings. <em>!Uninstalling</em> the htmLawed module will delete all htmLawed-related settings, but disabling will not result in any deletion.', array('!run_cron_manually' => l(t('run cron manually'), 'admin/reports/status'), '!Uninstalling' => l(t('Uninstalling'), 'admin/build/modules/uninstall'))) . '<br /><br />' . // Drupal 6 diff
393
394 t('It is important to understand the security implications of the htmLawed settings in use and the limitations of htmLawed. To keep the htmLawed script included with the module updated, replace the <em>htmLawed.php</em> and <em>htmLawed_README.htm</em> files inside the <em>htmLawed</em> sub-folder of the module folder with newer versions downloaded from the <a href="http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/index.php">htmLawed</a>.') . '<br /><br /></div>';
395 break;
396 case 'admin/settings/filter/%/configure': // Drupal 7 diff
397 $setting = variable_get('htmLawed_format_'. arg(3), 0);
398 if(!is_array($setting)) {
399 return '<p>'. t('Though the htmLawed filter settings are pre-filled below, you <em>must save</em> the configuration for the filter to be activated.') .'</p>';
400 }
401 break;
402 case 'admin/settings/filter/%': // Drupal 7 diff
403 $setting = variable_get('htmLawed_format_'. arg(3), 0);
404 if(!is_array($setting)) {
405 return '<p>'. t('Though the htmLawed filter is enabled, you <em>must <a href="!conf" title="!tip">configure</a></em> it to activate it for this text format.', array('!conf'=>url('admin/settings/filter/'. arg(3). '/configure'), '!tip'=>'proceed to configuration form')) .'</p>'; // Drupal 7 diff
406 }
407 break;
408 }
409 }
410
411 /*
412 * The module_nodeapi hook is used for 'save' for 'Body' (also, effectively, for 'save' for 'Teaser') and for 'show' for 'Teaser'
413 * Calls _htmLawed_process() to filter data before it is stored
414 * The module_filter hook is for the 'show', and module_comment hook for 'Comment' for'save'
415 * No default filtering for 'save' if content-type-settings are unavailable as hook_filter will always be run later
416 * For filtering of others, see htmLawed_filter(), htmLawed_node_rss_item(), and htmLawed_node_presave()
417 */
418 function htmLawed_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
419 $config = 0;
420 switch($op) {
421 // 'Teaser' 'show' for non-feed teaser; content already filtered, incl. by htmLawed_filter based on 'Body' 'show'
422 case 'alter':
423 $filters = array_keys(filter_list_format($node->format));
424 if(in_array('htmLawed/0', $filters) and isset($node->teaser)) {
425 $setting = variable_get('htmLawed_format_'. $node->format, 0);
426 if(!is_array($setting)) {
427 return;
428 }
429 $def_setting = isset($setting['htmLawedDef']['RSS']) ? $setting['htmLawedDef']['RSS'] : array('show'=>1, 'config'=>"'safe'=>1, 'elements'=>'a, em, strong, cite, code, ol, ul, li, dl, dt, dd, br, p', 'deny_attribute'=>'id, style'",'spec'=>'');
430 $setting = isset($setting[$node->type]['RSS']) ? $setting[$node->type]['RSS'] : $def_setting;
431 if(!empty($setting['show'])) {
432 $setting = !empty($setting['default']) ? $def_setting : $setting;
433 eval('$config = array('. $setting['config']. ');');
434 if(is_array($config)) {
435 $node->teaser = _htmLawed_process($node->teaser, $config, $setting['spec']);
436 }
437 }
438 }
439 break;
440 }
441 }
442
443 /*
444 * For 'save' for 'Body' (also, effectively, for 'save' for 'Teaser') - filter before saving to database
445 * For filtering of others, see htmLawed_filter(), htmLawed_node_rss_item(), htmLawed_comment(), and htmLawed_nodeapi()
446 */
447 function htmLawed_node_presave($node) { // Drupal 7 new
448 $config = 0;
449 $filters = array_keys(filter_list_format($node->format));
450 if(in_array('htmLawed/0', $filters)) {
451 $setting = variable_get('htmLawed_format_'. $node->format, 0);
452 if(!is_array($setting)) {
453 return;
454 }
455 $def_setting = isset($setting['htmLawedDef']['Body']) ? $setting['htmLawedDef']['Body'] : array('config'=>"'safe'=>1, 'elements'=>'a, em, strong, cite, code, ol, ul, li, dl, dt, dd', 'deny_attribute'=>'id, style'",'spec'=>'');
456 $setting = isset($setting[$node->type]['Body']) ? $setting[$node->type]['Body'] : array();
457 if(!empty($setting['save'])) {
458 $setting = !empty($setting['default']) ? $def_setting : $setting;
459 eval('$config = array('. $setting['config']. ');');
460 if(is_array($config)) {
461 if(isset($node->body)) {
462 // Leave any PHP code & Drupal's teaser mark intact
463 $htmLawed_hook_parameter = (in_array('php/0', $filters) && strpos($node->body, '<?') !== FALSE) ? 'save_php' : 0;
464 $node->body = _htmLawed_process($node->body, $config, $setting['spec'], $htmLawed_hook_parameter);
465 $node->body = str_replace('&lt;!--break--&gt;', '<!--break-->', $node->body);
466 }
467 if(isset($node->teaser)) {
468 $htmLawed_hook_parameter = (in_array('php/0', $filters) && strpos($node->teaser, '<?') !== FALSE) ? 'save_php' : 0;
469 $node->teaser = _htmLawed_process($node->teaser, $config, $setting['spec'], $htmLawed_hook_parameter);
470 }
471 }
472 }
473 }
474
475 }
476
477 /*
478 * Filter RSS item
479 * Note content already filtered, incl. by htmLawed_filter based on 'Body' 'show'
480 * For filtering of others, see htmLawed_filter(), htmLawed_comment(), htmLawed_node_presave(), and htmLawed_nodeapi()
481 */
482 function htmLawed_node_rss_item($node) { // Drupal 7 new
483 $config = 0;
484 $filters = array_keys(filter_list_format($node->format));
485 if(in_array('htmLawed/0', $filters) and isset($node->teaser)) {
486 $setting = variable_get('htmLawed_format_'. $node->format, 0);
487 if(!is_array($setting)) {
488 return;
489 }
490 $def_setting = isset($setting['htmLawedDef']['RSS']) ? $setting['htmLawedDef']['RSS'] : array('show'=>1, 'config'=>"'safe'=>1, 'elements'=>'a, em, strong, cite, code, ol, ul, li, dl, dt, dd, br, p', 'deny_attribute'=>'id, style'",'spec'=>'');
491 $setting = isset($setting[$node->type]['RSS']) ? $setting[$node->type]['RSS'] : $def_setting;
492 if(!empty($setting['show'])) {
493 $setting = !empty($setting['default']) ? $def_setting : $setting;
494 eval('$config = array('. $setting['config']. ');');
495 if(is_array($config)) {
496 $node->teaser = _htmLawed_process($node->teaser, $config, $setting['spec']);
497 }
498 }
499 }
500 }
501
502 /*
503 * Delete content-type htmLawed settings when the content-type is deleted
504 * Also see htmLawed_cron() and htmLawed_uninstall() in htmLawed.install
505 */
506 function htmLawed_node_type($op, $info) {
507 switch($op) {
508 case 'delete':
509 $result = db_query('SELECT format AS format FROM {filter_format}');
510 while($format = db_fetch_object($result)) {
511 $format = $format->format;
512 $setting = variable_get('htmLawed_format_'. $format, NULL);
513 if(isset($setting[$info->type]) and is_array($setting[$info->type])) {
514 unset($setting[$info->type]);
515 variable_set('htmLawed_format_'. $format, $setting);
516 }
517 }
518 break;
519 }
520 }
521
522 /*
523 * This also helps display the htmLawed section on the administration-by-module page
524 */
525 function htmLawed_perm() { // Drupal 7 diff
526 return array(
527 // This key should be same whereever user_access() is called
528 'administer htmLawed (X)HTML filter/purifier' => array(
529 'title' => t('Administer htmLawed (X)HTML filter/purifier'),
530 'description' => t('Manage the htmLawed (X)HTML filter/purifier, and select which roles may use them. %warning', array('%warning' => t('Warning: Give to trusted roles only; this permission has security implications.'))),
531 ),
532 );
533 }
534
535 function htmLawed_theme() { // Drupal 6 new
536 return array(
537 'htmLawed_tabled_subform' => array(
538 'arguments' => array('subform' => NULL)
539 )
540 );
541 }
542
543 /*
544 * Render sub-forms for htmLawed settings in tabular format
545 */
546 function theme_htmLawed_tabled_subform($subform = NULL) {
547 $output = '';
548 $my = array();
549 foreach($subform as $k=>$v) {
550 $my[substr(strrchr($k, '_'), 1)] = $v;
551 }
552 $rows[0][0] = array('data'=>drupal_render($my['guide']). (isset($my['default']) ? drupal_render($my['default']) : ''). (isset($my['show']) ? drupal_render($my['show']) : ''). (isset($my['save']) ? drupal_render($my['save']) : ''), 'style'=>'width: 50%');
553 $rows[0][1] = array('data'=>drupal_render($my['help']), 'style'=>'width: 50%');
554 $rows[1][0] = array('data'=>drupal_render($my['config']), 'style'=>'width: 50%');
555 $rows[1][1] = array('data'=>drupal_render($my['spec']), 'style'=>'width: 50%');
556
557 $output = theme('table', array(), $rows);
558 return $output;
559 }
560
561 /*
562 * The htmLawed filtering process
563 */
564 function _htmLawed_process($text = '', $config = NULL, $spec = NULL, $hook_parameter = 0) {
565 $module_path = drupal_get_path('module', 'htmLawed');
566 include_once "$module_path/htmLawed/htmLawed.php";
567 if($hook_parameter == 'save_php'){
568 $config['hook'] = '_htmLawed_save_php';
569 }
570 $text = htmLawed($text, $config, $spec);
571 if($hook_parameter == 'save_php'){
572 $text = preg_replace(array('`\x83\?php(.+?)\?\x84`sme', '`\x83\?php(.*)$`sme'), array("'<?php'. str_replace(array('&amp;', '&lt;', '&gt;'), array('&', '<', '>'), '$1'). '?>'", "'<?php'. str_replace(array('&amp;', '&lt;', '&gt;'), array('&', '<', '>'), '$1')"), $text);
573 }
574 return $text;
575 }
576
577 /*
578 * Using htmLawed's hook function to preserve PHP code before 'save'
579 */
580 function _htmLawed_save_php($text) {
581 return preg_replace(array('`<\?php(.+?)\?>`sme', '`<\?php(.*)$`sme'), array("\"\x83?php\". str_replace(array('<', '>', '&'), array('&lt;', '&gt;', '&amp;'), '$1'). \"?\x84\"", "\"\x83?php\". str_replace(array('<', '>', '&'), array('&lt;', '&gt;', '&amp;'), '$1')"), $text);
582 }
583
584 /*
585 * Content-type-specific and default htmLawed settings are stored in variable table in input-format specific fields: htmLawed_format_1, _2, etc.
586 * E.g., as array('story'=>array('Body'=>array('show'=>1, 'save'=>1,...), 'Comment'=>array('show'=>1...)), 'page'=>array('show'=>1...
587 * There is no 'save' key for 'RSS'.
588 * There are no 'save' or 'default' keys in the arrays of 'htmLawedDef'; also, 'show' is only for 'Other'
589 * 'Other' key is only for 'htmLawedDef'.
590 */
591 function _htmLawed_store_setting($form_id = NULL, &$form) { // Many Drupal 6 diff
592 // Content-specific values
593 $content_types = node_get_types('names');
594 foreach($content_types as $k=>$v) {
595 foreach(array('Body', 'Comment', 'RSS') as $for) {
596 $val[$for] = array('default'=>$form['values']['htmLawed_'. $k. '_'. $for. '_default'], 'show'=>$form['values']['htmLawed_'. $k. '_'. $for. '_show'], 'config'=>$form['values']['htmLawed_'. $k. '_'. $for. '_config'], 'spec'=>$form['values']['htmLawed_'. $k. '_'. $for. '_spec'], 'help'=>$form['values']['htmLawed_'. $k. '_'. $for. '_help']);
597 unset($form['values']['htmLawed_'. $k. '_'. $for. '_default'], $form['values']['htmLawed_'. $k. '_'. $for. '_show'], $form['values']['htmLawed_'. $k. '_'. $for. '_config'], $form['values']['htmLawed_'. $k. '_'. $for. '_spec'], $form['values']['htmLawed_'. $k. '_'. $for. '_help']);
598 if($for != 'RSS') {
599 $val[$for]['save'] = $form['values']['htmLawed_'. $k. '_'. $for. '_save'];
600 unset($form['values']['htmLawed_'. $k. '_'. $for. '_save']);
601 }
602 }
603 $setting[$k] = $val;
604 }
605
606 // Default values
607 foreach(array('Body', 'Comment', 'Other', 'RSS') as $for) {
608 $def[$for] = array('config'=>$form['values']['htmLawed_htmLawedDef_'. $for. '_config'], 'spec'=>$form['values']['htmLawed_htmLawedDef_'. $for. '_spec'], 'help'=>$form['values']['htmLawed_htmLawedDef_'. $for. '_help']);
609 unset($form['values']['htmLawed_htmLawedDef_'. $for. '_config'], $form['values']['htmLawed_htmLawedDef_'. $for. '_spec'], $form['values']['htmLawed_htmLawedDef_'. $for. '_help']);
610 if($for == 'Other') {
611 $def[$for]['show'] = $form['values']['htmLawed_htmLawedDef_'. $for. '_show'];
612 unset($form['values']['htmLawed_htmLawedDef_'. $for. '_show']);
613 }
614 }
615 $setting['htmLawedDef'] = $def;
616
617 variable_set('htmLawed_format_'. $form['values']['format'], $setting);
618 }

  ViewVC Help
Powered by ViewVC 1.1.2