182 |
ilm |
1 |
/*
|
|
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
|
|
3 |
*
|
|
|
4 |
* Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
|
|
|
5 |
*
|
|
|
6 |
* The contents of this file are subject to the terms of the GNU General Public License Version 3
|
|
|
7 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
|
|
|
8 |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
|
|
|
9 |
* language governing permissions and limitations under the License.
|
|
|
10 |
*
|
|
|
11 |
* When distributing the software, include this License Header Notice in each file.
|
|
|
12 |
*/
|
|
|
13 |
|
|
|
14 |
package org.openconcerto.erp.config;
|
|
|
15 |
|
|
|
16 |
import org.openconcerto.utils.Base64;
|
|
|
17 |
import org.openconcerto.utils.FileUtils;
|
|
|
18 |
import org.openconcerto.utils.JImage;
|
|
|
19 |
|
|
|
20 |
import java.awt.BorderLayout;
|
|
|
21 |
import java.awt.Color;
|
|
|
22 |
import java.awt.Dimension;
|
|
|
23 |
import java.awt.FlowLayout;
|
|
|
24 |
import java.awt.Font;
|
|
|
25 |
import java.awt.event.ActionEvent;
|
|
|
26 |
import java.awt.event.ActionListener;
|
|
|
27 |
import java.awt.image.BufferedImage;
|
|
|
28 |
import java.io.BufferedOutputStream;
|
|
|
29 |
import java.io.BufferedReader;
|
|
|
30 |
import java.io.ByteArrayInputStream;
|
|
|
31 |
import java.io.ByteArrayOutputStream;
|
|
|
32 |
import java.io.File;
|
|
|
33 |
import java.io.FileOutputStream;
|
|
|
34 |
import java.io.FileReader;
|
|
|
35 |
import java.io.IOException;
|
|
|
36 |
import java.io.InputStream;
|
|
|
37 |
import java.io.PrintStream;
|
|
|
38 |
import java.net.MalformedURLException;
|
|
|
39 |
import java.net.URL;
|
|
|
40 |
import java.net.URLConnection;
|
|
|
41 |
import java.nio.charset.StandardCharsets;
|
|
|
42 |
import java.security.MessageDigest;
|
|
|
43 |
import java.text.SimpleDateFormat;
|
|
|
44 |
import java.util.ArrayList;
|
|
|
45 |
import java.util.Date;
|
|
|
46 |
import java.util.List;
|
|
|
47 |
import java.util.Properties;
|
|
|
48 |
|
|
|
49 |
import javax.imageio.ImageIO;
|
|
|
50 |
import javax.swing.BorderFactory;
|
|
|
51 |
import javax.swing.JButton;
|
|
|
52 |
import javax.swing.JFrame;
|
|
|
53 |
import javax.swing.JPanel;
|
|
|
54 |
import javax.swing.JTextArea;
|
|
|
55 |
import javax.swing.JTextField;
|
|
|
56 |
import javax.swing.SwingUtilities;
|
|
|
57 |
import javax.swing.UIManager;
|
|
|
58 |
|
|
|
59 |
import net.minidev.json.JSONObject;
|
|
|
60 |
import net.minidev.json.parser.JSONParser;
|
|
|
61 |
|
|
|
62 |
public class NewsChecker {
|
|
|
63 |
public static class DateHash {
|
|
|
64 |
Long t;
|
|
|
65 |
String h;
|
|
|
66 |
|
|
|
67 |
public DateHash(Long time, String hash) {
|
|
|
68 |
this.t = time;
|
|
|
69 |
this.h = hash;
|
|
|
70 |
}
|
|
|
71 |
|
|
|
72 |
}
|
|
|
73 |
|
|
|
74 |
public static void check(Properties pTOS, File confDir, boolean useH2) {
|
|
|
75 |
if (!confDir.exists()) {
|
|
|
76 |
System.out.println("missing conf dir " + confDir.getAbsolutePath());
|
|
|
77 |
}
|
|
|
78 |
final boolean hasCloud = pTOS.getProperty("hasCloud", "false").equals("true");
|
|
|
79 |
final int launchCounter = Integer.parseInt(pTOS.getProperty("launchCounter", "0"));
|
|
|
80 |
Thread t = new Thread(new Runnable() {
|
|
|
81 |
|
|
|
82 |
@Override
|
|
|
83 |
public void run() {
|
|
|
84 |
try {
|
|
|
85 |
|
|
|
86 |
File historyFile = new File(confDir, "history.log");
|
|
|
87 |
if (!historyFile.exists()) {
|
|
|
88 |
FileUtils.writeUTF8("", historyFile);
|
|
|
89 |
}
|
|
|
90 |
List<DateHash> history = new ArrayList<>();
|
|
|
91 |
long today = System.currentTimeMillis();
|
|
|
92 |
// 60 days
|
|
|
93 |
long maxDate = today - 60 * 24 * 3600 * 1000;
|
|
|
94 |
try (BufferedReader reader = new BufferedReader(new FileReader(historyFile))) {
|
|
|
95 |
String line = reader.readLine();
|
|
|
96 |
while (line != null) {
|
|
|
97 |
Long t = Long.parseLong(line);
|
|
|
98 |
String h = reader.readLine();
|
|
|
99 |
if (t > maxDate) {
|
|
|
100 |
history.add(new DateHash(t, h));
|
|
|
101 |
}
|
|
|
102 |
line = reader.readLine();
|
|
|
103 |
}
|
|
|
104 |
} catch (Exception e) {
|
|
|
105 |
e.printStackTrace();
|
|
|
106 |
}
|
|
|
107 |
byte[] data = download("https://www.ilm-informatique.fr/openconcerto/ocnews");
|
|
|
108 |
MessageDigest digester = MessageDigest.getInstance("SHA-256");
|
|
|
109 |
digester.update(data);
|
|
|
110 |
String h = Base64.encodeBytes(digester.digest());
|
|
|
111 |
boolean found = false;
|
|
|
112 |
for (DateHash d : history) {
|
|
|
113 |
if (d.h.equals(h)) {
|
|
|
114 |
found = true;
|
|
|
115 |
break;
|
|
|
116 |
}
|
|
|
117 |
}
|
|
|
118 |
DateHash newLine = new DateHash(System.currentTimeMillis(), h);
|
|
|
119 |
history.add(newLine);
|
|
|
120 |
if (!found) {
|
|
|
121 |
final JSONParser jsonParser = new JSONParser(JSONParser.MODE_PERMISSIVE);
|
|
|
122 |
final String jsonString = new String(data, StandardCharsets.UTF_8);
|
|
|
123 |
JSONObject obj = (JSONObject) jsonParser.parse(jsonString);
|
|
|
124 |
|
|
|
125 |
String title = obj.getOrDefault("title", "").toString();
|
|
|
126 |
String text = obj.getOrDefault("text", "").toString();
|
|
|
127 |
String imageURL = obj.getOrDefault("image", "").toString();
|
|
|
128 |
String end = obj.getOrDefault("end", "1/12/2133").toString();
|
|
|
129 |
SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
|
|
|
130 |
Date dateEnd = df.parse(end);
|
|
|
131 |
boolean includeCloud = (Boolean) obj.getOrDefault("include-cloud", Boolean.FALSE);
|
|
|
132 |
boolean includeMono = (Boolean) obj.getOrDefault("include-mono", Boolean.FALSE);
|
|
|
133 |
boolean includeMulti = (Boolean) obj.getOrDefault("include-multi", Boolean.FALSE);
|
|
|
134 |
boolean isMono = useH2;
|
|
|
135 |
boolean isMulti = !hasCloud && !isMono;
|
|
|
136 |
int minLaunch = (Integer) obj.getOrDefault("min-launch", 0);
|
|
|
137 |
if (launchCounter < minLaunch) {
|
|
|
138 |
System.out.println("launch counter too small (" + launchCounter + ")");
|
|
|
139 |
} else {
|
|
|
140 |
if (dateEnd.before(new Date())) {
|
|
|
141 |
System.out.println("outdated news");
|
|
|
142 |
} else {
|
|
|
143 |
if (includeCloud && hasCloud || includeMono && isMono || includeMulti && isMulti) {
|
|
|
144 |
BufferedImage image = null;
|
|
|
145 |
if (imageURL != null && imageURL.length() > 5) {
|
|
|
146 |
try {
|
|
|
147 |
byte[] imageData = download(imageURL);
|
|
|
148 |
image = ImageIO.read(new ByteArrayInputStream(imageData));
|
|
|
149 |
} catch (Exception e) {
|
|
|
150 |
e.printStackTrace();
|
|
|
151 |
}
|
|
|
152 |
}
|
|
|
153 |
showFrame(title, text, image, history, historyFile);
|
|
|
154 |
} else {
|
|
|
155 |
System.out.println("news not relevant");
|
|
|
156 |
}
|
|
|
157 |
|
|
|
158 |
}
|
|
|
159 |
}
|
|
|
160 |
|
|
|
161 |
} else {
|
|
|
162 |
System.out.println("news already displayed");
|
|
|
163 |
}
|
|
|
164 |
|
|
|
165 |
} catch (Exception e) {
|
|
|
166 |
e.printStackTrace();
|
|
|
167 |
}
|
|
|
168 |
|
|
|
169 |
}
|
|
|
170 |
|
|
|
171 |
private byte[] download(String u) throws MalformedURLException, IOException {
|
|
|
172 |
URL url = new URL(u);
|
|
|
173 |
URLConnection connection = url.openConnection();
|
|
|
174 |
InputStream is = connection.getInputStream();
|
|
|
175 |
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
|
|
176 |
byte[] buffer = new byte[2048];
|
|
|
177 |
int length = 0;
|
|
|
178 |
while ((length = is.read(buffer)) != -1) {
|
|
|
179 |
out.write(buffer, 0, length);
|
|
|
180 |
}
|
|
|
181 |
is.close();
|
|
|
182 |
out.close();
|
|
|
183 |
byte[] data = out.toByteArray();
|
|
|
184 |
return data;
|
|
|
185 |
}
|
|
|
186 |
});
|
|
|
187 |
t.setPriority(Thread.MIN_PRIORITY);
|
|
|
188 |
t.setName("News checker");
|
|
|
189 |
t.setDaemon(true);
|
|
|
190 |
t.start();
|
|
|
191 |
|
|
|
192 |
}
|
|
|
193 |
|
|
|
194 |
protected static void showFrame(String title, String text, BufferedImage image, List<DateHash> history, File historyFile) {
|
|
|
195 |
SwingUtilities.invokeLater(new Runnable() {
|
|
|
196 |
|
|
|
197 |
@Override
|
|
|
198 |
public void run() {
|
|
|
199 |
JFrame f = new JFrame();
|
|
|
200 |
f.setIconImages(Gestion.getFrameIcon());
|
|
|
201 |
f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
|
|
202 |
if (title != null && !title.isEmpty()) {
|
|
|
203 |
f.setTitle(title);
|
|
|
204 |
} else {
|
|
|
205 |
f.setTitle("OpenConcerto");
|
|
|
206 |
}
|
|
|
207 |
JPanel p = new JPanel();
|
|
|
208 |
p.setBackground(Color.WHITE);
|
|
|
209 |
p.setLayout(new BorderLayout());
|
|
|
210 |
if (image != null) {
|
|
|
211 |
p.add(new JImage(image), BorderLayout.PAGE_START);
|
|
|
212 |
}
|
|
|
213 |
if (text != null && !text.isEmpty()) {
|
|
|
214 |
final String t = text.replace("\\n", "\n");
|
|
|
215 |
final JTextArea ta = new JTextArea(t);
|
|
|
216 |
ta.setBorder(BorderFactory.createLineBorder(Color.WHITE, 10));
|
|
|
217 |
Font font = new JTextField("hello").getFont();
|
|
|
218 |
font = font.deriveFont(font.getSize() + 2f);
|
|
|
219 |
ta.setFont(font);
|
|
|
220 |
ta.setEditable(false);
|
|
|
221 |
|
|
|
222 |
p.add(ta, BorderLayout.CENTER);
|
|
|
223 |
}
|
|
|
224 |
final JButton bOk = new JButton();
|
|
|
225 |
bOk.setEnabled(false);
|
|
|
226 |
Thread t = new Thread(new Runnable() {
|
|
|
227 |
|
|
|
228 |
@Override
|
|
|
229 |
public void run() {
|
|
|
230 |
for (int i = 10; i > 0; i--) {
|
|
|
231 |
|
|
|
232 |
final int c = i;
|
|
|
233 |
SwingUtilities.invokeLater(new Runnable() {
|
|
|
234 |
|
|
|
235 |
@Override
|
|
|
236 |
public void run() {
|
|
|
237 |
bOk.setText(String.valueOf(c) + "s");
|
|
|
238 |
}
|
|
|
239 |
});
|
|
|
240 |
try {
|
|
|
241 |
Thread.sleep(1000);
|
|
|
242 |
} catch (InterruptedException e) {
|
|
|
243 |
// Nothing
|
|
|
244 |
}
|
|
|
245 |
}
|
|
|
246 |
SwingUtilities.invokeLater(new Runnable() {
|
|
|
247 |
|
|
|
248 |
@Override
|
|
|
249 |
public void run() {
|
|
|
250 |
bOk.setText("OK");
|
|
|
251 |
bOk.setEnabled(true);
|
|
|
252 |
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
|
|
253 |
}
|
|
|
254 |
});
|
|
|
255 |
}
|
|
|
256 |
});
|
|
|
257 |
t.start();
|
|
|
258 |
bOk.addActionListener(new ActionListener() {
|
|
|
259 |
|
|
|
260 |
@Override
|
|
|
261 |
public void actionPerformed(ActionEvent e) {
|
|
|
262 |
// save history
|
|
|
263 |
if (history != null) {
|
|
|
264 |
try (FileOutputStream fOp = new FileOutputStream(historyFile)) {
|
|
|
265 |
PrintStream prt = new PrintStream(new BufferedOutputStream(fOp));
|
|
|
266 |
for (DateHash d : history) {
|
|
|
267 |
prt.println(d.t);
|
|
|
268 |
prt.println(d.h);
|
|
|
269 |
}
|
|
|
270 |
prt.close();
|
|
|
271 |
} catch (IOException e1) {
|
|
|
272 |
e1.printStackTrace();
|
|
|
273 |
}
|
|
|
274 |
System.out.println(historyFile.getAbsolutePath() + " saved");
|
|
|
275 |
}
|
|
|
276 |
// close
|
|
|
277 |
f.dispose();
|
|
|
278 |
|
|
|
279 |
}
|
|
|
280 |
});
|
|
|
281 |
|
|
|
282 |
final FlowLayout flowLayout = new FlowLayout(FlowLayout.RIGHT);
|
|
|
283 |
final JPanel pButtons = new JPanel();
|
|
|
284 |
pButtons.setLayout(flowLayout);
|
|
|
285 |
pButtons.setOpaque(false);
|
|
|
286 |
pButtons.add(bOk);
|
|
|
287 |
p.add(pButtons, BorderLayout.PAGE_END);
|
|
|
288 |
f.setContentPane(p);
|
|
|
289 |
f.pack();
|
|
|
290 |
f.setMinimumSize(new Dimension(300, 400));
|
|
|
291 |
f.setLocationRelativeTo(null);
|
|
|
292 |
f.setVisible(true);
|
|
|
293 |
}
|
|
|
294 |
|
|
|
295 |
});
|
|
|
296 |
|
|
|
297 |
}
|
|
|
298 |
|
|
|
299 |
public static void main(String[] args) {
|
|
|
300 |
SwingUtilities.invokeLater(new Runnable() {
|
|
|
301 |
|
|
|
302 |
@Override
|
|
|
303 |
public void run() {
|
|
|
304 |
try {
|
|
|
305 |
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
|
306 |
showFrame("Hello", "world\\nhhhf the window is enlarged or the center and the bottom.", null, null, null);
|
|
|
307 |
// showFrame("Hello", "world\\nhhh",
|
|
|
308 |
// ImageIO.read(this.getClass().getResourceAsStream("256.png")), null);
|
|
|
309 |
} catch (Exception e) {
|
|
|
310 |
e.printStackTrace();
|
|
|
311 |
}
|
|
|
312 |
|
|
|
313 |
}
|
|
|
314 |
});
|
|
|
315 |
}
|
|
|
316 |
}
|