diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..3e20b46d5b2c9e7b7153e2af6c9bcad183335306
--- /dev/null
+++ b/README.md
@@ -0,0 +1,28 @@
+# ckanext-odsh
+Diese CKAN-Extension enthält die wichtigsten Features und das Layout für das Tranzparenzportal Schleswig-Holstein.
+Sie ist eine Weiterentwicklung der gleichnamigen Extension, die im Zuge der Entwicklung des Open Data Portals Schleswig-Holstein entwickelt wurde.
+
+## Branches
+### master
+Dieser Branch enthält den aktuell auf den Stage- bzw. Prod-Servern laufenden Code.
+
+### dev
+Dieser Branch enthält den aktuellsten Stand mit allen fertig entwickelten Features.
+
+### andere Branches
+Für die Entwicklung neuer Features soll jeweils ein eigener Branch vom dev-Branch abgezweigt werden. Für den Branch soll ein sprechender Name gewählt werden.
+
+## Deployment auf Produktivsystem
+Das Deployment auf das Produktivsystem geschieht über Ansible. Die dafür benötigten Skripte befinden sich im Repository `tpsh_deploy`. 
+
+## Manuelle Installation
+
+
+## Konfiguration
+Die Extension benötigt Konfigurationsparameter in der CKAN-Konfigurationsdatei (z.B. `production.ini`). Die korrekten Parameter für das Produktivsystem befinden sich im Repository `tpsh_deploy` unter `resources/production.ini`. Folgende Parameter sollten für Enwicklungssysteme geändert werden:
+
+| Parameter                             | Erläuterung                                                   | Wert für Entwicklungssysteme              |
+|---------------------------------------|---------------------------------------------------------------|-------------------------------------------|
+| ckanext.odsh.use_matomo               | `true` schaltet das matomo-Tracking ein.                      | `false`                                   |
+| ckanext.odsh.skip_icap_virus_check    | `false` schaltet den Virus-Check ein.                         | `true`                                    |
+| ckanext.odsh.showtestbanner           | `true` schaltet das Banner "Testsystem" ein, Muss `false` für Production-Server sein. | -                 |
\ No newline at end of file
diff --git a/ckanext/odsh/controller.py b/ckanext/odsh/controller.py
index 78eee8959c9ef51ad97c495e56612ec3f6552597..aecd986ecd97aa21b64d1994a37bfa354ffc8f16 100644
--- a/ckanext/odsh/controller.py
+++ b/ckanext/odsh/controller.py
@@ -11,7 +11,6 @@ from ckan.controllers.package import PackageController
 from ckan.controllers.feed import FeedController, ITEMS_LIMIT, _package_search, _create_atom_id
 import ckan.lib.helpers as h
 import ckan.authz as authz
-from ckan.common import c
 import logging
 import matomo
 import ckan.logic as logic
diff --git a/ckanext/odsh/lib/odsh_icap_client.cfg b/ckanext/odsh/lib/odsh_icap_client.cfg
deleted file mode 100644
index 654b57a83fc705ebff6769c89035df98f583432a..0000000000000000000000000000000000000000
--- a/ckanext/odsh/lib/odsh_icap_client.cfg
+++ /dev/null
@@ -1,9 +0,0 @@
-[DEFAULT]
-# the IP of the ICAP-Server
-host = 10.61.127.77
-
-# The port of the ICAP-Server
-port = 1344
-
-# the IP of the client-machine
-clientip = 127.0.0.1
diff --git a/ckanext/odsh/lib/odsh_icap_client.py b/ckanext/odsh/lib/odsh_icap_client.py
index 703ac49eb3a7f1699e862433cca04a1704fbcdb3..91f04a432ea91f6378744b4eb3c0b5a8b69c52f7 100644
--- a/ckanext/odsh/lib/odsh_icap_client.py
+++ b/ckanext/odsh/lib/odsh_icap_client.py
@@ -1,20 +1,34 @@
 import socket
 import sys
 import time
-import ConfigParser
+import logging
+from ckan.common import config
+import ckan.plugins.toolkit as toolkit
+
+log = logging.getLogger(__name__)
+
+def _read_from_config(key):
+    value = config.get(key, None)
+    if value is None:
+        _raise_KeyError_if_not_in_config(key)
+    return value
+
+def _raise_KeyError_if_not_in_config(key):
+    raise KeyError('key {} is not defined in ckan config file.'.format(key))
 
 
 class ODSHICAPRequest(object):
 
-    def __init__(self, FILENAME, FILEBUFF, cfg_file='odsh_icap_client.cfg'):
-        config = ConfigParser.ConfigParser()
-        config.read(cfg_file)
-        self.HOST = '10.61.127.77'
-        self.PORT = 1344
-        self.CLIENTIP = '127.0.0.1'
+    def __init__(self, FILENAME, FILEBUFF):
+        try:
+            self.HOST = _read_from_config('ckanext.odsh.icap.host')
+            self.PORT = toolkit.asint(_read_from_config('ckanext.odsh.icap.port'))
+            self.CLIENTIP = _read_from_config('ckanext.odsh.icap.clientip')
+        except KeyError, e:
+            log.error(e)
         self.FILENAME = FILENAME
         self.FILEBUFF = FILEBUFF
-
+    
     def send(self):
         print("----- Starting ICAP-Request via RESPMOD -----")
 
@@ -82,21 +96,6 @@ class ODSHICAPRequest(object):
             sock.send(l)
             sock.send("\r\n".encode())
             l = fileBuffer.read(PACK_SIZE)
-
-    def _sendfile_old(self, fileName, sock):
-        print('start sending file')
-        PACK_SIZE = 1024 # in bytes
-    
-        with open(fileName) as f:
-            l = f.read(PACK_SIZE)
-            while(l):
-                print('sending %d bytes of data...' % len(l))
-                sock.send('{:02X}'.format(len(l)).encode())
-                sock.send("\r\n".encode())
-                sock.send(l)
-                sock.send("\r\n".encode())
-                l = f.read(PACK_SIZE)
-        print('done sending')
     
     def _recvall(self, sock):
         print('receiving response from icap server')
diff --git a/ckanext/odsh/public/odsh.css b/ckanext/odsh/public/odsh.css
index 650475d89b4035c3ade61b4a828ff4deaacf309a..47a567da70b96179e763434aadc828e8d5ee3194 100644
--- a/ckanext/odsh/public/odsh.css
+++ b/ckanext/odsh/public/odsh.css
@@ -79,6 +79,18 @@ h3{
     font-size:20px;
 }
 
+.skip-link {
+    position: fixed;
+    top: -200px;
+    text-decoration: none;
+    padding: 10px;
+    display: inline-block;
+  }
+
+.skip-link:focus {
+    top: 0;
+}
+
 .secondary h1.heading {
     color:black;
     font-weight: normal ;
@@ -639,7 +651,8 @@ label.rangesearch.disabled {
 .controls input.rangesearch{
     box-sizing: border-box;
     width: 100%;
-    padding: 12px 2px;
+    height: 1.5rem;
+    padding: 2px;
     font-style: normal;
     font-size: 12px;
     line-height: 1.16666667em;
@@ -930,6 +943,11 @@ label:after {
     font-style: normal;
 } 
 
+input#field-username {
+    margin-bottom: 30px;
+    vertical-align: super;
+}
+
 .control-group.error input,
 .control-group.error select,
 .control-group.error .select2-choices,
diff --git a/ckanext/odsh/templates/footer.html b/ckanext/odsh/templates/footer.html
index b1212dba15b04d860702804730bf8ee107168b81..03764a7c7b58782fb85faee0af0af365732205df 100644
--- a/ckanext/odsh/templates/footer.html
+++ b/ckanext/odsh/templates/footer.html
@@ -8,11 +8,11 @@
             <div class='footer-line'></div>
             <div class="footer-left">
                 <div class="footer-icon">&copy; {{g.site_title}}</div>
-                <div class="footer-right">
-                    <div class='footer-icon'><a href='http://www.schleswig-holstein.de/tpkontakt'>Kontakt</a></div>
-                    <div class='footer-icon'><a href='http://www.schleswig-holstein.de/tpimpressum'>Impressum</a></div>
-                    <div class='footer-icon last'><a href='http://www.schleswig-holstein.de/tpdatenschutz'>Datenschutz</a></div>
-                </div>
+            </div>
+            <div class="footer-right">
+                <div class='footer-icon'><a href='http://www.schleswig-holstein.de/tpkontakt'>Kontakt</a></div>
+                <div class='footer-icon'><a href='http://www.schleswig-holstein.de/tpimpressum'>Impressum</a></div>
+                <div class='footer-icon last'><a href='http://www.schleswig-holstein.de/tpdatenschutz'>Datenschutz</a></div>
             </div>
         </div>
     </div>
diff --git a/ckanext/odsh/templates/header.html b/ckanext/odsh/templates/header.html
index 662acfe5ab63466e0c799db0464492c5dfb44d00..f7419ab93400a1b6850cd432045dcd65e1d3e823 100644
--- a/ckanext/odsh/templates/header.html
+++ b/ckanext/odsh/templates/header.html
@@ -39,7 +39,7 @@
                 <ul class="nav nav-pills">
                     <li class="header-menu-mobile" data-module="tpsh_toggle_menu">
                         <a>Menü</a>
-                        <img src="/base/images/icon_close_white.svg">
+                        <img src="/base/images/icon_close_white.svg" alt="Menü schließen" aria-label="Menü schließen">
                     </li>
                     {% block header_site_navigation_tabs %}
                     {{ 
@@ -66,21 +66,21 @@
                                     d="M42.5,44.5h-31v-6.4c0-4.7,3.9-8.6,8.6-8.6h13.9c4.7,0,8.6,3.9,8.6,8.6V44.5z" />
                             </svg>
                             {{name}}</a>
-                        <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
+                        <ul class="dropdown-menu" role="menu">
                             <li>
                                 <svg class='user-icon-small' viewBox="0 0 54 54">
                                     <circle cx="27" cy="17" r="7.5" />
                                     <path
                                         d="M42.5,44.5h-31v-6.4c0-4.7,3.9-8.6,8.6-8.6h13.9c4.7,0,8.6,3.9,8.6,8.6V44.5z" />
                                 </svg>
-                                <a href="{{ h.url_for('/user/') }}" title="logout">
+                                <a href="{{ h.url_for('/user/') }}" title="logout" role="menuitem">
                                     <span class="text">
                                         Mein Profil einsehen
                                     </span>
                                 </a>
                             </li>
                             <li>
-                                <a href="{{ h.url_for('/user/edit') }}" title="logout">
+                                <a href="{{ h.url_for('/user/edit') }}" title="logout" role="menuitem">
                                     <i class='fa fa-edit'></i>
                                     <span class="text">
                                         Mein Profil bearbeiten
@@ -88,7 +88,7 @@
                                 </a>
                             </li>
                             <li>
-                                <a href="{{ h.url_for('/user/_logout') }}" title="logout">
+                                <a href="{{ h.url_for('/user/_logout') }}" title="logout" role="menuitem">
                                     <i class='fa fa-sign-out'></i>
                                     <span class="text">Logout</span>
                                 </a>
diff --git a/ckanext/odsh/templates/package/snippets/close_mobile_sidebar_button.html b/ckanext/odsh/templates/package/snippets/close_mobile_sidebar_button.html
index 87a19511442d1923bfef6b2c4f2e36a2f05dbadf..5e30ade9262d6db85bd7ed8792b3f92091950b7a 100644
--- a/ckanext/odsh/templates/package/snippets/close_mobile_sidebar_button.html
+++ b/ckanext/odsh/templates/package/snippets/close_mobile_sidebar_button.html
@@ -1,3 +1,3 @@
 <div class="container-fluid hide-filters-style">
-    <a class="no-text hide-filters"><img src="/base/images/icon_close.svg"><span class="text">close</span></a>
+    <a class="no-text hide-filters"><img src="/base/images/icon_close.svg" alt="Filterdialog schließen"><span class="text">close</span></a>
 </div>
\ No newline at end of file
diff --git a/ckanext/odsh/templates/page.html b/ckanext/odsh/templates/page.html
index 6e958cacd443657ef4eb249533197cc046b8e413..134079dd6ced8e52b3e01a7eec0fcef0a3db1a22 100644
--- a/ckanext/odsh/templates/page.html
+++ b/ckanext/odsh/templates/page.html
@@ -1,5 +1,10 @@
 {% ckan_extends %}
 
+{% block skip %}
+    <a class="skip-link" href="#content">
+        Zum Inhalt springen.
+    </a>
+{% endblock skip %}
 
 {%- block content %}
 <div class="blur-layer"></div>
diff --git a/ckanext/odsh/templates/snippets/facet_list.html b/ckanext/odsh/templates/snippets/facet_list.html
index ab0d8af05fdd028f4697ff60895f02d88120ddd2..d2b8521998aa412d9b20b7e92d7443c2bfa84bff 100644
--- a/ckanext/odsh/templates/snippets/facet_list.html
+++ b/ckanext/odsh/templates/snippets/facet_list.html
@@ -38,8 +38,8 @@
           >
           </span>
           {% if name=='groups' %}
-          <span class='group-icon-container'>
-            <img src="/base/images/icon_kat_{{item.name}}.svg"/>
+          <span class="group-icon-container" aria-hidden="true">
+            <img src="/base/images/icon_kat_{{item.name}}.svg" alt=""/>
           </span>
           {% endif %}
           
diff --git a/ckanext/odsh/templates/snippets/package_item.html b/ckanext/odsh/templates/snippets/package_item.html
index b31095c43ffbcff6b8aa792784da7c9c6685c7b4..419e685bc6eedfcb77f671a559ec19f408fbee75 100644
--- a/ckanext/odsh/templates/snippets/package_item.html
+++ b/ckanext/odsh/templates/snippets/package_item.html
@@ -109,8 +109,8 @@ Example:
             </span>
             {% for category in package.groups %}
             <span class='category-with-icon'>
-                <span class='category-icon-container'>
-                    <img src="/base/images/icon_kat_{{category.name}}.svg" />
+                <span class='category-icon-container' aria-hidden='true'>
+                    <img src="/base/images/icon_kat_{{category.name}}.svg" alt=""/>
                 </span>
                 <span class="category-name">
                     {{ category.display_name }}
diff --git a/ckanext/odsh/tests_tpsh/test_icap.py b/ckanext/odsh/tests_tpsh/test_icap.py
new file mode 100644
index 0000000000000000000000000000000000000000..f97bbc74249eadeeb2e36ebdf07aae53191d0d82
--- /dev/null
+++ b/ckanext/odsh/tests_tpsh/test_icap.py
@@ -0,0 +1,67 @@
+import nose.tools as nt
+from testfixtures import log_capture
+
+from ckan.common import config
+from ckanext.odsh.lib.odsh_icap_client import ODSHICAPRequest, _read_from_config
+
+class Test_ODSHICAPRequest(object):
+    def setUp(self):
+        config.update({
+            'ckanext.odsh.icap.host': 'some_host',
+            'ckanext.odsh.icap.port': '123',
+            'ckanext.odsh.icap.clientip': 'some_ip',
+        })
+    
+    def tearDown(self):
+        config.clear()
+
+    def test_it_initializes_with_parameters_set_in_config(self):
+        request = ODSHICAPRequest('some_filename', 'some_filebuffer')
+        nt.assert_equal(request.HOST, 'some_host')
+        nt.assert_equal(request.PORT, 123)
+        nt.assert_equal(request.CLIENTIP, 'some_ip')
+    
+    @log_capture()
+    def test_it_logs_missing_parameter_host_to_error_log(self, capture):
+        del config['ckanext.odsh.icap.host']
+        ODSHICAPRequest('some_filename', 'some_filebuffer')
+        capture.check((
+            'ckanext.odsh.lib.odsh_icap_client',
+            'ERROR',
+            "'key ckanext.odsh.icap.host is not defined in ckan config file.'"
+        ))
+    
+    @log_capture()
+    def test_it_logs_missing_parameter_port_to_error_log(self, capture):
+        del config['ckanext.odsh.icap.port']
+        ODSHICAPRequest('some_filename', 'some_filebuffer')
+        capture.check((
+            'ckanext.odsh.lib.odsh_icap_client',
+            'ERROR',
+            "'key ckanext.odsh.icap.port is not defined in ckan config file.'"
+        ))
+    
+    @log_capture()
+    def test_it_logs_missing_parameter_clientip_to_error_log(self, capture):
+        del config['ckanext.odsh.icap.clientip']
+        ODSHICAPRequest('some_filename', 'some_filebuffer')
+        capture.check((
+            'ckanext.odsh.lib.odsh_icap_client',
+            'ERROR',
+            "'key ckanext.odsh.icap.clientip is not defined in ckan config file.'"
+        ))
+    
+    def test_read_from_config_raises_KeyError_if_host_not_defined_in_config(self):
+        del config['ckanext.odsh.icap.host']
+        with nt.assert_raises(KeyError):
+            _read_from_config('ckanext.odsh.icap.host')
+    
+    def test_read_from_config_raises_KeyError_if_port_not_defined_in_config(self):
+        del config['ckanext.odsh.icap.port']
+        with nt.assert_raises(KeyError):
+            _read_from_config('ckanext.odsh.icap.port')
+    
+    def test_read_from_config_raises_KeyError_if_clientip_not_defined_in_config(self):
+        del config['ckanext.odsh.icap.clientip']
+        with nt.assert_raises(KeyError):
+            _read_from_config('ckanext.odsh.icap.clientip')
diff --git a/dev-requirements.txt b/dev-requirements.txt
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..c574e4eaf013c487e6c63e0048eb9132b71c2627 100644
--- a/dev-requirements.txt
+++ b/dev-requirements.txt
@@ -0,0 +1,185 @@
+alabaster==0.7.11
+amqp==1.4.9
+anyjson==0.3.3
+arrow==0.13.1
+asn1crypto==0.24.0
+astroid==1.6.6
+atomicwrites==1.3.0
+attrs==19.3.0
+Babel==2.3.4
+backports.functools-lru-cache==1.5
+Beaker==1.8.1
+beautifulsoup4==4.5.1
+billiard==3.3.0.23
+bleach==1.5.0
+blinker==1.4
+celery==3.1.25
+certifi==2018.8.13
+cffi==1.11.5
+chardet==3.0.4
+click==6.7
+configparser==3.7.4
+contextlib2==0.6.0.post1
+cookies==2.2.1
+coverage==4.5.1
+coveralls==1.3.0
+cryptography==2.3
+decorator==4.0.6
+defusedxml==0.6.0
+dnspython==1.16.0
+docopt==0.6.2
+docutils==0.12
+entrypoints==0.3
+enum34==1.1.6
+eventlet==0.24.1
+extras==1.0.0
+factory-boy==2.1.1
+fanstatic==0.12
+filehash==0.1.dev3
+first==2.0.1
+fixtures==3.0.0
+flake8==3.7.8
+Flask==0.11.1
+Flask-DebugToolbar==0.10.0
+FormEncode==1.3.0
+funcsigs==1.0.2
+functools32==3.2.3.post2
+futures==3.3.0
+GeoAlchemy==0.7.2
+GeoAlchemy2==0.4.2
+geolinks==0.2.0
+geomet==0.2.0.post2
+greenlet==0.4.15
+html5lib==0.9999999
+httpretty==0.8.3
+hupper==1.6.1
+idna==2.7
+imagesize==1.0.0
+importlib-metadata==0.23
+ipaddress==1.0.22
+isodate==0.6.0
+isort==4.3.21
+itsdangerous==0.24
+Jinja2==2.8
+json-table-schema==0.2.1
+kombu==3.0.37
+lazy-object-proxy==1.4.1
+linecache2==1.0.0
+lxml==3.6.2
+Mako==1.0.4
+Markdown==2.6.7
+MarkupSafe==0.23
+mccabe==0.6.1
+messytables==0.15.2
+mock==2.0.0
+monotonic==1.5
+more-itertools==5.0.0
+mox3==0.26.0
+multiline-log-formatter==0.1.8
+nose==1.3.7
+ofs==0.4.2
+ordereddict==1.1
+OWSLib==0.16.0
+packaging==17.1
+Pairtree===0.7.1-T
+passlib==1.6.5
+Paste==1.7.5.1
+PasteDeploy==2.0.1
+PasteScript==2.0.2
+pathlib==1.0.1
+pathlib2==2.3.5
+pbr==1.10.0
+pdf2image==1.9.0
+pdftotext==2.1.2
+pika==0.12.0
+Pillow==6.1.0
+pip-tools==1.7.0
+piwikapi==0.3
+pkg-resources==0.0.0
+plaster==1.0
+plaster-pastedeploy==0.7
+pluggy==0.13.0
+polib==1.0.7
+progressbar==2.3
+psycopg2==2.7.3.2
+py==1.8.0
+pyasn1==0.4.8
+pycodestyle==2.5.0
+pycountry==18.5.26
+pycparser==2.18
+pycrypto==2.6.1
+pycryptodome==3.9.0
+pycsw==2.2.0
+pyfakefs==2.9
+pyflakes==2.1.1
+Pygments==2.1.3
+pylint==1.9.5
+Pylons==0.9.7
+pymongo==3.9.0
+pyOpenSSL==18.0.0
+pyparsing==2.2.0
+pyproj==1.9.5.1
+pyramid==1.10.4
+pyramid-exclog==0.1
+-e git+https://github.com/IdentityPython/pysaml2.git@247e2f642b37de90a61c4f5ca49d8403840b6ea2#egg=pysaml2
+pysolr==3.6.0
+pytest==4.6.6
+pytest-cov==2.8.1
+python-dateutil==2.8.0
+python-json-logger==0.1.11
+python-magic==0.4.12
+python-memcached==1.48
+python-mimeparse==1.6.0
+pytz==2016.7
+pyutilib.component.core==4.6.4
+rdflib==4.2.1
+rdflib-jsonld==0.4.0
+redis==2.10.1
+repoze.lru==0.6
+repoze.who==2.3
+repoze.who-friendlyform==1.0.8
+requests==2.11.1
+responses==0.10.6
+rope==0.14.0
+Routes==1.13
+rq==0.6.0
+rq-dashboard==0.4.0
+scandir==1.10.0
+selenium==3.141.0
+Shapely==1.5.17
+simplejson==3.10.0
+singledispatch==3.4.0.3
+six==1.10.0
+snowballstemmer==1.2.1
+SPARQLWrapper==1.8.2
+Sphinx==1.7.1
+sphinx-rtd-theme==0.3.1
+sphinxcontrib-websupport==1.1.0
+SQLAlchemy==0.9.6
+sqlalchemy-migrate==0.10.0
+sqlparse==0.2.2
+Tempita==0.5.2
+testfixtures==6.10.3
+testtools==2.3.0
+traceback2==1.4.0
+translationstring==1.3
+typing==3.6.4
+tzlocal==1.3
+unicodecsv==0.14.1
+unittest2==1.1.0
+urllib3==1.23
+vdm==0.13
+venusian==1.2.0
+vine==1.1.4
+wcwidth==0.1.7
+WebError==0.13.1
+WebHelpers==1.3
+WebOb==1.0.8
+WebTest==1.4.3
+Werkzeug==0.11.10
+wrapt==1.11.2
+xlrd==1.0.0
+xmltodict==0.10.2
+zipp==0.6.0
+zope.deprecation==4.4.0
+zope.interface==4.3.2