OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 156 | Rev 182 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 156 Rev 180
Line 15... Line 15...
15
 
15
 
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
16
import org.openconcerto.erp.config.ComptaPropsConfiguration;
17
import org.openconcerto.erp.generationDoc.DocumentLocalStorageManager;
17
import org.openconcerto.erp.generationDoc.DocumentLocalStorageManager;
18
import org.openconcerto.erp.storage.StorageEngine;
18
import org.openconcerto.erp.storage.StorageEngine;
19
import org.openconcerto.erp.storage.StorageEngines;
19
import org.openconcerto.erp.storage.StorageEngines;
-
 
20
import org.openconcerto.sql.model.SQLInsert;
20
import org.openconcerto.sql.model.SQLRow;
21
import org.openconcerto.sql.model.SQLRow;
21
import org.openconcerto.sql.model.SQLRowAccessor;
22
import org.openconcerto.sql.model.SQLRowAccessor;
22
import org.openconcerto.sql.model.SQLRowValues;
23
import org.openconcerto.sql.model.SQLRowValues;
-
 
24
import org.openconcerto.sql.model.SQLSelect;
23
import org.openconcerto.sql.model.SQLTable;
25
import org.openconcerto.sql.model.SQLTable;
-
 
26
import org.openconcerto.sql.model.Where;
-
 
27
import org.openconcerto.utils.Base64;
24
import org.openconcerto.utils.ExceptionHandler;
28
import org.openconcerto.utils.ExceptionHandler;
25
import org.openconcerto.utils.FileUtils;
29
import org.openconcerto.utils.FileUtils;
26
import org.openconcerto.utils.sync.SyncClient;
30
import org.openconcerto.utils.sync.SyncClient;
27
 
31
 
28
import java.io.BufferedInputStream;
32
import java.io.BufferedInputStream;
29
import java.io.File;
33
import java.io.File;
30
import java.io.FileInputStream;
34
import java.io.FileInputStream;
31
import java.io.IOException;
35
import java.io.IOException;
-
 
36
import java.nio.charset.StandardCharsets;
32
import java.nio.file.Files;
37
import java.nio.file.Files;
-
 
38
import java.security.InvalidAlgorithmParameterException;
-
 
39
import java.security.InvalidKeyException;
-
 
40
import java.security.NoSuchAlgorithmException;
33
import java.sql.SQLException;
41
import java.sql.SQLException;
34
import java.util.List;
42
import java.util.List;
35
 
43
 
-
 
44
import javax.crypto.BadPaddingException;
-
 
45
import javax.crypto.Cipher;
-
 
46
import javax.crypto.IllegalBlockSizeException;
-
 
47
import javax.crypto.KeyGenerator;
-
 
48
import javax.crypto.NoSuchPaddingException;
-
 
49
import javax.crypto.SecretKey;
-
 
50
import javax.crypto.spec.GCMParameterSpec;
-
 
51
import javax.crypto.spec.SecretKeySpec;
36
import javax.swing.JOptionPane;
52
import javax.swing.JOptionPane;
37
 
53
 
38
public class AttachmentUtils {
54
public class AttachmentUtils {
39
 
55
 
-
 
56
    String generateBase64Key() throws NoSuchAlgorithmException {
-
 
57
        final KeyGenerator generator = KeyGenerator.getInstance("AES");
-
 
58
        generator.init(16 * 8);
-
 
59
        final SecretKey k = generator.generateKey();
-
 
60
        return Base64.encodeBytes(k.getEncoded(), Base64.DONT_BREAK_LINES);
-
 
61
    }
-
 
62
 
-
 
63
    SecretKey getSecretKey(String base64key) {
-
 
64
        byte[] b = Base64.decode(base64key.getBytes(StandardCharsets.UTF_8));
-
 
65
        if (b.length != 16) {
-
 
66
            throw new IllegalStateException("key length must be 16 bytes for AES");
-
 
67
        }
-
 
68
        return new SecretKeySpec(b, "AES");
-
 
69
    }
-
 
70
 
-
 
71
    public byte[] encrypt(SecretKey secretKey, byte[] in)
-
 
72
            throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
-
 
73
        return process(secretKey, in, Cipher.ENCRYPT_MODE);
-
 
74
    }
-
 
75
 
-
 
76
    public byte[] decrypt(SecretKey secretKey, byte[] in)
-
 
77
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
-
 
78
        return process(secretKey, in, Cipher.DECRYPT_MODE);
-
 
79
    }
-
 
80
 
-
 
81
    public byte[] process(SecretKey secretKey, byte[] in, int mode)
-
 
82
            throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException {
-
 
83
        final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
-
 
84
        final byte[] nonce = new byte[12];
-
 
85
        final byte[] e = secretKey.getEncoded();
-
 
86
        for (int i = 0; i < nonce.length; i++) {
-
 
87
            nonce[i] = (byte) (e[i] * e[i + 1] + e[i + 2]);
-
 
88
        }
-
 
89
        GCMParameterSpec spec = new GCMParameterSpec(16 * 8, nonce);
-
 
90
        cipher.init(mode, secretKey, spec);
-
 
91
        return cipher.doFinal(in);
-
 
92
    }
-
 
93
 
40
    public void uploadFile(File inFile, SQLRowAccessor rowSource, int idParent) {
94
    public void uploadFile(File inFile, SQLRowAccessor rowSource, int idParent) throws SQLException {
-
 
95
        uploadFile(inFile, rowSource, idParent, null);
41
        try {
96
    }
-
 
97
 
-
 
98
    public void uploadFile(File inFile, SQLRowAccessor rowSource, int idParent, String nameInGed) throws SQLException {
42
 
99
 
-
 
100
        String encodeKey = fetchEncodedKey(rowSource.getTable().getTable("FWK_SCHEMA_METADATA"));
43
            // Création de la row attachment
101
        // Création de la row attachment
44
            SQLRowValues rowValsAttachment = new SQLRowValues(rowSource.getTable().getTable("ATTACHMENT"));
102
        SQLRowValues rowValsAttachment = new SQLRowValues(rowSource.getTable().getTable("ATTACHMENT"));
45
            rowValsAttachment.put("SOURCE_TABLE", rowSource.getTable().getName());
103
        rowValsAttachment.put("SOURCE_TABLE", rowSource.getTable().getName());
46
            rowValsAttachment.put("SOURCE_ID", rowSource.getID());
104
        rowValsAttachment.put("SOURCE_ID", rowSource.getID());
47
            rowValsAttachment.put("ID_PARENT", idParent);
105
        rowValsAttachment.put("ID_PARENT", idParent);
-
 
106
        if (encodeKey != null) {
-
 
107
            rowValsAttachment.put("ENCRYPTED", true);
-
 
108
        }
-
 
109
 
48
            SQLRow rowAttachment = rowValsAttachment.insert();
110
        SQLRow rowAttachment = rowValsAttachment.insert();
49
            int id = rowAttachment.getID();
111
        int id = rowAttachment.getID();
50
 
112
 
51
            final String folderId = String.valueOf((id / 1000) * 1000);
113
        final String folderId = String.valueOf((id / 1000) * 1000);
52
            String subDir = "EDM/" + folderId;
114
        String subDir = "EDM/" + folderId;
Line 61... Line 123...
61
            final String fileWithIDNAme = fileNameID + "." + ext;
123
        final String fileWithIDNAme = fileNameID + "." + ext;
62
 
124
 
63
            final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
125
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
64
            boolean isOnCloud = config.isOnCloud();
126
        boolean isOnCloud = config.isOnCloud();
65
 
127
 
-
 
128
        try {
66
            if (isOnCloud) {
129
            if (isOnCloud) {
67
 
130
 
68
                String remotePath = subDir;
131
                String remotePath = subDir;
69
                List<StorageEngine> engines = StorageEngines.getInstance().getActiveEngines();
132
                final List<StorageEngine> engines = StorageEngines.getInstance().getActiveEngines();
-
 
133
                File encodedFile = inFile;
-
 
134
                if (encodeKey != null) {
-
 
135
                    encodedFile = File.createTempFile("encrypted", inFile.getName());
-
 
136
                    final byte[] enc = encrypt(getSecretKey(encodeKey), FileUtils.readBytes(inFile));
-
 
137
                    Files.write(encodedFile.toPath(), enc);
-
 
138
                }
-
 
139
 
70
                for (StorageEngine storageEngine : engines) {
140
                for (StorageEngine storageEngine : engines) {
71
                    if (storageEngine.isConfigured() && storageEngine.allowAutoStorage()) {
141
                    if (storageEngine.isConfigured() && storageEngine.allowAutoStorage()) {
72
                        final String path = remotePath;
142
                        final String path = remotePath;
73
 
143
 
74
                        try (FileInputStream in = new FileInputStream(inFile)) {
144
                        try (FileInputStream in = new FileInputStream(encodedFile)) {
75
                            storageEngine.connect();
145
                            storageEngine.connect();
76
                            final BufferedInputStream inStream = new BufferedInputStream(in);
146
                            final BufferedInputStream inStream = new BufferedInputStream(in);
77
                            storageEngine.store(inStream, path, fileWithIDNAme, true);
147
                            storageEngine.store(inStream, path, fileWithIDNAme, true);
78
                            inStream.close();
148
                            inStream.close();
79
                            storageEngine.disconnect();
149
                            storageEngine.disconnect();
80
                        } catch (IOException e) {
-
 
81
                            ExceptionHandler.handle("Impossible de sauvegarder le fichier " + inFile.getAbsolutePath() + " vers " + path + "(" + storageEngine + ")", e);
-
 
82
                        }
150
                        }
83
                        // if (storageEngine instanceof CloudStorageEngine) {
-
 
84
                        // try {
-
 
85
                        // storageEngine.connect();
-
 
86
                        // final BufferedInputStream inStream = new BufferedInputStream(new
-
 
87
                        // FileInputStream(generatedFile));
-
 
88
                        // storageEngine.store(inStream, path, generatedFile.getName(), true);
-
 
89
                        // inStream.close();
-
 
90
                        // storageEngine.disconnect();
-
 
91
                        // } catch (IOException e) {
-
 
92
                        // ExceptionHandler.handle("Impossible de sauvegarder le fichier généré " +
-
 
93
                        // generatedFile.getAbsolutePath() + " vers " + path + "(" + storageEngine +
-
 
94
                        // ")", e);
-
 
-
 
151
 
95
                        // }
-
 
96
                        // }
152
                    }
97
                    }
153
                }
-
 
154
                if (encodeKey != null) {
-
 
155
                    encodedFile.delete();
98
                }
156
                }
-
 
157
 
99
            } else {
158
            } else {
100
                // Upload File
159
                // Upload File
101
 
160
 
102
                // Get file out
161
                // Get file out
103
                File dirRoot = DocumentLocalStorageManager.getInstance().getDocumentOutputDirectory(AttachmentSQLElement.DIRECTORY_PREFS);
162
                File dirRoot = DocumentLocalStorageManager.getInstance().getDocumentOutputDirectory(AttachmentSQLElement.DIRECTORY_PREFS);
104
                File storagePathFile = new File(dirRoot, subDir);
163
                File storagePathFile = new File(dirRoot, subDir);
105
                storagePathFile.mkdirs();
164
                storagePathFile.mkdirs();
106
                // TODO CHECK IF FILE EXISTS
165
                // TODO CHECK IF FILE EXISTS
-
 
166
                if (encodeKey == null) {
107
                FileUtils.copyFile(inFile, new File(storagePathFile, fileWithIDNAme));
167
                    FileUtils.copyFile(inFile, new File(storagePathFile, fileWithIDNAme));
108
 
-
 
-
 
168
                } else {
-
 
169
                    final File encodedFile = new File(storagePathFile, fileWithIDNAme);
-
 
170
                    final byte[] enc = encrypt(getSecretKey(encodeKey), FileUtils.readBytes(inFile));
-
 
171
                    Files.write(encodedFile.toPath(), enc);
-
 
172
                }
109
            }
173
            }
110
 
174
 
111
            // Update rowAttachment
175
            // Update rowAttachment
112
            rowValsAttachment = rowAttachment.createEmptyUpdateRow();
176
            rowValsAttachment = rowAttachment.createEmptyUpdateRow();
113
 
177
 
114
            // Default is without extension
178
            // Default is without extension
115
            String fileName = inFile.getName();
179
            String fileName = inFile.getName();
-
 
180
            if (nameInGed != null) {
-
 
181
                rowValsAttachment.put("NAME", nameInGed);
-
 
182
            } else {
116
            String name = fileName;
183
                String name = fileName;
117
            int index = name.lastIndexOf('.');
184
                int index = name.lastIndexOf('.');
118
            if (index > 0) {
185
                if (index > 0) {
119
                name = name.substring(0, index);
186
                    name = name.substring(0, index);
120
            }
187
                }
121
            rowValsAttachment.put("NAME", name);
188
                rowValsAttachment.put("NAME", name);
-
 
189
            }
-
 
190
 
122
            rowValsAttachment.put("SOURCE_TABLE", rowSource.getTable().getName());
191
            rowValsAttachment.put("SOURCE_TABLE", rowSource.getTable().getName());
123
            rowValsAttachment.put("SOURCE_ID", rowSource.getID());
192
            rowValsAttachment.put("SOURCE_ID", rowSource.getID());
-
 
193
            rowValsAttachment.put("ID_PARENT", idParent);
124
            final String mimeType = Files.probeContentType(inFile.toPath());
194
            final String mimeType = Files.probeContentType(inFile.toPath());
125
            rowValsAttachment.put("MIMETYPE", mimeType != null ? mimeType : "application/octet-stream");
195
            rowValsAttachment.put("MIMETYPE", mimeType != null ? mimeType : "application/octet-stream");
126
            rowValsAttachment.put("FILENAME", fileName);
196
            rowValsAttachment.put("FILENAME", fileName);
127
            rowValsAttachment.put("FILESIZE", inFile.length());
197
            rowValsAttachment.put("FILESIZE", inFile.length());
128
            rowValsAttachment.put("STORAGE_PATH", subDir);
198
            rowValsAttachment.put("STORAGE_PATH", subDir);
129
            rowValsAttachment.put("STORAGE_FILENAME", fileWithIDNAme);
199
            rowValsAttachment.put("STORAGE_FILENAME", fileWithIDNAme);
-
 
200
            rowValsAttachment.put("ENCRYPTED", (encodeKey != null));
130
            // TODO THUMBNAIL
201
            // TODO THUMBNAIL
131
            // rowVals.put("THUMBNAIL", );
202
            // rowVals.put("THUMBNAIL", );
132
            // rowVals.put("THUMBNAIL_WIDTH", );
203
            // rowVals.put("THUMBNAIL_WIDTH", );
133
            // rowVals.put("THUMBNAIL_HEIGHT", );
204
            // rowVals.put("THUMBNAIL_HEIGHT", );
134
 
205
 
135
            // needed for update count
206
            // needed for update count
136
 
207
 
137
            rowValsAttachment.commit();
208
            rowValsAttachment.commit();
138
            final Attachment a = new Attachment(rowValsAttachment);
209
            final Attachment a = new Attachment(rowValsAttachment);
139
            updateAttachmentsCountFromAttachment(a);
210
            updateAttachmentsCountFromAttachment(a);
-
 
211
 
140
        } catch (Exception e) {
212
        } catch (Exception e) {
-
 
213
            if (rowAttachment != null) {
-
 
214
                config.getDirectory().getElement(AttachmentSQLElement.class).archive(rowAttachment.getID());
-
 
215
            }
-
 
216
            ExceptionHandler.handle("Impossible de sauvegarder le fichier " + inFile.getAbsolutePath(), e);
-
 
217
        }
-
 
218
 
-
 
219
    }
-
 
220
 
-
 
221
    public String fetchEncodedKey(SQLTable table) {
-
 
222
        final SQLSelect select = new SQLSelect();
-
 
223
        select.addSelect(table.getField("VALUE"));
-
 
224
        select.setWhere(new Where(table.getField("NAME"), "=", AttachmentSQLElement.EDM_KEY_METADATA));
-
 
225
        final List<?> rows = table.getDBSystemRoot().getDataSource().executeCol(select.asString());
-
 
226
        if (rows.size() == 1) {
141
            e.printStackTrace();
227
            return rows.get(0).toString();
142
        }
228
        }
-
 
229
        return null;
-
 
230
    }
-
 
231
 
-
 
232
    public void createKeyOnDatabase(SQLTable table) throws NoSuchAlgorithmException {
-
 
233
        final String s = fetchEncodedKey(table);
-
 
234
        if (s != null) {
-
 
235
            throw new IllegalStateException("key alread exists");
-
 
236
        }
-
 
237
 
-
 
238
        final SQLInsert insert = new SQLInsert();
-
 
239
        insert.add(table.getField("NAME"), AttachmentSQLElement.EDM_KEY_METADATA);
-
 
240
        insert.add(table.getField("VALUE"), generateBase64Key());
-
 
241
        table.getDBSystemRoot().getDataSource().execute(insert.asString());
143
    }
242
    }
144
 
243
 
145
    public File getFile(Attachment attachment) {
244
    public File getFile(Attachment attachment) {
146
 
245
 
147
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
246
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
Line 200... Line 299...
200
                ExceptionHandler.handle("Impossible de trouver le fichier\n" + storagePathFile + File.pathSeparator + fileName, e1);
299
                ExceptionHandler.handle("Impossible de trouver le fichier\n" + storagePathFile + File.pathSeparator + fileName, e1);
201
                return null;
300
                return null;
202
            }
301
            }
203
        }
302
        }
204
        final File outFile = new File(f, fileName);
303
        final File outFile = new File(f, fileName);
-
 
304
        if (attachment.isEncrypted() && outFile.length() > 0) {
-
 
305
            try {
-
 
306
                final byte[] bytes = FileUtils.readBytes(outFile);
-
 
307
                final String encodeKey = fetchEncodedKey(config.getRootSociete().getTable("FWK_SCHEMA_METADATA"));
-
 
308
                if (encodeKey == null) {
-
 
309
                    throw new IllegalStateException("missing key");
-
 
310
                }
-
 
311
                final byte[] decrypted = decrypt(getSecretKey(encodeKey), bytes);
-
 
312
                Files.write(outFile.toPath(), decrypted);
-
 
313
            } catch (Exception e) {
-
 
314
                ExceptionHandler.handle("Impossible de decrypter le fichier\n" + outFile.getAbsolutePath(), e);
-
 
315
                return null;
-
 
316
            }
-
 
317
 
-
 
318
        }
205
        outFile.setReadOnly();
319
        outFile.setReadOnly();
206
        return outFile;
320
        return outFile;
207
 
321
 
208
    }
322
    }
209
 
323
 
210
    public void deleteFile(Attachment rowAttachment) throws SQLException, IllegalStateException {
324
    public void deleteFile(Attachment rowAttachment) throws SQLException, IllegalStateException {
211
 
-
 
-
 
325
        // Delete Row
-
 
326
        // Remove from DB first
212
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
327
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
-
 
328
        config.getDirectory().getElement(AttachmentSQLElement.class).archive(rowAttachment.getId());
-
 
329
        updateAttachmentsCountFromAttachment(rowAttachment);
-
 
330
 
213
        if (!rowAttachment.isFolder()) {
331
        if (!rowAttachment.isFolder()) {
214
            boolean isOnCloud = config.isOnCloud();
332
            boolean isOnCloud = config.isOnCloud();
215
            // Delete File
333
            // Delete File
216
            String subDir = rowAttachment.getStoragePath();
334
            String subDir = rowAttachment.getStoragePath();
217
            String fileName = rowAttachment.getStorageFileName();
335
            String fileName = rowAttachment.getStorageFileName();
Line 235... Line 353...
235
                        throw new IllegalStateException("Une erreur est survenue lors de la suppression du fichier");
353
                        throw new IllegalStateException("Une erreur est survenue lors de la suppression du fichier");
236
                    }
354
                    }
237
                }
355
                }
238
            }
356
            }
239
        }
357
        }
240
        // Delete Row
-
 
241
        config.getDirectory().getElement(AttachmentSQLElement.class).archive(rowAttachment.getId());
-
 
242
        updateAttachmentsCountFromAttachment(rowAttachment);
-
 
-
 
358
 
243
    }
359
    }
244
 
360
 
245
    private void updateAttachmentsCountFromAttachment(Attachment rowAttachment) {
361
    private void updateAttachmentsCountFromAttachment(Attachment rowAttachment) {
246
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
362
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
247
        final SQLTable attachmentTable = config.getDirectory().getElement(AttachmentSQLElement.class).getTable();
363
        final SQLTable attachmentTable = config.getDirectory().getElement(AttachmentSQLElement.class).getTable();
Line 297... Line 413...
297
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
413
        final ComptaPropsConfiguration config = ComptaPropsConfiguration.getInstanceCompta();
298
        final SQLTable attachmentTable = config.getDirectory().getElement(AttachmentSQLElement.class).getTable();
414
        final SQLTable attachmentTable = config.getDirectory().getElement(AttachmentSQLElement.class).getTable();
299
        final String req = "UPDATE " + attachmentTable.getSQLName().quote() + " SET " + attachmentTable.getField("ID_PARENT").getQuotedName() + "=" + folderId + " WHERE "
415
        final String req = "UPDATE " + attachmentTable.getSQLName().quote() + " SET " + attachmentTable.getField("ID_PARENT").getQuotedName() + "=" + folderId + " WHERE "
300
                + attachmentTable.getKey().getQuotedName() + "=" + a.getId();
416
                + attachmentTable.getKey().getQuotedName() + "=" + a.getId();
301
        attachmentTable.getDBSystemRoot().getDataSource().execute(req);
417
        attachmentTable.getDBSystemRoot().getDataSource().execute(req);
-
 
418
 
302
    }
419
    }
303
 
420
 
-
 
421
    public static void main(String[] args) throws NoSuchAlgorithmException {
-
 
422
        System.err.println("AttachmentUtils.main() key : " + new AttachmentUtils().generateBase64Key());
-
 
423
    }
304
}
424
}