Browse Source

Fixes #3345 - Allow font colors in articles (not only in tables).

Martin Edenhofer 4 years ago
parent
commit
b85566c530

+ 117 - 3
app/assets/javascripts/app/lib/app_post/utils.coffee

@@ -1,6 +1,9 @@
 # coffeelint: disable=no_unnecessary_double_quotes
 class App.Utils
   @mapTagAttributes:
+    'FONT': ['color']
+    'SPAN': ['style']
+    'DIV': ['style']
     'TABLE': ['align', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'frame', 'rules', 'sortable', 'summary', 'width', 'style']
     'TD': ['abbr', 'align', 'axis', 'colspan', 'headers', 'rowspan', 'valign', 'width', 'style']
     'TH': ['abbr', 'align', 'axis', 'colspan', 'headers', 'rowspan', 'scope', 'sorted', 'valign', 'width', 'style']
@@ -9,6 +12,12 @@ class App.Utils
     'IMG': ['align', 'alt', 'border', 'height', 'src', 'srcset', 'width', 'style']
 
   @mapCss:
+    'SPAN': [
+      'color',
+    ]
+    'DIV': [
+      'color',
+    ]
     'TABLE': [
       'background', 'background-color', 'color', 'font-size', 'vertical-align',
       'margin', 'margin-top', 'margin-right', 'margin-bottom', 'margin-left',
@@ -60,6 +69,111 @@ class App.Utils
       'width', 'height',
     ]
 
+  @cssValuesBacklist:
+    'DIV': [
+      'color:white',
+      'color:black',
+      'color:#000',
+      'color:#000000',
+      'color:#fff',
+      'color:#ffffff',
+      'color:rgb(0,0,0)',
+      'color:#585856', # use in UI, ignore it
+      'color:rgb(88, 88, 86)' # use in UI, ignore it
+      'color:#b3b3b3' # use in UI, ignore it
+      'color:rgb(34, 34, 34)' # use in UI, ignore it
+    ],
+    'SPAN': [
+      'color:white',
+      'color:black',
+      'color:#000',
+      'color:#000000',
+      'color:#fff',
+      'color:#ffffff',
+      'color:rgb(0,0,0)',
+      'color:#585856', # use in UI, ignore it
+      'color:rgb(88, 88, 86)' # use in UI, ignore it
+      'color:#b3b3b3' # use in UI, ignore it
+      'color:rgb(34, 34, 34)' # use in UI, ignore it
+    ],
+    'TABLE': [
+      'font-size:0',
+      'font-size:0px',
+      'font-size:0em',
+      'font-size:0%',
+      'font-size:1px',
+      'font-size:1em',
+      'font-size:1%',
+      'font-size:2',
+      'font-size:2px',
+      'font-size:2em',
+      'font-size:2%',
+      'font-size:3',
+      'font-size:3px',
+      'font-size:3em',
+      'font-size:3%',
+      'display:none',
+      'visibility:hidden',
+    ],
+    'TH': [
+      'font-size:0',
+      'font-size:0px',
+      'font-size:0em',
+      'font-size:0%',
+      'font-size:1px',
+      'font-size:1em',
+      'font-size:1%',
+      'font-size:2',
+      'font-size:2px',
+      'font-size:2em',
+      'font-size:2%',
+      'font-size:3',
+      'font-size:3px',
+      'font-size:3em',
+      'font-size:3%',
+      'display:none',
+      'visibility:hidden',
+    ],
+    'TR': [
+      'font-size:0',
+      'font-size:0px',
+      'font-size:0em',
+      'font-size:0%',
+      'font-size:1',
+      'font-size:1px',
+      'font-size:1em',
+      'font-size:1%',
+      'font-size:2',
+      'font-size:2px',
+      'font-size:2em',
+      'font-size:2%',
+      'font-size:3',
+      'font-size:3px',
+      'font-size:3em',
+      'font-size:3%',
+      'display:none',
+      'visibility:hidden',
+    ],
+    'TD': [
+      'font-size:0',
+      'font-size:0px',
+      'font-size:0em',
+      'font-size:0%',
+      'font-size:1px',
+      'font-size:1em',
+      'font-size:1%',
+      'font-size:2',
+      'font-size:2px',
+      'font-size:2em',
+      'font-size:2%',
+      'font-size:3',
+      'font-size:3px',
+      'font-size:3em',
+      'font-size:3%',
+      'display:none',
+      'visibility:hidden',
+    ]
+
   # textCleand = App.Utils.textCleanup(rawText)
   @textCleanup: (ascii) ->
     $.trim( ascii )
@@ -269,7 +383,7 @@ class App.Utils
     @_stripDoubleDomainAnchors(html)
 
     # remove tags, keep content
-    html.find('font, small, time, form, label').replaceWith( ->
+    html.find('small, time, form, label').replaceWith( ->
       $(@).contents()
     )
 
@@ -293,7 +407,7 @@ class App.Utils
     )
 
     # remove tags & content
-    html.find('font, svg, input, select, button, style, applet, embed, noframes, canvas, script, frame, iframe, meta, link, title, head, fieldset').remove()
+    html.find('svg, input, select, button, style, applet, embed, noframes, canvas, script, frame, iframe, meta, link, title, head, fieldset').remove()
 
     # remove style and class
     @_cleanAttributes(html)
@@ -341,7 +455,7 @@ class App.Utils
           prop = local_pear.split(':')
           if prop[0] && prop[0].trim
             key = prop[0].trim()
-            if _.contains(@mapCss[element.nodeName], key)
+            if !(@cssValuesBacklist[element.nodeName] && _.contains(@cssValuesBacklist[element.nodeName], local_pear.toLowerCase())) && _.contains(@mapCss[element.nodeName], key)
               styleNew += "#{local_pear};"
         if styleNew isnt ''
           element.setAttribute('style', styleNew)

+ 67 - 0
config/initializers/html_sanitizer.rb

@@ -44,6 +44,7 @@ Rails.application.config.html_sanitizer_attributes_whitelist = {
   'ul'         => %w[type],
   'q'          => %w[cite],
   'span'       => %w[style],
+  'div'        => %w[style],
   'time'       => %w[datetime pubdate],
 }
 
@@ -57,6 +58,9 @@ Rails.application.config.html_sanitizer_css_properties_whitelist = {
   'span'  => %w[
     color
   ],
+  'div'   => %w[
+    color
+  ],
   'table' => %w[
     background background-color color font-size vertical-align
     margin margin-top margin-right margin-bottom margin-left
@@ -104,11 +108,40 @@ Rails.application.config.html_sanitizer_css_properties_whitelist = {
 }
 
 Rails.application.config.html_sanitizer_css_values_backlist = {
+  'div'   => [
+    'color:white',
+    'color:black',
+    'color:#000',
+    'color:#000000',
+    'color:#fff',
+    'color:#ffffff',
+    'color:rgb(0,0,0)',
+  ],
+  'span'  => [
+    'color:white',
+    'color:black',
+    'color:#000',
+    'color:#000000',
+    'color:#fff',
+    'color:#ffffff',
+    'color:rgb(0,0,0)',
+  ],
   'table' => [
     'font-size:0',
     'font-size:0px',
     'font-size:0em',
     'font-size:0%',
+    'font-size:1px',
+    'font-size:1em',
+    'font-size:1%',
+    'font-size:2',
+    'font-size:2px',
+    'font-size:2em',
+    'font-size:2%',
+    'font-size:3',
+    'font-size:3px',
+    'font-size:3em',
+    'font-size:3%',
     'display:none',
     'visibility:hidden',
   ],
@@ -117,6 +150,17 @@ Rails.application.config.html_sanitizer_css_values_backlist = {
     'font-size:0px',
     'font-size:0em',
     'font-size:0%',
+    'font-size:1px',
+    'font-size:1em',
+    'font-size:1%',
+    'font-size:2',
+    'font-size:2px',
+    'font-size:2em',
+    'font-size:2%',
+    'font-size:3',
+    'font-size:3px',
+    'font-size:3em',
+    'font-size:3%',
     'display:none',
     'visibility:hidden',
   ],
@@ -125,6 +169,18 @@ Rails.application.config.html_sanitizer_css_values_backlist = {
     'font-size:0px',
     'font-size:0em',
     'font-size:0%',
+    'font-size:1',
+    'font-size:1px',
+    'font-size:1em',
+    'font-size:1%',
+    'font-size:2',
+    'font-size:2px',
+    'font-size:2em',
+    'font-size:2%',
+    'font-size:3',
+    'font-size:3px',
+    'font-size:3em',
+    'font-size:3%',
     'display:none',
     'visibility:hidden',
   ],
@@ -133,6 +189,17 @@ Rails.application.config.html_sanitizer_css_values_backlist = {
     'font-size:0px',
     'font-size:0em',
     'font-size:0%',
+    'font-size:1px',
+    'font-size:1em',
+    'font-size:1%',
+    'font-size:2',
+    'font-size:2px',
+    'font-size:2em',
+    'font-size:2%',
+    'font-size:3',
+    'font-size:3px',
+    'font-size:3em',
+    'font-size:3%',
     'display:none',
     'visibility:hidden',
   ],

+ 5 - 3
lib/html_sanitizer.rb

@@ -267,6 +267,8 @@ cleanup html string:
       end
       next if hit && node.keys.count.positive?
 
+      next if node.name == 'span' && node['style'].present?
+
       node.replace cleanup_replace_tags(node.children.to_s)
       Loofah::Scrubber::STOP
     end
@@ -289,19 +291,19 @@ cleanup html string:
       end
 
       # remove empty childs
-      if node.content.blank? && remove_empty_nodes.include?(node.name) && node.children.size == 1 && remove_empty_nodes.include?(node.children.first.name)
+      if node.content.blank? && remove_empty_nodes.include?(node.name) && node.children.size == 1 && remove_empty_nodes.include?(node.children.first.name) && node['style'].blank? && node.children.first['style'].blank?
         node.replace node.children.to_s
         Loofah::Scrubber::STOP
       end
 
       # remove empty childs
-      if remove_empty_nodes.include?(node.name) && node.children.size == 1 && remove_empty_nodes.include?(node.children.first.name) && node.children.first.content == node.content
+      if remove_empty_nodes.include?(node.name) && node.children.size == 1 && remove_empty_nodes.include?(node.children.first.name) && node.children.first.content == node.content && node['style'].blank? && node.children.first['style'].blank?
         node.replace node.children.to_s
         Loofah::Scrubber::STOP
       end
 
       # remove node if empty and parent was already a remove node
-      if node.content.blank? && remove_empty_nodes.include?(node.name) && node.parent && node.children.size.zero? && remove_empty_nodes.include?(node.parent.name)
+      if (node.content.blank? || node.content.strip.blank? ) && remove_empty_nodes.include?(node.name) && node.parent && node.children.size.zero? && remove_empty_nodes.include?(node.parent.name)
         node.remove
         Loofah::Scrubber::STOP
       end

+ 2 - 2
public/assets/tests/html_utils.js

@@ -649,7 +649,7 @@ test("htmlCleanup", function() {
 
   source = "<div><font size=\"3\" color=\"red\">This is some text!</font><svg><use xlink:href=\"assets/images/icons.svg#icon-status\"></svg></div>"
   //should = "<div>This is some text!</div>"
-  should = "This is some text!"
+  should = "<font color=\"red\">This is some text!</font>"
   result = App.Utils.htmlCleanup($(source))
   equal(result.html(), should, source)
 
@@ -671,7 +671,7 @@ test("htmlCleanup", function() {
   equal(result.html().trim(), should, source)
 
   source = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">\n<html>\n<head>\n  <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\"/>\n  <title></title>\n  <meta name=\"generator\" content=\"LibreOffice 4.4.7.2 (MacOSX)\"/>\n  <style type=\"text/css\">\n    @page { margin: 0.79in }\n    p { margin-bottom: 0.1in; line-height: 120% }\n    a:link { so-language: zxx }\n  </style>\n</head>\n<body lang=\"en-US\" dir=\"ltr\">\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">1.\nGehe a<b>uf </b><b>https://www.pfe</b>rdiathek.ge</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\"><br/>\n\n</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">2.\nMel<font color=\"#800000\">de Dich mit folgende</font> Zugangsdaten an:</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">Benutzer:\nme@xxx.net</p>\n<p align=\"center\" style=\"margin-bottom: 0in; line-height: 100%\">Passwort:\nxxx.</p>\n</body>\n</html>"
-  should = "\n\n\n  \n  \n  \n  \n\n\n<p>1.\nGehe a<b>uf </b><b>https://www.pfe</b>rdiathek.ge</p>\n<p><br>\n\n</p>\n<p>2.\nMelde Dich mit folgende Zugangsdaten an:</p>\n<p>Benutzer:\nme@xxx.net</p>\n<p>Passwort:\nxxx.</p>\n\n"
+  should = "\n\n\n  \n  \n  \n  \n\n\n<p>1.\nGehe a<b>uf </b><b>https://www.pfe</b>rdiathek.ge</p>\n<p><br>\n\n</p>\n<p>2.\nMel<font color=\"#800000\">de Dich mit folgende</font> Zugangsdaten an:</p>\n<p>Benutzer:\nme@xxx.net</p>\n<p>Passwort:\nxxx.</p>\n\n"
   result = App.Utils.htmlCleanup(source)
   equal(result.html(), should, source)
 

File diff suppressed because it is too large
+ 46 - 13
spec/lib/core_ext/string_spec.rb


+ 3 - 3
spec/models/trigger_spec.rb

@@ -107,9 +107,9 @@ RSpec.describe Trigger, type: :model do
             <p>Geschäftsführer der example Straubing-Bogen</p>
             <p>Klosterhof 1 | 94327 Bogen-Oberalteich</p>
             <p>Tel: 09422-505601 | Fax: 09422-505620</p>
-            <p>Internet: <a href="http://example-straubing-bogen.de/" rel="nofollow noreferrer noopener" target="_blank">http://example-straubing-bogen.de</a></p>
-            <p>Facebook: <a href="http://facebook.de/examplesrbog" rel="nofollow noreferrer noopener" target="_blank">http://facebook.de/examplesrbog</a></p>
-            <p><b><img border="0" src="cid:image001.jpg@01CDB132.D8A510F0" alt="Beschreibung: Beschreibung: efqmLogo" style="width:60px;height:19px;"></b><b> - European Foundation für Quality Management</b></p>
+            <p>Internet: <a href="http://example-straubing-bogen.de/" rel="nofollow noreferrer noopener" target="_blank"><span style="color:blue;">http://example-straubing-bogen.de</span></a></p>
+            <p>Facebook: <a href="http://facebook.de/examplesrbog" rel="nofollow noreferrer noopener" target="_blank"><span lang="EN-US" style="color:blue;">http://facebook.de/examplesrbog</span></a></p>
+            <p><b><span style="color:navy;"><img border="0" src="cid:image001.jpg@01CDB132.D8A510F0" alt="Beschreibung: Beschreibung: efqmLogo" style="width:60px;height:19px;"></span></b><b><span lang="EN-US" style="color:navy;"> - European Foundation für Quality Management</span></b></p>
             <p> </p>
             </div>&gt;/snip&lt;
           RAW

File diff suppressed because it is too large
+ 2 - 2
test/data/mail/mail003.yml


+ 2 - 1
test/data/mail/mail006.yml

@@ -2,9 +2,10 @@
 from: '"Hans BÄKOSchönland" <me@bogen.net>'
 from_email: me@bogen.net
 from_display_name: Hans BÄKOSchönland
+to: Namedyński (hans@example.com)
 subject: 'utf8: 使って / ISO-8859-1: Priorität"  / cp-1251: Сергей Углицких'
-content_type: text/html
 body: '<p>this is a test</p><br><hr> <a href="http://localhost/8HMZENUS/2737??PS="
   rel="nofollow noreferrer noopener" target="_blank" title="http://localhost/8HMZENUS/2737??PS=">Compare
   Cable, DSL or Satellite plans: As low as $2.95. </a> <br> <br> Test1:– <br> Test2:&amp;
   <br> Test3:∋ <br> Test4:&amp; <br> Test5:='
+content_type: text/html

+ 3 - 2
test/data/mail/mail010.yml

@@ -2,8 +2,9 @@
 from: Smith Sepp <smith@example.com>
 from_email: smith@example.com
 from_display_name: Smith Sepp
+to: info@example.com
 subject: Gruß aus Oberalteich
-content_type: text/html
 body: |-
   <div>
-  <p>Herzliche Grüße aus Oberalteich sendet Herrn Smith</p><p>&nbsp;</p><p>Sepp Smith - Dipl.Ing. agr. (FH)</p><p>Geschäftsführer der example Straubing-Bogen</p><p>Klosterhof 1 | 94327 Bogen-Oberalteich</p><p>Tel: 09422-505601 | Fax: 09422-505620</p><p>Internet: <a href="http://example-straubing-bogen.de/" rel="nofollow noreferrer noopener" target="_blank">http://example-straubing-bogen.de</a></p><p>Facebook: <a href="http://facebook.de/examplesrbog" rel="nofollow noreferrer noopener" target="_blank">http://facebook.de/examplesrbog</a></p><p><b><img border="0" src="cid:image001.jpg@01CDB132.D8A510F0" alt="Beschreibung: Beschreibung: efqmLogo" style="width:60px;height:19px;"></b><b> - European Foundation für Quality Management</b></p><p>&nbsp;</p></div>
+  <p>Herzliche Grüße aus Oberalteich sendet Herrn Smith</p><p>&nbsp;</p><p>Sepp Smith - Dipl.Ing. agr. (FH)</p><p>Geschäftsführer der example Straubing-Bogen</p><p>Klosterhof 1 | 94327 Bogen-Oberalteich</p><p>Tel: 09422-505601 | Fax: 09422-505620</p><p>Internet: <a href="http://example-straubing-bogen.de/" rel="nofollow noreferrer noopener" target="_blank"><span style="color:blue;">http://example-straubing-bogen.de</span></a></p><p>Facebook: <a href="http://facebook.de/examplesrbog" rel="nofollow noreferrer noopener" target="_blank"><span lang="EN-US" style="color:blue;">http://facebook.de/examplesrbog</span></a></p><p><b><span style="color:navy;"><img border="0" src="cid:image001.jpg@01CDB132.D8A510F0" alt="Beschreibung: Beschreibung: efqmLogo" style="width:60px;height:19px;"></span></b><b><span lang="EN-US" style="color:navy;"> - European Foundation für Quality Management</span></b></p><p>&nbsp;</p></div>
+content_type: text/html

+ 3 - 3
test/data/mail/mail012.yml

@@ -2,15 +2,15 @@
 from: Alex.Smith@example.com
 from_email: Alex.Smith@example.com
 from_display_name: ''
-subject: 'AW: Agenda [Ticket#11995]'
 to: example@znuny.com
-content_type: text/html
+subject: 'AW: Agenda [Ticket#11995]'
 body: |-
   <div>
   <p>Hallo Herr Edenhofer,</p><p>&nbsp;</p><p>möglicherweise haben wir für unsere morgige Veranstaltung ein Problem mit unserer Develop-Umgebung.<br> Der Kollege Smith wollte uns noch die Möglichkeit geben, direkt auf die Datenbank zugreifen zu können, hierzu hat er Freitag noch einige Einstellungen vorgenommen und uns die Zugangsdaten mitgeteilt. Eine der Änderungen hatte aber offenbar zur Folge, dass ein Starten der Develop-Anwendung nicht mehr möglich ist (s. Fehlermeldung)<br>
   <img src="cid:image002.png@01CDD14F.29D467A0" style="width:577px;height:345px;"></p><p>&nbsp;</p><p>Herr Smith ist im Urlaub, er wurde von seinen Datenbank-Kollegen kontaktiert aber offenbar lässt sich nicht mehr 100%ig rekonstruieren, was am Freitag noch verändert wurde.<br> Meinen Sie, dass Sie uns bei der Behebung der o. a. Störung morgen helfen können? Die Datenbank-Kollegen werden uns nach besten Möglichkeiten unterstützen, Zugriff erhalten wir auch.</p><p>&nbsp;</p><p>Mit freundlichen Grüßen</p><p>&nbsp;</p><p>Alex Smith<br>
   <br> Abteilung IT-Strategie, Steuerung &amp; Support<br> im Bereich Informationstechnologie<br>
   <br> Example – Example GmbH<br> (Deutsche Example)<br> Longstreet 5<br> 11111 Frankfurt am Main<br>
-  <br> Telefon: (069) 11 1111 – 11 30</p><p>Telefon ServiceDesk: (069) 11 1111 – 12 22<br> Telefax: (069) 11 1111 – 14 85<br> Internet: <a href="http://www.example.com/" title="http://www.example.com/" rel="nofollow noreferrer noopener" target="_blank">www.example.com</a></p><p>&nbsp;</p><span class="js-signatureMarker"></span><p>-----Ursprüngliche Nachricht-----<br> Von: Martin Edenhofer via Znuny Sales [mailto:example@znuny.com] <br> Gesendet: Freitag, 30. November 2012 13:50<br> An: Smith, Alex<br> Betreff: Agenda [Ticket#11995]</p><p>&nbsp;</p><p>Sehr geehrte Frau Smith,</p><p>&nbsp;</p><p>ich habe (wie telefonisch avisiert) versucht eine Agenda für nächste Woche zusammen zu stellen.</p><p>&nbsp;</p><p>Leider ist es mir dies Inhaltlich nur unzureichend gelungen (es gibt zu wenig konkrete Anforderungen im Vorfeld :) ).</p><p>&nbsp;</p><p>Dadurch würde ich gerne am Dienstag als erste Amtshandlung (mit Herrn Molitor im Boot) die Anforderungen und Ziele der zwei Tage, Mittelfristig und Langfristig definieren. Aufgrund dessen können wir die Agenda der zwei Tage fixieren. Inhaltlich können wir (ich) alles abdecken, von daher gibt es hier keine Probleme. ;)</p><p>&nbsp;</p><p>Ist dies für Sie so in Ordnung?</p><p>&nbsp;</p><p>Für Fragen stehe ich gerne zur Verfügung!</p><p>&nbsp;</p><p>Ich freue mich auf Dienstag,</p><p>&nbsp;</p><p>Martin Edenhofer</p><p>&nbsp;</p><p>--</p><p>Enterprise Services for OTRS</p><p>&nbsp;</p><p>Znuny GmbH // Marienstraße 11 // 10117 Berlin // Germany</p><p>&nbsp;</p><p>P: +49 (0) 30 60 98 54 18-0</p><p>F: +49 (0) 30 60 98 54 18-8</p><p>W: <a href="http://znuny.com" rel="nofollow noreferrer noopener" target="_blank">http://znuny.com</a>
+  <br> Telefon: (069) 11 1111 – 11 30</p><p>Telefon ServiceDesk: (069) 11 1111 – 12 22<br> Telefax: (069) 11 1111 – 14 85<br> Internet: <span style="color:navy;"><a href="http://www.example.com/" title="http://www.example.com/" rel="nofollow noreferrer noopener" target="_blank">www.example.com</a></span></p><p>&nbsp;</p><span class="js-signatureMarker"></span><p>-----Ursprüngliche Nachricht-----<br> Von: Martin Edenhofer via Znuny Sales [mailto:example@znuny.com] <br> Gesendet: Freitag, 30. November 2012 13:50<br> An: Smith, Alex<br> Betreff: Agenda [Ticket#11995]</p><p>&nbsp;</p><p>Sehr geehrte Frau Smith,</p><p>&nbsp;</p><p>ich habe (wie telefonisch avisiert) versucht eine Agenda für nächste Woche zusammen zu stellen.</p><p>&nbsp;</p><p>Leider ist es mir dies Inhaltlich nur unzureichend gelungen (es gibt zu wenig konkrete Anforderungen im Vorfeld :) ).</p><p>&nbsp;</p><p>Dadurch würde ich gerne am Dienstag als erste Amtshandlung (mit Herrn Molitor im Boot) die Anforderungen und Ziele der zwei Tage, Mittelfristig und Langfristig definieren. Aufgrund dessen können wir die Agenda der zwei Tage fixieren. Inhaltlich können wir (ich) alles abdecken, von daher gibt es hier keine Probleme. ;)</p><p>&nbsp;</p><p>Ist dies für Sie so in Ordnung?</p><p>&nbsp;</p><p>Für Fragen stehe ich gerne zur Verfügung!</p><p>&nbsp;</p><p>Ich freue mich auf Dienstag,</p><p>&nbsp;</p><p>Martin Edenhofer</p><p>&nbsp;</p><p>--</p><p>Enterprise Services for OTRS</p><p>&nbsp;</p><p>Znuny GmbH // Marienstraße 11 // 10117 Berlin // Germany</p><p>&nbsp;</p><p>P: +49 (0) 30 60 98 54 18-0</p><p>F: +49 (0) 30 60 98 54 18-8</p><p>W: <a href="http://znuny.com" rel="nofollow noreferrer noopener" target="_blank"><span style="color:windowtext;">http://znuny.com</span></a>
   </p><p>&nbsp;</p><p>Location: Berlin - HRB 139852 B Amtsgericht Berlin-Charlottenburg Managing Director: Martin Edenhofer</p></div><div>
   <p>-------------------------------------------------------------------------------------------------</p><p>Rechtsform: GmbH</p><p>Geschaeftsfuehrer: Dr. Carl Heinz Smith, Dr. Carsten Smith</p><p>Sitz der Gesellschaft und Registergericht: Frankfurt/Main, HRB 11111</p><p>Alleiniger Gesellschafter: Bundesrepublik Deutschland,</p><p>vertreten durch das XXX der Finanzen.</p></div>
+content_type: text/html

Some files were not shown because too many files changed in this diff