diff --git a/wysiwyg.module b/wysiwyg.module index 000cab5..36c2acd 100644 --- a/wysiwyg.module +++ b/wysiwyg.module @@ -142,6 +142,12 @@ function wysiwyg_form_alter(&$form, &$form_state) { */ function wysiwyg_element_info_alter(&$types) { $types['text_format']['#pre_render'][] = 'wysiwyg_pre_render_text_format'; + + // Register input preprocessor to handle embedded files. + if (!isset($types['text_format']['#element_validate'])) { + $types['text_format']['#element_validate'] = array(); + } + array_unshift($types['text_format']['#element_validate'], 'wysiwyg_preprocess_input'); } /** @@ -272,6 +278,76 @@ function wysiwyg_pre_render_text_format($element) { } /** + * Preprocesses the input to do some cleanup. + * + * E.g. filter embedded files. + */ +function wysiwyg_preprocess_input(&$element, &$form_state, $form) { + $created_file_cache = &drupal_static(__FUNCTION__); + + // For now - only go with images. + $allowed_mime_types = variable_get('wysiwyg_allowed_embedded_mime_types', array( + 'image/gif' => 'gif', + 'image/jpeg' => 'jpg', + 'image/png ' => 'png', + )); + + // Handle embedded files. + if (isset($element['#value'])) { + if(($count = preg_match_all('/(data:([^;]+?);base64,([+=\\w\\s\\d\\/]+))/imu', $element['#value'], $matches))) { + foreach ($matches[0] as $index => $embedded_file) { + $matches[2][$index] = trim(strtolower($matches[2][$index])); + if (!isset($allowed_mime_types[$matches[2][$index]])) { + form_error($element, t('Only the following file types are allowed to embed: %mime_types', array('%mimy_types' => implode(', ', $allowed_mime_types)))); + continue; + } + // Create an unique filename - hashing the content helps to reuse files + // that are used several times. + $tmp_file_uri = 'public://wysiwyg_embedded_' . md5($matches[3][$index]) . '.' . $allowed_mime_types[$matches[2][$index]]; + + // Prepare regex pattern for replacement. + // The data have to be split to make sure we dont get a + // "regular expression is too large" error. + $data_start = preg_quote(substr($matches[1][$index], 0, 100), '/'); + $data_end = preg_quote(substr($matches[1][$index], -100), '/'); + $replacement_regexp = '/' . $data_start . '[+=\\w\\s\\d\\/]+' . $data_end . '/'; + + if (isset($created_file_cache[$tmp_file_uri])) { + if ($created_file_cache[$tmp_file_uri]) { + // If it's a valid file, replace with uri. + $element['#value'] = preg_replace($replacement_regexp, file_create_url($created_file_cache[$tmp_file_uri]->uri), $element['#value']); + } + continue; + } + $created_file_cache[$tmp_file_uri] = FALSE; + if (!($file = file_save_data(base64_decode($matches[3][$index]), $tmp_file_uri, FILE_EXISTS_REPLACE))) { + form_error($element, t('Unable to import embeded file, please use the regular file handling to manage files')); + continue; + } + + // We're picky here! Do our best to ensure nothing evil is uploaded. + if (file_get_mimetype($file->uri) != $matches[2][$index]) { + file_delete($file, TRUE); + form_error($element, t('Unable to validate embedded image. Upload denied!')); + continue; + } + $created_file_cache[$tmp_file_uri] = $file; + + // If file creation was successful replace the embedded file by a normal uri. + $element['#value'] = preg_replace($replacement_regexp, file_create_url($created_file_cache[$tmp_file_uri]->uri), $element['#value']); + } + // Also change the $form_state['values'] to keep the values consistent. + // @TODO Should $form_state['input'] also contain the handled code? + drupal_array_set_nested_value( + $form_state['values'], + $element['#array_parents'], + $element['#value'] + ); + } + } +} + +/** * Determine the profile to use for a given input format id. * * This function also performs sanity checks for the configured editor in a