diff --git a/application/libraries/DocsboxLib.php b/application/libraries/DocsboxLib.php new file mode 100644 index 000000000..f9167c379 --- /dev/null +++ b/application/libraries/DocsboxLib.php @@ -0,0 +1,304 @@ +attach(array('file' => $inputFileName)) + ->expectsJson() + ->send(); + + // Checks that: + // - the response is not empty + // - the reponse body has the property id + // - the property id is a valid string + // - the reponse body has the property status + // - docsbox queued the conversion of the posted file + if (is_object($postFileResponse) + && isset($postFileResponse->body) + && isset($postFileResponse->body->id) + && $postFileResponse->body->id != '' && $postFileResponse->body->id != null + && isset($postFileResponse->body->status) + && $postFileResponse->body->status == self::STATUS_QUEUED) + { + $queueId = $postFileResponse->body->id; + } + else + { + // If docsbox refused to convert the posted file + if (isset($postFileResponse->body->status) + && $postFileResponse->body->status != self::STATUS_QUEUED) + { + error_log( + 'Docsbox did not queue the posted file. Returned status: '. + $postFileResponse->body->status + ); + } + else // any other generic error + { + error_log( + 'An error occurred while posting to docsbox. Response: '. + print_r($postFileResponse, 1) + ); + } + } + } + catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception + { + error_log($cee->getMessage()); + } + catch (Exception $e) // any other exception + { + error_log($e->getMessage()); + } + + return $queueId; + } + + /** + * Check the status of the file convertion identified by the given queue element id + * A URL is returned with the path where it is possible to download the converted file + * If an error occurred then a null value is returned + */ + private static function _checkConvertion($queueId) + { + $resultUrl = null; + $startConvertionsTime = time(); // time when the file conversion has started + + // Until a timeout has occurred + while (time() - $startConvertionsTime <= DOCSBOX_CONVERSION_TIMEOUT) + { + sleep(DOCSBOX_WAITING_SLEEP_TIME); // takes a nap on every round + + try + { + // Calls the docsbox server to check the status of the + // file conversion using the provided queue id + // it expects a response in JSON format + $getStatusResponse = \Httpful\Request::get(DOCSBOX_SERVER.DOCSBOX_PATH_API.$queueId) + ->expectsJson() + ->send(); + + // Checks that: + // - the response is not empty + // - the reponse body has the property id + // - the property id is a valid string + // - the reponse body has the property status + // - docsbox is working the conversion of the posted file + if (is_object($getStatusResponse) + && isset($getStatusResponse->body->id) + && $getStatusResponse->body->id != '' && $getStatusResponse->body->id != null + && isset($getStatusResponse->body->status)) + { + // Checks that docsbox has finished working on the file conversion + // and that there is a valid resultUrl property + if ($getStatusResponse->body->status == self::STATUS_FINISHED + && isset($getStatusResponse->body->result_url) + && $getStatusResponse->body->result_url != '' + && $getStatusResponse->body->result_url != null) + { + $resultUrl = $getStatusResponse->body->result_url; + break; + } + // Just started or still working on it + elseif ($getStatusResponse->body->status == self::STATUS_WORKING + || $getStatusResponse->body->status == self::STATUS_STARTED) + { + // go on! + } + else // any other status is abnormal + { + error_log( + 'Not valid status for queue element: '.$queueId.'. Response: '. + print_r($getStatusResponse, 1) + ); + break; // interrupt the loop on error + } + } + else // if the response from the docsbox server is not valid + { + error_log( + 'An error occurred while checking the docsbox activity. Response: '. + print_r($getStatusResponse, 1) + ); + break; // interrupt the loop on error + } + } + catch(\Httpful\Exception\ConnectionErrorException $cee) // Httpful exception + { + error_log($cee->getMessage()); + break; // interrupt the loop on error + } + catch (Exception $e) // any other exception + { + error_log($e->getMessage()); + break; // interrupt the loop on error + } + } + + return $resultUrl; + } + + /** + * Download the converted file using the provided URL, unzip it, and renames it into the provided file name + */ + private static function _downloadFile($resultUrl, $outputFileName) + { + $downloaded = false; // pessimistic assumption + + try + { + // Download the file + $getFileResponse = \Httpful\Request::get(DOCSBOX_SERVER.$resultUrl)->send(); + + // If the downloaded file content is valid and not empty + if (isset($getFileResponse->body) + && $getFileResponse->body != null + && $getFileResponse->body != '') + { + // Output directory where to unzip the downloaded zip file + $outputDirectory = dirname($outputFileName); + // The path and name of the downloaded zip file + $temporaryDownloadedZip = sys_get_temp_dir().'/'.basename($resultUrl); + + // Write the file content into a temporary directory and file + if (file_put_contents($temporaryDownloadedZip, $getFileResponse->body) != false) + { + $zipArchive = new ZipArchive; + + // Open and extract the dowloaded zip file into the directory of the output file + if ($zipArchive->open($temporaryDownloadedZip) === true + && $zipArchive->extractTo($outputDirectory) === true + && $zipArchive->close() === true) + { + // Opened, extracted and closed! + + // Rename the extracted file to the given output file name + if (rename($outputDirectory.'/'.self::OUTPUT_FILENAME, $outputFileName)) + { + $downloaded = true; + } + else + { + error_log( + 'An error occurred while renaming the extracted file: '. + $outputDirectory.'/'.self::OUTPUT_FILENAME.' into: '. + $outputFileName + ); + } + } + else + { + error_log( + 'An error occurred while working the dowloaded zip file: '. + $temporaryDownloadedZip + ); + } + } + else // if an error occurred while writing + { + error_log( + 'An error occurred while writing the file content to: '. + $temporaryDownloadedZip + ); + } + } + else // if the downloaded file is not valid + { + error_log( + 'An error occurred while downloading the file from the docsbox server: '. + print_r($getFileResponse, 1) + ); + } + } + catch(\Httpful\Exception\ConnectionErrorException $cee) + { + error_log($cee->getMessage()); + } + catch (Exception $e) + { + error_log($e->getMessage()); + } + + return $downloaded; + } +} + diff --git a/application/libraries/DocumentLib.php b/application/libraries/DocumentLib.php index 98e546b4e..c1dd21c29 100644 --- a/application/libraries/DocumentLib.php +++ b/application/libraries/DocumentLib.php @@ -14,20 +14,28 @@ class DocumentLib // Gets CI instance $this->ci =& get_instance(); - exec('unoconv --version', $ret_arr); - - if(isset($ret_arr[0])) + // Which document converter has to be used + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) { - $hlp = explode(' ', $ret_arr[0]); - if(isset($hlp[1])) - { - $this->unoconv_version = $hlp[1]; - } - else - show_error('Could not get Unoconv Version'); + // Use docsbox!! } else - show_error('Unoconv not found - Please install Unoconv'); + { + exec('unoconv --version', $ret_arr); + + if(isset($ret_arr[0])) + { + $hlp = explode(' ', $ret_arr[0]); + if(isset($hlp[1])) + { + $this->unoconv_version = $hlp[1]; + } + else + show_error('Could not get Unoconv Version'); + } + else + show_error('Unoconv not found - Please install Unoconv'); + } } /** @@ -57,9 +65,16 @@ class DocumentLib case 'application/vnd.ms-word': case 'application/vnd.oasis.opendocument.text': case 'text/plain': - // Unoconv Version 0.6 seems to fail on converting TXT Files - if ($this->unoconv_version == '0.6') - return error(); + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) + { + // Use docsbox + } + else + { + // Unoconv Version 0.6 seems to fail on converting TXT Files + if ($this->unoconv_version == '0.6') + return error(); + } $ret = $this->convert($filename, $outFile, 'pdf'); if(isSuccess($ret)) @@ -105,6 +120,7 @@ class DocumentLib finfo_close($finfo); + $out = null; exec($cmd, $out, $ret); if ($ret != 0) { @@ -123,13 +139,26 @@ class DocumentLib */ public function convert($inFile, $outFile, $format) { - if ($this->unoconv_version == '0.6') - $command = 'unoconv -f %1$s %3$s > %2$s'; - else - $command = 'unoconv -f %s --output %s %s 2>&1'; - $command = sprintf($command, $format, $outFile, $inFile); + $ret = 0; - exec($command, $out, $ret); + // If it is set to use docsbox + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) + { + require_once(dirname(__FILE__).'/../application/libraries/DocsboxLib.php'); + + $ret = DocsboxLib::convert($inFile, $outFile, $format); + } + else // otherwise use unoconv + { + if ($this->unoconv_version == '0.6') + $command = 'unoconv -f %1$s %3$s > %2$s'; + else + $command = 'unoconv -f %s --output %s %s 2>&1'; + $command = sprintf($command, $format, $outFile, $inFile); + + $out = null; + exec($command, $out, $ret); + } if ($ret != 0) { @@ -191,6 +220,7 @@ class DocumentLib $cmd .= '/countspaces { [ exch { dup 32 ne { pop } if } forall ] length } bind def >> '; $cmd .= 'setpagedevice viewJPEG"'; + $out = null; exec($cmd, $out, $ret); if ($ret != 0) { diff --git a/config/cis.config-default.inc.php b/config/cis.config-default.inc.php index 027af9504..cb670b5dd 100644 --- a/config/cis.config-default.inc.php +++ b/config/cis.config-default.inc.php @@ -260,10 +260,17 @@ define('CIS_ZEITWUNSCH_GD', false); // Covid-Status anzeigen define('CIS_SHOW_COVID_STATUS', false); +// Docsbox configs +define('DOCSBOX_SERVER', 'http://docconverter.technikum-wien.at/'); +define('DOCSBOX_PATH_API', 'api/v1/'); +define('DOCSBOX_CONVERSION_TIMEOUT', 30); // seconds +define('DOCSBOX_WAITING_SLEEP_TIME', 1); + //Vertrag Allin define ('DEFAULT_ALLIN_DIENSTVERTRAG',[111]); //Echter Dienstvertrag define ('DEFAULT_ECHTER_DIENSTVERTRAG',[103,111]); + ?> diff --git a/config/global.config-default.inc.php b/config/global.config-default.inc.php index 0380ea8d5..8990bbd81 100644 --- a/config/global.config-default.inc.php +++ b/config/global.config-default.inc.php @@ -316,4 +316,7 @@ define ('ZAHLUNGSBESTAETIGUNG_ANZEIGEN_FUER_LEHRGAENGE', true); // Gibt an, ob im CIS die Zahlungsreferenz angezeigt wird define ('ZAHLUNGSBESTAETIGUNG_ZAHLUNGSREFERENZ_ANZEIGEN', false); + +define('DOCSBOX_ENABLED', false); + ?> diff --git a/config/vilesci.config-default.inc.php b/config/vilesci.config-default.inc.php index 17f668b90..e98de9ce0 100644 --- a/config/vilesci.config-default.inc.php +++ b/config/vilesci.config-default.inc.php @@ -257,6 +257,12 @@ define('BIS_FUNKTIONSCODE_6_ARR', array( // bPk Abfrage define('BPK_FUER_ALLE_BENUTZER_ABFRAGEN', false); +// Docsbox configs +define('DOCSBOX_SERVER', 'http://docconverter.technikum-wien.at/'); +define('DOCSBOX_PATH_API', 'api/v1/'); +define('DOCSBOX_CONVERSION_TIMEOUT', 30); // seconds +define('DOCSBOX_WAITING_SLEEP_TIME', 1); + // Bei folgenden Buchungstypen wird ein Anlegen geprüft ob bereits ein Eintrag für diesen Typ vorhanden ist im selben // Semester und ggf ein Hinweis ausgegeben define('FAS_DOPPELTE_BUCHUNGSTYPEN_CHECK', serialize( @@ -269,6 +275,8 @@ define('ZEUGNISNOTE_NICHT_ANZEIGEN',serialize(array('iar', 'nz'))); //Default Lehrmodus define ('DEFAULT_LEHRMODUS','regulaer'); + //Echter Dienstvertrag define ('DEFAULT_ECHTER_DIENSTVERTRAG',[103,110]); + ?> diff --git a/include/dokument_export.class.php b/include/dokument_export.class.php index 4f23a7dcd..0d4f2c660 100644 --- a/include/dokument_export.class.php +++ b/include/dokument_export.class.php @@ -50,17 +50,24 @@ class dokument_export if(!isset($vorlage)) return; - exec('unoconv --version',$ret_arr); - if(isset($ret_arr[0])) + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) { - $hlp = explode(' ',$ret_arr[0]); - if(isset($hlp[1])) - $this->unoconv_version = $hlp[1]; - else - die('Could not get Unoconv Version'); + // Use docsbox!! } else - die('Unoconv not found'); + { + exec('unoconv --version',$ret_arr); + if(isset($ret_arr[0])) + { + $hlp = explode(' ',$ret_arr[0]); + if(isset($hlp[1])) + $this->unoconv_version = $hlp[1]; + else + die('Could not get Unoconv Version'); + } + else + die('Unoconv not found'); + } //Vorlage aus der Datenbank holen $this->vorlage = new vorlage(); @@ -276,21 +283,32 @@ class dokument_export { case 'pdf': case 'doc': + $ret = 0; $this->temp_filename = $this->temp_folder . '/out.' . $this->outputformat; - // Unoconv Version 0.6 hat eine Bug wodurch die Berechtigungen des PDF/Doc nicht korrekt gesetzt - // werden. Deshalb wird dies hier speziell behandelt. - // Die 2. Variante hat den Vorteil dass hier eine bessere Fehlerbehandlung moeglich ist - if($this->unoconv_version=='0.6') - $command = 'unoconv -e IsSkipEmptyPages=false -f ' . $this->outputformat . ' %2$s > %1$s'; - else - $command = 'unoconv -e IsSkipEmptyPages=false -f ' . $this->outputformat . ' --output %s %s 2>&1'; + // If it is set to use docsbox + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) + { + require_once(dirname(__FILE__).'/../application/libraries/DocsboxLib.php'); - $command = sprintf($command, $this->temp_filename, $tempname_zip); + $ret = DocsboxLib::convert($tempname_zip, $this->temp_filename, $this->outputformat); + } + else // otherwise use unoconv + { + // Unoconv Version 0.6 hat eine Bug wodurch die Berechtigungen des PDF/Doc nicht korrekt gesetzt + // werden. Deshalb wird dies hier speziell behandelt. + // Die 2. Variante hat den Vorteil dass hier eine bessere Fehlerbehandlung moeglich ist + if ($this->unoconv_version == '0.6') + $command = 'unoconv -e IsSkipEmptyPages=false -f ' . $this->outputformat . ' %2$s > %1$s'; + else + $command = 'unoconv -e IsSkipEmptyPages=false -f ' . $this->outputformat . ' --output %s %s 2>&1'; - exec($command, $out, $ret); + $command = sprintf($command, $this->temp_filename, $tempname_zip); - if($ret!=0) + exec($command, $out, $ret); + } + + if ($ret != 0) { $this->errormsg = 'Dokumentenkonvertierung ist derzeit nicht möglich. Bitte versuchen Sie es in einer Minute erneut oder kontaktieren Sie einen Administrator'; return false; @@ -455,15 +473,27 @@ class dokument_export */ public function convert($inFile, $outFile, $format = "pdf") { - if($this->unoconv_version=='0.6') - $command = 'unoconv -f %1$s %3$s > %2$s'; - else - $command = 'unoconv -f %s --output %s %s 2>&1'; - $command = sprintf($command, $format, $outFile, $inFile); + $ret = 0; - exec($command, $out, $ret); + // If it is set to use DOCSBOX + if (defined('DOCSBOX_ENABLED') && DOCSBOX_ENABLED === true) + { + require_once(dirname(__FILE__).'/../application/libraries/DocsboxLib.php'); - if($ret!=0) + $ret = DocsboxLib::convert($inFile, $outFile, $format); + } + else // fallback to unoconv + { + if($this->unoconv_version=='0.6') + $command = 'unoconv -f %1$s %3$s > %2$s'; + else + $command = 'unoconv -f %s --output %s %s 2>&1'; + $command = sprintf($command, $format, $outFile, $inFile); + + exec($command, $out, $ret); + } + + if ($ret != 0) { $this->errormsg = 'Dokumentenkonvertierung ist derzeit nicht möglich. Bitte versuchen Sie es in einer Minute erneut oder kontaktieren Sie einen Administrator'; return false;