diff --git a/config.ini b/config.ini
new file mode 100644
index 0000000000000000000000000000000000000000..b15f3dedfc99572c2ba896d032554808a78a96f9
--- /dev/null
+++ b/config.ini
@@ -0,0 +1,9 @@
+[META]
+author = Jan Maximilian Michal
+
+
+[UPLAODER]
+user = root
+pass = homer
+host = http://localhost:8000/
+rtoken = c13456ec3d71dc657e19fb826750f676
diff --git a/grim.py b/grim.py
index 0c4e576e73b10bfc87295959f2eb052cfb6fba39..25c063d2625194e61b62a119bd9fe28d011245e2 100755
--- a/grim.py
+++ b/grim.py
@@ -1,6 +1,6 @@
 #!/usr/local/bin/python3
 
-################################################################################
+##########################################################################
 #
 # This script contains the main part of hallgrim and is the only script that
 # needs to be invoked. The steps it takes to generate a task are as follows:
@@ -15,12 +15,13 @@
 # * a finisher compresses data if needed (needs to be implemented, maybe as
 #   separate subparser).
 #
-################################################################################
+##########################################################################
 
 import importlib
 import argparse
 import os
 import sys
+import configparser
 
 # local import
 from hallgrim.IliasXMLCreator import packer
@@ -29,18 +30,11 @@ from hallgrim.messages import *
 from hallgrim.parser import *
 from hallgrim.uploader import send_script
 
-scaffolding = r'''
-meta = {{
-    'author': '{}',
-    'title': '{}',
-    'type': '{}',
-    'points': {},
-}}
 
-task = """ decription """
-{}
-feedback = """ decription """
-'''
+def get_config():
+    config = configparser.ConfigParser()
+    config.read('config.ini')
+    return config
 
 
 def file_to_module(name):
@@ -93,7 +87,6 @@ def parseme():
         "-a",
         "--author",
         help="Name of the scripts author",
-        default='ILIAS Author',
         metavar='AUTHOR'
     )
     parser_new.add_argument(
@@ -129,10 +122,6 @@ def parseme():
 
     parser_gen = subparsers.add_parser(
         "upload", help="Subcommand to upload created xml instances.")
-    parser_gen.add_argument(
-        '--host',
-        help='The hostname of the ilias test implementation',
-        metavar='HOST')
     parser_gen.add_argument(
         'script',
         help='The script that should be uploaded',
@@ -152,6 +141,16 @@ def parseme():
 
 
 def delegator(output, script_list, instances):
+    """
+    It gets a list of filenames and delegates them to the correct handler.
+    Every file that does not end with .py will be ignored. Each script
+    is imported and then passed as module to the handler.
+
+    Arguments:
+        output {filename}  -- where to write the finished XML document
+        script_list {list} -- a list of filenames that contain scripts
+        instances {int}    -- number of instances that should be generated
+    """
     for script_name in filter(lambda a: a.endswith('.py'), script_list):
         script = importlib.import_module(file_to_module(script_name))
         handler = {
@@ -166,6 +165,18 @@ def delegator(output, script_list, instances):
 
 
 def handle_gap_questions(output, script, instances):
+    """ Handles gap questions of all kinds
+
+    A script can contain any mixture of gap, numeric gap and choice gap
+    questions. The data object that is needed by the XML creating scripts
+    is generated and the task itself is handled by the parser. The parser
+    returns the intermediate representation of the task.
+
+    Arguments:
+        output {str}    -- where to write the final file
+        script {module} -- the loaded module that describes the task
+        instances {int} -- number of instances that should be generated
+    """
     script_is_valid(script, required=['meta', 'task', 'feedback'])
     data = {
         'type': type_selector(script.meta['type']),
@@ -186,6 +197,16 @@ def handle_gap_questions(output, script, instances):
 
 
 def handle_choice_questions(output, script, instances):
+    """
+    Handles multiple and single choice questions. The relevant parts of the
+    script are fed into a parser that return the correct intermediate
+    representation for the task. In this case a list of answers.
+
+    Arguments:
+        output {str}    -- where to write the finished XML document
+        script {module} -- the loaded module that describes the task
+        instances {int} -- number of instances that should be generated
+    """
     script_is_valid(script, required=['meta', 'task', 'choices', 'feedback'])
     data = {
         'type': type_selector(script.meta['type']),
@@ -207,6 +228,25 @@ def handle_choice_questions(output, script, instances):
 
 
 def handle_new_script(name, qtype, author, points):
+    """ Creates a new script file.
+
+    Takes in some meta information from the command line of if not present takes
+    it from the config.ini or uses default values.
+
+    TODO: put the configuration before the parser and use as default values
+
+    Arguments:
+        name {str}     -- name of the script, will also become filename
+        qtype {str}    -- question type (choice, gap, alignment)
+        author {str}   -- the author of the script
+        points {float} -- number of points for the task
+    """
+    from hallgrim.templates import scaffolding
+    config = get_config()
+
+    if not author:
+        author = config['META']['author']
+
     with open('scripts/' + name + '.py', 'w') as new_script:
         choice = ''
         if qtype in ['multiple choice', 'single choice']:
@@ -216,9 +256,27 @@ def handle_new_script(name, qtype, author, points):
             author, name, qtype, points, choice).strip(), file=new_script)
         info('Generated new script "{}."'.format(new_script.name))
 
-def handle_upload(script_path, hostname):
-    r = send_script(script_path)
-    info("Uploaded %s. Status code looks %s." % (script_path, "good" if r else "bad"))
+
+def handle_upload(script_path):
+    """ Passes data to the upload script.
+
+    The status code should be 500, since ILIAS always replies with that error
+    code after an upload is confirmed. If anything else the script will say
+    the status code was bad.
+
+    Arguments:
+        script_path {str} -- path to the file that should be uploaded
+    """
+    config = get_config()
+    r = send_script(
+        script_path,
+        config['UPLAODER']['host'],
+        config['UPLAODER']['user'],
+        config['UPLAODER']['pass'],
+        config['UPLAODER']['rtoken'],
+    )
+    info("Uploaded %s. Status code looks %s." %
+         (script_path, "good" if r else "bad"))
 
 if __name__ == '__main__':
     markdown = get_markdown()
diff --git a/hallgrim/IliasXMLCreator/gap.py b/hallgrim/IliasXMLCreator/gap.py
index 010a2fb709f076d7e9089eed916e1d686cf82d15..71b5923df326595fdf5ba816bb09dcad6e390955 100644
--- a/hallgrim/IliasXMLCreator/gap.py
+++ b/hallgrim/IliasXMLCreator/gap.py
@@ -10,15 +10,14 @@ def xml_print(element, **kwargs):
 
 
 ###
-# Solution 1
-# ['text', 'text', 'text']
-# [('gap_solution', points), ..., (['one', 'two', 'three'], points)]
 #
+# Type of first item in gap tuple determines the gap type. gap might be changed
+# to set
 # str : str_gap
 # list : choice_gap
 # tuple : num_gap (x, min, max)
 #
-# Solution 2
+# Format of gap_list
 # ['text', ('gap_solution', points), ('gap_solution', points), 'text', ...]
 #
 ###
diff --git a/hallgrim/templates.py b/hallgrim/templates.py
new file mode 100644
index 0000000000000000000000000000000000000000..d17f246a246a73a68a9adbe69c8f624b7a3594e5
--- /dev/null
+++ b/hallgrim/templates.py
@@ -0,0 +1,12 @@
+scaffolding = r'''
+meta = {{
+    'author': '{}',
+    'title': '{}',
+    'type': '{}',
+    'points': {},
+}}
+
+task = """ decription """
+{}
+feedback = """ decription """
+'''
\ No newline at end of file
diff --git a/hallgrim/uploader.py b/hallgrim/uploader.py
index 3abd403ca54cacc8ec983c91656ecaf15dfcc8be..0cfca4c55ada94b2ef6c5daf33946b5ce2f683ac 100644
--- a/hallgrim/uploader.py
+++ b/hallgrim/uploader.py
@@ -1,4 +1,4 @@
-################################################################################
+##########################################################################
 #
 # This is the uploader. It simplifies the testing process immensely and  makes
 # autoILIAS finally obsolete, since this system uses a proper Ilias
@@ -13,34 +13,34 @@
 #
 # Sadly this script adds some ugly dependencies like requests_toolbelt.
 #
-################################################################################
+##########################################################################
 
 import os
 
 import requests
 from requests_toolbelt import MultipartEncoder
-from lxml import html
 
 __all__ = ['send_script']
 
 # static data
-host = "http://localhost:8000/"
-login = {"username" : "root", "password" : "homer", "cmd[showLogin]" : "Login"}
-upload_url = host + "ilias/ilias.php?ref_id=65&cmd=post&cmdClass=ilobjquestionpoolgui&cmdNode=26:gb&baseClass=ilRepositoryGUI&fallbackCmd=upload&rtoken=c13456ec3d71dc657e19fb826750f676"
-import_url = host + "ilias/ilias.php?ref_id=65&cmd=post&cmdClass=ilobjquestionpoolgui&cmdNode=26:gb&baseClass=ilRepositoryGUI&fallbackCmd=questions&rtoken=c13456ec3d71dc657e19fb826750f676"
-confirm_url = host + "ilias/ilias.php?ref_id=65&cmd=post&cmdClass=ilobjquestionpoolgui&cmdNode=26:gb&baseClass=ilRepositoryGUI&rtoken=c13456ec3d71dc657e19fb826750f676"
+login_url = "ilias/login.php"
+upload_url = "ilias/ilias.php?ref_id=67&cmd=post&cmdClass=ilobjquestionpoolgui&cmdNode=26:gb&baseClass=ilRepositoryGUI&fallbackCmd=upload&rtoken=%s"
+import_url = "ilias/ilias.php?ref_id=67&cmd=post&cmdClass=ilobjquestionpoolgui&cmdNode=26:gb&baseClass=ilRepositoryGUI&fallbackCmd=questions&rtoken=%s"
+confirm_url = "ilias/ilias.php?ref_id=67&cmd=post&cmdClass=ilobjquestionpoolgui&cmdNode=26:gb&baseClass=ilRepositoryGUI&rtoken=%s"
 
 import_data = {
-    "cmd[importQuestions]" : "Import",
+    "cmd[importQuestions]": "Import",
 }
 
 confirm_data = {
-    "cmd[importVerifiedFile]" : "Import",
-    "questions_only" : "1",
+    "cmd[importVerifiedFile]": "Import",
+    "questions_only": "1",
 }
 
 
-def send_script(filepath):
+def send_script(filepath, host, user, password, rtoken):
+    login = {"username": user, "password": password, "cmd[showLogin]": "Login"}
+
     file = MultipartEncoder(fields={
         'xmldoc': (
             os.path.basename(filepath),
@@ -48,13 +48,13 @@ def send_script(filepath):
             'text/xml'
         )
     })
+    header = {'Content-Type': file.content_type}
 
     # session create and login
     session = requests.Session()
-    r = session.post(host + "ilias/login.php", data=login)
-    r = session.post(import_url, data=import_data)
-    r = session.post(upload_url, data=file, headers={'Content-Type': file.content_type})
-    r = session.post(confirm_url, data=confirm_data)
+    r = session.post(host + login_url, data=login)
+    r = session.post(host + (import_url % rtoken), data=import_data)
+    r = session.post(host + (upload_url % rtoken), data=file, headers=header)
+    r = session.post(host + (confirm_url % rtoken), data=confirm_data)
 
     return r.status_code == 500
-
diff --git a/scripts/Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0).py b/scripts/Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0).py
index 0316f0da01d0e5a1f7d8d0e72cd809ad690738ed..68cd72145e3e60b07a5a054c069fc2436362995a 100644
--- a/scripts/Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0).py	
+++ b/scripts/Vermischtes aus Kapitel 3 (I1-ID: uo93wey0oog0).py	
@@ -21,12 +21,12 @@ choices = """
 feedback = """
 | Aussage                                                                                                 |  Wert   |   Begründung                                                                                                                                                                                                                                                                                                         |
 |---------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| Formalparameter sind lokale Variablen.                                                                  | TRUE    |  Die im Methodenkopf definierten Parameter heißen auch Formalparameter und werden innerhalb der Methode als Variable gebraucht. Tatsächliche Parameter sind die im Programmablauf übergebenen Werte oder Referenzen.                                                                                               |
+| Formalparameter sind lokale Variablen.                                                                  | TRUE    |  Die im Methodenkopf definierten Parameter heißen auch Formalparameter und werden innerhalb der Methode als Variable gebraucht. Tatsächliche Parameter sind die im Programmablauf übergebenen Werte oder Referenzen.                                                                                                |
 | Die JVM interpretiert Java-Bytecode.                                                                    | TRUE    |  Java-Bytecode ist das Instruction-Set der Java-Virtual-Machine                                                                                                                                                                                                                                                      |
 | (false ? true : false) == (true ? false : true)                                                         | TRUE    |  (false ? true : false) == (true ? false : true) -> false == false -> true                                                                                                                                                                                                                                           |
 | Das rekursive Grundschema lautet: Rekurriere - Finalisiere (falls trivial)                              | FALSE   |  Das rekursive Grundschema lautet: Finalisiere (falls trivial) - Rekurriere                                                                                                                                                                                                                                          |
-| Die Java-Laufzeitumgebung beinhaltet Compiler, Klassenbibliotheken und die (JVM) Java Virtual Machine.  | FALSE   |  Wikipedia: "Allgemein besteht die Laufzeitumgebung aus der Java Virtual Machine (Java VM), die für die Ausführung der Java-Anwendungen verantwortlich ist, einer Programmierschnittstelle (API, für Application and Programming Interface) und weiteren Programmbibliotheken." Ein Compiler gehört nicht dazu.  |
-| An Ausdrücke dürfen keine Zuweisungen erfolgen.                                                       | FALSE   |  Da zum Beispiel x[0] = 1                                                                                                                                                                                                                                                                                            |
+| Die Java-Laufzeitumgebung beinhaltet Compiler, Klassenbibliotheken und die (JVM) Java Virtual Machine.  | FALSE   |  Wikipedia: "Allgemein besteht die Laufzeitumgebung aus der Java Virtual Machine (Java VM), die für die Ausführung der Java-Anwendungen verantwortlich ist, einer Programmierschnittstelle (API, für Application and Programming Interface) und weiteren Programmbibliotheken." Ein Compiler gehört nicht dazu.      |
+| An Ausdrücke dürfen keine Zuweisungen erfolgen.                                                         | FALSE   |  Da zum Beispiel x[0] = 1                                                                                                                                                                                                                                                                                            |
 | Methoden mit Signatur int (int) werden mit call-by-reference aufgerufen.                                | FALSE   |  Sämtliche Java Methoden werden mit call-by-value aufgerufen. Eine gute Erklärung zu den Unterschieden finden Sie hier.                                                                                                                                                                                            |
 | (false ? false : true) == (false ? true : false)                                                        | FALSE   |  (false ? false : true) == (false ? true : false) -> true == false -> false                                                                                                                                                                                                                                          |
 """