1<?php 2/** 3 * Action Plugin 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Greg BELLAMY <garlik.crx@gmail.com> [Gag] 7 * @version 0.08beta 8 */ 9// must be run within Dokuwiki 10if(!defined('DOKU_INC')) die(); 11if (!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN', DOKU_INC . 'lib/plugins/'); 12 13class action_plugin_odt2dw extends DokuWiki_Action_Plugin { 14 15 /** 16 * Registers a callback function for a given event 17 */ 18 function register(Doku_Event_Handler $controller) { 19 // OdtFile Parser hook 20 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, '_parser', array()); 21 // Display form hook before the wiki page (on top); Maybe create a param to display the form after the page 22 $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, '_render', array()); 23 $controller->register_hook('TEMPLATE_PAGETOOLS_DISPLAY', 'BEFORE', $this, 'addbutton', array()); 24 } 25 26 /** 27 * Add 'import odt'-button to pagetools 28 * 29 * @param Doku_Event $event 30 * @param mixed $param not defined 31 */ 32 public function addbutton(&$event, $param) { 33 global $ID, $REV, $conf; 34 35 if($this->getConf('showimportbutton') && $event->data['view'] == 'main') { 36 $params = array('do' => 'odt2dw'); 37 if($REV) $params['rev'] = $REV; 38 39 switch($conf['template']) { 40 case 'dokuwiki': 41 case 'arago': 42 $event->data['items']['import_odt'] = 43 '<li>' 44 .'<a href='.wl($ID, $params).' class="action import_odt" rel="nofollow" title="'.$this->getLang('import_odt_button').'">' 45 .'<span>'.$this->getLang('import_odt_button').'</span>' 46 .'</a>' 47 .'</li>'; 48 break; 49 } 50 } 51 } 52 53 function _render(&$event, $param) { 54 ### _render : displays the upload form in the pages according to authorized action 55 # INPUT : it's a dokuwiki event function 56 # OUTPUT : void 57 # DISPLAY : upload form 58 global $ID, $lang; 59 // Check if the current action is in the action allow table 60 if ( strpos( $this->getConf('formDisplayRule'), $event->data) === false ) return; 61 // Check if the page exists 62 if ( page_exists( $ID ) && $event->data != "odt2dw" ) return; 63 if ( page_exists( $ID ) ) echo p_render('xhtml',p_get_instructions( $this->getLang( 'formPageExistMessage' ) ), $info ); 64 // Check auth user can edit this page 65 if ( auth_quickaclcheck( $ID ) < AUTH_EDIT ) return; 66 // If all check is ok, display the form 67 $message = $this->getConf('formIntroMessage'); 68 if ( $message == 'default' ) $message = $this->getLang('formIntroMessage'); 69 if ($message) echo p_render('xhtml',p_get_instructions($message),$info); 70 // FIXME create the form with dokuwiki method ? 71 echo '<form method="post" action="" enctype="multipart/form-data"> 72<fieldset> 73<legend>'.$this->getLang('formLegend').'</legend> 74<input type="hidden" name="MAX_FILE_SIZE" value="'.$this->getConf('formMaxFileSize').'"/> 75<input type="hidden" name="do" value="odt2dw"/> 76<input type="hidden" name="id" value="'.$ID.'"/> 77<input type="file" name="odtFile"/> 78<input type="submit" value="'.$lang['btn_upload'].'"/> 79</fieldset> 80</form>'; 81 if ( $event->data == 'odt2dw' ) $event->preventDefault(); 82 } 83 84 function _parser(&$event, $param) { 85 ### _parser : check if an odtFile migth be upload than call the odt2dw converter 86 # INPUT : it's a dokuwiki event function 87 # OUTPUT : void 88 89 // Check action is odt2dw 90 if ( $event->data != 'odt2dw' ) return; 91 92 ###Preparation of the message renderer 93 //Set the debug lvl 94 $this->debug = $this->getConf( 'debugLvl' ); 95 //If used, open the logFile 96 if ( $this->debug >= 2 ) { 97 $this->logFile = $this->getConf( 'logFile' ); 98 if ( isset( $this->logFile ) ) if ( file_exists( dirname( $this->logFile ) ) || mkdir( dirname( $this->logFile ) ) ) { 99 if ( ! ( $this->logFileHandle = @fopen( $this->logFile, 'a' ) ) ) unset( $this->logFileHandle, $this->logFile ); 100 } else unset( $this->logFile ); 101 if ( ! isset( $this->logFileHandle ) ) $this->_msg( 'er_logFile' ); 102 } 103 ### 104 105 // Check upload file defined 106 $retour = false; 107 if ( $_FILES['odtFile'] ) { 108 // If parse work, change action to defined one in conf/local.php file 109 $retour = $this->_odt2dw(); 110 # Delete temp file 111 $this->_purge_env(); 112 } 113 //if the file is correctly parsed, change the action to the action defined in the conf 114 //otherwise the action stay odt2dw -> the display form hook will be call by render trigger 115 if ( $retour === true ) { 116 $event->data = $this->getConf('parserPostDisplay'); 117 } else { 118 $event->preventDefault(); 119 } 120 121 ### Clear the message renderer 122 // Close the log file if used 123 if ( isset( $this->logFileHandle ) ) @fclose( $this->logFileHandle ); 124 ### 125 } 126 127 function _odt2dw() { 128 ### _odt2dw : Translate an odt File into dokuwiki syntax 129 # OUTPUT : 130 # * true -> process successfully 131 # * false -> something wrong; using _msg to display what's wrong 132 133 global $ID, $conf; 134 135 //Table use to convert urn to url -> without this, xslProc won t parse correctly 136 //Table corrigeant les attributs de la racine du fichier content.xml : urn -> url 137 $this->conversion = array( 138 "xmlns:office" => "http://openoffice.org/2000/office", 139 "xmlns:style" => "http://openoffice.org/2000/style", 140 "xmlns:text" => "http://openoffice.org/2000/text", 141 "xmlns:table" => "http://openoffice.org/2000/table", 142 "xmlns:draw" => "http://openoffice.org/2000/drawing", 143 "xmlns:fo" => "http://www.w3.org/1999/XSL/Format", 144 "xmlns:xlink" => "http://www.w3.org/1999/xlink", 145 "xmlns:dc" => "http://purl.org/dc/elements/1.1/", 146 "xmlns:meta" => "http://openoffice.org/2000/meta", 147 "xmlns:number" => "http://openoffice.org/2000/datastyle", 148 "xmlns:svg" => "http://www.w3.org/2000/svg", 149 "xmlns:chart" => "http://openoffice.org/2000/chart", 150 "xmlns:dr3d" => "http://openoffice.org/2000/dr3d", 151 "xmlns:math" => "http://www.w3.org/1998/Math/MathML", 152 "xmlns:form" => "http://openoffice.org/2000/form", 153 "xmlns:script" => "http://openoffice.org/2000/script", 154 "xmlns:config" => "http://openoffice.org/2001/config", 155 "xmlns:ooo" => "http://openoffice.org/2004/office", 156 "xmlns:ooow" => "http://openoffice.org/2004/writer", 157 "xmlns:oooc" => "http://openoffice.org/2004/calc", 158 "xmlns:dom" => "http://www.w3.org/2001/xml-events", 159 "xmlns:xforms" => "http://www.w3.org/2002/xforms", 160 "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema", 161 "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance", 162 "xmlns:rpt" => "http://openoffice.org/2005/report", 163 "xmlns:of" => "urn:oasis:names:tc:opendocument:xmlns:of:1.2", 164 "xmlns:xhtml" => "http://www.w3.org/1999/xhtml", 165 "xmlns:grddl" => "http://www.w3.org/2003/g/data-view#", 166 "xmlns:tableooo" => "http://openoffice.org/2009/table", 167 "xmlns:css3t" => "http://www.w3.org/TR/css3-text/" 168 ); 169 // urn wont be/need to convert -- keep for further odtFile version 170 // "xmlns:field" => "urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0", 171 //"xmlns:formx" => "urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0", 172 // CONSTANT : Content file extract from the odt file 173 $this->xmlFile = "content.xml"; 174 175 ### Check parameter ### 176 177 // Page receive content 178 if ( ! $this->pageName = $ID ) return $this->_msg('er_id'); 179 $this->nsName = getNS($this->pageName); 180 // Check right to change the page 181 if ( page_exists($ID) ) { 182 if ( auth_quickaclcheck($ID) < AUTH_EDIT ) return $this->_msg('er_acl_edit'); 183 } else { 184 if ( auth_quickaclcheck($ID) < AUTH_CREATE ) return $this->_msg('er_acl_create'); 185 } 186 187 // Check the Odt file uploaded 188 if ( ! $this->_checkUploadFile() ) return $this->_msg('er_checkUploadResult'); 189 190 // Check the xslFile 191 if ( ! $this->getConf( 'parserXslFile' ) ) return $this->_msg('er_xslFile_notset'); 192 $this->xslFile = DOKU_PLUGIN.'odt2dw/'.$this->getConf('parserXslFile'); 193 if ( ! file_exists($this->xslFile) ) return $this->_msg('er_xslFile_exists'); 194 if ( ! is_file($this->xslFile) ) return $this->_msg('er_xslFile_isfile'); 195 196 // Class Control 197 if ( ! class_exists( XSLTProcessor ) ) return $this->_msg('er_class_xsltProcessor'); 198 if ( ! class_exists( ZipArchive ) ) return $this->_msg('er_class_zipArchive'); 199 if ( ! class_exists( DOMDocument ) ) return $this->_msg('er_class_domDocument'); 200 // Create instance of needed class 201 $this->XSLT = new XSLTProcessor; 202 $this->ZIP = new ZipArchive; 203 $this->XSL = new DOMDocument; 204 $this->XML = new DOMDocument; 205 206 // Load the xslFile 207 if ( ! ($this->XSL->load( $this->xslFile ) ) ) return $this->_msg('er_loadXsl'); 208 // Build the xsl processor 209 if ( ! $this->_set_xsltProcessor() ) return $this->_msg('er_xsltProc'); 210 // Extract content file from odtFile 211 if ( ! $this->_unzip( $this->xmlFile ) ) return $this->_msg('er_odtFile_unzip'); 212 // Load the xmlFile 213 if ( ! $this->XML->load($this->uploadDir.'/'.$this->xmlFile) ) return $this->_msg('er_loadXml'); 214 if ( ! $this->racine = $this->XML->getElementsByTagName('document-content')->item(0) ) return $this->_msg('er_invalidRoot'); 215 // Correction for urn bug 216 foreach ( $this->conversion as $attr => $value ) if ( $this->racine->hasAttribute($attr) ) $this->racine->setAttributeNS( "http://www.w3.org/2000/xmlns/", $attr, $value ); 217 // Transformation du fichier XML 218 $this->result = '====== '.basename($this->odtFileName,'.odt').' ====== 219'; 220 if ( $this->getConf('parserLinkToOriginalFile') && auth_quickaclcheck($ID) >= AUTH_UPLOAD ) $this->result .= '<sub>{{'.$this->odtFileName.'|'.$this->getLang('parserOriginalFile').'}}</sub> 221 222'; 223 224 ### Parameters have been checked successfully ### 225 226 227 // Set specific time out to parse the odtfile into dw syntax 228 set_time_limit( $this->getConf('parserCoreTimeOut') ); 229 // Parse the content - This is the CORE 230 if ( ! $tmp = html_entity_decode($this->XSLT->transformToDoc( $this->XML )->saveHTML(), ENT_COMPAT, 'UTF-8') ) return $this->_msg('er_transform'); 231 $this->result .= $tmp; 232 // Set the time out to default 233 set_time_limit(30); 234 // Extract and store image files from odtFile to Dokuwiki mediaManager 235 $this->_parse_image(); 236 237 // Store the result 238 if ( ! $this->_apply_result() ) return $this->_msg('er_apply'); 239 240 return true; 241 } 242 243 function _msg( $message, $type=null, $force=false ) { 244 ### _msg : display message using the debugLvl value 245 # $message : mixed : 246 # * string : key for $this->getLang() function 247 # * array : 248 # $message[0] : string : key for $this->getLang() function 249 # $message[1] : string : additional information 250 # $type : integer : (check the dokuwiki msg function) 251 # * -1 : error message 252 # * 0 : normal message 253 # * 1 : info message 254 # if type == null, the first 3 char of the key define the message type 255 # * er_ : -1 256 # * ok_ : 1 257 # * otherwise : 0 258 # $force : boolean : force displaying the message without checking debugLvl 259 # OUTPUT : 260 # * true -> display a normal message 261 # * false -> display an error message 262 # DISPLAY : call dokuwiki msg function 263 if ( is_array( $message ) ) { 264 $output = $message[0]; 265 } else { 266 $output = $message; 267 } 268 // If output is empty, crash with error display; 269 if ( ! $output ) die( $this->getLang( 'er_msg_nomessage' ) ); 270 if ( is_null( $type ) ) { 271 $val = substr( $output, 0, strpos( $output, '_' )+1 ); 272 switch ($val) { 273 case 'er_' : 274 $err = -1; 275 break; 276 case 'ok_' : 277 $err = 1; 278 break; 279 default : 280 $err = 0; 281 } 282 } else { 283 if ( $type < -1 || $type > 1 ) return false; 284 $err = $type; 285 } 286 // Dev debugging mode; manually set to 4; this dirtily display some informations 287 if ( $this->debug > 3 ) echo '<p>message : '.$message.' |output : '.$output.' |val : '.$val.' |err : '.$err.'</p>'; 288 289 // Debug = 0 => No message 290 if ( !$force && $this->debug == 0 ) return ( $err == -1 ? false : true ); 291 292 // Debug < 3 => Only error message; If it s not an error message, message return true; 293 if ( !$force && $err != -1 && $this->debug < 3 ) return true; 294 // Otherwise display the message 295 $content = $output.' : '.$this->getLang( $output ).( is_array( $message ) ? ' : '.$message[1] : '' ); 296 msg( 'odt2dw : '.$content, $err ); 297 if ( isset( $this->logFileHandle ) ) fwrite( $this->logFileHandle, date(DATE_ATOM).':'.$_SERVER['REMOTE_USER'].':'.$content.' 298' ); 299 // If error message, return false 300 if ( $err == -1 ) return false; 301 // Otherwise return true; 302 return true; 303 } 304 305 306 307 function _checkUploadFile() { 308 ### _checkUploadFile : group all process about the uploadFile, like uploadStatus, file format, move it in a working directory, etc. ### 309 # OUTPUT : 310 # * true -> process successfully 311 # * false -> something wrong; using _msg to display what's wrong 312 // Check a file will be upload 313 if ( ! $_FILES['odtFile'] ) return $this->_msg('er_odtFile_miss'); 314 // Check the file status 315 if ( $_FILES['odtFile']['error'] > 0 ) return $this->_msg( array( 'er_odtFile_upload', $_FILES['odtFile']['error'] ) ); 316 // Check the file has an authorized mimetype 317 if ( $this->getConf( 'parserMimeTypeAuthorized' ) != "" && strpos( $this->getConf( 'parserMimeTypeAuthorized' ), $_FILES['odtFile']['type'] ) === false ) return $this->_msg( array( 'er_odtFile_format', $_FILES['odtFile']['type'] ) ); 318 // Create an unique temp work dir name 319 while ( file_exists( $this->uploadDir = $this->getConf( 'parserUploadDir' ).rand( 10000, 100000 ) ) ) {}; 320 // Create the directory 321 if ( ! mkdir( $this->uploadDir, 0777, true ) ) return $this->_msg( 'er_odtFile_tmpDir' ); 322 // Move the upload file into the work directory 323 $this->odtFileName = $_FILES['odtFile']['name']; 324 $this->odtFile = $this->uploadDir.'/'.$this->odtFileName; 325 if ( ! move_uploaded_file( $_FILES['odtFile']['tmp_name'], $this->odtFile ) ) return $this->_msg('er_odtFile_getFromDownload'); 326 // All upload file checking are OK 327 return true; 328 } 329 330 function _purge_env() { 331 ### _purge_env : clean the system from temporary file ### 332 # OUTPUT : 333 # void 334 # Display some error message if something wrong in the delete process (might delete the file manually) 335 336 // Perhaps this would not be needed if use temp dir. 337 // No timeOut : the cleanning process wont be interrupted. 338 set_time_limit(0); 339 // use @ to catch the system error message 340 // If exists, delete the download file 341 if ( file_exists( $this->odtFile ) ) if ( ! @unlink( $this->odtFile ) ) $this->_msg( array( 'er_pg_file', $this->odtFile ) ); 342 // Delete each file extracted for the uploaded file 343 if ( $this->file_extract ) foreach ($this->file_extract as $file) if ( file_exists( $file ) ) if ( ! @unlink( $file ) ) $this->_msg( array( 'er_pg_file', $file ) ); 344 // Delete each image would be rename and not move to the wiki 345 if ( $this->file_import ) foreach ( $this->file_import as $file ) if ( file_exists( $this->uploadDir.'/'.$this->pictpath.'/'.$file ) ) if ( ! @unlink( $this->uploadDir.'/'.$this->pictpath.'/'.$file ) ) $this->_msg( array( 'er_pg_file', $this->uploadDir.'/'.$this->pictpath.'/'.$file ) ); 346 // Delete the Pictures directory 347 if ( file_exists( $this->uploadDir.'/'.$this->pictpath) ) if ( ! @rmdir( $this->uploadDir.'/'.$this->pictpath ) ) $this->_msg( array( 'er_pg_dir', $this->uploadDir.'/'.$this->pictpath ) ); 348 // Than delete the temporary directory 349 if ( file_exists( $this->uploadDir ) ) if ( ! @rmdir( $this->uploadDir ) ) $this->_msg( array( 'er_pg_dir', $this->uploadDir ) ); 350 // Set back default timeOut 351 set_time_limit(30); 352 } 353 354 function _set_xsltProcessor(){ 355 ### _set_xsltProcessor : set all xslt param regarding the dokuwiki plugin installed ### 356 # OUTPUT : 357 # * true -> process successfully 358 # * false -> something wrong; using _msg to display what's wrong 359 # _msg info report ( debugLvl >= 2 ) display message about active plugin 360 361 // Gag : I think it s a Nasty way to check plugin - must be rewrite but i don t know how 362 $tmp_plugin_lst = plugin_list(); 363 if ( ! $this->XSLT->importStylesheet( $this->XSL ) ) return $this->_msg('er_xslt_invalid'); 364 foreach ( array('numberedheadings') as $param ) if ( array_search( $param, $tmp_plugin_lst ) !== false ) { 365 if ( ! $this->XSLT->setParameter( '', $param, '1' ) ) return $this->_msg( array( 'inf_xslt_param', $param ), -1 ); 366 // _msg info report 367 $this->_msg( array( 'ok_infoPlugin', $param ), 1 ); 368 } 369 // 370 foreach ( array('subtable_message') as $lang_elt ) if ( ! $this->XSLT->setParameter( '', $lang_elt, $this->getLang('xsl_'.$lang_elt ) ) ) $this->_msg( array( 'inf_xslt_lang', $param ), 0 ); 371 return true; 372 } 373 374 function _apply_result() { 375 ### _apply_result : store the content in dokuwiki page and the attache file (img) in dokuwiki media 376 # OUTPUT : 377 # * true -> process successfully 378 # * false -> something wrong; using _msg to display what's wrong 379 global $INFO; 380 // Save the content in data/page 381 saveWikiText( $this->pageName, $this->result, $this->getLang( 'parserSummary' ).$this->odtFileName ); 382 if ( ! page_exists($this->pageName) ) return $this->_msg('er_apply_content'); 383 // Check if the user could upload file (ACL : permission lvl 8) 384 if ( auth_quickaclcheck($ID) >= AUTH_UPLOAD ) { 385 // Import the image file in the mediaManager (data/media) 386 $destDir = mediaFN( $this->nsName ); 387 if ( ! ( file_exists( $destDir ) || mkdir( $destDir, 0777, true ) ) ) return $this->_msg( array( 'er_apply_dirCreate' ) ); 388 if ( $this->file_import ) foreach ( $this->file_import as $pict ) { 389 $destFile = mediaFN( $this->nsName.':'.$pict ); 390 list( $ext, $mime ) = mimetype( $this->uploadDir.'/'.$this->pictpath.'/'.$pict ); 391 if ( media_upload_finish($this->uploadDir.'/'.$this->pictpath.'/'.$pict, $destFile, $this->nsName, $mime, @file_exists($destFile), 'rename' ) != $this->nsName ) return $this->_msg( array( 'er_apply_img', $this->uploadDir.'/'.$this->pictpath.'/'.$pict ) ); 392 } 393 // Keep the original file (import the upload file in the mediaManager) 394 $destFile = mediaFN( $this->nsName.':'.$this->odtFileName ); 395 list( $ext, $mime ) = mimetype( $this->uploadDir.'/'.$this->odtFileName ); 396 if ( media_upload_finish($this->uploadDir.'/'.$this->odtFileName, $destFile, $this->nsName, $mime, @file_exists($destFile), 'rename' ) != $this->nsName ) return $this->_msg( array( 'er_apply_odtFile' ) ); 397 } else { 398 // If not allowed to upload, display a message. 399 $this->_msg( 'inf_acl_upload', 0, true ); 400 } 401 # Refresh info about the current page (see doku.php where $INFO is initiate) - Needed for edit or preview "parserPostDisplay" option 402 $INFO = pageinfo(); 403 return true; 404 } 405 406 function _parse_image() { 407 ### _parse_image : search dokuwiki img markup in $this->result than extract the img file and rename it to easier name ### 408 # OUTPUT : 409 # void 410 # using _msg to display each img file wont be process successfully 411 412 global $ID; 413 $imgs = array(); 414 if ( preg_match_all( '|{{((?:[^/}]+/)*[^/}]+)/([0-9a-zA-Z]+)(\.[a-z]+)(\?[0-9]+(?:x[0-9]+)?)?}}|', $this->result, $imgs, PREG_SET_ORDER ) ) { 415 if ( auth_quickaclcheck( $ID ) < AUTH_UPLOAD ) return $this->_msg( 'er_acl_upload' ); 416 $this->err['ok'] = array(); 417 foreach ( $imgs as $key => $value ) { 418 set_time_limit(20); 419 $this->pictpath = $value[1]; 420 $pict = $value[2].$value[3]; 421 $ext = $value[3]; 422 $other = $value[4]; 423 if ( $this->_unzip($this->pictpath.'/'.$pict) ) { 424 $newname = noNS($this->pageName).'_Image_'.$key.$ext; 425 if ( rename( $this->uploadDir.'/'.$this->pictpath.'/'.$pict, $this->uploadDir.'/'.$this->pictpath.'/'.$newname ) ) { 426 $this->result = str_replace( '{{'.$this->pictpath.'/'.$pict.$other.'}}' , '{{'.$newname.$other.'}}' , $this->result ); 427 $this->file_import[] = $newname; 428 if ( $this->debug ) $this->err['ok'][] = $pict.' : '.$newname; 429 } else $this->err[$pict] = 'rename'; 430 } else $this->err[$pict] = 'unzip'; 431 } 432 } 433 if ( $this->err ) foreach ( $this->err as $key => $value ) { 434 switch ( $key ) { 435 case 'ok': 436 foreach ( $value as $msg ) $this->_msg( array( 'ok_img', $msg ) ); 437 break; 438 default : 439 // $value E ( rename, unzip) => er_img_rename, er_img_unzip 440 $this->_msg( array( 'er_img_'.$value, $key ) ); 441 } 442 } 443 } 444 445 function _unzip( $entrie ) { 446 ### _unzip : extract $entrie file from $this->odtFile to $this->uploadDir using $this->ZIP object instance of ZipArchive Class ### 447 # $entrie : string : fullFileName (with the internal path in the archive) 448 # OUTPUT : 449 # * true -> extraction ok 450 # * false -> something wrong; using _msg to display what's wrong 451 452 if ( ! $this->ZIP ) return $this->_msg('er_unzip_object'); 453 if ( ! file_exists( $this->odtFile ) ) return $this->_msg('er_unzip_nofile'); 454 if ( ! ( $this->ZIP->open( $this->odtFile ) === true ) ) return $this->_msg( 'er_unzip_open' ); 455 $res = $this->ZIP->extractTo( $this->uploadDir, $entrie ); 456 $this->ZIP->close(); 457 if ( ! $res ) return $this->_msg( array( 'er_unzip_error', $entrie ) ); 458 $this->file_extract[] = $this->uploadDir.'/'.$entrie; 459 return $this->_msg( array( 'ok_unzip', $entrie ) ); 460 } 461 462} 463