View source
<?php
define("DEFAULT_SERVLET_URL", variable_get('fillpdf_remote_protocol', 'http') . "://" . variable_get('fillpdf_remote_endpoint', "fillpdf-service.com/xmlrpc.php"));
module_load_include('inc', 'fillpdf', 'fillpdf.admin');
if (module_exists('webform')) {
module_load_include('inc', 'fillpdf', 'webform_tokens');
}
function fillpdf_help($path, $arg) {
switch ($path) {
case 'admin/help#fillpdf':
$content = _fillpdf_get_file_contents(drupal_get_path('module', 'fillpdf') . '/README.txt');
$content = '<pre>' . check_plain($content) . '</pre>';
return $content;
case 'admin/content/fillpdf':
if (module_exists('help')) {
return t('See the !link for an explanation on downloading these forms to PDF', array(
'!link' => l(t('Documentation'), 'admin/help/fillpdf'),
));
}
else {
return t('Activate the help module if you need an ' . 'explanation on downloading these forms to PDF.');
}
}
}
function fillpdf_menu() {
$access = array(
'administer pdfs',
);
$items = array();
$items['fillpdf'] = array(
'page callback' => 'fillpdf_parse_uri',
'access arguments' => array(
'access content',
),
'type' => MENU_CALLBACK,
);
$items['admin/settings/fillpdf'] = array(
'title' => 'Fill PDF Settings',
'description' => 'Configure Fill PDF Servelet Information',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fillpdf_settings',
),
'access arguments' => $access,
);
$items['admin/content/fillpdf'] = array(
'title' => 'Fill PDF',
'description' => 'Manage your PDFs',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fillpdf_forms',
),
'access arguments' => $access,
);
$items['admin/content/fillpdf/%'] = array(
'title' => 'Edit PDF Form',
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fillpdf_form_edit',
3,
),
'access arguments' => $access,
);
$items['admin/content/fillpdf/%/delete'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fillpdf_form_delete_confirm',
3,
),
'access arguments' => $access,
'type' => MENU_CALLBACK,
);
$items['admin/content/fillpdf/%/export'] = array(
'title' => t('Export Fill PDF Field Mappings'),
'page callback' => 'fillpdf_form_export',
'page arguments' => array(
3,
),
'access arguments' => $access,
);
$items['admin/content/fillpdf/%/import'] = array(
'title' => t('Import Fill PDF Field Mappings'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fillpdf_form_import_form',
3,
),
'access arguments' => $access,
);
$items['admin/content/fillpdf/%/add'] = array(
'title' => 'Add field',
'page callback' => 'fillpdf_field',
'page arguments' => array(
4,
3,
),
'access arguments' => $access,
'type' => MENU_LOCAL_TASK,
);
$items['admin/content/fillpdf/%/edit/%'] = array(
'page callback' => 'fillpdf_field',
'page arguments' => array(
4,
3,
5,
),
'access arguments' => $access,
'type' => MENU_CALLBACK,
);
$items['admin/content/fillpdf/%/delete/%'] = array(
'page callback' => 'drupal_get_form',
'page arguments' => array(
'fillpdf_field_delete_confirm',
3,
5,
),
'access arguments' => $access,
'type' => MENU_CALLBACK,
);
return $items;
}
function fillpdf_perm() {
return array(
'administer pdfs',
'publish own pdfs',
'publish all pdfs',
);
}
function fillpdf_pdf_link($fid, $nids = null, $webform_arr = null, $sample = false) {
if (is_array($nids)) {
$nids_uri = '&nids[]=' . implode('&nids[]=', $nids);
}
elseif (isset($nids)) {
$nids_uri = "&nids[]={$nids}";
}
if (is_array($webform_arr)) {
if ($webform_arr['nid']) {
$webform_arr = array(
$webform_arr,
);
}
foreach ($webform_arr as $key => $webform) {
$webforms_uri .= "&webforms[{$key}][nid]={$webform['nid']}";
}
$webforms_uri .= $webform['sid'] ? "&webforms[{$key}][sid]={$webform['sid']}" : "";
}
$sample = $sample ? '&sample=true' : '';
return url('', array(
'absolute' => true,
)) . "fillpdf?fid={$fid}{$nids_uri}{$webforms_uri}{$sample}";
}
function fillpdf_parse_uri() {
$sample = $_GET['sample'];
$fid = $_GET['fid'];
$nids = $webforms = array();
$force_download = FALSE;
$flatten = TRUE;
if ($_GET['nid'] || $_GET['nids']) {
$nids = $_GET['nid'] ? array(
$_GET['nid'],
) : $_GET['nids'];
}
if ($_GET['webform'] || $_GET['webforms']) {
$webforms = $_GET['webform'] ? array(
$_GET['webform'],
) : $_GET['webforms'];
}
if (isset($_GET['download']) && (int) $_GET['download'] == 1) {
$force_download = TRUE;
}
if (isset($_GET['flatten']) && (int) $_GET['flatten'] == 0) {
$flatten = FALSE;
}
fillpdf_merge_pdf($fid, $nids, $webforms, $sample, $force_download, FALSE, $flatten);
}
function fillpdf_merge_pdf($fid, $nids = null, $webform_arr = null, $sample = null, $force_download = FALSE, $skip_access_check = FALSE, $flatten = TRUE) {
if (is_null($fid)) {
drupal_set_message('Fillpdf Form ID required to print a PDF', 'warning');
drupal_goto();
}
$fillpdf_info = db_fetch_object(db_query("SELECT title, url, destination_path, replacements, destination_redirect FROM {fillpdf_forms} WHERE fid=%d", $fid));
if ($fillpdf_info === FALSE) {
drupal_set_message(t('Non-existent Fill PDF Form ID.'), 'error');
drupal_not_found();
exit;
}
$fillpdf_info->replacements = _fillpdf_replacements_to_array($fillpdf_info->replacements);
global $user;
$nodes = $webforms = array();
if (is_array($nids)) {
foreach ($nids as $nid) {
$nodes[] = node_load($nid);
}
}
if (module_exists('webform') && is_array($webform_arr)) {
$webform_info_file = drupal_parse_info_file(drupal_get_path('module', 'webform') . '/webform.info');
if (strstr($webform_info_file['version'], "6.x-2") === FALSE) {
module_load_include('inc', 'webform', 'includes/webform.submissions');
}
else {
module_load_include('inc', 'webform', 'webform_submissions');
}
foreach ($webform_arr as $webform) {
if (!$webform['sid']) {
$webform['sid'] = db_result(db_query('select sid from {webform_submissions}
where nid=%d and uid=%d order by submitted desc', $webform['nid'], $user->uid));
}
$webforms[] = array(
'webform' => node_load($webform['nid']),
'submission' => webform_get_submission($webform['nid'], $webform['sid']),
);
}
}
if ($skip_access_check !== TRUE) {
if (!fillpdf_merge_pdf_access($nodes, $webforms)) {
drupal_access_denied();
module_invoke_all('exit');
exit;
}
}
$fields = $token_objects = $image_data = array();
$query = db_query("SELECT * FROM {fillpdf_fields} WHERE fid=%d", $fid);
while ($obj = db_fetch_object($query)) {
$obj->replacements = _fillpdf_replacements_to_array($obj->replacements);
$transform_string = FALSE;
if ($sample == 'true') {
$fields[$obj->pdf_key] = $obj->pdf_key;
$_REQUEST['destination'] = "admin/content/fillpdf/{$fid}";
}
else {
$nodes = array_reverse($nodes);
$webforms = array_reverse($webforms);
if (!empty($nodes)) {
foreach ($nodes as $node) {
$token_objects['node'] = $node;
$token = token_replace($obj->value, $type = 'node', $object = $node);
if ($token && $token != $obj->value) {
break;
}
}
$transform_string = TRUE;
}
if (strstr($obj->value, 'filefield-fid]')) {
module_load_include('inc', 'filefield', 'field_file');
$filefield = field_file_load($token);
$file_bytes = _fillpdf_get_file_contents($filefield['filepath']);
$str = base64_encode($file_bytes);
$transform_string = FALSE;
$fields[$obj->pdf_key] = '{image}' . realpath($filefield['filepath']);
$image_path_info = pathinfo(realpath($filefield['filepath']));
$image_data[$obj->pdf_key] = array(
'data' => base64_encode(file_get_contents(realpath($filefield['filepath']))),
'filenamehash' => md5($image_path_info['filename']) . '.' . $image_path_info['extension'],
);
}
else {
}
if (!empty($webforms)) {
foreach ($webforms as $webform) {
$token_objects['webform'] = $webform['submission'];
$token = token_replace($obj->value, $type = 'webform', $webform['submission']);
if ($token) {
break;
}
}
$transform_string = TRUE;
}
if ($transform_string) {
$str = preg_replace('|<br />|', '
', $token);
$str = _fillpdf_transform_field_value($str, $fillpdf_info->replacements, $obj->replacements);
$fields[$obj->pdf_key] = $str;
}
}
}
$pdf_data = _fillpdf_get_file_contents($fillpdf_info->url, "<front>");
$fillpdf_remote_service = variable_get('fillpdf_remote_service', TRUE);
$fillpdf_local_service = variable_get('fillpdf_local_service', TRUE);
if ($fillpdf_remote_service) {
$api_key = variable_get('fillpdf_api_key', '0');
$result = _fillpdf_xmlrpc_request(DEFAULT_SERVLET_URL, 'merge_pdf_v3', base64_encode($pdf_data), $fields, $api_key, $flatten, $image_data);
if ($result->error == true) {
drupal_goto();
}
$data = base64_decode($result->data);
}
elseif ($fillpdf_local_service) {
$require = drupal_get_path('module', 'fillpdf') . '/lib/JavaBridge/java/Java.inc';
require_once $require;
try {
$fillpdf = new java('com.ocdevel.FillpdfService', base64_encode($pdf_data), 'bytes');
foreach ($fields as $key => $field) {
if (substr($field, 0, 7) == '{image}') {
$image_bytes = substr($field, 7);
$fillpdf
->image($key, $image_bytes, "file");
}
else {
$fillpdf
->text($key, $field);
}
}
} catch (JavaException $e) {
drupal_set_message(java_truncate((string) $e), 'error');
drupal_goto();
}
try {
if ($flatten) {
$data = java_values(base64_decode($fillpdf
->toByteArray()));
}
else {
$data = java_values(base64_decode($fillpdf
->toByteArrayUnflattened()));
}
} catch (JavaException $e) {
drupal_set_message(java_truncate((string) $e), 'error');
drupal_goto();
}
}
else {
$data = fillpdf_execute_merge('pdftk', $fields, $fillpdf_info, 'url', $flatten);
}
watchdog('fillpdf', 'User %user has generated form %form for node %node.', array(
'%user' => $user->name,
'%form' => $fillpdf_info->title,
'%node' => $node->title,
));
$output_name = _fillpdf_process_filename($fillpdf_info->title, $token_objects);
if (!empty($fillpdf_info->destination_path)) {
$destination_path = _fillpdf_process_destination_path($fillpdf_info->destination_path, $token_objects);
$path_exists = file_check_directory($destination_path, FILE_CREATE_DIRECTORY);
if ($path_exists === FALSE) {
watchdog('fillpdf', "The path %destination_path does not exist and could not be\n automatically created. Therefore, the previous submission was not saved. If\n the URL contained download=1, then the PDF was still sent to the user's browser.\n If the destination path looks wrong and you have used tokens, check that you have\n used the correct token and that it is available to Fill PDF at the time of PDF\n generation.", array(
'%destination_path' => $destination_path,
));
}
else {
$saved_file_path = file_save_data($data, $destination_path . "/{$output_name}", FILE_EXISTS_RENAME);
}
if ($force_download === FALSE) {
if (isset($_GET['destination']) === FALSE) {
if ($fillpdf_info->destination_redirect) {
drupal_goto(file_create_url($saved_file_path));
}
}
drupal_goto();
}
}
drupal_set_header('Pragma: public');
drupal_set_header('Expires: 0');
drupal_set_header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
drupal_set_header('Content-type:application/pdf');
drupal_set_header('Content-Length: ' . strlen($data));
drupal_set_header('Content-disposition:attachment; filename="' . $output_name . '"');
drupal_set_header('Content-Transfer-Encoding: binary');
echo $data;
exit;
}
function fillpdf_merge_pdf_access($nodes = array(), $webforms = array()) {
if (user_access('administer pdfs') || user_access('publish all pdfs')) {
return TRUE;
}
if (!user_access('publish own pdfs')) {
return FALSE;
}
global $user;
if (empty($webforms)) {
foreach ($nodes as $node) {
if (!node_access('view', $node) || $node->uid != $user->uid) {
return FALSE;
}
}
}
else {
foreach ($webforms as $webform) {
if (!node_access('view', node_load($webform['webform']->nid))) {
return FALSE;
}
}
}
if (!empty($webforms)) {
if (!($user->uid && (user_access('access own webform submissions') || user_access('access webform results') || user_access('access webform submissions')))) {
return FALSE;
}
foreach ($webforms as $webform) {
if (!webform_submission_access($webform['webform'], $webform['submission'], 'view')) {
return FALSE;
}
}
}
return TRUE;
}
function _fillpdf_process_filename($original, $token_objects) {
if (!empty($token_objects)) {
if (isset($token_objects['node'])) {
$type = 'node';
}
elseif (isset($token_objects['webform'])) {
$type = 'webform';
}
$original = token_replace($original, $type, $token_objects[$type]);
}
$output_name = str_replace(' ', '_', $original);
$output_name = preg_replace('/\\.pdf$/i', '', $output_name);
$output_name = preg_replace('/[^a-zA-Z0-9_.-]+/', '', $output_name) . '.pdf';
return $output_name;
}
function fillpdf_execute_merge($method, $fields, $fillpdf, $mode = 'url', $flatten = TRUE) {
$data = NULL;
switch ($mode) {
case 'url':
$filename = $fillpdf->url;
break;
case 'stream':
$filename = file_save_data($fillpdf, file_directory_temp() . '/pdf_data.pdf', FILE_EXISTS_RENAME);
break;
}
switch ($method) {
case 'pdftk':
module_load_include('inc', 'fillpdf', 'xfdf');
$xfdfname = $filename . '.xfdf';
$xfdf = create_xfdf(basename($xfdfname), $fields);
$xfdffile = file_save_data($xfdf, $xfdfname, FILE_EXISTS_RENAME);
$data = shell_exec('pdftk ' . escapeshellarg($filename) . ' fill_form ' . escapeshellarg($xfdffile) . ' output - ' . ($flatten ? 'flatten ' : '') . 'drop_xfa');
if ($data === NULL) {
drupal_set_message(t('pdftk not properly installed. No PDF generated.'), 'error');
}
file_delete($xfdffile);
if ($mode == 'stream') {
file_delete($filename);
}
break;
}
if ($data) {
return $data;
}
else {
return FALSE;
}
}
function fillpdf_parse_pdf($fid) {
$filename = db_result(db_query("SELECT url FROM {fillpdf_forms} WHERE fid=%d", $fid));
$content = _fillpdf_get_file_contents($filename, '<front>');
$fillpdf_remote_service = variable_get('fillpdf_remote_service', true);
$fillpdf_local_service = variable_get('fillpdf_local_service', TRUE);
if ($fillpdf_remote_service) {
$result = _fillpdf_xmlrpc_request(DEFAULT_SERVLET_URL, 'parse_pdf_fields', base64_encode($content));
if ($result->error == true) {
drupal_goto("admin/content/fillpdf");
}
$fields = $result->data;
}
elseif ($fillpdf_local_service) {
$require = drupal_get_path('module', 'fillpdf') . '/lib/JavaBridge/java/Java.inc';
require_once $require;
try {
$fillpdf = new java('com.ocdevel.FillpdfService', base64_encode($content), 'bytes');
$fields = java_values($fillpdf
->parse());
} catch (JavaException $e) {
drupal_set_message(java_truncate((string) $e), 'error');
drupal_goto("admin/content/fillpdf");
}
}
else {
$fields = fillpdf_execute_parse('pdftk', $filename);
}
foreach ((array) $fields as $key => $arr) {
if ($arr['type']) {
$arr['name'] = str_replace('�', '', $arr['name']);
$field = new stdClass();
$field->fid = $fid;
$field->pdf_key = $arr['name'];
$field->label = $arr['name'];
drupal_write_record('fillpdf_fields', $field);
}
}
}
function fillpdf_execute_parse($method, $fillpdf, $mode = 'url') {
switch ($mode) {
case 'url':
$filename = $fillpdf;
break;
case 'stream':
$filename = file_save_data($fillpdf, file_directory_temp() . '/pdf_data.pdf', FILE_EXISTS_RENAME);
break;
}
$output = array();
$status = NULL;
exec('pdftk ' . escapeshellarg($filename) . ' dump_data_fields', $output, $status);
if (in_array($status, array(
126,
127,
))) {
drupal_set_message(t('pdftk not properly installed.'), 'error');
return array();
}
elseif (count($output) === 0) {
drupal_set_message(t('PDF does not contain fillable fields.'), 'warning');
return array();
}
$data_fields_map = array(
'FieldType' => 'type',
'FieldName' => 'name',
'FieldFlags' => 'flags',
'FieldJustification' => 'justification',
);
$fields = array();
$fieldindex = -1;
foreach ($output as $line => $lineitem) {
if ($lineitem == '---') {
$fieldindex++;
continue;
}
$linedata = explode(':', $lineitem);
if (in_array($linedata[0], array_keys($data_fields_map))) {
$fields[$fieldindex][$data_fields_map[$linedata[0]]] = trim($linedata[1]);
}
}
if ($mode == 'stream') {
file_delete($filename);
}
return $fields;
}
function _fillpdf_get_file_contents($filepath, $error_goto = null) {
if ($error_goto && !file_exists($filepath)) {
drupal_set_message("{$filepath} does not exist. Check your\n filesystem settings, as well as http://drupal.org/node/764936", 'error');
drupal_goto($error_goto);
}
$handle = fopen($filepath, "r");
$content = fread($handle, filesize($filepath));
fclose($handle);
return $content;
}
function _fillpdf_xmlrpc_request($url, $method) {
$args = func_get_args();
$result = call_user_func_array('xmlrpc', $args);
$ret = new stdClass();
if (isset($result['error'])) {
drupal_set_message($result['error'], 'error');
$ret->error = true;
}
else {
if ($result == false || xmlrpc_error()) {
$error = xmlrpc_error();
$ret->error = true;
drupal_set_message("There was a problem contacting the Fill PDF service.\n It maybe be down, or you may not have internet access. [ERROR {$error->code}: {$error->message}]", 'error');
}
else {
$ret->data = $result['data'];
$ret->error = false;
}
}
return $ret;
}
function fillpdf_get_fields($fid) {
$result = db_query('select * from {fillpdf_fields} where fid = %d', $fid);
$return = array();
while ($result_array = db_fetch_array($result)) {
$return[$result_array['pdf_key']] = array(
'label' => $result_array['label'],
'value' => $result_array['value'],
);
}
return $return;
}
function _fillpdf_process_destination_path($destination_path, $token_objects) {
$orig_path = $destination_path;
$destination_path = trim($orig_path);
$types = array();
if (isset($token_objects['node'])) {
$types[] = 'node';
}
elseif (isset($token_objects['webform'])) {
$types[] = 'webform';
}
if (substr($destination_path, 0, 1) == '/') {
}
else {
$destination_path = file_directory_path() . "/{$destination_path}";
}
foreach ($types as $type) {
$destination_path = token_replace($destination_path, $type, $token_objects[$type]);
}
return $destination_path;
}
function _fillpdf_replacements_to_array($replacements) {
$standardized_replacements = str_replace(array(
"\r\n",
"\r",
), "\n", $replacements);
$lines = explode("\n", $standardized_replacements);
$return = array();
foreach ($lines as $replacement) {
if (!empty($replacement)) {
$split = explode('|', $replacement);
$return[$split[0]] = preg_replace('|<br />|', '
', $split[1]);
}
}
return $return;
}
function _fillpdf_transform_field_value($value, $pdf_replacements, $field_replacements) {
if (empty($pdf_replacements) && empty($field_replacements)) {
return $value;
}
elseif (!empty($field_replacements) && isset($field_replacements[$value])) {
return $field_replacements[$value];
}
elseif (!empty($pdf_replacements) && isset($pdf_replacements[$value])) {
return $pdf_replacements[$value];
}
else {
return $value;
}
}