Proyectos de Subversion Android Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
package com.cesams.twogetskills.library;/*
2
* Base64.java
3
* Created by Walczak on Sep 8, 2005.
4
*
5
* Licence (BSD):
6
* ==============
7
*
8
* Copyright (c) 2005, Andrzej Walczak, University of Hamburg
9
* All rights reserved.
10
*
11
* Redistribution and use in source and binary forms, with or without modification,
12
* are permitted provided that the following conditions are met:
13
* Redistributions of source code must retain the above copyright notice, this list
14
* of conditions and the following disclaimer.
15
* Redistributions in binary form must reproduce the above copyright notice, this
16
* list of conditions and the following disclaimer in the documentation and/or other
17
* materials provided with the distribution.
18
* Neither the name of the University of Hamburg nor the names of its contributors may be
19
* used to endorse or promote products derived from this software without specific
20
* prior written permission.
21
*
22
* this SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
23
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24
* WARRANTIES OF MERCHANTABILITY AND FITNESS for A PARTICULAR PURPOSE ARE DISCLAIMED.
25
* in NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE for ANY DIRECT,
26
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
28
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
* WHETHER in CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
* ARISING IN ANY WAY OUT OF THE USE OF this SOFTWARE, EVEN if ADVISED OF THE POSSIBILITY
31
* OF SUCH DAMAGE.
32
*
33
*/
34
 
35
 
36
/**
37
 * Base64 <br>
38
 * Contains lots of utilities for coding and decoding text and character arrays
39
 * fore and back to the Base64 encoding. It is quite the fastest that I know.
40
 *
41
 * @author Walczak
42
 * @since Sep 8, 2005
43
 * @version 1.1
44
 */
45
 
46
public final class Base64 {
47
    // ------------------------ ENCODER --------------------
48
    /**
49
     * This is a wrapper to
50
     * <code>toCharArray(final byte[] text, final int from, final int len)</code>
51
     *
52
     * @param text
53
     * @return an encoded char array from the text
54
     */
55
    public final static char[] toCharArray(final byte[] text) {
56
        return toCharArray(text, 0, text.length);
57
    }
58
 
59
    /**
60
     * This will encode the text without line feeds added
61
     *
62
     * @param text
63
     * @param from
64
     *            where to start
65
     * @param len
66
     *            how long is the byte array
67
     * @return an encoded char array from the text
68
     */
69
    public final static char[] toCharArray(final byte[] text, final int from,
70
            final int len) {
71
        final char[] code;
72
        int bi = from + len;
73
        int ci = (len / 3) << 2;
74
        int i;
75
        switch (len % 3) { // length of padding
76
        case 1:
77
            ci += 4;
78
            code = new char[ci];
79
            i = text[--bi] << 4;
80
            code[--ci] = '=';
81
            code[--ci] = '=';
82
            code[--ci] = C[i & 0x3F];
83
            code[--ci] = C[(i >>> 6) & 0x3F];
84
            break;
85
        case 2:
86
            ci += 4;
87
            code = new char[ci];
88
            i = (text[--bi] & 0xFF) << 2 | text[--bi] << 10;
89
            code[--ci] = '=';
90
            code[--ci] = C[i & 0x3F];
91
            code[--ci] = C[(i >>> 6) & 0x3F];
92
            code[--ci] = C[(i >>> 12) & 0x3F];
93
            break;
94
        default: // 0
95
            code = new char[ci];
96
        }
97
 
98
        while (ci > 00) {
99
            i = (text[--bi] & 0xFF) | (text[--bi] & 0xFF) << 8
100
                    | text[--bi] << 16;
101
            code[--ci] = C[i & 0x3F];
102
            code[--ci] = C[(i >>> 6) & 0x3F];
103
            code[--ci] = C[(i >>> 12) & 0x3F];
104
            code[--ci] = C[(i >>> 18) & 0x3F];
105
        }
106
        return code;
107
    }
108
 
109
    /**
110
     * @param text
111
     * @return encoded text
112
     */
113
    public final static byte[] encode(final byte[] text) {
114
        return encode(text, 0, text.length);
115
    }
116
 
117
    /**
118
     * This will encode the text without line feeds added
119
     *
120
     * @param text
121
     * @param from
122
     *            where to start
123
     * @param len
124
     *            how long is the byte array
125
     * @return an encoded byte array from the text
126
     */
127
    public final static byte[] encode(final byte[] text, final int from,
128
            final int len) {
129
        final byte[] code;
130
        int bi = from + len;
131
        int ci = (len / 3) << 2;
132
        int i;
133
        switch (len % 3) { // length of padding
134
        case 1:
135
            ci += 4;
136
            code = new byte[ci];
137
            i = text[--bi] << 4;
138
            code[--ci] = '=';
139
            code[--ci] = '=';
140
            code[--ci] = B[i & 0x3F];
141
            code[--ci] = B[(i >>> 6) & 0x3F];
142
            break;
143
        case 2:
144
            ci += 4;
145
            code = new byte[ci];
146
            i = (text[--bi] & 0xFF) << 2 | text[--bi] << 10;
147
            code[--ci] = '=';
148
            code[--ci] = B[i & 0x3F];
149
            code[--ci] = B[(i >>> 6) & 0x3F];
150
            code[--ci] = B[(i >>> 12) & 0x3F];
151
            break;
152
        default: // 0
153
            code = new byte[ci];
154
        }
155
 
156
        while (ci > 00) {
157
            i = (text[--bi] & 0xFF) | (text[--bi] & 0xFF) << 8
158
                    | text[--bi] << 16;
159
            code[--ci] = B[i & 0x3F];
160
            code[--ci] = B[(i >>> 6) & 0x3F];
161
            code[--ci] = B[(i >>> 12) & 0x3F];
162
            code[--ci] = B[(i >>> 18) & 0x3F];
163
        }
164
        return code;
165
    }
166
 
167
    /**
168
     * This will encode the text without line feeds added. It will write all
169
     * output to the dest buffer begining from dstart. <br>
170
     * Both src and dest may be the same provided (sstart <=dstart).
171
     *
172
     * @param src
173
     * @param sstart
174
     *            where to start
175
     * @param len
176
     *            how long is the byte array
177
     * @param dest
178
     * @param dstart
179
     * @return index to the buffer byte ofter the text
180
     */
181
 
182
    public final static int encode(final byte[] src, final int sstart,
183
            final int len, final byte[] dest, final int dstart) {
184
        int bi = sstart + len;
185
        int ci = ((len / 3) << 2) + dstart;
186
        int dend;
187
        int i;
188
        switch (len % 3) { // length of padding
189
        case 1:
190
            ci += 4;
191
            dend = ci;
192
            i = src[--bi] << 4;
193
            dest[--ci] = '=';
194
            dest[--ci] = '=';
195
            dest[--ci] = B[i & 0x3F];
196
            dest[--ci] = B[(i >>> 6) & 0x3F];
197
            break;
198
        case 2:
199
            ci += 4;
200
            dend = ci;
201
            i = (src[--bi] & 0xFF) << 2 | src[--bi] << 10;
202
            dest[--ci] = '=';
203
            dest[--ci] = B[i & 0x3F];
204
            dest[--ci] = B[(i >>> 6) & 0x3F];
205
            dest[--ci] = B[(i >>> 12) & 0x3F];
206
            break;
207
        default:
208
            dend = ci;
209
        }
210
 
211
        while (ci > dstart) {
212
            i = (src[--bi] & 0xFF) | (src[--bi] & 0xFF) << 8 | src[--bi] << 16;
213
            dest[--ci] = B[i & 0x3F];
214
            dest[--ci] = B[(i >>> 6) & 0x3F];
215
            dest[--ci] = B[(i >>> 12) & 0x3F];
216
            dest[--ci] = B[(i >>> 18) & 0x3F];
217
        }
218
        return dend;
219
    }
220
 
221
    /**
222
     * This will encode the text. The CRLF comes after <code>lb</code>
223
     * characters.
224
     *
225
     * @param text
226
     * @param llen
227
     *            the length of line (without CRLF) must be a multiple of 4
228
     * @return an encoded char array from the text
229
     */
230
    public final static char[] toCharArray(final byte[] text, final int llen) {
231
        final char[] code;
232
        int bi = text.length;
233
        int ci = (bi / 3) << 2;
234
        int i;
235
        //@goal determine padding
236
        switch (bi % 3) { // length of padding
237
        case 1: // @goal pad two text
238
            ci += 4;
239
            ci += (ci / llen) << 1;
240
            code = new char[ci];
241
 
242
            if (ci % llen == 4) {
243
                code[--ci] = '\n';
244
                code[--ci] = '\r';
245
            }
246
            i = text[--bi] << 4;
247
            code[--ci] = '=';
248
            code[--ci] = '=';
249
            code[--ci] = C[i & 0x3F];
250
            code[--ci] = C[(i >>> 6) & 0x3F];
251
            break;
252
        case 2: // @goal pad one byte
253
            ci += 4;
254
            ci += (ci / llen) << 1;
255
            code = new char[ci];
256
 
257
            if (ci % llen == 4) {
258
                code[--ci] = '\n';
259
                code[--ci] = '\r';
260
            }
261
            i = (text[--bi] & 0xFF) << 2 | text[--bi] << 10;
262
            code[--ci] = '=';
263
            code[--ci] = C[i & 0x3F];
264
            code[--ci] = C[(i >>> 6) & 0x3F];
265
            code[--ci] = C[(i >>> 12) & 0x3F];
266
            break;
267
        default: // 0
268
            ci += (ci / llen) << 1;
269
            code = new char[ci];
270
        }
271
        //@goal calculate the line breaking constant and variable
272
        int lmax = (llen >>> 2) - 1; // will break after this many quadruples
273
        int li = (ci % (llen + 2)) >>> 2; // initialize the counter
274
 
275
        while (bi > 00) {
276
 
277
            if (li > 0) {
278
                --li;
279
 
280
            } else {
281
                code[--ci] = '\n';
282
                code[--ci] = '\r';
283
                li = lmax;
284
            }
285
            i = (text[--bi] & 0xFF) | (text[--bi] & 0xFF) << 8
286
                    | text[--bi] << 16;
287
            code[--ci] = C[i & 0x3F];
288
            code[--ci] = C[(i >>> 6) & 0x3F];
289
            code[--ci] = C[(i >>> 12) & 0x3F];
290
            code[--ci] = C[(i >>> 18) & 0x3F];
291
        }
292
        return code;
293
    }
294
 
295
    /**
296
     * This will encode the text. The CRLF comes after <code>lb</code>
297
     * characters.
298
     *
299
     * @param text
300
     * @param llen
301
     *            the length of line (without CRLF) must be a multiple of 4
302
     * @return an encoded byte array from the text
303
     */
304
 
305
    public final static byte[] encode(final byte[] text, final int llen) {
306
        final byte[] code;
307
        int bi = text.length;
308
        int ci = (bi / 3) << 2;
309
        int i;
310
        //@goal determine padding
311
        switch (bi % 3) { // length of padding
312
        case 1: // @goal pad two text
313
            ci += 4;
314
            ci += (ci / llen) << 1;
315
            code = new byte[ci];
316
 
317
            if (ci % llen == 4) {
318
                code[--ci] = '\n';
319
                code[--ci] = '\r';
320
            }
321
            i = text[--bi] << 4;
322
            code[--ci] = '=';
323
            code[--ci] = '=';
324
            code[--ci] = B[i & 0x3F];
325
            code[--ci] = B[(i >>> 6) & 0x3F];
326
            break;
327
        case 2: // @goal pad one byte
328
            ci += 4;
329
            ci += (ci / llen) << 1;
330
            code = new byte[ci];
331
 
332
            if (ci % llen == 4) {
333
                code[--ci] = '\n';
334
                code[--ci] = '\r';
335
            }
336
            i = (text[--bi] & 0xFF) << 2 | text[--bi] << 10;
337
            code[--ci] = '=';
338
            code[--ci] = B[i & 0x3F];
339
            code[--ci] = B[(i >>> 6) & 0x3F];
340
            code[--ci] = B[(i >>> 12) & 0x3F];
341
            break;
342
        default: // 0
343
            ci += (ci / llen) << 1;
344
            code = new byte[ci];
345
        }
346
        //@goal calculate the line breaking constant and variable
347
        int lmax = (llen >>> 2) - 1; // will break after this many quadruples
348
        int li = (ci % (llen + 2)) >>> 2; // initialize the counter
349
 
350
        while (ci > 00) {
351
 
352
            if (li > 0) {
353
                --li;
354
 
355
            } else {
356
                code[--ci] = '\n';
357
                code[--ci] = '\r';
358
                li = lmax;
359
            }
360
            i = (text[--bi] & 0xFF) | (text[--bi] & 0xFF) << 8
361
                    | text[--bi] << 16;
362
            code[--ci] = B[i & 0x3F];
363
            code[--ci] = B[(i >>> 6) & 0x3F];
364
            code[--ci] = B[(i >>> 12) & 0x3F];
365
            code[--ci] = B[(i >>> 18) & 0x3F];
366
        }
367
        return code;
368
    }
369
 
370
    //###################### DECODER #####################################
371
    /**
372
     * This is a wrapper to
373
     * <code>decode(final char[] code, final int from, final int len)</code>
374
     *
375
     * @param code
376
     * @return a byte array holding encoded char data
377
     */
378
    public final static byte[] decode(final char[] code) {
379
        return decode(code, 0, code.length);
380
    }
381
 
382
    /**
383
     * This will decode base64 data without line feeds. The char array should be
384
     * multiple of 4 in length.
385
     *
386
     * @param code
387
     * @param from
388
     *            start position in code
389
     * @param len
390
     *            length of the part
391
     * @return the decoded sequence of text
392
     */
393
    public final static byte[] decode(final char[] code, final int from,
394
            final int len) {
395
        int bi = (len >>> 2) * 3;
396
        int ci = from + len;
397
        int i;
398
        final byte[] text;
399
 
400
        if (code[ci - 1] == '=') {
401
            if (code[ci - 2] == '=') { // padding 2
402
                ci -= 3;
403
                bi -= 2;
404
                text = new byte[bi];
405
                text[--bi] = (byte) ((I[code[ci]] | I[code[--ci]] << 6) >> 4);
406
            } else { // padding 1
407
                ci -= 2;
408
                --bi;
409
                text = new byte[bi];
410
                i = I[code[ci]] | I[code[--ci]] << 6 | I[code[--ci]] << 12;
411
                text[--bi] = (byte) (i >>> 2);
412
                text[--bi] = (byte) (i >>> 10);
413
            }
414
 
415
        } else {
416
            text = new byte[bi];
417
        }
418
 
419
        while (bi > 00) {
420
            i = I[code[--ci]] | I[code[--ci]] << 6 | I[code[--ci]] << 12
421
                    | I[code[--ci]] << 18;
422
            text[--bi] = (byte) (i);
423
            text[--bi] = (byte) (i >>> 8);
424
            text[--bi] = (byte) (i >>> 16);
425
        }
426
        return text;
427
    }
428
 
429
    /**
430
     * This is a wrapper to
431
     * <code>decode(final byte[] code, final int from, final int len)</code>
432
     *
433
     * @param code
434
     * @return a byte array holding encoded char data
435
     */
436
    public final static byte[] decode(final byte[] code) {
437
        return decode(code, 0, code.length);
438
    }
439
 
440
    /**
441
     * a copy of the char part
442
     *
443
     * @param src
444
     * @param from
445
     * @param len
446
     * @return decoded byte array
447
     */
448
    public final static byte[] decode(final byte[] src, final int from,
449
            final int len) {
450
        int bi = (len >>> 2) * 3;
451
        int ci = from + len;
452
        int i;
453
        final byte[] text;
454
 
455
        if (src[ci - 1] == '=') {
456
            if (src[ci - 2] == '=') { // padding 2
457
                ci -= 3;
458
                bi -= 2;
459
                text = new byte[bi];
460
                text[--bi] = (byte) ((I[src[ci]] | I[src[--ci]] << 6) >> 4);
461
            } else { // padding 1
462
                ci -= 2;
463
                --bi;
464
                text = new byte[bi];
465
                i = I[src[ci]] | I[src[--ci]] << 6 | I[src[--ci]] << 12;
466
                text[--bi] = (byte) (i >>> 2);
467
                text[--bi] = (byte) (i >>> 10);
468
            }
469
 
470
        } else {
471
            text = new byte[bi];
472
        }
473
 
474
        while (bi > 00) {
475
            i = I[src[--ci]] | I[src[--ci]] << 6 | I[src[--ci]] << 12
476
                    | I[src[--ci]] << 18;
477
            text[--bi] = (byte) (i);
478
            text[--bi] = (byte) (i >>> 8);
479
            text[--bi] = (byte) (i >>> 16);
480
        }
481
        return text;
482
    }
483
 
484
    /**
485
     * <code>decodeCRLF(code, 0, code.length, 76)</code>
486
     *
487
     * @param code
488
     * @return the encoded text;
489
     */
490
    public final static byte[] decode76(final char[] code) {
491
        return decodeCRLF(code, 0, code.length, 76);
492
    }
493
 
494
    /**
495
     * This will decode base64 data. The starting point and length must be
496
     * accurate. The data must end on a multiple of 4 boundary and must include
497
     * the '=' padding, if any.
498
     *
499
     * @param code
500
     * @param from
501
     * @param len
502
     *            the length of data
503
     * @param llen
504
     *            the line length of this base64 (without CRLF)
505
     * @return the decoded sequence of text
506
     */
507
    public final static byte[] decodeCRLF(final char[] code, final int from,
508
            final int len, final int llen) {
509
        int bi = ((len - ((len / (llen + 2)) << 1)) >>> 2) * 3;
510
        int ci = from + len;
511
        int lmax = (llen >>> 2);
512
        int li = (ci % (llen + 2)) >>> 2;
513
        int i;
514
        if (li == 0) { // skip crlf
515
            ci -= 2;
516
            li = lmax;
517
        }
518
        final byte[] text;
519
 
520
        if (code[ci - 1] == '=') {
521
            if (code[ci - 2] == '=') { // padding 2
522
                ci -= 3;
523
                bi -= 2;
524
                text = new byte[bi];
525
                text[--bi] = (byte) ((I[code[ci]] | I[code[--ci]] << 6) >> 4);
526
                --li;
527
            } else { // padding 1
528
                ci -= 2;
529
                --bi;
530
                text = new byte[bi];
531
                i = I[code[ci]] | I[code[--ci]] << 6 | I[code[--ci]] << 12;
532
                text[--bi] = (byte) (i >>> 2);
533
                text[--bi] = (byte) (i >>> 10);
534
                --li;
535
            }
536
 
537
        } else {
538
            text = new byte[bi];
539
        }
540
 
541
        while (bi > 00) {
542
 
543
            if (li == 0) {
544
                ci -= 2;
545
                li = lmax;
546
            }
547
            i = I[code[--ci]] | I[code[--ci]] << 6 | I[code[--ci]] << 12
548
                    | I[code[--ci]] << 18;
549
            text[--bi] = (byte) (i);
550
            text[--bi] = (byte) (i >>> 8);
551
            text[--bi] = (byte) (i >>> 16);
552
            --li;
553
        }
554
        return text;
555
    }
556
 
557
    /**
558
     * This will decode base64 data with CRLF at 4 character boundary. <br>
559
     * The sequence may look like:
560
     * <p>
561
     * ABCDABCD\r\nABCDABCD or even ABCDABCD#####ABCD###ABCD#ABCD.
562
     * </p>
563
     * <p>
564
     * The array must be multiple of 4 + number of CRLF or illegal characters
565
     * and the line length may vary.
566
     * </p>
567
     *
568
     * @param code
569
     * @param from
570
     * @param len
571
     * @return the decoded sequence of text
572
     */
573
    public final static byte[] decodeCRLF(final char[] code, final int from,
574
            final int len) {
575
        int bi = len;
576
        int ci = from + len;
577
        int i;
578
        //@goal determine the number of valid code
579
 
580
        while (ci > from) {
581
            if (I[code[--ci]] < 0)
582
                --bi;
583
        }
584
        //@goal allocate byte array
585
        bi = (bi >>> 2) * 3;
586
        final byte[] text = new byte[bi];
587
        //@goal decode the sequence
588
        ci = from + len;
589
 
590
        while (bi > 00) {
591
            do
592
                i = I[code[--ci]]; // look ahead
593
            while (i < 0);
594
            i |= I[code[--ci]] << 6 | I[code[--ci]] << 12 | I[code[--ci]] << 18;
595
            text[--bi] = (byte) (i);
596
            text[--bi] = (byte) (i >>> 8);
597
            text[--bi] = (byte) (i >>> 16);
598
        }
599
        return text;
600
    }
601
 
602
    /**
603
     * @param code
604
     * @return the decoded array
605
     */
606
    public final static byte[] decodeFailSafe(char[] code) {
607
        return decodeFailSafe(code, 0, code.length);
608
    }
609
 
610
    /**
611
     * This removes all bad characters from the char array. It modifies the
612
     * array in the scope of the process !!! Than simply calls decode;
613
     *
614
     * @param code
615
     * @param from
616
     * @param len
617
     * @return decoded text
618
     */
619
    public final static byte[] decodeFailSafe(final char[] code,
620
            final int from, final int len) {
621
        char c;
622
        int ci = from;
623
        int cj = from;
624
        int ce = from + len;
625
 
626
        while (ci < ce) {
627
            c = code[ci];
628
            if (c == '=')
629
                break;
630
 
631
            try {
632
                if (I[c] >= 0)
633
                    code[cj++] = c;
634
            } catch (Exception e) {/**/
635
            }
636
            ci++;
637
        }
638
 
639
        switch (((cj - from) & 0x3)) {
640
        case 1:
641
            code[cj++] = C[0];
642
        case 2:
643
            code[cj++] = '=';
644
        case 3:
645
            code[cj++] = '=';
646
        default:
647
        }
648
        return decode(code, from, cj - from);
649
    }
650
 
651
    //------------------ static fields -------------------
652
 
653
    private static final byte[] B = new byte[] {
654
            65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
655
            81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99,100,101,102,
656
           103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,
657
           119,120,121,122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47, };
658
 
659
      private static final char[] C = new char[] {
660
           'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
661
           'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
662
           'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
663
           'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/', };
664
 
665
      private static final int[]  I = new int[] {
666
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
667
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
668
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
669
            52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1,  0, -1, -1,
670
            -1,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
671
            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
672
            -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
673
            41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, };
674
}