1 package de.tivsource.lib.jcyradm;
2
3 import java.io.BufferedReader;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.io.InputStream;
7 import java.io.InputStreamReader;
8 import java.io.PrintStream;
9 import java.math.BigDecimal;
10 import java.net.Socket;
11 import java.util.HashMap;
12 import java.util.Locale;
13 import java.util.Map;
14 import java.util.Properties;
15 import java.util.ResourceBundle;
16 import java.util.regex.Pattern;
17
18 import javax.net.ssl.SSLSocket;
19 import javax.net.ssl.SSLSocketFactory;
20
21 import org.apache.log4j.Logger;
22
23 import de.tivsource.lib.jcyradm.exception.AuthenticationFailure;
24 import de.tivsource.lib.jcyradm.exception.MailboxExists;
25 import de.tivsource.lib.jcyradm.exception.NoLogMessagesFile;
26 import de.tivsource.lib.jcyradm.exception.NoMailbox;
27 import de.tivsource.lib.jcyradm.exception.NoPropertiesFile;
28 import de.tivsource.lib.jcyradm.exception.NoQuota;
29 import de.tivsource.lib.jcyradm.exception.NoServerAnswerFile;
30 import de.tivsource.lib.jcyradm.exception.NoServerResponse;
31 import de.tivsource.lib.jcyradm.exception.NoServerStream;
32 import de.tivsource.lib.jcyradm.exception.NoValidMailboxName;
33 import de.tivsource.lib.jcyradm.exception.QuotaNotInitialized;
34 import de.tivsource.lib.jcyradm.exception.UnexpectedExtraArguments;
35 import de.tivsource.lib.jcyradm.exception.UnexpectedServerAnswer;
36
37
38
39
40
41
42
43
44
45 public class JCyrAdm {
46
47
48
49
50
51 private static final Logger LOGGER = Logger.getLogger(JCyrAdm.class);
52
53
54
55
56 private static final int DEFAULT_IMAP_PORT = 143;
57
58
59
60
61 private static final int DEFAULT_IMAP_SSL_PORT = 993;
62
63
64
65
66 private static final String DEFAULT_PROPERTIES_FILE = "jcyradm.properties";
67
68
69
70
71 private String host = "localhost";
72
73
74
75
76 private Integer port;
77
78
79
80
81 private String allacl = "lrswipcda";
82
83
84
85
86 private String administrator;
87
88
89
90
91 private String password;
92
93
94
95
96 private BigDecimal used;
97
98
99
100
101
102 private BigDecimal quota;
103
104
105
106
107 private BigDecimal load;
108
109
110
111
112 private String welcomeMsg;
113
114
115
116
117 private SSLSocket sslRequestSocket;
118
119
120
121
122 private Socket requestSocket;
123
124
125
126
127 private PrintStream out;
128
129
130
131
132 private BufferedReader in;
133
134
135
136
137 private Map<String, String> acls;
138
139
140
141
142 private Map<String, String> idMap = new HashMap<String, String>();
143
144
145
146
147 private Properties props;
148
149
150
151
152 private ResourceBundle serverAnswers;
153
154
155
156
157 private ResourceBundle logMessages;
158
159
160
161
162
163
164
165
166
167
168 public JCyrAdm() throws NoPropertiesFile, NoServerAnswerFile,
169 NoLogMessagesFile {
170 super();
171 LOGGER.debug("Aktuelle Sprache: " + Locale.getDefault().getLanguage());
172 props = new Properties();
173
174 try {
175 LOGGER.debug("Lade Standard Properties Datei.");
176 InputStream inputStream = getClass().getClassLoader()
177 .getResourceAsStream(DEFAULT_PROPERTIES_FILE);
178 props.load(inputStream);
179 inputStream.close();
180 } catch (Exception e1) {
181 throw new NoPropertiesFile();
182 }
183
184 try {
185 LOGGER.debug("Lade Server Antworten Datei.");
186 serverAnswers = ResourceBundle.getBundle("server");
187 } catch (Exception e2) {
188 throw new NoServerAnswerFile();
189 }
190
191 try {
192 LOGGER.debug("Lade Log-Nachrichten Datei.");
193 logMessages = ResourceBundle.getBundle("logging");
194 } catch (Exception e3) {
195 throw new NoLogMessagesFile();
196 }
197
198 }
199
200
201
202
203
204
205
206
207
208
209
210 public JCyrAdm(String properties) throws NoPropertiesFile,
211 NoServerAnswerFile, NoLogMessagesFile {
212 super();
213 LOGGER.debug("Aktuelle Sprache: " + Locale.getDefault().getLanguage());
214 props = new Properties();
215
216 try {
217 LOGGER.debug("Lade Properties Datei.");
218 InputStream inputStream = new FileInputStream(properties);
219 props.load(inputStream);
220 inputStream.close();
221 } catch (Exception e1) {
222 throw new NoPropertiesFile();
223 }
224
225 try {
226 LOGGER.debug("Lade Server Antworten Datei.");
227 serverAnswers = ResourceBundle.getBundle("server");
228 } catch (Exception e2) {
229 throw new NoServerAnswerFile();
230 }
231
232 try {
233 LOGGER.debug("Lade Log-Nachrichten Datei.");
234 logMessages = ResourceBundle.getBundle("logging");
235 } catch (Exception e3) {
236 throw new NoLogMessagesFile();
237 }
238
239 }
240
241
242
243
244
245
246
247
248
249
250 public final void connect(final Boolean ssl) throws IOException {
251 LOGGER.debug(logMessages.getString("logger.trace.connect"));
252 if (ssl) {
253 LOGGER.trace("öffne Verschlüsselte Verbindung");
254 if (isNull(port)) {
255 port = DEFAULT_IMAP_SSL_PORT;
256 }
257 SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
258 .getDefault();
259 sslRequestSocket = (SSLSocket) factory.createSocket(host, port);
260 out = new PrintStream(sslRequestSocket.getOutputStream());
261 out.flush();
262 in = new BufferedReader(new InputStreamReader(
263 sslRequestSocket.getInputStream()));
264 } else {
265 LOGGER.trace("öffne Ungesicherte Verbindung");
266 if (isNull(port)) {
267 port = DEFAULT_IMAP_PORT;
268 }
269 requestSocket = new Socket(host, port);
270 out = new PrintStream(requestSocket.getOutputStream());
271 out.flush();
272 in = new BufferedReader(new InputStreamReader(
273 requestSocket.getInputStream()));
274
275 }
276 welcomeMsg = in.readLine();
277 LOGGER.debug("Server >| " + welcomeMsg);
278 }
279
280
281
282
283
284
285
286 public final void disconnect() throws IOException {
287 LOGGER.trace(logMessages.getString("logger.trace.disconnect"));
288 if (sslRequestSocket != null) {
289 LOGGER.trace("schließe Verschlüsselte Verbindung");
290 sslRequestSocket.close();
291 } else {
292 LOGGER.trace("schließe Ungesicherte Verbindung");
293 requestSocket.close();
294 }
295 }
296
297
298
299
300
301
302
303
304 public final void capability() throws IOException {
305 LOGGER.trace("capability() aufgerufen.");
306 sendCommand(". capability");
307 String line = in.readLine();
308 LOGGER.debug("Server >| " + line);
309
310 line = in.readLine();
311 LOGGER.debug("Server >| " + line);
312
313
314
315 allacl = "lrswipkxtecda";
316 }
317
318
319
320
321
322
323
324
325
326 public final void login() throws NoServerResponse, UnexpectedServerAnswer, AuthenticationFailure {
327 LOGGER.trace("login() aufgerufen.");
328 sendCommand(". login \"" + administrator + "\" \"" + password + "\"");
329 try {
330
331 String line = in.readLine();
332 LOGGER.debug("Server >| " + line);
333
334
335 if(serverAnswers.getString("server.answer.login.failed")
336 .contentEquals(new StringBuffer(line))) {
337 LOGGER.error("Fehler >| " + line);
338 throw new AuthenticationFailure();
339 }
340
341 else if(Pattern.matches(serverAnswers.getString("server.answer.login"), line)) {
342 LOGGER.info("Authen >| " + line);
343 }
344
345 else {
346 System.out.println(serverAnswers.getString("server.answer.login"));
347 LOGGER.error("Fehler >| " + line);
348 throw new UnexpectedServerAnswer();
349 }
350
351 } catch (IOException e) {
352 throw new NoServerResponse();
353 }
354 }
355
356
357
358
359
360
361
362
363
364 public final void logout() throws NoServerResponse, NoServerStream, UnexpectedServerAnswer {
365 LOGGER.trace("logout() aufgerufen.");
366
367
368 sendCommand(". logout");
369
370 try {
371
372 String line = in.readLine();
373 LOGGER.debug("Server >| " + line);
374 if(!serverAnswers.getString("server.answer.logout")
375 .contentEquals(new StringBuffer(line))) {
376 LOGGER.error("Fehler >| " + line);
377 throw new UnexpectedServerAnswer();
378 }
379 } catch (IOException e) {
380 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
381 throw new NoServerResponse();
382 }
383
384 try {
385
386 String line = in.readLine();
387 LOGGER.debug("Server >| " + line);
388 if(!serverAnswers.getString("server.answer.ok")
389 .contentEquals(new StringBuffer(line))) {
390 LOGGER.error("Fehler >| " + line);
391 throw new UnexpectedServerAnswer();
392 }
393 } catch (IOException e) {
394 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
395 throw new NoServerResponse();
396 }
397
398 try {
399
400 in.close();
401 } catch (IOException e) {
402 LOGGER.error("Fehler >| Keine Stream vom Server vorhanden");
403 throw new NoServerStream();
404 }
405
406 out.close();
407 }
408
409
410
411
412
413
414
415
416
417
418 public final void acl(final String mailbox) throws NoValidMailboxName,
419 NoServerResponse, UnexpectedServerAnswer {
420
421
422
423 if (!isValid(mailbox)) {
424 LOGGER.error("Fehler >| Ungültiger Mailboxname");
425 throw new NoValidMailboxName();
426 }
427
428
429
430
431 sendCommand(". getacl \"user." + mailbox + "\"");
432
433
434
435
436 try {
437 String line = in.readLine();
438 LOGGER.debug("Server >| " + line);
439
440 if(!Pattern.matches(serverAnswers.getString("server.answer.acl"), line)) {
441 LOGGER.error("Fehler >| " + line);
442 throw new UnexpectedServerAnswer();
443 }
444
445 acls = new HashMap<String, String>();
446 String keys[] = line.split(" ");
447 for(int i=0; i < keys.length; i++) {
448 if(i > 2) {
449 if(i % 2 == 1) {
450 acls.put(keys[i], keys[i+1]);
451 }
452 }
453 }
454
455 } catch (IOException e) {
456 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
457 throw new NoServerResponse();
458 }
459
460
461
462
463 try {
464 String line = in.readLine();
465 LOGGER.debug("Server >| " + line);
466 if(!serverAnswers.getString("server.answer.ok")
467 .contentEquals(new StringBuffer(line))) {
468 LOGGER.error("Fehler >| " + line);
469 throw new UnexpectedServerAnswer();
470 }
471 } catch (IOException e) {
472 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
473 throw new NoServerResponse();
474 }
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488 public final void setAcl(final String mailbox, final String user,
489 final String acl) throws NoValidMailboxName, NoServerResponse, UnexpectedServerAnswer {
490
491
492
493 if (!isValid(mailbox)) {
494 LOGGER.error("Fehler >| Ungültiger Mailboxname");
495 throw new NoValidMailboxName();
496 }
497
498
499
500
501 sendCommand(". setacl \"user." + mailbox + "\" \"" + user + "\" " + acl);
502
503
504
505
506 try {
507 String line = in.readLine();
508 LOGGER.debug("Server >| " + line);
509 if(!serverAnswers.getString("server.answer.ok")
510 .contentEquals(new StringBuffer(line))) {
511 LOGGER.error("Fehler >| " + line);
512 throw new UnexpectedServerAnswer();
513 }
514 } catch (IOException e) {
515 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
516 throw new NoServerResponse();
517 }
518 }
519
520
521
522
523
524
525
526
527
528
529
530
531 public final void deleteAcl(final String mailbox, final String user)
532 throws NoValidMailboxName, NoServerResponse, UnexpectedServerAnswer {
533
534
535
536 if (!isValid(mailbox)) {
537 LOGGER.error("Fehler >| Ungültiger Mailboxname");
538 throw new NoValidMailboxName();
539 }
540
541
542
543
544 sendCommand(". deleteacl \"user." + mailbox + "\" \"" + user + "\"");
545
546
547
548
549 try {
550 String line = in.readLine();
551 LOGGER.debug("Server >| " + line);
552 if(!serverAnswers.getString("server.answer.ok")
553 .contentEquals(new StringBuffer(line))) {
554 LOGGER.error("Fehler >| " + line);
555 throw new UnexpectedServerAnswer();
556 }
557 } catch (IOException e) {
558 LOGGER.error("Fehler >| Keine Antwort von Server erhalten");
559 throw new NoServerResponse();
560 }
561
562 }
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577 public final void quota(final String mailbox) throws IOException,
578 NoMailbox, NoQuota, UnexpectedExtraArguments, NoServerResponse,
579 NoValidMailboxName {
580
581
582
583
584 if (!isValid(mailbox)) {
585 LOGGER.error("Fehler >| Ungültiger Mailboxname");
586 throw new NoValidMailboxName();
587 }
588
589
590
591
592 sendCommand(". getquota \"user." + mailbox + "\"");
593 String line = in.readLine();
594 LOGGER.debug("Server >| " + line);
595
596
597
598
599 if (isNull(line)) {
600 LOGGER.warn("Kein Antwort vom Server.");
601 throw new NoServerResponse();
602 }
603
604
605
606
607 if (line.startsWith(". NO Mailbox")) {
608 LOGGER.warn("Mailbox existiert nicht.");
609 throw new NoMailbox();
610 }
611
612
613
614
615 if (line.startsWith(". NO Quota root does not exist")) {
616 LOGGER.warn("Es wurde bis jetzt noch keine Quota gesetzt.");
617 throw new NoQuota();
618 }
619
620
621
622
623
624 if (line.startsWith(". BAD Unexpected extra arguments to Getquota")) {
625 LOGGER.warn("Es wurden weiter Argumente dem Befehl hinzugefügt.");
626 throw new UnexpectedExtraArguments();
627 }
628
629
630
631
632
633 if (!line.startsWith("* QUOTA")) {
634 LOGGER.warn("In der Server-Anwort war keine Quota enthalten.");
635
636 }
637
638
639
640
641 int start = line.lastIndexOf("(");
642 int end = line.lastIndexOf(")");
643
644
645
646
647
648 String[] storage = line.substring(start + 1, end).split(" ");
649 used = new BigDecimal(storage[1]);
650 quota = new BigDecimal(storage[2]);
651 LOGGER.debug(line.substring(start + 1, end));
652
653
654
655
656
657 load = used.multiply(new BigDecimal("100")).divide(quota, 2,
658 BigDecimal.ROUND_UP);
659
660
661
662
663 line = in.readLine();
664 LOGGER.debug("Server >| " + line);
665
666
667
668
669 if (isNull(line)) {
670 LOGGER.warn("Kein Antwort vom Server.");
671 throw new NoServerResponse();
672 }
673
674
675
676
677 if (!line.startsWith(". OK")) {
678 LOGGER.warn(
679 "Der letzte Befehl wurde nicht erfolgreich ausgeführt."
680 );
681
682 }
683
684 }
685
686
687
688
689
690
691
692
693
694 public final void setQuota(final String mailbox,
695 final BigDecimal quotaToSet)
696 throws IOException, NoValidMailboxName {
697
698
699
700 if (!isValid(mailbox)) {
701 LOGGER.warn("Ungültiger Mailboxname");
702 throw new NoValidMailboxName();
703 }
704
705
706
707
708 sendCommand((new StringBuilder())
709 .append(". setquota \"")
710 .append("user.")
711 .append(mailbox)
712 .append("\" (STORAGE ")
713 .append(quotaToSet)
714 .append(")").toString());
715
716 String line = in.readLine();
717 LOGGER.debug("Server >| " + line);
718
719
720
721
722 }
723
724
725
726
727
728
729
730
731
732
733
734
735
736 public final void createMailBox(final String mailbox) throws IOException,
737 MailboxExists, NoServerResponse, NoValidMailboxName {
738
739
740
741 System.out.println(mailbox);
742 if (!isValid(mailbox)) {
743
744 LOGGER.warn("Ungültiger Mailboxname");
745 throw new NoValidMailboxName();
746 }
747
748
749
750
751 sendCommand((new StringBuilder())
752 .append(". create \"")
753 .append("user.")
754 .append(mailbox)
755 .append("\"")
756 .toString());
757
758
759
760
761 String line = in.readLine();
762 LOGGER.debug("Server >| " + line);
763
764
765
766
767 if (isNull(line)) {
768 LOGGER.warn("Keine Antwort vom Server.");
769 throw new NoServerResponse();
770 }
771
772
773
774
775 if (line.startsWith(". NO Mailbox already exists")) {
776 LOGGER.warn("Die Mailbox existiert schon.");
777 throw new MailboxExists();
778 }
779 }
780
781
782
783
784
785
786
787
788
789 public final void deleteMailBox(final String mailbox) throws IOException,
790 NoValidMailboxName {
791
792
793
794 if (!isValid(mailbox)) {
795 LOGGER.warn("Ungültiger Mailboxname");
796 throw new NoValidMailboxName();
797 }
798
799
800
801
802 try {
803 setAcl(mailbox, administrator, allacl);
804 } catch (NoServerResponse e) {
805
806 e.printStackTrace();
807 } catch (UnexpectedServerAnswer e) {
808
809 e.printStackTrace();
810 }
811
812 sendCommand(". delete \"user." + mailbox + "\"");
813 String line = in.readLine();
814 LOGGER.debug("Server >| " + line);
815
816 }
817
818
819
820
821
822
823
824
825
826 public final void setHost(final String hostname) {
827 this.host = hostname;
828 }
829
830
831
832
833
834
835
836
837 public final void setPort(final Integer portNumber) {
838 this.port = portNumber;
839 }
840
841
842
843
844
845
846 public final void setAdministrator(final String set) {
847 this.administrator = set;
848 }
849
850
851
852
853
854
855 public final void setPassword(final String set) {
856 this.password = set;
857 }
858
859
860
861
862
863
864
865
866
867 public final String version() throws IOException {
868 sendCommand(". id NIL");
869 String line = in.readLine();
870 LOGGER.debug("Server >| " + line);
871
872 if (isNull(line)) {
873
874 LOGGER.warn("Keine Server Antwort.");
875 }
876
877 int start = line.indexOf("(");
878 int end = line.lastIndexOf(")");
879
880 String[] storage = line.substring(start + 1, end).split("\" \"");
881
882 for (int i = 0; i < storage.length; i++) {
883 idMap.put(storage[i], storage[i + 1]);
884 i++;
885 }
886
887 line = in.readLine();
888 LOGGER.debug("Server >| " + line);
889
890
891 return idMap.get("version").split(" ")[0];
892 }
893
894
895
896
897
898
899
900
901 public final String getWelcomeMsg() {
902 return welcomeMsg;
903 }
904
905
906
907
908
909 public Map<String, String> getAcls() {
910 return acls;
911 }
912
913
914
915
916
917
918
919
920
921
922 public final BigDecimal getUsed() throws QuotaNotInitialized {
923 if (isNull(used)) {
924 throw new QuotaNotInitialized();
925 }
926 return used;
927 }
928
929
930
931
932
933
934
935
936
937
938 public final BigDecimal getQuota() throws QuotaNotInitialized {
939 if (isNull(used)) {
940 throw new QuotaNotInitialized();
941 }
942 return quota;
943 }
944
945
946
947
948
949
950
951
952
953
954 public final BigDecimal getLoad() throws QuotaNotInitialized {
955 if (isNull(used)) {
956 throw new QuotaNotInitialized();
957 }
958 return load;
959 }
960
961
962
963
964
965
966 private void sendCommand(final String command) {
967 out.println(command);
968 out.flush();
969 LOGGER.debug("Client >| " + command);
970 }
971
972
973
974
975
976
977
978 private Boolean isNull(final Object isNull) {
979 return isNull != null ? false : true;
980 }
981
982
983
984
985
986
987
988
989 private Boolean isValid(final String mbString) {
990 return Pattern.matches("[a-zA-Z_]*", mbString)? true : false;
991 }
992
993
994
995
996
997
998
999
1000
1001 @Deprecated
1002 private String getText(String text) {
1003 if ((props != null) && (props.getProperty(text) != null)) {
1004 return props.getProperty(text);
1005 }
1006 return text;
1007 }
1008
1009
1010 }