prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  App Generator creates faulty info.xml when using umlauts (special characters äöü)
  Problem: nextcloud/apps/foo/appinfo/info.xml misses the closing **</info>** tag. Just generates **</**
  
  ## Details
  
  * Browser and browser version: Firefox 55.0.3
  
  ## Steps to reproduce
  
  Steps to reproduce:
  
  - visit https://apps.nextcloud.com/developer/apps/generate
  - enter the required information; in summary and description enter "This is a test app äöü"
  - click generate and download.
  - look at the generated info.xml
  
  
  App Generator creates faulty info.xml when using umlauts (special characters äöü)
  Problem: nextcloud/apps/foo/appinfo/info.xml misses the closing **</info>** tag. Just generates **</**
  
  ## Details
  
  * Browser and browser version: Firefox 55.0.3
  
  ## Steps to reproduce
  
  Steps to reproduce:
  
  - visit https://apps.nextcloud.com/developer/apps/generate
  - enter the required information; in summary and description enter "This is a test app äöü"
  - click generate and download.
  - look at the generated info.xml
  
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `nextcloudappstore/scaffolding/archive.py`
  Content:
  ```
  1 import re
  2 import tarfile
  3 from io import BytesIO, StringIO
  4 from typing import Dict
  5 from os.path import join, isdir, relpath
  6 from os import walk
  7 
  8 from django.template import Context
  9 from django.template import Template
  10 
  11 from nextcloudappstore.core.facades import resolve_file_relative_path
  12 from nextcloudappstore.settings.base import APP_SCAFFOLDING_PROFILES
  13 
  14 
  15 def build_files(args: Dict[str, str]) -> Dict[str, str]:
  16     platform = int(args['platform'])  # prevent path traversal
  17     vars = {
  18         'id': args['name'].lower(),
  19         'summary': args['summary'],
  20         'description': args['description'],
  21         'name': ' '.join(re.findall(r'[A-Z][^A-Z]*', args['name'])),
  22         'namespace': args['name'],
  23         'author_name': args['author_name'],
  24         'author_mail': args['author_email'],
  25         'author_homepage': args['author_homepage'],
  26         'issue_tracker': args['issue_tracker'],
  27         'categories': args['categories'],
  28         'nextcloud_version': platform
  29     }
  30     vars.update(APP_SCAFFOLDING_PROFILES.get(platform, {}))
  31     relative_base = 'app-templates/%i/app/' % platform
  32     base = resolve_file_relative_path(__file__, relative_base)
  33 
  34     context = Context({'app': vars})
  35     result = {}
  36     if isdir(base):
  37         for root, dirs, files in walk(base):
  38             for file in files:
  39                 file_path = join(root, file)
  40                 rel_file_path = '%s/%s' % (
  41                     vars['id'], relpath(file_path, base)
  42                 )
  43                 with open(file_path) as f:
  44                     t = Template(f.read())
  45                     result[rel_file_path] = t.render(context)
  46 
  47     return result
  48 
  49 
  50 def build_archive(parameters: Dict[str, str]) -> BytesIO:
  51     buffer = BytesIO()
  52     with tarfile.open(fileobj=buffer, mode='w:gz') as f:
  53         files = build_files(parameters)
  54         for path, contents in files.items():
  55             info = tarfile.TarInfo(path)
  56             info.size = len(contents)
  57             f.addfile(info, BytesIO(contents.encode()))
  58     buffer.seek(0)
  59     return buffer
  60
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/nextcloudappstore/scaffolding/archive.py b/nextcloudappstore/scaffolding/archive.py
  --- a/nextcloudappstore/scaffolding/archive.py
  +++ b/nextcloudappstore/scaffolding/archive.py
  @@ -1,9 +1,9 @@
   import re
   import tarfile
  -from io import BytesIO, StringIO
  -from typing import Dict
  -from os.path import join, isdir, relpath
  +from io import BytesIO
   from os import walk
  +from os.path import join, isdir, relpath
  +from typing import Dict
   
   from django.template import Context
   from django.template import Template
  @@ -53,7 +53,8 @@
           files = build_files(parameters)
           for path, contents in files.items():
               info = tarfile.TarInfo(path)
  -            info.size = len(contents)
  -            f.addfile(info, BytesIO(contents.encode()))
  +            encoded_content = contents.encode()
  +            info.size = len(encoded_content)
  +            f.addfile(info, BytesIO(encoded_content))
       buffer.seek(0)
       return buffer
  
verification_info: {"golden_diff": "diff --git a/nextcloudappstore/scaffolding/archive.py b/nextcloudappstore/scaffolding/archive.py\n--- a/nextcloudappstore/scaffolding/archive.py\n+++ b/nextcloudappstore/scaffolding/archive.py\n@@ -1,9 +1,9 @@\n import re\n import tarfile\n-from io import BytesIO, StringIO\n-from typing import Dict\n-from os.path import join, isdir, relpath\n+from io import BytesIO\n from os import walk\n+from os.path import join, isdir, relpath\n+from typing import Dict\n \n from django.template import Context\n from django.template import Template\n@@ -53,7 +53,8 @@\n         files = build_files(parameters)\n         for path, contents in files.items():\n             info = tarfile.TarInfo(path)\n-            info.size = len(contents)\n-            f.addfile(info, BytesIO(contents.encode()))\n+            encoded_content = contents.encode()\n+            info.size = len(encoded_content)\n+            f.addfile(info, BytesIO(encoded_content))\n     buffer.seek(0)\n     return buffer\n", "issue": "App Generator creates faulty info.xml when using umlauts (special characters \u00e4\u00f6\u00fc)\nProblem: nextcloud/apps/foo/appinfo/info.xml misses the closing **</info>** tag. Just generates **</**\r\n\r\n## Details\r\n\r\n* Browser and browser version: Firefox 55.0.3\r\n\r\n## Steps to reproduce\r\n\r\nSteps to reproduce:\r\n\r\n- visit https://apps.nextcloud.com/developer/apps/generate\r\n- enter the required information; in summary and description enter \"This is a test app \u00e4\u00f6\u00fc\"\r\n- click generate and download.\r\n- look at the generated info.xml\r\n\r\n\nApp Generator creates faulty info.xml when using umlauts (special characters \u00e4\u00f6\u00fc)\nProblem: nextcloud/apps/foo/appinfo/info.xml misses the closing **</info>** tag. Just generates **</**\r\n\r\n## Details\r\n\r\n* Browser and browser version: Firefox 55.0.3\r\n\r\n## Steps to reproduce\r\n\r\nSteps to reproduce:\r\n\r\n- visit https://apps.nextcloud.com/developer/apps/generate\r\n- enter the required information; in summary and description enter \"This is a test app \u00e4\u00f6\u00fc\"\r\n- click generate and download.\r\n- look at the generated info.xml\r\n\r\n\n", "before_files": [{"content": "import re\nimport tarfile\nfrom io import BytesIO, StringIO\nfrom typing import Dict\nfrom os.path import join, isdir, relpath\nfrom os import walk\n\nfrom django.template import Context\nfrom django.template import Template\n\nfrom nextcloudappstore.core.facades import resolve_file_relative_path\nfrom nextcloudappstore.settings.base import APP_SCAFFOLDING_PROFILES\n\n\ndef build_files(args: Dict[str, str]) -> Dict[str, str]:\n    platform = int(args['platform'])  # prevent path traversal\n    vars = {\n        'id': args['name'].lower(),\n        'summary': args['summary'],\n        'description': args['description'],\n        'name': ' '.join(re.findall(r'[A-Z][^A-Z]*', args['name'])),\n        'namespace': args['name'],\n        'author_name': args['author_name'],\n        'author_mail': args['author_email'],\n        'author_homepage': args['author_homepage'],\n        'issue_tracker': args['issue_tracker'],\n        'categories': args['categories'],\n        'nextcloud_version': platform\n    }\n    vars.update(APP_SCAFFOLDING_PROFILES.get(platform, {}))\n    relative_base = 'app-templates/%i/app/' % platform\n    base = resolve_file_relative_path(__file__, relative_base)\n\n    context = Context({'app': vars})\n    result = {}\n    if isdir(base):\n        for root, dirs, files in walk(base):\n            for file in files:\n                file_path = join(root, file)\n                rel_file_path = '%s/%s' % (\n                    vars['id'], relpath(file_path, base)\n                )\n                with open(file_path) as f:\n                    t = Template(f.read())\n                    result[rel_file_path] = t.render(context)\n\n    return result\n\n\ndef build_archive(parameters: Dict[str, str]) -> BytesIO:\n    buffer = BytesIO()\n    with tarfile.open(fileobj=buffer, mode='w:gz') as f:\n        files = build_files(parameters)\n        for path, contents in files.items():\n            info = tarfile.TarInfo(path)\n            info.size = len(contents)\n            f.addfile(info, BytesIO(contents.encode()))\n    buffer.seek(0)\n    return buffer\n", "path": "nextcloudappstore/scaffolding/archive.py"}], "after_files": [{"content": "import re\nimport tarfile\nfrom io import BytesIO\nfrom os import walk\nfrom os.path import join, isdir, relpath\nfrom typing import Dict\n\nfrom django.template import Context\nfrom django.template import Template\n\nfrom nextcloudappstore.core.facades import resolve_file_relative_path\nfrom nextcloudappstore.settings.base import APP_SCAFFOLDING_PROFILES\n\n\ndef build_files(args: Dict[str, str]) -> Dict[str, str]:\n    platform = int(args['platform'])  # prevent path traversal\n    vars = {\n        'id': args['name'].lower(),\n        'summary': args['summary'],\n        'description': args['description'],\n        'name': ' '.join(re.findall(r'[A-Z][^A-Z]*', args['name'])),\n        'namespace': args['name'],\n        'author_name': args['author_name'],\n        'author_mail': args['author_email'],\n        'author_homepage': args['author_homepage'],\n        'issue_tracker': args['issue_tracker'],\n        'categories': args['categories'],\n        'nextcloud_version': platform\n    }\n    vars.update(APP_SCAFFOLDING_PROFILES.get(platform, {}))\n    relative_base = 'app-templates/%i/app/' % platform\n    base = resolve_file_relative_path(__file__, relative_base)\n\n    context = Context({'app': vars})\n    result = {}\n    if isdir(base):\n        for root, dirs, files in walk(base):\n            for file in files:\n                file_path = join(root, file)\n                rel_file_path = '%s/%s' % (\n                    vars['id'], relpath(file_path, base)\n                )\n                with open(file_path) as f:\n                    t = Template(f.read())\n                    result[rel_file_path] = t.render(context)\n\n    return result\n\n\ndef build_archive(parameters: Dict[str, str]) -> BytesIO:\n    buffer = BytesIO()\n    with tarfile.open(fileobj=buffer, mode='w:gz') as f:\n        files = build_files(parameters)\n        for path, contents in files.items():\n            info = tarfile.TarInfo(path)\n            encoded_content = contents.encode()\n            info.size = len(encoded_content)\n            f.addfile(info, BytesIO(encoded_content))\n    buffer.seek(0)\n    return buffer\n", "path": "nextcloudappstore/scaffolding/archive.py"}]}