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