/** * @dataProvider get_converted_document_provider */ public function test_get_converted_document($source, $sourcefilename, $format, $mimetype) { global $CFG; if (empty($CFG->pathtounoconv) || !file_is_executable(trim($CFG->pathtounoconv))) { // No conversions are possible, sorry. return $this->markTestSkipped(); } $this->resetAfterTest(); $filerecord = array('contextid' => context_system::instance()->id, 'component' => 'test', 'filearea' => 'unittest', 'itemid' => 0, 'filepath' => '/', 'filename' => $sourcefilename); $fs = get_file_storage(); //$testfile = $fs->create_file_from_string($filerecord, file_get_contents($source)); $testfile = $fs->create_file_from_pathname($filerecord, $source); $result = $fs->get_converted_document($testfile, $format); $this->assertNotFalse($result); $this->assertSame($mimetype, $result->get_mimetype()); $this->assertGreaterThan(0, $result->get_filesize()); // Repeat immediately with the file forcing re-generation. $new = $fs->get_converted_document($testfile, $format, true); $this->assertNotFalse($new); $this->assertSame($mimetype, $new->get_mimetype()); $this->assertGreaterThan(0, $new->get_filesize()); $this->assertNotEquals($result->get_id(), $new->get_id()); // Note: We cannot compare contenthash for PDF because the PDF has a unique ID, and a creation timestamp // imprinted in the file. }
public function test_generate_markdown() { global $CFG; if (empty($CFG->pathtounoconv) || !file_is_executable(trim($CFG->pathtounoconv))) { // No conversions are possible, sorry. return $this->markTestSkipped(); } $fs = get_file_storage(); $result = $fs->get_converted_document($this->testfile1, 'txt'); $this->assertNotFalse($result); $this->assertSame($result->get_mimetype(), 'text/plain'); $this->assertGreaterThan(0, $result->get_filesize()); $result = $fs->get_converted_document($this->testfile2, 'txt'); $this->assertNotFalse($result); $this->assertSame($result->get_mimetype(), 'text/plain'); $this->assertGreaterThan(0, $result->get_filesize()); }
/** * Perform a file format conversion on the specified document. * * @param stored_file $file the file we want to preview * @param string $format The desired format - e.g. 'pdf'. Formats are specified by file extension. * @return stored_file|bool false if unable to create the conversion, stored file otherwise */ protected function create_converted_document(stored_file $file, $format) { global $CFG; if (empty($CFG->pathtounoconv) || !file_is_executable(trim($CFG->pathtounoconv))) { // No conversions are possible, sorry. return false; } $fileextension = core_text::strtolower(pathinfo($file->get_filename(), PATHINFO_EXTENSION)); if (!self::is_format_supported_by_unoconv($fileextension)) { return false; } if (!self::is_format_supported_by_unoconv($format)) { return false; } // Copy the file to the tmp dir. $uniqdir = "core_file/conversions/" . uniqid($file->get_id() . "-", true); $tmp = make_temp_directory($uniqdir); $localfilename = $file->get_filename(); // Safety. $localfilename = clean_param($localfilename, PARAM_FILE); $filename = $tmp . '/' . $localfilename; try { // This function can either return false, or throw an exception so we need to handle both. if ($file->copy_content_to($filename) === false) { throw new file_exception('storedfileproblem', 'Could not copy file contents to temp file.'); } } catch (file_exception $fe) { remove_dir($uniqdir); throw $fe; } $newtmpfile = pathinfo($filename, PATHINFO_FILENAME) . '.' . $format; // Safety. $newtmpfile = $tmp . '/' . clean_param($newtmpfile, PARAM_FILE); $cmd = escapeshellcmd(trim($CFG->pathtounoconv)) . ' ' . escapeshellarg('-f') . ' ' . escapeshellarg($format) . ' ' . escapeshellarg('-o') . ' ' . escapeshellarg($newtmpfile) . ' ' . escapeshellarg($filename); $output = null; $currentdir = getcwd(); chdir($tmp); $result = exec($cmd, $output); chdir($currentdir); if (!file_exists($newtmpfile)) { remove_dir($uniqdir); // Cleanup. return false; } $context = context_system::instance(); $record = array('contextid' => $context->id, 'component' => 'core', 'filearea' => 'documentconversion', 'itemid' => 0, 'filepath' => '/' . $format . '/', 'filename' => $file->get_contenthash()); $convertedfile = $this->create_file_from_pathname($record, $newtmpfile); // Cleanup. remove_dir($uniqdir); return $convertedfile; }
/** * Perform a file format conversion on the specified document. * * @param stored_file $file the file we want to preview * @param string $format The desired format - e.g. 'pdf'. Formats are specified by file extension. * @return stored_file|bool false if unable to create the conversion, stored file otherwise */ protected function create_converted_document(stored_file $file, $format) { global $CFG; if (empty($CFG->pathtounoconv) || !file_is_executable(trim($CFG->pathtounoconv))) { // No conversions are possible, sorry. return false; } $fileextension = core_text::strtolower(pathinfo($file->get_filename(), PATHINFO_EXTENSION)); if (!self::is_format_supported_by_unoconv($fileextension)) { return false; } if (!self::is_format_supported_by_unoconv($format)) { return false; } // Copy the file to the local tmp dir. $tmp = make_request_directory(); $localfilename = $file->get_filename(); // Safety. $localfilename = clean_param($localfilename, PARAM_FILE); $filename = $tmp . '/' . $localfilename; $file->copy_content_to($filename); $newtmpfile = pathinfo($filename, PATHINFO_FILENAME) . '.' . $format; // Safety. $newtmpfile = $tmp . '/' . clean_param($newtmpfile, PARAM_FILE); $cmd = escapeshellcmd(trim($CFG->pathtounoconv)) . ' ' . escapeshellarg('-f') . ' ' . escapeshellarg($format) . ' ' . escapeshellarg('-o') . ' ' . escapeshellarg($newtmpfile) . ' ' . escapeshellarg($filename); $e = file_exists($filename); $output = null; $currentdir = getcwd(); chdir($tmp); $result = exec($cmd, $output); chdir($currentdir); if (!file_exists($newtmpfile)) { return false; } $context = context_system::instance(); $record = array('contextid' => $context->id, 'component' => 'core', 'filearea' => 'documentconversion', 'itemid' => 0, 'filepath' => '/' . $format . '/', 'filename' => $file->get_contenthash()); return $this->create_file_from_pathname($record, $newtmpfile); }
/** * Method used to check the installed unoconv version. * * @param environment_results $result object to update, if relevant. * @return environment_results|null updated results or null if unoconv path is not executable. */ function check_unoconv_version(environment_results $result) { global $CFG; if (!during_initial_install() && !empty($CFG->pathtounoconv) && file_is_executable(trim($CFG->pathtounoconv))) { $currentversion = 0; $supportedversion = 0.7; $unoconvbin = \escapeshellarg($CFG->pathtounoconv); $command = "{$unoconvbin} --version"; exec($command, $output); // If the command execution returned some output, then get the unoconv version. if ($output) { foreach ($output as $response) { if (preg_match('/unoconv (\\d+\\.\\d+)/', $response, $matches)) { $currentversion = (double) $matches[1]; } } } if ($currentversion < $supportedversion) { $result->setInfo('unoconv version not supported'); $result->setStatus(false); return $result; } } return null; }
/** * Returns an XHTML field * * @param string $data This is the value for the field * @param string $query * @return string XHTML field */ public function output_html($data, $query = '') { global $CFG; $default = $this->get_defaultsetting(); require_once "{$CFG->libdir}/filelib.php"; if ($data) { if (file_exists($data) and !is_dir($data) and file_is_executable($data)) { $executable = '<span class="pathok">✔</span>'; } else { $executable = '<span class="patherror">✘</span>'; } } else { $executable = ''; } $readonly = ''; if (!empty($CFG->preventexecpath)) { $this->visiblename .= '<div class="form-overridden">' . get_string('execpathnotallowed', 'admin') . '</div>'; $readonly = 'readonly="readonly"'; } return format_admin_setting($this, $this->visiblename, '<div class="form-file defaultsnext"><input ' . $readonly . ' type="text" size="' . $this->size . '" id="' . $this->get_id() . '" name="' . $this->get_full_name() . '" value="' . s($data) . '" />' . $executable . '</div>', $this->description, true, '', $default, $query); }
/** * Returns an XHTML field * * @param string $data This is the value for the field * @param string $query * @return string XHTML field */ public function output_html($data, $query='') { global $CFG, $OUTPUT; $default = $this->get_defaultsetting(); require_once("$CFG->libdir/filelib.php"); $context = (object) [ 'id' => $this->get_id(), 'name' => $this->get_full_name(), 'size' => $this->size, 'value' => $data, 'showvalidity' => !empty($data), 'valid' => $data && file_exists($data) && !is_dir($data) && file_is_executable($data), 'readonly' => !empty($CFG->preventexecpath), 'forceltr' => $this->get_force_ltr() ]; if (!empty($CFG->preventexecpath)) { $this->visiblename .= '<div class="form-overridden">'.get_string('execpathnotallowed', 'admin').'</div>'; } $element = $OUTPUT->render_from_template('core_admin/setting_configexecutable', $context); return format_admin_setting($this, $this->visiblename, $element, $this->description, true, '', $default, $query); }
/** * Method used to check the installed unoconv version. * * @param environment_results $result object to update, if relevant. * @return environment_results|null updated results or null if unoconv path is not executable. */ function check_unoconv_version(environment_results $result) { global $CFG; if (!during_initial_install() && !empty($CFG->pathtounoconv) && file_is_executable(trim($CFG->pathtounoconv))) { $unoconvbin = \escapeshellarg($CFG->pathtounoconv); $command = "{$unoconvbin} --version"; exec($command, $output); preg_match('/([0-9]+\\.[0-9]+)/', $output[0], $matches); $currentversion = (double) $matches[0]; $supportedversion = 0.7; if ($currentversion < $supportedversion) { $result->setInfo('unoconv version not supported'); $result->setStatus(false); return $result; } } return null; }