-
Notifications
You must be signed in to change notification settings - Fork 1
/
builder.go
267 lines (210 loc) · 6.11 KB
/
builder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
package rpcsrv
import (
"bytes"
"github.com/sigex-kz/ddc"
)
// Builder can be exported via net/rpc and used to build DDC
type Builder int
// BuilderRegisterArgs used to pass data to Builder.Register
type BuilderRegisterArgs struct {
// Title of the document
Title string
// Description of the document
Description string
// Optional id of the document
ID string
// Optional qr code with the id of the document, should be set if id is set
IDQRCode []byte
// FileName of the original document
FileName string
}
// BuilderRegisterResp used to retrieve data from Builder.Register
type BuilderRegisterResp struct {
// Error is not "" if any error occurred during the operation
Error string
// ID of the new builder slot
ID string
}
// Register new builder slot and retrieve it's id
func (t *Builder) Register(args *BuilderRegisterArgs, resp *BuilderRegisterResp) error {
be := builderEntry{
di: ddc.DocumentInfo{
Title: args.Title,
Description: args.Description,
ID: args.ID,
IDQRCode: args.IDQRCode,
Signatures: []ddc.SignatureInfo{},
},
embeddedFileName: args.FileName,
}
resp.ID = newStoreEntry(&be, nil)
return nil
}
// BuilderAppendDocumentPartArgs used to pass data to Builder.AppendDocumentPart
type BuilderAppendDocumentPartArgs struct {
// ID of the builder slot to use
ID string
// Part of the original document
Bytes []byte
}
// BuilderAppendDocumentPartResp used to retrieve data from Builder.AppendDocumentPart
type BuilderAppendDocumentPartResp struct {
// Error is not "" if any error occurred during the operation
Error string
}
// AppendDocumentPart to the specified builder slot
func (t *Builder) AppendDocumentPart(args *BuilderAppendDocumentPartArgs, resp *BuilderAppendDocumentPartResp) error {
e, err := getStoreEntry(args.ID)
if err != nil {
resp.Error = err.Error()
return nil
}
e.mutex.Lock()
defer e.mutex.Unlock()
if e.be == nil {
resp.Error = "unknown id"
return nil
}
_, err = e.be.embeddedFileBuffer.Write(args.Bytes)
if err != nil {
resp.Error = err.Error()
return nil
}
return nil
}
// BuilderAppendSignatureArgs used to pass data to Builder.AppendSignature
type BuilderAppendSignatureArgs struct {
// ID of the builder slot to use
ID string
// SignatureInfo describes the signature
SignatureInfo ddc.SignatureInfo
}
// BuilderAppendSignatureResp used to retrieve data from Builder.AppendSignature
type BuilderAppendSignatureResp struct {
// Error is not "" if any error occurred during the operation
Error string
}
// AppendSignature to the specified builder slot
func (t *Builder) AppendSignature(args *BuilderAppendSignatureArgs, resp *BuilderAppendSignatureResp) error {
err := clamAVScan(args.SignatureInfo.Body)
if err != nil {
resp.Error = err.Error()
return nil
}
e, err := getStoreEntry(args.ID)
if err != nil {
resp.Error = err.Error()
return nil
}
e.mutex.Lock()
defer e.mutex.Unlock()
if e.be == nil {
resp.Error = "unknown id"
return nil
}
e.be.di.Signatures = append(e.be.di.Signatures, args.SignatureInfo)
return nil
}
// BuilderBuildArgs used to pass data to Builder.Build
type BuilderBuildArgs struct {
// ID of the builder slot to use
ID string
// CreationDate should be current date and time in format "2021.01.31 13:45:00 UTC+6"
// converted to time zone of Nur-Sultan.
CreationDate string
// BuilderName would be embedded into DDC visualization
BuilderName string
// HowToVerify should provide instructions to verify DDC
HowToVerify string
}
// BuilderBuildResp used to retrieve data from Builder.Build
type BuilderBuildResp struct {
// Error is not "" if any error occurred during the operation
Error string
}
// Build DDC in the specified slot, should be called once after all data've been passed
// to the slot via calls to AppendDocumentPart and AppendSignature
func (t *Builder) Build(args *BuilderBuildArgs, resp *BuilderBuildResp) error {
e, err := getStoreEntry(args.ID)
if err != nil {
resp.Error = err.Error()
return nil
}
e.mutex.Lock()
defer e.mutex.Unlock()
err = clamAVScan(e.be.embeddedFileBuffer.Bytes())
if err != nil {
resp.Error = err.Error()
return nil
}
if e.be == nil {
resp.Error = "unknown id"
return nil
}
ddcBuilder, err := ddc.NewBuilder(&e.be.di)
if err != nil {
resp.Error = err.Error()
return nil
}
err = ddcBuilder.EmbedPDF(bytes.NewReader(e.be.embeddedFileBuffer.Bytes()), e.be.embeddedFileName)
if err != nil {
resp.Error = err.Error()
return nil
}
err = ddcBuilder.Build(true, true, args.CreationDate, args.BuilderName, args.HowToVerify, &e.be.ddcFileBuffer)
if err != nil {
resp.Error = err.Error()
return nil
}
return nil
}
// BuilderGetDDCPartArgs used to pass data to Builder.GetDDCPart
type BuilderGetDDCPartArgs struct {
// ID of the builder slot to use
ID string
// MaxPartSize should be used to limit the size of the part
MaxPartSize int
}
// BuilderGetDDCPartResp used to retrieve data from Builder.GetDDCPart
type BuilderGetDDCPartResp struct {
// Error is not "" if any error occurred during the operation
Error string
// Part of DDC not larger than MaxPartSize
Part []byte
// IsFinal signals that there are no more parts to return
IsFinal bool
}
// GetDDCPart retrieves parts of the DDC in the specified slot successively, should be called after Build
func (t *Builder) GetDDCPart(args *BuilderGetDDCPartArgs, resp *BuilderGetDDCPartResp) error {
e, err := getStoreEntry(args.ID)
if err != nil {
resp.Error = err.Error()
return nil
}
e.mutex.Lock()
defer e.mutex.Unlock()
if e.be == nil {
resp.Error = "unknown id"
return nil
}
resp.Part = e.be.ddcFileBuffer.Next(args.MaxPartSize)
if e.be.ddcFileBuffer.Len() == 0 {
resp.IsFinal = true
}
return nil
}
// BuilderDropArgs used to pass data to Builder.Drop
type BuilderDropArgs struct {
// ID of the builder slot to use
ID string
}
// BuilderDropResp used to retrieve data from Builder.Drop
type BuilderDropResp struct {
// Error is not "" if any error occurred during the operation
Error string
}
// Drop DDC in the specified slot
func (t *Builder) Drop(args *BuilderDropArgs, resp *BuilderDropResp) error {
deleteStoreEntry(args.ID)
return nil
}