Fix Reverse Proxy Support: http://drupal.org/node/244593 http://drupal.org/files/issues/drupal_80.patch Index: includes/bootstrap.inc --- includes/bootstrap.inc.orig 2008-02-11 15:36:21 +0100 +++ includes/bootstrap.inc 2008-04-09 20:47:49 +0200 @@ -272,6 +272,7 @@ */ function conf_init() { global $base_url, $base_path, $base_root; + global $base_url_local; // Export the following settings.php variables to the global namespace global $db_url, $db_prefix, $cookie_domain, $conf, $installed_profile, $update_free_access; @@ -723,9 +724,22 @@ * generate an equivalent using other environment variables. */ function request_uri() { + global $base_url; + global $base_url_local; if (isset($_SERVER['REQUEST_URI'])) { $uri = $_SERVER['REQUEST_URI']; + if (isset($base_url) && isset($base_url_local)) { + $parts = parse_url($base_url_local); + if ( strlen($uri) >= strlen($base_url_local) + && substr($uri, 0, strlen($base_url_local)) == $base_url_local) { + $uri = $base_url . substr($uri, strlen($base_url_local)); + } + elseif ( strlen($uri) >= strlen($parts["path"]) + && substr($uri, 0, strlen($parts["path"])) == $parts["path"]) { + $uri = $base_url . substr($uri, strlen($parts["path"])); + } + } } else { if (isset($_SERVER['argv'])) { Index: sites/default/default.settings.php --- sites/default/default.settings.php.orig 2007-12-20 10:35:10 +0100 +++ sites/default/default.settings.php 2008-04-09 20:47:32 +0200 @@ -126,6 +126,24 @@ # $base_url = 'http://www.example.com'; // NO trailing slash! /** + * Local Base URL (optional). + * + * If you are running Drupal behind a reverse proxy, $base_url (see above) + * usually points to the URL of the reverse proxy. Drupal uses this for + * all sorts of external URLs. In order to correctly calculate sub-URLs + * below $base_url for embedded HTML forms, Drupal also has to know the + * URL on the local/origin server under which Drupal is contacted by the + * reverse proxy. This is what $base_url_local is for. + * + * Examples: + * $base_url_local = 'http://www.example.com:8080/drupal'; + * + * It is not allowed to have a trailing slash; Drupal will add it + * for you. + */ +# $base_url_local = 'http://www.example.com:8080/drupal'; // NO trailing slash! + +/** * PHP settings: * * To see what PHP settings are possible, including whether they can ----------------------------------------------------------------------------- Support HTTP Proxies (mainly for update checks, RSS fetching, etc) http://drupal.org/node/7881 http://drupal.org/files/issues/proxy_11.patch (post-adjusted and improved by RSE) Index: includes/common.inc --- includes/common.inc.orig 2008-04-09 23:11:44 +0200 +++ includes/common.inc 2008-04-24 11:41:40 +0200 @@ -439,13 +439,27 @@ case 'http': $port = isset($uri['port']) ? $uri['port'] : 80; $host = $uri['host'] . ($port != 80 ? ':'. $port : ''); - $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15); + if (variable_get('proxy_server', '') != '') { + $proxy_server = variable_get('proxy_server', ''); + $proxy_port = variable_get('proxy_port', 8080); + $fp = @fsockopen($proxy_server, $proxy_port, $errno, $errstr, 15); + } + else { + $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15); + } break; case 'https': // Note: Only works for PHP 4.3 compiled with OpenSSL. $port = isset($uri['port']) ? $uri['port'] : 443; $host = $uri['host'] . ($port != 443 ? ':'. $port : ''); - $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20); + if (variable_get('proxy_server', '') != '') { + $proxy_server = variable_get('proxy_server', ''); + $proxy_port = variable_get('proxy_port', 8080); + $fp = @fsockopen($proxy_server, $proxy_port, $errno, $errstr, 15); + } + else { + $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20); + } break; default: $result->error = 'invalid schema '. $uri['scheme']; @@ -462,9 +476,14 @@ } // Construct the path to act on. - $path = isset($uri['path']) ? $uri['path'] : '/'; - if (isset($uri['query'])) { - $path .= '?'. $uri['query']; + if (variable_get('proxy_server', '') != '') { + $path = $url; + } + else { + $path = isset($uri['path']) ? $uri['path'] : '/'; + if (isset($uri['query'])) { + $path .= '?'. $uri['query']; + } } // Create HTTP request. @@ -482,6 +501,14 @@ $defaults['Authorization'] = 'Authorization: Basic '. base64_encode($uri['user'] . (!empty($uri['pass']) ? ":". $uri['pass'] : '')); } + // If the proxy server required a username then attempt to authenticate with it + if (variable_get('proxy_username', '') != '') { + $username = variable_get('proxy_username', ''); + $password = variable_get('proxy_password', ''); + $auth_string = base64_encode($username . ($password != '' ? ':'. $password : '')); + $defaults['Proxy-Authorization'] = 'Proxy-Authorization: Basic '. $auth_string ."\r\n"; + } + foreach ($headers as $header => $value) { $defaults[$header] = $header .': '. $value; } Index: modules/system/system.admin.inc --- modules/system/system.admin.inc.orig 2008-03-25 12:58:16 +0100 +++ modules/system/system.admin.inc 2008-04-24 11:43:07 +0200 @@ -1363,6 +1363,65 @@ } /** + * Form builder; Configure the site proxy settings. + * + * @ingroup forms + * @see system_settings_form() + */ +function system_proxy_settings() { + + $form['forward_proxy'] = array( + '#type' => 'fieldset', + '#title' => t('Forward proxy settings'), + '#description' => t('The proxy server used when Drupal needs to connect to other sites on the Internet.'), + ); + $form['forward_proxy']['proxy_server'] = array( + '#type' => 'textfield', + '#title' => t('Proxy host name'), + '#default_value' => variable_get('proxy_server', ''), + '#description' => t('The host name of the proxy server, eg. localhost. If this is empty Drupal will connect directly to the internet.') + ); + $form['forward_proxy']['proxy_port'] = array( + '#type' => 'textfield', + '#title' => t('Proxy port number'), + '#default_value' => variable_get('proxy_port', 8080), + '#description' => t('The port number of the proxy server, eg. 8080'), + ); + $form['forward_proxy']['proxy_username'] = array( + '#type' => 'textfield', + '#title' => t('Proxy username'), + '#default_value' => variable_get('proxy_username', ''), + '#description' => t('The username used to authenticate with the proxy server.'), + ); + $form['forward_proxy']['proxy_password'] = array( + '#type' => 'textfield', + '#title' => t('Proxy password'), + '#default_value' => variable_get('proxy_password', ''), + '#description' => t('The password used to connect to the proxy server. This is kept as plain text.', '') + ); + $form['#validate'][] = 'system_proxy_settings_validate'; + + return system_settings_form($form); +} + +/** + * Validate the submitted proxy form. + */ +function system_proxy_settings_validate($form, &$form_state) { + // Validate the proxy settings + $form_state['values']['proxy_server'] = trim($form_state['values']['proxy_server']); + if ($form_state['values']['proxy_server'] != '') { + // TCP allows the port to be between 0 and 65536 inclusive + if (!is_numeric($form_state['values']['proxy_port'])) { + form_set_error('proxy_port', t('The proxy port is invalid. It must be a number between 0 and 65535.')); + } + elseif ($form_state['values']['proxy_port'] < 0 || $form_state['values']['proxy_port'] >= 65536) { + form_set_error('proxy_port', t('The proxy port is invalid. It must be between 0 and 65535.')); + } + } +} + +/** * Form builder; Configure the site file handling. * * @ingroup forms Index: modules/system/system.module --- modules/system/system.module.orig 2008-04-09 23:11:49 +0200 +++ modules/system/system.module 2008-04-24 11:43:47 +0200 @@ -55,7 +55,7 @@ $output .= '
'. t('For more information, see the online handbook entry for System module.', array('@system' => 'http://drupal.org/handbook/modules/system/')) .'
'; return $output; case 'admin': @@ -406,6 +406,14 @@ 'access arguments' => array('administer site configuration'), 'file' => 'system.admin.inc', ); + $items['admin/settings/proxy'] = array( + 'title' => 'Proxy server', + 'description' => 'Configure settings when the site is behind a proxy server.', + 'page callback' => 'drupal_get_form', + 'page arguments' => array('system_proxy_settings'), + 'access arguments' => array('administer site configuration'), + 'file' => 'system.admin.inc', + ); $items['admin/settings/file-system'] = array( 'title' => 'File system', 'description' => 'Tell Drupal where to store uploaded files and how they are accessed.', ----------------------------------------------------------------------------- Properly activate Drupal support module in TinyMCE Index: sites/all/modules/tinymce/plugin_reg.php --- sites/all/modules/tinymce/plugin_reg.php.orig 2008-03-27 21:11:17 +0100 +++ sites/all/modules/tinymce/plugin_reg.php 2008-05-02 20:56:56 +0200 @@ -102,5 +102,9 @@ $plugins['zoom'] = array(); $plugins['zoom']['theme_advanced_buttons2'] = array('zoom'); +$plugins['drupalimage'] = array(); +$plugins['drupalimage']['theme_advanced_buttons1'] = array('drupalimage'); +$plugins['drupalimage']['extended_valid_elements'] = array('img[class|src|border=0|alt|title|width|height|align|name]'); + return $plugins; } ----------------------------------------------------------------------------- Fix SQL in "remove" functionality of "img_assist" module. http://drupal.org/node/250128 Index: sites/all/modules/img_assist/img_assist.module --- sites/all/modules/img_assist/img_assist.module.orig 2008-04-06 19:32:33 +0200 +++ sites/all/modules/img_assist/img_assist.module 2008-05-02 21:00:24 +0200 @@ -1239,7 +1239,7 @@ } function _img_assist_remove($node, $size) { - $result = db_query("SELECT * FROM {files} f INNER JOIN {image} i WHERE f.fid = i.fid AND i.nid = %d AND f.filename = '%s'", $node->nid, $size['key']); + $result = db_query("SELECT * FROM {files} f INNER JOIN {image} ON f.fid = i.fid WHERE i.nid = %d AND f.filename = '%s'", $node->nid, $size['key']); while ($file = db_fetch_object($result)) { // Never delete original image. if ($file->filepath != $node->images[IMAGE_ORIGINAL]) { ----------------------------------------------------------------------------- Optimize "img_assist" module by loading only when necessary. http://drupal.org/node/55101 Index: sites/all/modules/img_assist/img_assist.js --- sites/all/modules/img_assist/img_assist.js.orig 2008-04-06 18:43:18 +0200 +++ sites/all/modules/img_assist/img_assist.js 2008-05-02 21:05:56 +0200 @@ -130,6 +130,24 @@ var win = window.open(BASE_URL + 'index.php?q=img_assist/popup/' + nid, 'imagev', 'height='+oy+'-10,width='+ox+',top='+winy+',left='+winx+',scrollbars='+use_scrollbars+',resizable'); } +function launch_popup(nid, mw, mh) { + var ox = mw; + var oy = mh; + if((ox>=screen.width) || (oy>=screen.height)){ + var ox = screen.width-150; + var oy = screen.height-150; + var winx = (screen.width / 2)-(ox / 2); + var winy = (screen.height / 2)-(oy / 2); + var use_scrollbars = 1; + } + else{ + var winx = (screen.width / 2)-(ox / 2); + var winy = (screen.height / 2)-(oy / 2); + var use_scrollbars = 0; + } + var win = window.open(BASE_URL + 'index.php?q=img_assist/popup/' + nid, 'imagev', 'height='+oy+'-10,width='+ox+',top='+winy+',left='+winx+',scrollbars='+use_scrollbars+',resizable'); +} + function insertImage() { if (window.opener) { // Get variables from the fields on the properties frame Index: sites/all/modules/img_assist/img_assist.module --- sites/all/modules/img_assist/img_assist.module.orig 2008-05-02 21:04:49 +0200 +++ sites/all/modules/img_assist/img_assist.module 2008-05-02 21:07:24 +0200 @@ -126,7 +126,7 @@ } // Assign base_path to insert in image source by javascript. drupal_add_js('var BASE_URL = "'. base_path() .'";', 'inline'); - drupal_add_js($path .'/img_assist.js'); + drupal_add_js($path .'/img_assist_popup.js'); } /** @@ -150,6 +150,9 @@ * Add image link underneath textareas. */ function img_assist_textarea($element) { + $path = drupal_get_path('module', 'img_assist'); + drupal_add_js($path .'/img_assist.js'); + $link = variable_get('img_assist_link', 'icon'); if (($link == 'icon') || ($link == 'text')) { if (_img_assist_textarea_match($element['#id']) && _img_assist_page_match() && !strstr($_GET['q'], 'img_assist')) { Index: sites/all/modules/img_assist/img_assist_popup.js --- /dev/null 2008-05-02 21:08:21 +0200 +++ sites/all/modules/img_assist/img_assist_popup.js 2008-05-02 21:05:56 +0200 @@ -0,0 +1,20 @@ +/* $Id: drupal.patch,v 1.19 2008/05/29 11:13:43 rse Exp $ */ + +function launch_popup(nid, mw, mh) { + var ox = mw; + var oy = mh; + if((ox>=screen.width) || (oy>=screen.height)){ + var ox = screen.width-150; + var oy = screen.height-150; + var winx = (screen.width / 2)-(ox / 2); + var winy = (screen.height / 2)-(oy / 2); + var use_scrollbars = 1; + } + else{ + var winx = (screen.width / 2)-(ox / 2); + var winy = (screen.height / 2)-(oy / 2); + var use_scrollbars = 0; + } + var win = window.open(BASE_URL + 'index.php?q=img_assist/popup/' + nid, 'imagev', 'height='+oy+'-10,width='+ox+',top='+winy+',left='+winx+',scrollbars='+use_scrollbars+',resizable'); +} + ----------------------------------------------------------------------------- Fix file permissions. http://drupal.org/node/247992 Index: sites/all/modules/img_assist/img_assist.module --- sites/all/modules/img_assist/img_assist.module.orig 2008-05-02 21:11:15 +0200 +++ sites/all/modules/img_assist/img_assist.module 2008-05-02 21:11:48 +0200 @@ -1230,6 +1230,8 @@ drupal_set_message(t('Unable to create %label image', array('%label' => $size['label'])), 'error'); } else { + // Set standard file permissions for webserver-generated files + @chmod(file_create_path($destination), 0664); $node->images[$key] = $destination; _image_insert($node, $key, file_create_path($destination)); } ----------------------------------------------------------------------------- Activate the Drupal glue code for the FCKeditor filemanager. Index: sites/all/modules/fckeditor/fckeditor/editor/filemanager/connectors/php/config.php --- sites/all/modules/fckeditor/fckeditor/editor/filemanager/connectors/php/config.php.orig 2008-03-25 16:28:24 +0100 +++ sites/all/modules/fckeditor/fckeditor/editor/filemanager/connectors/php/config.php 2008-05-02 23:02:23 +0200 @@ -39,6 +39,9 @@ // Attention: The above 'UserFilesPath' must point to the same directory. $Config['UserFilesAbsolutePath'] = '' ; +// activate Drupal glue code for filemanager +require_once "../../../../../filemanager.config.php"; + // Due to security issues with Apache modules, it is recommended to leave the // following setting enabled. $Config['ForceSingleExtension'] = true ; ----------------------------------------------------------------------------- Degrade the "Update notification" check from ERROR to WARNING severity as for a packaged Drupal as in OpenPKG the Update notification is less important and actually confusing anyway. With WARNING one at least still sees the issue, but under "Administer" one doesn't get the confusing red error message and longer. Index: modules/system/system.install --- modules/system/system.install.orig 2008-02-08 18:07:55 +0100 +++ modules/system/system.install 2008-05-03 10:42:23 +0200 @@ -273,7 +273,7 @@ if (!module_exists('update')) { $requirements['update status'] = array( 'value' => $t('Not enabled'), - 'severity' => REQUIREMENT_ERROR, + 'severity' => REQUIREMENT_WARNING, 'description' => $t('Update notifications are not enabled. It is highly recommended that you enable the update status module from the module administration page in order to stay up-to-date on new releases. For more information please read the Update status handbook page.', array('@update' => 'http://drupal.org/handbook/modules/update', '@module' => url('admin/build/modules'))), ); } ----------------------------------------------------------------------------- Disable "Update notifications" check by default during installation. Index: install.php --- install.php.orig 2008-02-08 23:00:45 +0100 +++ install.php 2008-05-09 13:18:09 +0200 @@ -1069,7 +1069,7 @@ '#type' => 'checkboxes', '#title' => st('Update notifications'), '#options' => array(1 => st('Check for updates automatically')), - '#default_value' => array(1), + '#default_value' => array(), '#description' => st('With this option enabled, Drupal will notify you when new releases are available. This will significantly enhance your site\'s security and is highly recommended. This requires your site to periodically send anonymous information on its installed components to drupal.org. For more information please see the update notification information.', array('@drupal' => 'http://drupal.org', '@update' => 'http://drupal.org/handbook/modules/update')), '#weight' => 15, ); ----------------------------------------------------------------------------- No need to always expand the "Menu settings" on node edit pages. Index: modules/menu/menu.module --- modules/menu/menu.module.orig 2008-04-09 23:11:48 +0200 +++ modules/menu/menu.module 2008-05-16 20:03:48 +0200 @@ -366,7 +366,7 @@ '#title' => t('Menu settings'), '#access' => user_access('administer menu'), '#collapsible' => TRUE, - '#collapsed' => FALSE, + '#collapsed' => TRUE, '#tree' => TRUE, '#weight' => -2, '#attributes' => array('class' => 'menu-item-form'), ----------------------------------------------------------------------------- Use a larger text-area on node edit pages. Index: modules/node/node.pages.inc --- modules/node/node.pages.inc.orig 2008-02-27 20:44:44 +0100 +++ modules/node/node.pages.inc 2008-05-16 20:06:45 +0200 @@ -287,7 +287,8 @@ '#type' => 'textarea', '#title' => check_plain($label), '#default_value' => $include ? $node->body : ($node->teaser . $node->body), - '#rows' => 20, + '#rows' => 30, + '#cols' => 80, '#required' => ($word_count > 0), ); ----------------------------------------------------------------------------- Fix "Action" related administration dialog and corresponding run-time handling. Index: modules/system/system.module --- modules/system/system.module.orig 2008-04-09 23:11:49 +0200 +++ modules/system/system.module 2008-05-23 10:41:26 +0200 @@ -1431,7 +1439,7 @@ if (is_numeric($action)) { $aid = $action; // Load stored parameter values from database. - $data = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", intval($aid))); + $data = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $aid)); $edit['actions_description'] = $data->description; $edit['actions_type'] = $data->type; $function = $data->callback; Index: includes/actions.inc --- includes/actions.inc.orig 2007-12-31 15:51:04 +0100 +++ includes/actions.inc 2008-05-23 11:22:17 +0200 @@ -54,7 +54,7 @@ $where_values = array(); foreach ($action_ids as $action_id) { if (is_numeric($action_id)) { - $where[] = 'OR aid = %d'; + $where[] = "OR aid = '%s'"; $where_values[] = $action_id; } elseif (isset($available_actions[$action_id])) { @@ -93,7 +93,7 @@ else { // If it's a configurable action, retrieve stored parameters. if (is_numeric($action_ids)) { - $action = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $action_ids)); + $action = db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $action_ids)); $function = $action->callback; $context = array_merge($context, unserialize($action->parameters)); $result[$action_ids] = $function($object, $context, $a1, $a2); @@ -325,7 +325,7 @@ function actions_save($function, $type, $params, $desc, $aid = NULL) { $serialized = serialize($params); if ($aid) { - db_query("UPDATE {actions} SET callback = '%s', type = '%s', parameters = '%s', description = '%s' WHERE aid = %d", $function, $type, $serialized, $desc, $aid); + db_query("UPDATE {actions} SET callback = '%s', type = '%s', parameters = '%s', description = '%s' WHERE aid = '%s'", $function, $type, $serialized, $desc, $aid); watchdog('actions', 'Action %action saved.', array('%action' => $desc)); } else { @@ -333,7 +333,7 @@ // separate table for numeric aids. db_query('INSERT INTO {actions_aid} VALUES (default)'); $aid = db_last_insert_id('actions_aid', 'aid'); - db_query("INSERT INTO {actions} (aid, callback, type, parameters, description) VALUES (%d, '%s', '%s', '%s', '%s')", $aid, $function, $type, $serialized, $desc); + db_query("INSERT INTO {actions} (aid, callback, type, parameters, description) VALUES ('%s', '%s', '%s', '%s', '%s')", $aid, $function, $type, $serialized, $desc); watchdog('actions', 'Action %action created.', array('%action' => $desc)); } @@ -350,7 +350,7 @@ * The appropriate action row from the database as an object. */ function actions_load($aid) { - return db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = %d", $aid)); + return db_fetch_object(db_query("SELECT * FROM {actions} WHERE aid = '%s'", $aid)); } /** @@ -360,6 +360,6 @@ * integer The ID of the action to delete. */ function actions_delete($aid) { - db_query("DELETE FROM {actions} WHERE aid = %d", $aid); + db_query("DELETE FROM {actions} WHERE aid = '%s'", $aid); module_invoke_all('actions_delete', $aid); } Index: modules/user/user.admin.inc --- modules/user/user.admin.inc.orig 2008-01-16 23:54:41 +0100 +++ modules/user/user.admin.inc 2008-05-23 11:24:13 +0200 @@ -737,13 +737,13 @@ form_set_error('mask', t('You must enter a mask.')); } else { - db_query("UPDATE {access} SET mask = '%s', type = '%s', status = '%s' WHERE aid = %d", $edit['mask'], $edit['type'], $edit['status'], $aid); + db_query("UPDATE {access} SET mask = '%s', type = '%s', status = '%s' WHERE aid = '%s'", $edit['mask'], $edit['type'], $edit['status'], $aid); drupal_set_message(t('The access rule has been saved.')); drupal_goto('admin/user/rules'); } } else { - $edit = db_fetch_array(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid)); + $edit = db_fetch_array(db_query("SELECT aid, type, status, mask FROM {access} WHERE aid = '%s'", $aid)); } return drupal_get_form('user_admin_access_edit_form', $edit, t('Save rule')); } @@ -859,7 +859,7 @@ */ function user_admin_access_delete_confirm($form_state, $aid = 0) { $access_types = array('user' => t('username'), 'mail' => t('e-mail'), 'host' => t('host')); - $edit = db_fetch_object(db_query('SELECT aid, type, status, mask FROM {access} WHERE aid = %d', $aid)); + $edit = db_fetch_object(db_query("SELECT aid, type, status, mask FROM {access} WHERE aid = '%s'", $aid)); $form = array(); $form['aid'] = array('#type' => 'hidden', '#value' => $aid); @@ -873,7 +873,7 @@ } function user_admin_access_delete_confirm_submit($form, &$form_state) { - db_query('DELETE FROM {access} WHERE aid = %d', $form_state['values']['aid']); + db_query("DELETE FROM {access} WHERE aid = '%s'", $form_state['values']['aid']); drupal_set_message(t('The access rule has been deleted.')); $form_state['redirect'] = 'admin/user/rules'; return; ----------------------------------------------------------------------------- 1. Fix content validation in "xmlcontent" module in case one has enabled multiple filters on a particular input format. 2. Additionally, allow absolute paths to support .xsd/.xsl files in arbitrary directories. 3. Finally, do not create a new DOM and output it as XML. Instead directly output the transformed XML in order to get rid of the declaration. 4. Additionally, support an optional XML content template (mainly for loading ENTITY definitions which cannot be done via XSD and XSLT) Index: sites/all/modules/xmlcontent/xmlcontent.module --- sites/all/modules/xmlcontent/xmlcontent.module.orig 2007-03-14 22:59:59 +0100 +++ sites/all/modules/xmlcontent/xmlcontent.module 2008-05-29 13:11:51 +0200 @@ -39,7 +39,16 @@ return t('Allows users to post XML node content and get it transformed through a configured XSLT script'); case 'process': - $xslt_path = drupal_get_path('module', 'xmlcontent'). '/' . variable_get("xmlcontent_xslt_path_$format", ''); + $tpl_path = variable_get("xmlcontent_tpl_path_$format", ''); + if ($tpl_path) { + if (substr($tpl_path, 0, 1) != "/") + $tpl_path = drupal_get_path('module', 'xmlcontent') . '/' . $tpl_path; + $tpl = file_get_contents($tpl_path); + $text = preg_replace("/&template_body;/", $text, $tpl); + } + $xslt_path = variable_get("xmlcontent_xslt_path_$format", ''); + if (substr($xslt_path, 0, 1) != "/") + $xslt_path = drupal_get_path('module', 'xmlcontent') . '/' . $xslt_path; return _xmlcontent_transform($text, $xslt_path); case 'settings': @@ -72,7 +81,7 @@ } // Does the input format of this node use XML Content filter? $format = filter_resolve_format($node->format); - $module = db_result(db_query('SELECT module FROM {filters} WHERE format = %d', $format)); + $module = db_result(db_query("SELECT module FROM {filters} WHERE format = %d AND module = 'xmlcontent'", $format)); if ($module != 'xmlcontent') { return; } @@ -83,7 +92,10 @@ return; } - $schema_path = drupal_get_path('module', 'xmlcontent'). '/' . variable_get("xmlcontent_schema_path_$format",''); + $schema_path = variable_get("xmlcontent_schema_path_$format", ''); + if (substr($schema_path, 0, 1) != "/") + $schema_path = drupal_get_path('module', 'xmlcontent') . '/' . $schema_path; + if (!is_file($schema_path) && ($validation == 'xsd' or $validation == 'rng')) { $schema_path = null; watchdog( 'xmlcontent', t('Validation required but no schema file'), WATCHDOG_WARNING ); @@ -93,7 +105,16 @@ libxml_clear_errors(); libxml_use_internal_errors(true); - if (!_xmlcontent_validate($node->body, $validation, $schema_path)) { + $text = $node->body; + $tpl_path = variable_get("xmlcontent_tpl_path_$format", ''); + if ($tpl_path) { + if (substr($tpl_path, 0, 1) != "/") + $tpl_path = drupal_get_path('module', 'xmlcontent') . '/' . $tpl_path; + $tpl = file_get_contents($tpl_path); + $text = preg_replace("/&template_body;/", $text, $tpl); + } + + if (!_xmlcontent_validate($text, $validation, $schema_path)) { form_set_error('body', t('XML Content: Invalid XML') . libxml_errors_string()); } @@ -156,6 +177,13 @@ '#collapsible' => TRUE, '#collapsed' => FALSE, ); + $form['xmlcontent']["xmlcontent_tpl_path_$format"] = array( + '#type' => 'textfield', + '#title' => t('Optional XML Template File Path'), + '#default_value' => variable_get("xmlcontent_tpl_path_$format", ''), + '#field_prefix' => drupal_get_path('module', 'xmlcontent'). '/', + '#description' => t('The file path to the optional XML template, wrapper around the XML content before processing.'), + ); $form['xmlcontent']["xmlcontent_xslt_path_$format"] = array( '#type' => 'textfield', '#title' => t('XSLT Script File Path'), @@ -218,6 +246,8 @@ // Load the XML document $dom = new DomDocument('1.0', 'UTF-8'); + $dom->resolveExternals = true; + $dom->substituteEntities = true; $valid = $dom->loadXML($xml); if (!$valid) { watchdog('xmlcontent', "Invalid XML Content", WATCHDOG_WARNING); @@ -227,6 +257,8 @@ // Load the XSLT script // TODO: is there a way to cache it, or not necessary $xsl = new DomDocument('1.0', 'UTF-8'); + $xsl->resolveExternals = true; + $xsl->substituteEntities = true; $xsl->load($path_to_xslt); // Create the XSLT processor @@ -242,10 +274,8 @@ } // Transform - $newdom = $proc->transformToDoc($dom); - - // Return the output as XML text (in fact subset of XHTML, depending on the XSLT script) - return $newdom->saveXML(); + $xml = $proc->transformToXML($dom); + return $xml; }