diff --git a/etemplate/inc/class.bo_merge.inc.php b/etemplate/inc/class.bo_merge.inc.php index 6587778932..280f2d2290 100644 --- a/etemplate/inc/class.bo_merge.inc.php +++ b/etemplate/inc/class.bo_merge.inc.php @@ -313,12 +313,99 @@ abstract class bo_merge { $mimetype = 'application/rtf'; } + try { - return $this->merge_string($content,$ids,$err,$mimetype,$fix); + $content = $this->merge_string($content,$ids,$err,$mimetype,$fix); } catch (Exception $e) { $err = $e->getMessage(); return false; } + return $content; + } + + protected function apply_styles (&$content, $mimetype) + { + if ($mimetype == 'application/xml' && + preg_match('/'.preg_quote('').'/',substr($content,0,200),$matches)) + { + $mso_application_progid = $matches[1]; + } + else + { + $mso_application_progid = ''; + } + // Tags we can replace with the target document's version + $replace_tags = array(); + switch($mimetype.$mso_application_progid) + { + case 'application/vnd.oasis.opendocument.text': // open office + case 'application/vnd.oasis.opendocument.spreadsheet': + // It seems easier to split the parent tags here + $replace_tags = array( + '/<(ol|ul|table)( [^>]*)?>/' => '<$1$2>', + '/<\/(ol|ul|table)>/' => '', + //'/<(li)(.*?)>(.*?)<\/\1>/' => '<$1 $2>$3', + ); + $content = preg_replace(array_keys($replace_tags),array_values($replace_tags),$content); + + $doc = new DOMDocument(); + $xslt = new XSLTProcessor(); + $doc->load(EGW_INCLUDE_ROOT.'/etemplate/templates/default/openoffice.xslt'); + $xslt->importStyleSheet($doc); + +//echo $content;die(); + break; + case 'application/xmlWord.Document': // Word 2003*/ + case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // ms office 2007 + case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': + $replace_tags = array( + 'b','strong','i','em','u','span' + ); + // It seems easier to split the parent tags here + $replace_tags = array( + // Tables, lists don't go inside + '/<(ol|ul|table)( [^>]*)?>/' => '<$1$2>', + '/<\/(ol|ul|table)>/' => '', + // Fix for things other than text (newlines) inside table row + '/<(td)( [^>]*)?>((?!))(.*?)<\/td>[\s]*?/' => '<$1$2>$4', + '/<(li)(.*?)>(.*?)<\/\1>/' => '<$1 $2>$3', + // Remove extra whitespace + '/[\s]+(.*?)<\/w:t>/' => '$1' + ); + $content = preg_replace(array_keys($replace_tags),array_values($replace_tags),$content); +//echo $content;die(); + $doc = new DOMDocument(); + $xslt = new XSLTProcessor(); + $xslt_file = $mimetype == 'application/xml' ? 'wordml.xslt' : 'msoffice.xslt'; + $doc->load(EGW_INCLUDE_ROOT.'/etemplate/templates/default/'.$xslt_file); + $xslt->importStyleSheet($doc); + break; + } + // XSLT transform known tags + if($xslt) + { + try + { + $element = new SimpleXMLelement($content); + $content = @$xslt->transformToXml($element); + + // Word 2003 needs two declarations, add extra declaration back in + if($mimetype == 'application/xml' && $mso_application_progid == 'Word.Document' && strpos($content, ''.$content; + } + // Validate + /* + $doc = new DOMDocument(); + $doc->loadXML($content); + $doc->schemaValidate(*Schema (xsd) file*); + */ + } + catch (Exception $e) + { + error_log($e); + // Failed... + } + } } /** @@ -478,8 +565,7 @@ abstract class bo_merge return $contentstart.implode('\\par \\page\\pard\\plain',$contentrepeatpages).$contentend; case 'application/vnd.oasis.opendocument.text': case 'application/vnd.oasis.opendocument.spreadsheet': - // todo OO writer files - break; + return $contentstart.implode('',$contentrepeatpages).$contentend; case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': return $contentstart.implode('',$contentrep).$contentend; @@ -543,6 +629,7 @@ abstract class bo_merge break; } //error_log(__METHOD__."('$document', ... ,$mimetype) --> $charset (egw=".translation::charset().', export='.$this->contacts->prefs['csv_charset'].')'); + // do we need to convert charset if ($charset && $charset != translation::charset()) { @@ -553,6 +640,26 @@ abstract class bo_merge // Numeric fields $names = array(); + // Tags we can replace with the target document's version + $replace_tags = array(); + switch($mimetype.$mso_application_progid) + { + case 'application/vnd.oasis.opendocument.text': // open office + case 'application/vnd.oasis.opendocument.spreadsheet': + $replace_tags = array( + '','','','','','','
    ','
      ','
    • ', + '','','
      ', + ); + break; + case 'application/xmlWord.Document': // Word 2003*/ + case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // ms office 2007 + case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': + $replace_tags = array( + '','','','','','','
        ','
          ','
        • ', + '','','
          ', + ); + break; + } // clean replacements from array values and html or html-entities, which mess up xml foreach($replacements as $name => &$value) { @@ -578,7 +685,7 @@ abstract class bo_merge { // replace

          and
          with CRLF (remove

          and CRLF) $value = str_replace(array("\r","\n",'

          ','

          ','
          '),array('','','',"\r\n","\r\n"),$value); - $value = strip_tags($value); + $value = strip_tags($value,implode('',$replace_tags)); } // replace all control chars (C0+C1) but CR (\015), LF (\012) and TAB (\011) (eg. vertical tabulators) with space // as they are not allowed in xml @@ -637,13 +744,13 @@ abstract class bo_merge $break = ''; break; case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': // ms word 2007 - $break = ''; + $break = ''; break; case 'application/xmlExcel.Sheet': // Excel 2003 $break = ' '; break; case 'application/xmlWord.Document': // Word 2003*/ - $break = ''; + $break = ''; break; case 'text/html': $break = '
          '; @@ -654,7 +761,7 @@ abstract class bo_merge break; } // now decode &, < and >, which need to be encoded as entities in xml - $replacements = str_replace(array('&','<','>',"\r","\n"),array('&','<','>','',$break),$replacements); + $replacements = str_replace(array('&',"\r","\n"),array('&','',$break),$replacements); } return str_replace(array_keys($replacements),array_values($replacements),$content); } @@ -859,6 +966,10 @@ abstract class bo_merge //error_log(__METHOD__."() !this->merge() err=$err"); return $err; } + + // Apply HTML formatting to target document, if possible + $this->apply_styles($merged, $mimetype); + if(!empty($name)) { if(empty($ext)) diff --git a/etemplate/templates/default/msoffice.xslt b/etemplate/templates/default/msoffice.xslt new file mode 100644 index 0000000000..ebee7ad9dc --- /dev/null +++ b/etemplate/templates/default/msoffice.xslt @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + + · + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etemplate/templates/default/openoffice.xslt b/etemplate/templates/default/openoffice.xslt new file mode 100644 index 0000000000..147631eedf --- /dev/null +++ b/etemplate/templates/default/openoffice.xslt @@ -0,0 +1,367 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pul + Pol + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etemplate/templates/default/wordml.xslt b/etemplate/templates/default/wordml.xslt new file mode 100644 index 0000000000..15025c4255 --- /dev/null +++ b/etemplate/templates/default/wordml.xslt @@ -0,0 +1,247 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + . + + + + + + · + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +