Commit | Line | Data |
---|---|---|
7da41ecd NR |
1 | package be.nikiroo.jvcard.launcher; |
2 | ||
3 | import java.io.File; | |
4 | import java.io.IOException; | |
5 | import java.lang.reflect.Field; | |
7da41ecd NR |
6 | import java.net.Socket; |
7 | import java.nio.charset.Charset; | |
8 | import java.util.LinkedList; | |
9 | import java.util.List; | |
10 | ||
26d254a3 NR |
11 | import javax.imageio.ImageIO; |
12 | ||
7da41ecd | 13 | import be.nikiroo.jvcard.Card; |
26d254a3 NR |
14 | import be.nikiroo.jvcard.Contact; |
15 | import be.nikiroo.jvcard.Data; | |
16 | import be.nikiroo.jvcard.TypeInfo; | |
5ad0e17e | 17 | import be.nikiroo.jvcard.launcher.CardResult.MergeCallback; |
7da41ecd | 18 | import be.nikiroo.jvcard.parsers.Format; |
845fb1d7 | 19 | import be.nikiroo.jvcard.remote.Command; |
7da41ecd NR |
20 | import be.nikiroo.jvcard.remote.SimpleSocket; |
21 | import be.nikiroo.jvcard.resources.Bundles; | |
22 | import be.nikiroo.jvcard.resources.StringUtils; | |
e119a1c1 NR |
23 | import be.nikiroo.jvcard.resources.bundles.ColorBundle; |
24 | import be.nikiroo.jvcard.resources.bundles.DisplayBundle; | |
25 | import be.nikiroo.jvcard.resources.bundles.RemoteBundle; | |
26 | import be.nikiroo.jvcard.resources.bundles.TransBundle; | |
27 | import be.nikiroo.jvcard.resources.enums.DisplayOption; | |
28 | import be.nikiroo.jvcard.resources.enums.StringId; | |
7da41ecd NR |
29 | |
30 | /** | |
31 | * This class contains the runnable Main method. It will parse the user supplied | |
32 | * parameters and take action based upon those. Most of the time, it will start | |
33 | * a MainWindow. | |
34 | * | |
35 | * @author niki | |
36 | * | |
37 | */ | |
38 | public class Main { | |
39 | static public final String APPLICATION_TITLE = "jVcard"; | |
4477025c | 40 | static public final String APPLICATION_VERSION = "1.0-beta3-dev"; |
7da41ecd NR |
41 | |
42 | static private final int ERR_NO_FILE = 1; | |
43 | static private final int ERR_SYNTAX = 2; | |
44 | static private final int ERR_INTERNAL = 3; | |
e119a1c1 | 45 | static private TransBundle transService; |
7da41ecd | 46 | |
30a4aa17 NR |
47 | static private String defaultFn; |
48 | static private boolean forceComputedFn; | |
49 | ||
26d254a3 | 50 | enum Mode { |
e119a1c1 | 51 | CONTACT_MANAGER, I18N, SERVER, LOAD_PHOTO, SAVE_PHOTO, ONLY_PHOTO, SAVE_CONFIG |
26d254a3 NR |
52 | } |
53 | ||
7da41ecd | 54 | /** |
9b8cb729 | 55 | * Translate the given {@link StringId} into user text. |
7da41ecd | 56 | * |
9b8cb729 | 57 | * @param stringId |
7da41ecd | 58 | * the ID to translate |
9b8cb729 NR |
59 | * @param values |
60 | * the values to insert instead of the place holders in the | |
61 | * translation | |
7da41ecd | 62 | * |
9b8cb729 | 63 | * @return the translated text with the given value where required |
7da41ecd | 64 | */ |
e119a1c1 NR |
65 | static public String trans(StringId id, Object... values) { |
66 | return transService.getString(id, (Object[]) values); | |
7da41ecd NR |
67 | } |
68 | ||
69 | /** | |
70 | * Check if unicode characters should be used. | |
71 | * | |
72 | * @return TRUE to allow unicode | |
73 | */ | |
74 | static public boolean isUnicode() { | |
75 | return transService.isUnicode(); | |
76 | } | |
77 | ||
78 | /** | |
79 | * Start the application. | |
80 | * | |
81 | * <p> | |
82 | * The returned exit codes are: | |
83 | * <ul> | |
84 | * <li>1: no files to open</li> | |
85 | * <li>2: invalid syntax</li> | |
86 | * <li>3: internal error</li> | |
87 | * </ul> | |
88 | * </p> | |
89 | * | |
90 | * @param args | |
91 | * the parameters (see <tt>--help</tt> to know which are | |
92 | * supported) | |
93 | */ | |
94 | public static void main(String[] args) { | |
95 | Boolean textMode = null; | |
96 | boolean noMoreParams = false; | |
97 | boolean filesTried = false; | |
98 | ||
99 | // get the "system default" language to help translate the --help | |
100 | // message if needed | |
101 | String language = null; | |
e119a1c1 | 102 | transService = new TransBundle(language); |
7da41ecd NR |
103 | |
104 | boolean unicode = transService.isUnicode(); | |
26d254a3 | 105 | String dir = null; |
7da41ecd | 106 | List<String> files = new LinkedList<String>(); |
26d254a3 NR |
107 | int port = -1; |
108 | Mode mode = Mode.CONTACT_MANAGER; | |
109 | String format = null; | |
7da41ecd NR |
110 | for (int index = 0; index < args.length; index++) { |
111 | String arg = args[index]; | |
112 | if (!noMoreParams && arg.equals("--")) { | |
113 | noMoreParams = true; | |
114 | } else if (!noMoreParams && arg.equals("--help")) { | |
115 | System.out | |
116 | .println("TODO: implement some help text.\n" | |
117 | + "Usable switches:\n" | |
118 | + "\t--: stop looking for switches\n" | |
119 | + "\t--help: this here thingy\n" | |
120 | + "\t--lang LANGUAGE: choose the language, for instance en_GB\n" | |
121 | + "\t--tui: force pure text mode even if swing treminal is available\n" | |
122 | + "\t--gui: force swing terminal mode\n" | |
123 | + "\t--noutf: force non-utf8 mode if you need it\n" | |
e119a1c1 NR |
124 | + "\t--config DIRECTORY: use the given directory as a CONFIG_DIR\n" |
125 | + "\t--save-config DIRECTORY: save the current config to DIRECTORY (lang: only current)\n" | |
7da41ecd NR |
126 | + "\t--server PORT: start a remoting server instead of a client\n" |
127 | + "\t--i18n DIR: generate the translation file for the given language (can be \"\") to/from the .properties given dir\n" | |
26d254a3 NR |
128 | + "\t--save-photo DIR FORMAT: save the contacts' photos to DIR, named after FORMAT\n" |
129 | + "\t--load-photo DIR FORMAT: load the contacts' photos from DIR, named after FORMAT\n" | |
130 | + "\t--only-photo DIR FORMAT: load the contacts' photos from DIR, named after FORMAT, overwrite all other photos of selected contacts\n" | |
7da41ecd NR |
131 | + "everyhing else is either a file to open or a directory to open\n" |
132 | + "(we will only open 1st level files in given directories)\n" | |
133 | + "('jvcard://hostname:8888/file' links -- or without 'file' -- are also ok)\n"); | |
134 | return; | |
135 | } else if (!noMoreParams && arg.equals("--tui")) { | |
136 | textMode = true; | |
137 | } else if (!noMoreParams && arg.equals("--gui")) { | |
138 | textMode = false; | |
139 | } else if (!noMoreParams && arg.equals("--noutf")) { | |
140 | unicode = false; | |
141 | transService.setUnicode(unicode); | |
142 | } else if (!noMoreParams && arg.equals("--lang")) { | |
143 | index++; | |
144 | if (index >= args.length) { | |
145 | System.err.println("Syntax error: no language given"); | |
146 | System.exit(ERR_SYNTAX); | |
147 | return; | |
148 | } | |
149 | ||
150 | language = args[index]; | |
e119a1c1 | 151 | transService = new TransBundle(language); |
7da41ecd NR |
152 | transService.setUnicode(unicode); |
153 | } else if (!noMoreParams && arg.equals("--config")) { | |
154 | index++; | |
155 | if (index >= args.length) { | |
156 | System.err | |
157 | .println("Syntax error: no config directory given"); | |
158 | System.exit(ERR_SYNTAX); | |
159 | return; | |
160 | } | |
161 | ||
162 | Bundles.setDirectory(args[index]); | |
e119a1c1 | 163 | transService = new TransBundle(language); |
7da41ecd | 164 | transService.setUnicode(unicode); |
e119a1c1 NR |
165 | } else if (!noMoreParams && arg.equals("--save-config")) { |
166 | index++; | |
167 | if (index >= args.length) { | |
168 | System.err | |
169 | .println("Syntax error: no config directory given"); | |
170 | System.exit(ERR_SYNTAX); | |
171 | return; | |
172 | } | |
173 | dir = args[index]; | |
174 | ||
175 | if (mode != Mode.CONTACT_MANAGER) { | |
176 | System.err | |
177 | .println("Syntax error: you can only use one of: \n" | |
178 | + "--server\n" | |
179 | + "--save-config\n" | |
180 | + "--i18n\n" | |
181 | + "--load-photo\n" | |
182 | + "--save-photo\n" + "--only-photo\n"); | |
183 | System.exit(ERR_SYNTAX); | |
184 | return; | |
185 | } | |
186 | mode = Mode.SAVE_CONFIG; | |
7da41ecd | 187 | } else if (!noMoreParams && arg.equals("--server")) { |
26d254a3 NR |
188 | if (mode != Mode.CONTACT_MANAGER) { |
189 | System.err | |
190 | .println("Syntax error: you can only use one of: \n" | |
191 | + "--server\n" | |
e119a1c1 | 192 | + "--save-config\n" |
26d254a3 NR |
193 | + "--i18n\n" |
194 | + "--load-photo\n" | |
e119a1c1 | 195 | + "--save-photo\n" + "--only-photo\n"); |
26d254a3 NR |
196 | System.exit(ERR_SYNTAX); |
197 | return; | |
198 | } | |
199 | mode = Mode.SERVER; | |
200 | ||
7da41ecd NR |
201 | index++; |
202 | if (index >= args.length) { | |
203 | System.err.println("Syntax error: no port given"); | |
204 | System.exit(ERR_SYNTAX); | |
205 | return; | |
206 | } | |
207 | ||
208 | try { | |
209 | port = Integer.parseInt(args[index]); | |
210 | } catch (NumberFormatException e) { | |
211 | System.err.println("Invalid port number: " + args[index]); | |
212 | System.exit(ERR_SYNTAX); | |
213 | return; | |
214 | } | |
215 | } else if (!noMoreParams && arg.equals("--i18n")) { | |
26d254a3 NR |
216 | if (mode != Mode.CONTACT_MANAGER) { |
217 | System.err | |
218 | .println("Syntax error: you can only use one of: \n" | |
219 | + "--server\n" | |
e119a1c1 | 220 | + "--save-config\n" |
26d254a3 NR |
221 | + "--i18n\n" |
222 | + "--load-photo\n" | |
e119a1c1 | 223 | + "--save-photo\n" + "--only-photo\n"); |
26d254a3 NR |
224 | System.exit(ERR_SYNTAX); |
225 | return; | |
226 | } | |
227 | mode = Mode.I18N; | |
228 | ||
7da41ecd NR |
229 | index++; |
230 | if (index >= args.length) { | |
231 | System.err | |
232 | .println("Syntax error: no .properties directory given"); | |
233 | System.exit(ERR_SYNTAX); | |
234 | return; | |
235 | } | |
9b8cb729 | 236 | |
26d254a3 NR |
237 | dir = args[index]; |
238 | } else if (!noMoreParams | |
239 | && (arg.equals("--load-photo") | |
240 | || arg.equals("--save-photo") || arg | |
241 | .equals("--only-photo"))) { | |
242 | if (mode != Mode.CONTACT_MANAGER) { | |
243 | System.err | |
244 | .println("Syntax error: you can only use one of: \n" | |
245 | + "--server\n" | |
e119a1c1 | 246 | + "--save-config\n" |
26d254a3 NR |
247 | + "--i18n\n" |
248 | + "--load-photo\n" | |
e119a1c1 | 249 | + "--save-photo\n" + "--only-photo\n"); |
26d254a3 NR |
250 | System.exit(ERR_SYNTAX); |
251 | return; | |
252 | } | |
253 | ||
254 | if (arg.equals("--load-photo")) { | |
255 | mode = Mode.LOAD_PHOTO; | |
256 | } else if (arg.equals("--save-photo")) { | |
257 | mode = Mode.SAVE_PHOTO; | |
258 | } else { | |
259 | mode = Mode.ONLY_PHOTO; | |
260 | } | |
261 | ||
262 | index++; | |
263 | if (index >= args.length) { | |
264 | System.err.println("Syntax error: photo directory given"); | |
265 | System.exit(ERR_SYNTAX); | |
266 | return; | |
267 | } | |
268 | ||
269 | dir = args[index]; | |
270 | ||
271 | index++; | |
272 | if (index >= args.length) { | |
273 | System.err.println("Syntax error: photo format given"); | |
274 | System.exit(ERR_SYNTAX); | |
275 | return; | |
276 | } | |
277 | ||
278 | format = args[index]; | |
7da41ecd NR |
279 | } else { |
280 | filesTried = true; | |
281 | files.addAll(open(arg)); | |
282 | } | |
283 | } | |
9b8cb729 | 284 | |
f578f3af | 285 | // Force headless mode if we run in forced-text mode |
26d254a3 | 286 | if (mode != Mode.CONTACT_MANAGER || (textMode != null && textMode)) { |
f578f3af NR |
287 | // same as -Djava.awt.headless=true |
288 | System.setProperty("java.awt.headless", "true"); | |
289 | } | |
7da41ecd NR |
290 | |
291 | if (unicode) { | |
292 | utf8(); | |
293 | } | |
294 | ||
30a4aa17 NR |
295 | // N/FN fix information: |
296 | readNFN(); | |
297 | ||
7da41ecd | 298 | // Error management: |
26d254a3 | 299 | if (mode == Mode.SERVER && files.size() > 0) { |
7da41ecd NR |
300 | System.err |
301 | .println("Invalid syntax: you cannot both use --server and provide card files"); | |
302 | System.exit(ERR_SYNTAX); | |
26d254a3 | 303 | } else if (mode == Mode.I18N && files.size() > 0) { |
7da41ecd NR |
304 | System.err |
305 | .println("Invalid syntax: you cannot both use --i18n and provide card files"); | |
306 | System.exit(ERR_SYNTAX); | |
26d254a3 | 307 | } else if (mode == Mode.I18N && language == null) { |
7da41ecd NR |
308 | System.err |
309 | .println("Invalid syntax: you cannot use --i18n without --lang"); | |
310 | System.exit(ERR_SYNTAX); | |
26d254a3 NR |
311 | } else if ((mode == Mode.CONTACT_MANAGER || mode == Mode.SAVE_PHOTO || mode == Mode.LOAD_PHOTO) |
312 | && files.size() == 0) { | |
7da41ecd NR |
313 | if (files.size() == 0 && !filesTried) { |
314 | files.addAll(open(".")); | |
315 | } | |
316 | ||
317 | if (files.size() == 0) { | |
318 | System.err.println("No files to open"); | |
319 | System.exit(ERR_NO_FILE); | |
320 | return; | |
321 | } | |
322 | } | |
323 | // | |
324 | ||
26d254a3 | 325 | switch (mode) { |
e119a1c1 NR |
326 | case SAVE_CONFIG: { |
327 | try { | |
328 | if (!new File(dir).isDirectory()) { | |
329 | if (!new File(dir).mkdir()) { | |
330 | System.err | |
331 | .println("Cannot create configuration directory: " | |
332 | + dir); | |
333 | } | |
334 | } | |
335 | ||
336 | transService.updateFile(dir); // current lang TransBundle | |
337 | new TransBundle().updateFile(dir); | |
338 | new ColorBundle().updateFile(dir); | |
339 | new DisplayBundle().updateFile(dir); | |
340 | new RemoteBundle().updateFile(dir); | |
341 | } catch (IOException e) { | |
342 | e.printStackTrace(); | |
343 | System.exit(ERR_INTERNAL); | |
344 | } | |
345 | break; | |
346 | } | |
26d254a3 | 347 | case SERVER: { |
7da41ecd | 348 | try { |
02b341aa | 349 | Optional.runServer(port); |
7da41ecd NR |
350 | } catch (Exception e) { |
351 | if (e instanceof IOException) { | |
352 | System.err | |
353 | .println("I/O Exception: Cannot start the server"); | |
354 | } else { | |
4298276a | 355 | System.err.println("Remoting support not available"); |
7da41ecd NR |
356 | System.exit(ERR_INTERNAL); |
357 | } | |
358 | } | |
26d254a3 NR |
359 | break; |
360 | } | |
361 | case I18N: { | |
7da41ecd | 362 | try { |
e119a1c1 | 363 | transService.updateFile(dir); |
7da41ecd NR |
364 | } catch (IOException e) { |
365 | System.err | |
366 | .println("I/O Exception: Cannot create/update a language in directory: " | |
26d254a3 | 367 | + dir); |
e119a1c1 | 368 | e.printStackTrace(); |
7da41ecd | 369 | } |
26d254a3 NR |
370 | break; |
371 | } | |
372 | case ONLY_PHOTO: | |
373 | case LOAD_PHOTO: { | |
374 | for (String file : files) { | |
375 | try { | |
376 | Card card = getCard(file, null).getCard(); | |
377 | for (Contact contact : card) { | |
378 | String filename = contact.toString(format, ""); | |
f29274a7 | 379 | File f = new File(dir, filename); |
26d254a3 NR |
380 | |
381 | if (f.exists()) { | |
382 | try { | |
383 | String b64 = StringUtils.fromImage(ImageIO | |
384 | .read(f)); | |
385 | ||
386 | if (mode == Mode.ONLY_PHOTO) { | |
387 | for (Data photo = contact | |
388 | .getPreferredData("PHOTO"); photo != null; photo = contact | |
389 | .getPreferredData("PHOTO")) { | |
390 | photo.delete(); | |
391 | } | |
392 | } | |
393 | ||
394 | List<TypeInfo> types = new LinkedList<TypeInfo>(); | |
395 | types.add(new TypeInfo("ENCODING", "b")); | |
396 | types.add(new TypeInfo("TYPE", "png")); | |
397 | Data photo = new Data(types, "PHOTO", b64, null); | |
398 | contact.add(photo); | |
399 | } catch (IOException e) { | |
400 | System.err.println("Cannot read photo: " | |
401 | + filename); | |
402 | } | |
403 | } | |
404 | } | |
405 | card.save(); | |
406 | } catch (IOException e) { | |
407 | System.err.println("Card cannot be opened: " + file); | |
408 | } | |
409 | } | |
410 | break; | |
411 | } | |
412 | case SAVE_PHOTO: { | |
413 | for (String file : files) { | |
414 | try { | |
415 | Card card = getCard(file, null).getCard(); | |
416 | for (Contact contact : card) { | |
417 | Data photo = contact.getPreferredData("PHOTO"); | |
418 | if (photo != null) { | |
419 | String filename = contact.toString(format, ""); | |
420 | File f = new File(dir, filename + ".png"); | |
421 | try { | |
422 | ImageIO.write( | |
423 | StringUtils.toImage(photo.getValue()), | |
424 | "png", f); | |
425 | } catch (IOException e) { | |
426 | System.err | |
427 | .println("Cannot save photo of contact: " | |
428 | + contact | |
429 | .getPreferredDataValue("FN")); | |
430 | } | |
431 | } | |
432 | } | |
433 | } catch (IOException e) { | |
434 | System.err.println("Card cannot be opened: " + file); | |
435 | } | |
436 | } | |
437 | break; | |
438 | } | |
439 | case CONTACT_MANAGER: { | |
7da41ecd | 440 | try { |
02b341aa | 441 | Optional.startTui(textMode, files); |
7da41ecd NR |
442 | } catch (Exception e) { |
443 | if (e instanceof IOException) { | |
444 | System.err | |
445 | .println("I/O Exception: Cannot start the program with the given cards"); | |
446 | } else { | |
4298276a | 447 | System.err.println("TUI support not available"); |
7da41ecd NR |
448 | System.exit(ERR_INTERNAL); |
449 | } | |
450 | } | |
26d254a3 NR |
451 | break; |
452 | } | |
7da41ecd NR |
453 | } |
454 | } | |
455 | ||
456 | /** | |
457 | * Return the {@link Card} corresponding to the given resource name -- a | |
30a4aa17 NR |
458 | * file or a remote jvcard URL. |
459 | * | |
460 | * <p> | |
461 | * Will also fix the FN if required (see display.properties). | |
462 | * </p> | |
7da41ecd NR |
463 | * |
464 | * @param input | |
465 | * a filename or a remote jvcard url with named resource (e.g.: | |
466 | * <tt>jvcard://localhost:4444/coworkers.vcf</tt>) | |
5ad0e17e NR |
467 | * @param callback |
468 | * the {@link MergeCallback} to call in case of conflict, or NULL | |
469 | * to disallow conflict management (the {@link Card} will not be | |
470 | * allowed to synchronise in case of conflicts) | |
7da41ecd NR |
471 | * |
472 | * @return the {@link Card} | |
473 | * | |
474 | * @throws IOException | |
475 | * in case of IO error or remoting not available | |
476 | */ | |
5ad0e17e NR |
477 | static public CardResult getCard(String input, MergeCallback callback) |
478 | throws IOException { | |
7da41ecd NR |
479 | boolean remote = false; |
480 | Format format = Format.Abook; | |
481 | String ext = input; | |
482 | if (ext.contains(".")) { | |
483 | String tab[] = ext.split("\\."); | |
484 | if (tab.length > 1 && tab[tab.length - 1].equalsIgnoreCase("vcf")) { | |
485 | format = Format.VCard21; | |
486 | } | |
487 | } | |
488 | ||
489 | if (input.contains("://")) { | |
490 | format = Format.VCard21; | |
491 | remote = true; | |
492 | } | |
493 | ||
5ad0e17e | 494 | CardResult card = null; |
7da41ecd NR |
495 | try { |
496 | if (remote) { | |
5ad0e17e | 497 | card = Optional.syncCard(input, callback); |
7da41ecd | 498 | } else { |
5ad0e17e NR |
499 | card = new CardResult(new Card(new File(input), format), false, |
500 | false, false); | |
7da41ecd NR |
501 | } |
502 | } catch (IOException ioe) { | |
503 | throw ioe; | |
504 | } catch (Exception e) { | |
4298276a | 505 | throw new IOException("Remoting support not available", e); |
7da41ecd NR |
506 | } |
507 | ||
30a4aa17 NR |
508 | // Fix the FN value |
509 | if (defaultFn != null) { | |
510 | try { | |
511 | for (Contact contact : card.getCard()) { | |
512 | Data name = contact.getPreferredData("FN"); | |
513 | if (name == null || name.getValue().length() == 0 | |
514 | || forceComputedFn) { | |
515 | name.setValue(contact.toString(defaultFn, "")); | |
516 | } | |
517 | } | |
518 | } catch (Exception e) { | |
519 | // sync failed -> getCard() throws. | |
520 | // do not update. | |
521 | } | |
522 | } | |
523 | ||
7da41ecd NR |
524 | return card; |
525 | } | |
526 | ||
7da41ecd NR |
527 | /** |
528 | * Open the given path and add all its files if it is a directory or just | |
529 | * this one if not to the returned list. | |
530 | * | |
531 | * @param path | |
532 | * the path to open | |
533 | * | |
534 | * @return the list of opened files | |
535 | */ | |
536 | static private List<String> open(String path) { | |
537 | List<String> files = new LinkedList<String>(); | |
538 | ||
539 | if (path != null && path.startsWith("jvcard://")) { | |
540 | if (path.endsWith("/")) { | |
541 | files.addAll(list(path)); | |
542 | } else { | |
543 | files.add(path); | |
544 | } | |
545 | } else { | |
546 | File file = new File(path); | |
547 | if (file.exists()) { | |
548 | if (file.isDirectory()) { | |
549 | for (File subfile : file.listFiles()) { | |
550 | if (!subfile.isDirectory()) | |
551 | files.add(subfile.getAbsolutePath()); | |
552 | } | |
553 | } else { | |
554 | files.add(file.getAbsolutePath()); | |
555 | } | |
556 | } else { | |
557 | System.err.println("File or directory not found: \"" + path | |
558 | + "\""); | |
559 | } | |
560 | } | |
561 | ||
562 | return files; | |
563 | } | |
564 | ||
565 | /** | |
566 | * List all the available {@link Card}s on the given network location (which | |
567 | * is expected to be a jVCard remote server, obviously). | |
568 | * | |
569 | * @param path | |
570 | * the jVCard remote server path (e.g.: | |
571 | * <tt>jvcard://localhost:4444/</tt>) | |
572 | * | |
573 | * @return the list of {@link Card}s | |
574 | */ | |
575 | static private List<String> list(String path) { | |
576 | List<String> files = new LinkedList<String>(); | |
577 | ||
578 | try { | |
579 | String host = path.split("\\:")[1].substring(2); | |
580 | int port = Integer.parseInt(path.split("\\:")[2].replaceAll("/$", | |
581 | "")); | |
582 | SimpleSocket s = new SimpleSocket(new Socket(host, port), | |
583 | "sync client"); | |
584 | s.open(true); | |
585 | ||
845fb1d7 | 586 | s.sendCommand(Command.LIST_CARD); |
7da41ecd NR |
587 | for (String p : s.receiveBlock()) { |
588 | files.add(path | |
589 | + p.substring(StringUtils.fromTime(0).length() + 1)); | |
590 | } | |
591 | s.close(); | |
592 | } catch (Exception e) { | |
593 | e.printStackTrace(); | |
594 | } | |
595 | ||
596 | return files; | |
597 | } | |
598 | ||
599 | /** | |
600 | * Really, really ask for UTF-8 encoding. | |
601 | */ | |
602 | static private void utf8() { | |
603 | try { | |
604 | System.setProperty("file.encoding", "UTF-8"); | |
605 | Field charset = Charset.class.getDeclaredField("defaultCharset"); | |
606 | charset.setAccessible(true); | |
607 | charset.set(null, null); | |
608 | } catch (SecurityException e) { | |
609 | } catch (NoSuchFieldException e) { | |
610 | } catch (IllegalArgumentException e) { | |
611 | } catch (IllegalAccessException e) { | |
612 | } | |
613 | } | |
30a4aa17 NR |
614 | |
615 | /** | |
616 | * Read display.properties to know if we should fix the FN field when empty, | |
617 | * or always, or never. | |
618 | */ | |
619 | static private void readNFN() { | |
e119a1c1 | 620 | DisplayBundle map = new DisplayBundle(); |
30a4aa17 | 621 | |
e119a1c1 NR |
622 | defaultFn = map.getString(DisplayOption.CONTACT_DETAILS_DEFAULT_FN); |
623 | ||
624 | forceComputedFn = map.getBoolean( | |
625 | DisplayOption.CONTACT_DETAILS_SHOW_COMPUTED_FN, false); | |
30a4aa17 | 626 | } |
7da41ecd | 627 | } |