1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml.util;
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 public class Base64 {
61
62
63
64
65 public final static int NO_OPTIONS = 0;
66
67
68 public final static int ENCODE = 1;
69
70
71 public final static int DECODE = 0;
72
73
74 public final static int GZIP = 2;
75
76
77 public final static int DONT_BREAK_LINES = 8;
78
79
80
81
82 private final static int MAX_LINE_LENGTH = 76;
83
84
85 private final static byte EQUALS_SIGN = (byte) '=';
86
87
88 private final static byte NEW_LINE = (byte) '\n';
89
90
91 private final static String PREFERRED_ENCODING = "UTF-8";
92
93
94 private final static byte[] ALPHABET;
95
96 private final static byte[] _NATIVE_ALPHABET =
97 { (byte) 'A', (byte) 'B', (byte) 'C', (byte) 'D', (byte) 'E', (byte) 'F', (byte) 'G', (byte) 'H', (byte) 'I',
98 (byte) 'J', (byte) 'K', (byte) 'L', (byte) 'M', (byte) 'N', (byte) 'O', (byte) 'P', (byte) 'Q', (byte) 'R',
99 (byte) 'S', (byte) 'T', (byte) 'U', (byte) 'V', (byte) 'W', (byte) 'X', (byte) 'Y', (byte) 'Z', (byte) 'a',
100 (byte) 'b', (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f', (byte) 'g', (byte) 'h', (byte) 'i', (byte) 'j',
101 (byte) 'k', (byte) 'l', (byte) 'm', (byte) 'n', (byte) 'o', (byte) 'p', (byte) 'q', (byte) 'r', (byte) 's',
102 (byte) 't', (byte) 'u', (byte) 'v', (byte) 'w', (byte) 'x', (byte) 'y', (byte) 'z', (byte) '0', (byte) '1',
103 (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) '+',
104 (byte) '/' };
105
106
107 static {
108 byte[] __bytes;
109 try {
110 __bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".getBytes(PREFERRED_ENCODING);
111 }
112 catch (java.io.UnsupportedEncodingException use) {
113 __bytes = _NATIVE_ALPHABET;
114 }
115 ALPHABET = __bytes;
116 }
117
118
119
120
121
122 private final static byte[] DECODABET = { -9, -9, -9, -9, -9, -9, -9, -9, -9,
123 -5, -5,
124 -9, -9,
125 -5,
126 -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
127 -9, -9, -9, -9, -9,
128 -5,
129 -9, -9, -9, -9, -9, -9, -9, -9, -9, -9,
130 62,
131 -9, -9, -9,
132 63,
133 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
134 -9, -9, -9,
135 -1,
136 -9, -9, -9,
137 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
138 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
139 -9, -9, -9, -9, -9, -9,
140 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
141 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
142 -9, -9, -9, -9
143
144
145
146
147
148
149
150
151 };
152
153
154
155 private final static byte WHITE_SPACE_ENC = -5;
156
157 private final static byte EQUALS_SIGN_ENC = -1;
158
159
160 private Base64() {
161 }
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177 private static byte[] encode3to4(byte[] b4, byte[] threeBytes, int numSigBytes) {
178 encode3to4(threeBytes, 0, numSigBytes, b4, 0);
179 return b4;
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198 private static byte[] encode3to4(byte[] source, int srcOffset, int numSigBytes, byte[] destination, int destOffset) {
199
200
201
202
203
204
205
206
207
208
209
210 int inBuff = (numSigBytes > 0 ? ((source[srcOffset] << 24) >>> 8) : 0)
211 | (numSigBytes > 1 ? ((source[srcOffset + 1] << 24) >>> 16) : 0)
212 | (numSigBytes > 2 ? ((source[srcOffset + 2] << 24) >>> 24) : 0);
213
214 switch (numSigBytes) {
215 case 3:
216 destination[destOffset] = ALPHABET[(inBuff >>> 18)];
217 destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
218 destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
219 destination[destOffset + 3] = ALPHABET[(inBuff) & 0x3f];
220 return destination;
221
222 case 2:
223 destination[destOffset] = ALPHABET[(inBuff >>> 18)];
224 destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
225 destination[destOffset + 2] = ALPHABET[(inBuff >>> 6) & 0x3f];
226 destination[destOffset + 3] = EQUALS_SIGN;
227 return destination;
228
229 case 1:
230 destination[destOffset] = ALPHABET[(inBuff >>> 18)];
231 destination[destOffset + 1] = ALPHABET[(inBuff >>> 12) & 0x3f];
232 destination[destOffset + 2] = EQUALS_SIGN;
233 destination[destOffset + 3] = EQUALS_SIGN;
234 return destination;
235
236 default:
237 return destination;
238 }
239 }
240
241
242
243
244
245
246
247
248
249
250 public static String encodeObject(java.io.Serializable serializableObject) {
251 return encodeObject(serializableObject, NO_OPTIONS);
252 }
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 public static String encodeObject(java.io.Serializable serializableObject, int options) {
279
280 java.io.ByteArrayOutputStream baos = null;
281 java.io.OutputStream b64os = null;
282 java.io.ObjectOutputStream oos = null;
283 java.util.zip.GZIPOutputStream gzos = null;
284
285
286 int gzip = (options & GZIP);
287 int dontBreakLines = (options & DONT_BREAK_LINES);
288
289 try {
290
291 baos = new java.io.ByteArrayOutputStream();
292 b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines);
293
294
295 if (gzip == GZIP) {
296 gzos = new java.util.zip.GZIPOutputStream(b64os);
297 oos = new java.io.ObjectOutputStream(gzos);
298 }
299 else
300 oos = new java.io.ObjectOutputStream(b64os);
301
302 oos.writeObject(serializableObject);
303 }
304 catch (java.io.IOException e) {
305 e.printStackTrace();
306 return null;
307 }
308 finally {
309 try {
310 oos.close();
311 } catch (Exception e) {
312 }
313 try {
314 gzos.close();
315 } catch (Exception e) {
316 }
317 try {
318 b64os.close();
319 } catch (Exception e) {
320 }
321 try {
322 baos.close();
323 } catch (Exception e) {
324 }
325 }
326
327
328 try {
329 return new String(baos.toByteArray(), PREFERRED_ENCODING);
330 }
331 catch (java.io.UnsupportedEncodingException uue) {
332 return new String(baos.toByteArray());
333 }
334
335 }
336
337
338
339
340
341
342
343 public static String encodeBytes(byte[] source) {
344 return encodeBytes(source, 0, source.length, NO_OPTIONS);
345 }
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370 public static String encodeBytes(byte[] source, int options) {
371 return encodeBytes(source, 0, source.length, options);
372 }
373
374
375
376
377
378
379
380
381
382 public static String encodeBytes(byte[] source, int off, int len) {
383 return encodeBytes(source, off, len, NO_OPTIONS);
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411 public static String encodeBytes(byte[] source, int off, int len, int options) {
412
413 int dontBreakLines = (options & DONT_BREAK_LINES);
414 int gzip = (options & GZIP);
415
416
417 if (gzip == GZIP) {
418 java.io.ByteArrayOutputStream baos = null;
419 java.util.zip.GZIPOutputStream gzos = null;
420 Base64.OutputStream b64os = null;
421
422 try {
423
424 baos = new java.io.ByteArrayOutputStream();
425 b64os = new Base64.OutputStream(baos, ENCODE | dontBreakLines);
426 gzos = new java.util.zip.GZIPOutputStream(b64os);
427
428 gzos.write(source, off, len);
429 gzos.close();
430 }
431 catch (java.io.IOException e) {
432 e.printStackTrace();
433 return null;
434 }
435 finally {
436 try {
437 gzos.close();
438 } catch (Exception e) {
439 }
440 try {
441 b64os.close();
442 } catch (Exception e) {
443 }
444 try {
445 baos.close();
446 } catch (Exception e) {
447 }
448 }
449
450
451 try {
452 return new String(baos.toByteArray(), PREFERRED_ENCODING);
453 }
454 catch (java.io.UnsupportedEncodingException uue) {
455 return new String(baos.toByteArray());
456 }
457 }
458
459
460 else {
461
462 boolean breakLines = dontBreakLines == 0;
463
464 int len43 = len * 4 / 3;
465 byte[] outBuff = new byte[(len43)
466 + ((len % 3) > 0 ? 4 : 0)
467 + (breakLines ? (len43 / MAX_LINE_LENGTH) : 0)];
468 int d = 0;
469 int e = 0;
470 int len2 = len - 2;
471 int lineLength = 0;
472 for (; d < len2; d += 3, e += 4) {
473 encode3to4(source, d + off, 3, outBuff, e);
474
475 lineLength += 4;
476 if (breakLines && lineLength == MAX_LINE_LENGTH) {
477 outBuff[e + 4] = NEW_LINE;
478 e++;
479 lineLength = 0;
480 }
481 }
482
483 if (d < len) {
484 encode3to4(source, d + off, len - d, outBuff, e);
485 e += 4;
486 }
487
488
489 try {
490 return new String(outBuff, 0, e, PREFERRED_ENCODING);
491 }
492 catch (java.io.UnsupportedEncodingException uue) {
493 return new String(outBuff, 0, e);
494 }
495
496 }
497
498 }
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518 private static int decode4to3(byte[] source, int srcOffset, byte[] destination, int destOffset) {
519
520 if (source[srcOffset + 2] == EQUALS_SIGN) {
521
522
523
524 int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
525 | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12);
526
527 destination[destOffset] = (byte) (outBuff >>> 16);
528 return 1;
529 }
530
531
532 else if (source[srcOffset + 3] == EQUALS_SIGN) {
533
534
535
536
537 int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
538 | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
539 | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6);
540
541 destination[destOffset] = (byte) (outBuff >>> 16);
542 destination[destOffset + 1] = (byte) (outBuff >>> 8);
543 return 2;
544 }
545
546
547 else {
548 try {
549
550
551
552
553
554 int outBuff = ((DECODABET[source[srcOffset]] & 0xFF) << 18)
555 | ((DECODABET[source[srcOffset + 1]] & 0xFF) << 12)
556 | ((DECODABET[source[srcOffset + 2]] & 0xFF) << 6)
557 | ((DECODABET[source[srcOffset + 3]] & 0xFF));
558
559 destination[destOffset] = (byte) (outBuff >> 16);
560 destination[destOffset + 1] = (byte) (outBuff >> 8);
561 destination[destOffset + 2] = (byte) (outBuff);
562
563 return 3;
564 } catch (Exception e) {
565 System.out.println("" + source[srcOffset] + ": " + (DECODABET[source[srcOffset]]));
566 System.out.println("" + source[srcOffset + 1] + ": " + (DECODABET[source[srcOffset + 1]]));
567 System.out.println("" + source[srcOffset + 2] + ": " + (DECODABET[source[srcOffset + 2]]));
568 System.out.println("" + source[srcOffset + 3] + ": " + (DECODABET[source[srcOffset + 3]]));
569 return -1;
570 }
571 }
572 }
573
574
575
576
577
578
579
580
581
582
583
584 public static byte[] decode(byte[] source, int off, int len) {
585 int len34 = len * 3 / 4;
586 byte[] outBuff = new byte[len34];
587 int outBuffPosn = 0;
588
589 byte[] b4 = new byte[4];
590 int b4Posn = 0;
591 int i = 0;
592 byte sbiCrop = 0;
593 byte sbiDecode = 0;
594 for (i = off; i < off + len; i++) {
595 sbiCrop = (byte) (source[i] & 0x7f);
596 sbiDecode = DECODABET[sbiCrop];
597
598 if (sbiDecode >= WHITE_SPACE_ENC)
599 {
600 if (sbiDecode >= EQUALS_SIGN_ENC) {
601 b4[b4Posn++] = sbiCrop;
602 if (b4Posn > 3) {
603 outBuffPosn += decode4to3(b4, 0, outBuff, outBuffPosn);
604 b4Posn = 0;
605
606
607 if (sbiCrop == EQUALS_SIGN)
608 break;
609 }
610
611 }
612
613 }
614 else {
615 System.err.println("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
616 return null;
617 }
618 }
619
620 byte[] out = new byte[outBuffPosn];
621 System.arraycopy(outBuff, 0, out, 0, outBuffPosn);
622 return out;
623 }
624
625
626
627
628
629
630
631
632 public static byte[] decode(String s) {
633 byte[] bytes;
634 try {
635 bytes = s.getBytes(PREFERRED_ENCODING);
636 }
637 catch (java.io.UnsupportedEncodingException uee) {
638 bytes = s.getBytes();
639 }
640
641
642
643 bytes = decode(bytes, 0, bytes.length);
644
645
646
647 if (bytes != null && bytes.length >= 4) {
648
649 int head = ((int) bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
650 if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) {
651 java.io.ByteArrayInputStream bais = null;
652 java.util.zip.GZIPInputStream gzis = null;
653 java.io.ByteArrayOutputStream baos = null;
654 byte[] buffer = new byte[2048];
655 int length = 0;
656
657 try {
658 baos = new java.io.ByteArrayOutputStream();
659 bais = new java.io.ByteArrayInputStream(bytes);
660 gzis = new java.util.zip.GZIPInputStream(bais);
661
662 while ((length = gzis.read(buffer)) >= 0) {
663 baos.write(buffer, 0, length);
664 }
665
666
667 bytes = baos.toByteArray();
668
669 }
670 catch (java.io.IOException e) {
671
672 }
673 finally {
674 try {
675 baos.close();
676 } catch (Exception e) {
677 }
678 try {
679 gzis.close();
680 } catch (Exception e) {
681 }
682 try {
683 bais.close();
684 } catch (Exception e) {
685 }
686 }
687
688 }
689 }
690
691 return bytes;
692 }
693
694
695
696
697
698
699
700
701
702 public static Object decodeToObject(String encodedObject) {
703
704 byte[] objBytes = decode(encodedObject);
705
706 java.io.ByteArrayInputStream bais = null;
707 java.io.ObjectInputStream ois = null;
708 Object obj = null;
709
710 try {
711 bais = new java.io.ByteArrayInputStream(objBytes);
712 ois = new java.io.ObjectInputStream(bais);
713
714 obj = ois.readObject();
715 }
716 catch (java.io.IOException e) {
717 e.printStackTrace();
718 obj = null;
719 }
720 catch (java.lang.ClassNotFoundException e) {
721 e.printStackTrace();
722 obj = null;
723 }
724 finally {
725 try {
726 bais.close();
727 } catch (Exception e) {
728 }
729 try {
730 ois.close();
731 } catch (Exception e) {
732 }
733 }
734
735 return obj;
736 }
737
738
739
740
741
742
743
744
745
746
747 public static boolean encodeToFile(byte[] dataToEncode, String filename) {
748 boolean success = false;
749 Base64.OutputStream bos = null;
750 try {
751 bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.ENCODE);
752 bos.write(dataToEncode);
753 success = true;
754 }
755 catch (java.io.IOException e) {
756
757 success = false;
758 }
759 finally {
760 try {
761 bos.close();
762 } catch (Exception e) {
763 }
764 }
765
766 return success;
767 }
768
769
770
771
772
773
774
775
776
777
778 public static boolean decodeToFile(String dataToDecode, String filename) {
779 boolean success = false;
780 Base64.OutputStream bos = null;
781 try {
782 bos = new Base64.OutputStream(new java.io.FileOutputStream(filename), Base64.DECODE);
783 bos.write(dataToDecode.getBytes(PREFERRED_ENCODING));
784 success = true;
785 }
786 catch (java.io.IOException e) {
787 success = false;
788 }
789 finally {
790 try {
791 bos.close();
792 } catch (Exception e) {
793 }
794 }
795
796 return success;
797 }
798
799
800
801
802
803
804
805
806
807 public static byte[] decodeFromFile(String filename) {
808 byte[] decodedData = null;
809 Base64.InputStream bis = null;
810 try {
811
812 java.io.File file = new java.io.File(filename);
813 byte[] buffer = null;
814 int length = 0;
815 int numBytes = 0;
816
817
818 if (file.length() > Integer.MAX_VALUE) {
819 System.err.println("File is too big for this convenience method (" + file.length() + " bytes).");
820 return null;
821 }
822 buffer = new byte[(int) file.length()];
823
824
825 bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)),
826 Base64.DECODE);
827
828
829 while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
830 length += numBytes;
831
832
833 decodedData = new byte[length];
834 System.arraycopy(buffer, 0, decodedData, 0, length);
835
836 }
837 catch (java.io.IOException e) {
838 System.err.println("Error decoding from file " + filename);
839 }
840 finally {
841 try {
842 bis.close();
843 } catch (Exception e) {
844 }
845 }
846
847 return decodedData;
848 }
849
850
851
852
853
854
855
856
857
858 public static String encodeFromFile(String filename) {
859 String encodedData = null;
860 Base64.InputStream bis = null;
861 try {
862
863 java.io.File file = new java.io.File(filename);
864 byte[] buffer = new byte[(int) (file.length() * 1.4)];
865 int length = 0;
866 int numBytes = 0;
867
868
869 bis = new Base64.InputStream(new java.io.BufferedInputStream(new java.io.FileInputStream(file)),
870 Base64.ENCODE);
871
872
873 while ((numBytes = bis.read(buffer, length, 4096)) >= 0)
874 length += numBytes;
875
876
877 encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING);
878
879 }
880 catch (java.io.IOException e) {
881 System.err.println("Error encoding from file " + filename);
882 }
883 finally {
884 try {
885 bis.close();
886 } catch (Exception e) {
887 }
888 }
889
890 return encodedData;
891 }
892
893
894
895
896
897
898
899
900
901
902 public static class InputStream extends java.io.FilterInputStream {
903 private boolean encode;
904
905 private int position;
906
907 private byte[] buffer;
908
909 private int bufferLength;
910
911 private int numSigBytes;
912
913 private int lineLength;
914
915 private boolean breakLines;
916
917
918
919
920
921
922
923 public InputStream(java.io.InputStream in) {
924 this(in, DECODE);
925 }
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950 public InputStream(java.io.InputStream in, int options) {
951 super(in);
952 this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
953 this.encode = (options & ENCODE) == ENCODE;
954 this.bufferLength = encode ? 4 : 3;
955 this.buffer = new byte[bufferLength];
956 this.position = -1;
957 this.lineLength = 0;
958 }
959
960
961
962
963
964
965
966 public int read() throws java.io.IOException {
967
968 if (position < 0) {
969 if (encode) {
970 byte[] b3 = new byte[3];
971 int numBinaryBytes = 0;
972 for (int i = 0; i < 3; i++) {
973 try {
974 int b = in.read();
975
976
977 if (b >= 0) {
978 b3[i] = (byte) b;
979 numBinaryBytes++;
980 }
981
982 }
983 catch (java.io.IOException e) {
984
985 if (i == 0)
986 throw e;
987
988 }
989 }
990
991 if (numBinaryBytes > 0) {
992 encode3to4(b3, 0, numBinaryBytes, buffer, 0);
993 position = 0;
994 numSigBytes = 4;
995 }
996 else {
997 return -1;
998 }
999 }
1000
1001
1002 else {
1003 byte[] b4 = new byte[4];
1004 int i = 0;
1005 for (i = 0; i < 4; i++) {
1006
1007 int b = 0;
1008 do {
1009 b = in.read();
1010 } while (b >= 0 && DECODABET[b & 0x7f] <= WHITE_SPACE_ENC);
1011
1012 if (b < 0)
1013 break;
1014
1015 b4[i] = (byte) b;
1016 }
1017
1018 if (i == 4) {
1019 numSigBytes = decode4to3(b4, 0, buffer, 0);
1020 position = 0;
1021 }
1022 else if (i == 0) {
1023 return -1;
1024 }
1025 else {
1026
1027 throw new java.io.IOException("Improperly padded Base64 input.");
1028 }
1029
1030 }
1031 }
1032
1033
1034 if (position >= 0) {
1035
1036 if (
1037 return -1;
1038
1039 if (encode && breakLines && lineLength >= MAX_LINE_LENGTH) {
1040 lineLength = 0;
1041 return '\n';
1042 }
1043 else {
1044 lineLength++;
1045
1046
1047
1048 int b = buffer[position++];
1049
1050 if (position >= bufferLength)
1051 position = -1;
1052
1053 return b & 0xFF;
1054
1055 }
1056 }
1057
1058
1059 else {
1060
1061 throw new java.io.IOException("Error in Base64 code reading stream.");
1062 }
1063 }
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075 public int read(byte[] dest, int off, int len) throws java.io.IOException {
1076 int i;
1077 int b;
1078 for (i = 0; i < len; i++) {
1079 b = read();
1080
1081
1082
1083
1084 if (b >= 0)
1085 dest[off + i] = (byte) b;
1086 else if (i == 0)
1087 return -1;
1088 else
1089 break;
1090 }
1091 return i;
1092 }
1093
1094 }
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105 public static class OutputStream extends java.io.FilterOutputStream {
1106 private boolean encode;
1107
1108 private int position;
1109
1110 private byte[] buffer;
1111
1112 private int bufferLength;
1113
1114 private int lineLength;
1115
1116 private boolean breakLines;
1117
1118 private byte[] b4;
1119
1120 private boolean suspendEncoding;
1121
1122
1123
1124
1125
1126
1127
1128 public OutputStream(java.io.OutputStream out) {
1129 this(out, ENCODE);
1130 }
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154 public OutputStream(java.io.OutputStream out, int options) {
1155 super(out);
1156 this.breakLines = (options & DONT_BREAK_LINES) != DONT_BREAK_LINES;
1157 this.encode = (options & ENCODE) == ENCODE;
1158 this.bufferLength = encode ? 3 : 4;
1159 this.buffer = new byte[bufferLength];
1160 this.position = 0;
1161 this.lineLength = 0;
1162 this.suspendEncoding = false;
1163 this.b4 = new byte[4];
1164 }
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174 public void write(int theByte) throws java.io.IOException {
1175
1176 if (suspendEncoding) {
1177 super.out.write(theByte);
1178 return;
1179 }
1180
1181
1182 if (encode) {
1183 buffer[position++] = (byte) theByte;
1184 if (position >= bufferLength) {
1185 out.write(encode3to4(b4, buffer, bufferLength));
1186
1187 lineLength += 4;
1188 if (breakLines && lineLength >= MAX_LINE_LENGTH) {
1189 out.write(NEW_LINE);
1190 lineLength = 0;
1191 }
1192
1193 position = 0;
1194 }
1195 }
1196
1197
1198 else {
1199
1200 if (DECODABET[theByte & 0x7f] > WHITE_SPACE_ENC) {
1201 buffer[position++] = (byte) theByte;
1202 if (position >= bufferLength) {
1203 int len = Base64.decode4to3(buffer, 0, b4, 0);
1204 out.write(b4, 0, len);
1205
1206 position = 0;
1207 }
1208 }
1209 else if (DECODABET[theByte & 0x7f] != WHITE_SPACE_ENC) {
1210 throw new java.io.IOException("Invalid character in Base64 data.");
1211 }
1212 }
1213 }
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223 public void write(byte[] theBytes, int off, int len) throws java.io.IOException {
1224
1225 if (suspendEncoding) {
1226 super.out.write(theBytes, off, len);
1227 return;
1228 }
1229
1230 for (int i = 0; i < len; i++) {
1231 write(theBytes[off + i]);
1232 }
1233
1234 }
1235
1236
1237
1238
1239 public void flushBase64() throws java.io.IOException {
1240 if (position > 0) {
1241 if (encode) {
1242 out.write(encode3to4(b4, buffer, position));
1243 position = 0;
1244 }
1245 else {
1246 throw new java.io.IOException("Base64 input not properly padded.");
1247 }
1248 }
1249
1250 }
1251
1252
1253
1254
1255
1256
1257 public void close() throws java.io.IOException {
1258
1259 flushBase64();
1260
1261
1262
1263 super.close();
1264
1265 buffer = null;
1266 out = null;
1267 }
1268
1269
1270
1271
1272
1273
1274
1275 public void suspendEncoding() throws java.io.IOException {
1276 flushBase64();
1277 this.suspendEncoding = true;
1278 }
1279
1280
1281
1282
1283
1284
1285
1286 public void resumeEncoding() {
1287 this.suspendEncoding = false;
1288 }
1289
1290 }
1291
1292 }