xref: /trunk/test/odf-validate/fixtures/encrypted/make.py (revision 0e16a31d78a652c56c5c0fc79c752f48b9048df9)
1#**************************************************************
2#
3#  Licensed to the Apache Software Foundation (ASF) under one
4#  or more contributor license agreements.  See the NOTICE file
5#  distributed with this work for additional information
6#  regarding copyright ownership.  The ASF licenses this file
7#  to you under the Apache License, Version 2.0 (the
8#  "License"); you may not use this file except in compliance
9#  with the License.  You may obtain a copy of the License at
10#
11#    http://www.apache.org/licenses/LICENSE-2.0
12#
13#  Unless required by applicable law or agreed to in writing,
14#  software distributed under the License is distributed on an
15#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16#  KIND, either express or implied.  See the License for the
17#  specific language governing permissions and limitations
18#  under the License.
19#
20#**************************************************************
21
22# usage: runpy.sh fixtures/encrypted/make.py <port> <outdir> [<twindir>]   (fixtures/encrypted/run.sh drives it)
23# Saves password-protected packages with the office's configured ODF version and UseSHA1InODF12 /
24# UseBlowfishInODF12 values; <twindir> gets the same documents without a password.
25import sys, os, zlib, struct, hashlib, uno
26from com.sun.star.awt import Point, Size
27from com.sun.star.table import CellRangeAddress
28from unohelp import connect, desktop, pv, FILTERS
29
30PASSWORD = "t12-Password"
31port, outdir = int(sys.argv[1]), os.path.abspath(sys.argv[2])
32twindir = os.path.abspath(sys.argv[3]) if len(sys.argv) > 3 else None
33ctx = connect(port)
34d = desktop(ctx)
35os.makedirs(outdir, exist_ok=True)
36if twindir:
37    os.makedirs(twindir, exist_ok=True)
38
39
40def png(path):
41    raw = b"".join(b"\x00" + b"".join(bytes((x * 16, y * 16, 128)) for x in range(16)) for y in range(16))
42
43    def chunk(t, b):
44        c = struct.pack(">I", len(b)) + t + b
45        return c + struct.pack(">I", zlib.crc32(t + b) & 0xFFFFFFFF)
46    with open(path, "wb") as f:
47        f.write(b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", 16, 16, 8, 2, 0, 0, 0))
48                + chunk(b"IDAT", zlib.compress(raw)) + chunk(b"IEND", b""))
49
50
51def algs_in_use():
52    cp = ctx.ServiceManager.createInstanceWithContext("com.sun.star.configuration.ConfigurationProvider", ctx)
53    ca = cp.createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess",
54                                        (pv("nodepath", "/org.openoffice.Office.Common/Save/ODF"),))
55    return {(True, True): "", (False, False): "-aes", (True, False): "-sha1-aes",
56            (False, True): "-sha256-blowfish"}[(ca.getByName("UseSHA1InODF12"), ca.getByName("UseBlowfishInODF12"))]
57
58
59def graphic(url):
60    gp = ctx.ServiceManager.createInstanceWithContext("com.sun.star.graphic.GraphicProvider", ctx)
61    return gp.queryGraphic((pv("URL", url),))
62
63
64def new(kind):
65    url = {"odt": "swriter", "ods": "scalc", "odp": "simpress", "odg": "sdraw"}[kind]
66    return d.loadComponentFromURL("private:factory/" + url, "_blank", 0, (pv("Hidden", True),))
67
68
69def pic(doc, page, url, x, y):
70    g = doc.createInstance("com.sun.star.drawing.GraphicObjectShape")
71    page.add(g)
72    g.Graphic = graphic(url)
73    g.Position = Point(x, y)
74    g.Size = Size(4000, 4000)
75
76
77def shape(doc, page, svc, x, y, w, h, text=None):
78    s = doc.createInstance("com.sun.star.drawing." + svc)
79    page.add(s)
80    s.Position = Point(x, y)
81    s.Size = Size(w, h)
82    if text:
83        s.String = text
84    return s
85
86
87def writer(doc, img, objects):
88    text = doc.Text
89    cur = text.createTextCursor()
90    text.insertString(cur, "Encrypted text document. \u00c4\u00f6\u00fc \u20ac \u4e2d\u6587\n", False)
91    text.insertString(cur, "Second paragraph with enough words to make the content stream longer. " * 40, False)
92    if img:
93        g = doc.createInstance("com.sun.star.text.TextGraphicObject")
94        g.Graphic = graphic(img)
95        g.Width, g.Height = 4000, 4000
96        text.insertTextContent(cur, g, False)
97    if objects:
98        for clsid, name in (("12dcae26-281f-416f-a234-c3086127382e", "Chart1"),
99                            ("078B7ABA-54FC-457F-8551-6147e776a997", "Formula1")):
100            o = doc.createInstance("com.sun.star.text.TextEmbeddedObject")
101            o.CLSID = clsid
102            o.Name = name
103            o.Width, o.Height = 8000, 6000
104            text.insertTextContent(cur, o, False)
105            if name == "Formula1":
106                o.Model.Formula = "a + b over c"
107
108
109def calc(doc, img, objects):
110    sh = doc.Sheets.getByIndex(0)
111    for r in range(10):
112        sh.getCellByPosition(0, r).Value = r + 1
113        sh.getCellByPosition(1, r).Value = (r + 1) * 3.5
114        sh.getCellByPosition(2, r).String = "row %d \u00e9" % r
115    sh.getCellByPosition(3, 0).Formula = "=SUM(A1:A10)"
116    if objects:
117        ra = CellRangeAddress()
118        ra.Sheet, ra.StartColumn, ra.StartRow, ra.EndColumn, ra.EndRow = 0, 0, 0, 1, 9
119        sh.Charts.addNewByName("C1", uno.createUnoStruct("com.sun.star.awt.Rectangle", 8000, 1000, 8000, 6000), (ra,), True, True)
120    if img:
121        pic(doc, sh.DrawPage, img, 1000, 12000)
122
123
124def impress(doc, img, objects):
125    p = doc.DrawPages.getByIndex(0)
126    shape(doc, p, "TextShape", 2000, 2000, 10000, 2000, "Encrypted slide one")
127    shape(doc, p, "RectangleShape", 2000, 6000, 5000, 3000, "box")
128    if img:
129        pic(doc, p, img, 14000, 6000)
130    p2 = doc.DrawPages.insertNewByIndex(1)
131    shape(doc, p2, "EllipseShape", 3000, 3000, 6000, 4000, "slide two")
132
133
134def draw(doc, img, objects):
135    p = doc.DrawPages.getByIndex(0)
136    shape(doc, p, "RectangleShape", 2000, 2000, 6000, 3000, "rect")
137    shape(doc, p, "TextShape", 2000, 7000, 8000, 2000, "Encrypted drawing \u00e4")
138    if img:
139        pic(doc, p, img, 12000, 2000)
140
141
142FILL = {"odt": writer, "ods": calc, "odp": impress, "odg": draw}
143TAG = {"odt": "text", "ods": "calc", "odp": "impress", "odg": "draw"}
144
145
146def modify_info(password):
147    salt = os.urandom(16)
148    h = hashlib.pbkdf2_hmac("sha1", password.encode("utf-8"), salt, 1024, 16)
149    return uno.Any("[]com.sun.star.beans.PropertyValue",
150                   (pv("algorithm-name", "PBKDF2"), pv("salt", uno.ByteSequence(salt)),
151                    pv("iteration-count", 1024), pv("hash", uno.ByteSequence(h))))
152
153
154def make(kind, suffix, img, objects, tag, encrypt=True, modify=False):
155    doc = new(kind)
156    FILL[kind](doc, img, objects)
157    name = "encrypted-%s%s.%s" % (tag, suffix, kind)
158    props = [pv("FilterName", FILTERS[kind])]
159    if encrypt:
160        props.append(pv("Password", PASSWORD))
161    if modify:
162        props.append(pv("ModifyPasswordInfo", modify_info(PASSWORD)))
163    doc.storeToURL(uno.systemPathToFileUrl(os.path.join(outdir, name)), tuple(props))
164    if twindir:
165        doc.storeToURL(uno.systemPathToFileUrl(os.path.join(twindir, name)), (pv("FilterName", FILTERS[kind]),))
166    doc.close(True)
167    print(name)
168
169
170img = os.path.join(os.path.dirname(outdir), "pic.png")
171png(img)
172imgurl = uno.systemPathToFileUrl(img)
173suffix = algs_in_use()
174print("algorithms:", suffix or "default")
175for kind in FILL if suffix in ("", "-aes") else ("odt",):
176    make(kind, suffix, None, False, TAG[kind])
177    make(kind, suffix, imgurl, kind in ("odt", "ods"), TAG[kind] + "-objects")
178if not suffix:
179    for kind in ("odt", "ods"):
180        make(kind, suffix, None, False, TAG[kind] + "-modifyonly", encrypt=False, modify=True)
181        make(kind, suffix, None, False, TAG[kind] + "-modify", modify=True)
182