Source Code Cross Referenced for Base64.java in  » Template-Engine » ostermillerutils » com » Ostermiller » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Template Engine » ostermillerutils » com.Ostermiller.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (C) 2001-2007 Stephen Ostermiller
0003:         * http://ostermiller.org/contact.pl?regarding=Java+Utilities
0004:         *
0005:         * This program is free software; you can redistribute it and/or modify
0006:         * it under the terms of the GNU General Public License as published by
0007:         * the Free Software Foundation; either version 2 of the License, or
0008:         * (at your option) any later version.
0009:         *
0010:         * This program is distributed in the hope that it will be useful,
0011:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013:         * GNU General Public License for more details.
0014:         *
0015:         * See COPYING.TXT for details.
0016:         */
0017:        package com.Ostermiller.util;
0018:
0019:        import java.io.*;
0020:        import java.text.MessageFormat;
0021:        import java.util.ResourceBundle;
0022:        import java.util.Locale;
0023:
0024:        /**
0025:         * Implements Base64 encoding and decoding as defined by RFC 2045: "Multi-purpose Internet
0026:         * Mail Extensions (MIME) Part One: Format of Internet Message Bodies" page 23.
0027:         * More information about this class is available from <a target="_top" href=
0028:         * "http://ostermiller.org/utils/Base64.html">ostermiller.org</a>.
0029:         *
0030:         * <blockquote>
0031:         * <p>The Base64 Content-Transfer-Encoding is designed to represent
0032:         * arbitrary sequences of octets in a form that need not be humanly
0033:         * readable.  The encoding and decoding algorithms are simple, but the
0034:         * encoded data are consistently only about 33 percent larger than the
0035:         * unencoded data.  This encoding is virtually identical to the one used
0036:         * in Privacy Enhanced Mail (PEM) applications, as defined in RFC 1421.</p>
0037:         *
0038:         * <p>A 65-character subset of US-ASCII is used, enabling 6 bits to be
0039:         * represented per printable character. (The extra 65th character, "=",
0040:         * is used to signify a special processing function.)</p>
0041:         *
0042:         * <p>NOTE:  This subset has the important property that it is represented
0043:         * identically in all versions of ISO 646, including US-ASCII, and all
0044:         * characters in the subset are also represented identically in all
0045:         * versions of EBCDIC. Other popular encodings, such as the encoding
0046:         * used by the uuencode utility, MacIntosh binhex 4.0 [RFC-1741], and
0047:         * the base85 encoding specified as part of Level 2 PostScript, do no
0048:         * share these properties, and thus do not fulfill the portability
0049:         * requirements a binary transport encoding for mail must meet.</p>
0050:         *
0051:         * <p>The encoding process represents 24-bit groups of input bits as output
0052:         * strings of 4 encoded characters.  Proceeding from left to right, a
0053:         * 24-bit input group is formed by concatenating 3 8bit input groups.
0054:         * These 24 bits are then treated as 4 concatenated 6-bit groups, each
0055:         * of which is translated into a single digit in the base64 alphabet.
0056:         * When encoding a bit stream via the base64 encoding, the bit stream
0057:         * must be presumed to be ordered with the most-significant-bit first.
0058:         * That is, the first bit in the stream will be the high-order bit in
0059:         * the first 8bit byte, and the eighth bit will be the low-order bit in
0060:         * the first 8bit byte, and so on.</p>
0061:         *
0062:         * <p>Each 6-bit group is used as an index into an array of 64 printable
0063:         * characters.  The character referenced by the index is placed in the
0064:         * output string.  These characters, identified in Table 1, below, are
0065:         * selected so as to be universally representable, and the set excludes
0066:         * characters with particular significance to SMTP (e.g., ".", CR, LF)
0067:         * and to the multi-part boundary delimiters defined in RFC 2046 (e.g.,
0068:         * "-").</p>
0069:         * <pre>
0070:         *                  Table 1: The Base64 Alphabet
0071:         *
0072:         *   Value Encoding  Value Encoding  Value Encoding  Value Encoding
0073:         *       0 A            17 R            34 i            51 z
0074:         *       1 B            18 S            35 j            52 0
0075:         *       2 C            19 T            36 k            53 1
0076:         *       3 D            20 U            37 l            54 2
0077:         *       4 E            21 V            38 m            55 3
0078:         *       5 F            22 W            39 n            56 4
0079:         *       6 G            23 X            40 o            57 5
0080:         *       7 H            24 Y            41 p            58 6
0081:         *       8 I            25 Z            42 q            59 7
0082:         *       9 J            26 a            43 r            60 8
0083:         *      10 K            27 b            44 s            61 9
0084:         *      11 L            28 c            45 t            62 +
0085:         *      12 M            29 d            46 u            63 /
0086:         *      13 N            30 e            47 v
0087:         *      14 O            31 f            48 w         (pad) =
0088:         *      15 P            32 g            49 x
0089:         *      16 Q            33 h            50 y
0090:         * </pre>
0091:         * <p>The encoded output stream must be represented in lines of no more
0092:         * than 76 characters each.  All line breaks or other characters no
0093:         * found in Table 1 must be ignored by decoding software.  In base64
0094:         * data, characters other than those in Table 1, line breaks, and other
0095:         * white space probably indicate a transmission error, about which a
0096:         * warning message or even a message rejection might be appropriate
0097:         * under some circumstances.</p>
0098:         *
0099:         * <p>Special processing is performed if fewer than 24 bits are available
0100:         * at the end of the data being encoded.  A full encoding quantum is
0101:         * always completed at the end of a body.  When fewer than 24 input bits
0102:         * are available in an input group, zero bits are added (on the right)
0103:         * to form an integral number of 6-bit groups.  Padding at the end of
0104:         * the data is performed using the "=" character.  Since all base64
0105:         * input is an integral number of octets, only the following cases can
0106:         * arise: (1) the final quantum of encoding input is an integral
0107:         * multiple of 24 bits; here, the final unit of encoded output will be
0108:         * an integral multiple of 4 characters with no "=" padding, (2) the
0109:         * final quantum of encoding input is exactly 8 bits; here, the final
0110:         * unit of encoded output will be two characters followed by two "="
0111:         * padding characters, or (3) the final quantum of encoding input is
0112:         * exactly 16 bits; here, the final unit of encoded output will be three
0113:         * characters followed by one "=" padding character.</p>
0114:         *
0115:         * <p>Because it is used only for padding at the end of the data, the
0116:         * occurrence of any "=" characters may be taken as evidence that the
0117:         * end of the data has been reached (without truncation in transit).  No
0118:         * such assurance is possible, however, when the number of octets
0119:         * transmitted was a multiple of three and no "=" characters are
0120:         * present.</p>
0121:         *
0122:         * <p>Any characters outside of the base64 alphabet are to be ignored in
0123:         * base64-encoded data.</p>
0124:         *
0125:         * <p>Care must be taken to use the proper octets for line breaks if base64
0126:         * encoding is applied directly to text material that has not been
0127:         * converted to canonical form.  In particular, text line breaks must be
0128:         * converted into CRLF sequences prior to base64 encoding.  The
0129:         * important thing to note is that this may be done directly by the
0130:         * encoder rather than in a prior canonicalization step in some
0131:         * implementations.</p>
0132:         *
0133:         * <p>NOTE: There is no need to worry about quoting potential boundary
0134:         * delimiters within base64-encoded bodies within multi-part entities
0135:         * because no hyphen characters are used in the base64 encoding.</p>
0136:         * </blockquote>
0137:         *
0138:         * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
0139:         * @since ostermillerutils 1.00.00
0140:         */
0141:        public class Base64 {
0142:
0143:            /**
0144:             * Symbol that represents the end of an input stream
0145:             *
0146:             * @since ostermillerutils 1.00.00
0147:             */
0148:            private static final int END_OF_INPUT = -1;
0149:
0150:            /**
0151:             * A character that is not a valid base 64 character.
0152:             *
0153:             * @since ostermillerutils 1.00.00
0154:             */
0155:            private static final int NON_BASE_64 = -1;
0156:
0157:            /**
0158:             * A character that is not a valid base 64 character.
0159:             *
0160:             * @since ostermillerutils 1.00.00
0161:             */
0162:            private static final int NON_BASE_64_WHITESPACE = -2;
0163:
0164:            /**
0165:             * A character that is not a valid base 64 character.
0166:             *
0167:             * @since ostermillerutils 1.00.00
0168:             */
0169:            private static final int NON_BASE_64_PADDING = -3;
0170:
0171:            /**
0172:             * This class need not be instantiated, all methods are static.
0173:             *
0174:             * @since ostermillerutils 1.00.00
0175:             */
0176:            private Base64() {
0177:                // should not be called
0178:            }
0179:
0180:            /**
0181:             * Table of the sixty-four characters that are used as
0182:             * the Base64 alphabet: [a-z0-9A-Z+/]
0183:             *
0184:             * @since ostermillerutils 1.00.00
0185:             */
0186:            protected static final byte[] base64Chars = { 'A', 'B', 'C', 'D',
0187:                    'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
0188:                    'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
0189:                    'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
0190:                    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
0191:                    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', };
0192:
0193:            /**
0194:             * Reverse lookup table for the Base64 alphabet.
0195:             * reversebase64Chars[byte] gives n for the nth Base64
0196:             * character or negative if a character is not a Base64 character.
0197:             *
0198:             * @since ostermillerutils 1.00.00
0199:             */
0200:            protected static final byte[] reverseBase64Chars = new byte[0x100];
0201:            static {
0202:                // Fill in NON_BASE_64 for all characters to start with
0203:                for (int i = 0; i < reverseBase64Chars.length; i++) {
0204:                    reverseBase64Chars[i] = NON_BASE_64;
0205:                }
0206:                // For characters that are base64Chars, adjust
0207:                // the reverse lookup table.
0208:                for (byte i = 0; i < base64Chars.length; i++) {
0209:                    reverseBase64Chars[base64Chars[i]] = i;
0210:                }
0211:                reverseBase64Chars[' '] = NON_BASE_64_WHITESPACE;
0212:                reverseBase64Chars['\n'] = NON_BASE_64_WHITESPACE;
0213:                reverseBase64Chars['\r'] = NON_BASE_64_WHITESPACE;
0214:                reverseBase64Chars['\t'] = NON_BASE_64_WHITESPACE;
0215:                reverseBase64Chars['\f'] = NON_BASE_64_WHITESPACE;
0216:                reverseBase64Chars['='] = NON_BASE_64_PADDING;
0217:            }
0218:
0219:            /**
0220:             * Version number of this program
0221:             *
0222:             * @since ostermillerutils 1.00.00
0223:             */
0224:            public static final String version = "1.2";
0225:
0226:            /**
0227:             * Locale specific strings displayed to the user.
0228:             *
0229:             * @since ostermillerutils 1.00.00
0230:             */
0231:            protected static ResourceBundle labels = ResourceBundle.getBundle(
0232:                    "com.Ostermiller.util.Base64", Locale.getDefault());
0233:
0234:            private static final int ACTION_GUESS = 0;
0235:            private static final int ACTION_ENCODE = 1;
0236:            private static final int ACTION_DECODE = 2;
0237:
0238:            private static final int ARGUMENT_GUESS = 0;
0239:            private static final int ARGUMENT_STRING = 1;
0240:            private static final int ARGUMENT_FILE = 2;
0241:
0242:            private enum Base64CmdLnOption {
0243:                /** --help */
0244:                HELP(new CmdLnOption(labels.getString("help.option"))
0245:                        .setDescription(labels.getString("help.message"))),
0246:                /** --version */
0247:                VERSION(new CmdLnOption(labels.getString("version.option"))
0248:                        .setDescription(labels.getString("version.message"))),
0249:                /** --about */
0250:                ABOUT(new CmdLnOption(labels.getString("about.option"))
0251:                        .setDescription(labels.getString("about.message"))),
0252:                /** --guess */
0253:                GUESS(new CmdLnOption(labels.getString("guess.option"), 'g')
0254:                        .setDescription(labels.getString("g.message") + " ("
0255:                                + labels.getString("default") + ")")),
0256:                /** --encode */
0257:                ENCODE(new CmdLnOption(labels.getString("encode.option"), 'e')
0258:                        .setDescription(labels.getString("e.message"))),
0259:                /** --lines */
0260:                LINES(new CmdLnOption(labels.getString("lines.option"), 'l')
0261:                        .setDescription(labels.getString("l.message") + " ("
0262:                                + labels.getString("default") + ")")),
0263:                /** --nolines */
0264:                NOLINES(new CmdLnOption(labels.getString("nolines.option"))
0265:                        .setDescription(labels.getString("nolines.message"))),
0266:                /** --decode */
0267:                DECODE(new CmdLnOption(labels.getString("decode.option"), 'd')
0268:                        .setDescription(labels.getString("d.message"))),
0269:                /** --decodeall */
0270:                DECODEALL(new CmdLnOption(labels.getString("decodeall.option"),
0271:                        'a').setDescription(labels.getString("a.message"))),
0272:                /** --decodegood */
0273:                DECODEGOOD(new CmdLnOption(labels
0274:                        .getString("decodegood.option")).setDescription(labels
0275:                        .getString("decodegood.message")
0276:                        + " (" + labels.getString("default") + ")")),
0277:                /** --ext */
0278:                EXT(new CmdLnOption(labels.getString("ext.option"), 'x')
0279:                        .setOptionalArgument().setDescription(
0280:                                labels.getString("x.message"))),
0281:                /** --force */
0282:                FORCE(new CmdLnOption(labels.getString("force.option"), 'f')
0283:                        .setDescription(labels.getString("f.message"))),
0284:                /** --noforce */
0285:                NOFORCE(new CmdLnOption(labels.getString("noforce.option"))
0286:                        .setDescription(labels.getString("noforce.message")
0287:                                + " (" + labels.getString("default") + ")")),
0288:                /** --verbose */
0289:                VERBOSE(
0290:                        new CmdLnOption(labels.getString("verbose.option"), 'v')
0291:                                .setDescription(labels.getString("v.message")
0292:                                        + " (" + labels.getString("default")
0293:                                        + ")")),
0294:                /** --quiet */
0295:                QUIET(new CmdLnOption(labels.getString("quiet.option"), 'q')
0296:                        .setDescription(labels.getString("q.message"))),
0297:                /** --reallyquiet */
0298:                REALLYQUIET(new CmdLnOption(labels
0299:                        .getString("reallyquiet.option"), 'Q')
0300:                        .setDescription(labels.getString("Q.message"))),
0301:                /** --file */
0302:                FILE(new CmdLnOption(labels.getString("file.option"))
0303:                        .setDescription(labels.getString("file.message"))),
0304:                /** --string */
0305:                STRING(new CmdLnOption(labels.getString("string.option"))
0306:                        .setDescription(labels.getString("string.message"))),
0307:                /** --endline */
0308:                ENDLINE(
0309:                        new CmdLnOption(labels.getString("newline.option"), 'n')
0310:                                .setDescription(labels
0311:                                        .getString("newline.message"))),
0312:                /** --noendline */
0313:                NOENDLINE(new CmdLnOption(labels.getString("nonewline.option"))
0314:                        .setDescription(labels.getString("nonewline.message")));
0315:
0316:                private CmdLnOption option;
0317:
0318:                private Base64CmdLnOption(CmdLnOption option) {
0319:                    option.setUserObject(this );
0320:                    this .option = option;
0321:                }
0322:
0323:                private CmdLnOption getCmdLineOption() {
0324:                    return option;
0325:                }
0326:            }
0327:
0328:            /**
0329:             * Converts the line ending on files, or standard input.
0330:             * Run with --help argument for more information.
0331:             *
0332:             * @param args Command line arguments.
0333:             *
0334:             * @since ostermillerutils 1.00.00
0335:             */
0336:            public static void main(String[] args) {
0337:                CmdLn commandLine = new CmdLn(args).setDescription(labels
0338:                        .getString("base64")
0339:                        + labels.getString("purpose.message"));
0340:                for (Base64CmdLnOption option : Base64CmdLnOption.values()) {
0341:                    commandLine.addOption(option.getCmdLineOption());
0342:                }
0343:                int action = ACTION_GUESS;
0344:                String extension = "base64";
0345:                boolean force = false;
0346:                boolean printMessages = true;
0347:                boolean printErrors = true;
0348:                boolean forceDecode = false;
0349:                boolean lineBreaks = true;
0350:                int argumentType = ARGUMENT_GUESS;
0351:                boolean decodeEndLine = false;
0352:                for (CmdLnResult result : commandLine.getResults()) {
0353:                    switch ((Base64CmdLnOption) result.getOption()
0354:                            .getUserObject()) {
0355:                    case HELP: {
0356:                        // print out the help message
0357:                        commandLine.printHelp();
0358:                        System.exit(0);
0359:                    }
0360:                        break;
0361:                    case VERSION: {
0362:                        // print out the version message
0363:                        System.out.println(MessageFormat.format(labels
0364:                                .getString("version"),
0365:                                (Object[]) new String[] { version }));
0366:                        System.exit(0);
0367:                    }
0368:                        break;
0369:                    case ABOUT: {
0370:                        System.out
0371:                                .println(labels.getString("base64")
0372:                                        + " -- "
0373:                                        + labels.getString("purpose.message")
0374:                                        + "\n"
0375:                                        + MessageFormat
0376:                                                .format(
0377:                                                        labels
0378:                                                                .getString("copyright"),
0379:                                                        (Object[]) new String[] {
0380:                                                                "2001-2007",
0381:                                                                "Stephen Ostermiller (http://ostermiller.org/contact.pl?regarding=Java+Utilities)" })
0382:                                        + "\n\n" + labels.getString("license"));
0383:                        System.exit(0);
0384:                    }
0385:                        break;
0386:                    case DECODE: {
0387:                        action = ACTION_DECODE;
0388:                    }
0389:                        break;
0390:                    case DECODEALL: {
0391:                        forceDecode = true;
0392:                    }
0393:                        break;
0394:                    case DECODEGOOD: {
0395:                        forceDecode = false;
0396:                    }
0397:                        break;
0398:                    case ENCODE: {
0399:                        action = ACTION_ENCODE;
0400:                    }
0401:                        break;
0402:                    case LINES: {
0403:                        lineBreaks = true;
0404:                    }
0405:                        break;
0406:                    case NOLINES: {
0407:                        lineBreaks = false;
0408:                    }
0409:                        break;
0410:                    case GUESS: {
0411:                        action = ACTION_GUESS;
0412:                    }
0413:                        break;
0414:                    case EXT: {
0415:                        extension = result.getArgument();
0416:                        if (extension == null)
0417:                            extension = "";
0418:                    }
0419:                        break;
0420:                    case FORCE: {
0421:                        force = true;
0422:                    }
0423:                        break;
0424:                    case NOFORCE: {
0425:                        force = false;
0426:                    }
0427:                        break;
0428:                    case VERBOSE: {
0429:                        printMessages = true;
0430:                        printErrors = true;
0431:                    }
0432:                        break;
0433:                    case QUIET: {
0434:                        printMessages = false;
0435:                        printErrors = true;
0436:                    }
0437:                        break;
0438:                    case REALLYQUIET: {
0439:                        printMessages = false;
0440:                        printErrors = false;
0441:                    }
0442:                        break;
0443:                    case FILE: {
0444:                        argumentType = ARGUMENT_FILE;
0445:                    }
0446:                        break;
0447:                    case STRING: {
0448:                        argumentType = ARGUMENT_STRING;
0449:                    }
0450:                        break;
0451:                    case ENDLINE: {
0452:                        decodeEndLine = true;
0453:                    }
0454:                        break;
0455:                    case NOENDLINE: {
0456:                        decodeEndLine = false;
0457:                    }
0458:                        break;
0459:                    }
0460:                }
0461:
0462:                int exitCond = 0;
0463:                boolean done = false;
0464:                for (String argument : commandLine.getNonOptionArguments()) {
0465:                    done = true;
0466:                    File source = new File(argument);
0467:                    if (argumentType == ARGUMENT_STRING
0468:                            || (argumentType == ARGUMENT_GUESS && !source
0469:                                    .exists())) {
0470:                        try {
0471:                            int fileAction = action;
0472:                            if (fileAction == ACTION_GUESS) {
0473:                                if (isBase64(argument)) {
0474:                                    fileAction = ACTION_DECODE;
0475:                                } else {
0476:                                    fileAction = ACTION_ENCODE;
0477:                                }
0478:                            }
0479:                            if (fileAction == ACTION_ENCODE) {
0480:                                if (printMessages) {
0481:                                    System.out.println(labels
0482:                                            .getString("encodingarg"));
0483:                                }
0484:                                encode(new ByteArrayInputStream(argument
0485:                                        .getBytes()), System.out, lineBreaks);
0486:                            } else {
0487:                                if (printMessages) {
0488:                                    System.out.println(labels
0489:                                            .getString("decodingarg"));
0490:                                }
0491:                                decode(new ByteArrayInputStream(argument
0492:                                        .getBytes()), System.out, !forceDecode);
0493:                                if (decodeEndLine)
0494:                                    System.out.println();
0495:                            }
0496:                        } catch (Base64DecodingException x) {
0497:                            if (printErrors) {
0498:                                System.err
0499:                                        .println(argument
0500:                                                + ": "
0501:                                                + x.getMessage()
0502:                                                + " "
0503:                                                + labels
0504:                                                        .getString("unexpectedcharforce"));
0505:                            }
0506:                            exitCond = 1;
0507:                        } catch (IOException x) {
0508:                            if (printErrors) {
0509:                                System.err.println(argument + ": "
0510:                                        + x.getMessage());
0511:                            }
0512:                            exitCond = 1;
0513:                        }
0514:                    } else if (!source.exists()) {
0515:                        if (printErrors) {
0516:                            System.err.println(MessageFormat.format(labels
0517:                                    .getString("doesnotexist"),
0518:                                    (Object[]) new String[] { argument }));
0519:                        }
0520:                        exitCond = 1;
0521:                    } else if (!source.canRead()) {
0522:                        if (printErrors) {
0523:                            System.err.println(MessageFormat.format(labels
0524:                                    .getString("cantread"),
0525:                                    (Object[]) new String[] { argument }));
0526:                        }
0527:                        exitCond = 1;
0528:                    } else {
0529:                        try {
0530:                            int fileAction = action;
0531:                            if (fileAction == ACTION_GUESS) {
0532:                                if (isBase64(source)) {
0533:                                    fileAction = ACTION_DECODE;
0534:                                } else {
0535:                                    fileAction = ACTION_ENCODE;
0536:                                }
0537:                            }
0538:                            String outName = argument;
0539:                            if (extension.length() > 0) {
0540:                                if (fileAction == ACTION_ENCODE) {
0541:                                    outName = argument + "." + extension;
0542:                                } else {
0543:                                    if (argument.endsWith("." + extension)) {
0544:                                        outName = argument
0545:                                                .substring(
0546:                                                        0,
0547:                                                        argument.length()
0548:                                                                - (extension
0549:                                                                        .length() + 1));
0550:                                    }
0551:                                }
0552:                            }
0553:                            File outFile = new File(outName);
0554:                            if (!force && outFile.exists()) {
0555:                                if (printErrors) {
0556:                                    System.err
0557:                                            .println(MessageFormat
0558:                                                    .format(
0559:                                                            labels
0560:                                                                    .getString("overwrite"),
0561:                                                            (Object[]) new String[] { outName }));
0562:                                }
0563:                                exitCond = 1;
0564:                            } else if (!(outFile.exists() || outFile
0565:                                    .createNewFile())
0566:                                    || !outFile.canWrite()) {
0567:                                if (printErrors) {
0568:                                    System.err
0569:                                            .println(MessageFormat
0570:                                                    .format(
0571:                                                            labels
0572:                                                                    .getString("cantwrite"),
0573:                                                            (Object[]) new String[] { outName }));
0574:                                }
0575:                                exitCond = 1;
0576:                            } else {
0577:                                if (fileAction == ACTION_ENCODE) {
0578:                                    if (printMessages) {
0579:                                        System.out
0580:                                                .println(MessageFormat
0581:                                                        .format(
0582:                                                                labels
0583:                                                                        .getString("encoding"),
0584:                                                                (Object[]) new String[] {
0585:                                                                        argument,
0586:                                                                        outName }));
0587:                                    }
0588:                                    encode(source, outFile, lineBreaks);
0589:                                } else {
0590:                                    if (printMessages) {
0591:                                        System.out
0592:                                                .println(MessageFormat
0593:                                                        .format(
0594:                                                                labels
0595:                                                                        .getString("decoding"),
0596:                                                                (Object[]) new String[] {
0597:                                                                        argument,
0598:                                                                        outName }));
0599:                                    }
0600:                                    decode(source, outFile, !forceDecode);
0601:                                }
0602:                            }
0603:                        } catch (Base64DecodingException x) {
0604:                            if (printErrors) {
0605:                                System.err
0606:                                        .println(argument
0607:                                                + ": "
0608:                                                + x.getMessage()
0609:                                                + " "
0610:                                                + labels
0611:                                                        .getString("unexpectedcharforce"));
0612:                            }
0613:                            exitCond = 1;
0614:                        } catch (IOException x) {
0615:                            if (printErrors) {
0616:                                System.err.println(argument + ": "
0617:                                        + x.getMessage());
0618:                            }
0619:                            exitCond = 1;
0620:                        }
0621:                    }
0622:                }
0623:                if (!done) {
0624:                    try {
0625:                        if (action == ACTION_GUESS) {
0626:                            if (printErrors) {
0627:                                System.err.println(labels
0628:                                        .getString("cantguess"));
0629:                            }
0630:                            exitCond = 1;
0631:                        } else if (action == ACTION_ENCODE) {
0632:                            encode(new BufferedInputStream(System.in),
0633:                                    new BufferedOutputStream(System.out),
0634:                                    lineBreaks);
0635:                        } else {
0636:                            decode(new BufferedInputStream(System.in),
0637:                                    new BufferedOutputStream(System.out),
0638:                                    !forceDecode);
0639:                            if (decodeEndLine)
0640:                                System.out.println();
0641:                        }
0642:                    } catch (Base64DecodingException x) {
0643:                        if (printErrors) {
0644:                            System.err.println(x.getMessage() + " "
0645:                                    + labels.getString("unexpectedcharforce"));
0646:                        }
0647:                        exitCond = 1;
0648:                    } catch (IOException x) {
0649:                        if (printErrors) {
0650:                            System.err.println(x.getMessage());
0651:                        }
0652:                        exitCond = 1;
0653:                    }
0654:                }
0655:                System.exit(exitCond);
0656:            }
0657:
0658:            /**
0659:             * Encode a String in Base64.
0660:             * The String is converted to and from bytes according to the platform's
0661:             * default character encoding.
0662:             * No line breaks or other white space are inserted into the encoded data.
0663:             *
0664:             * @param string The data to encode.
0665:             * @return An encoded String.
0666:             *
0667:             * @since ostermillerutils 1.00.00
0668:             */
0669:            public static String encode(String string) {
0670:                return new String(encode(string.getBytes()));
0671:            }
0672:
0673:            /**
0674:             * Encode a String in Base64.
0675:             * No line breaks or other white space are inserted into the encoded data.
0676:             *
0677:             * @param string The data to encode.
0678:             * @param enc Character encoding to use when converting to and from bytes.
0679:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
0680:             * @return An encoded String.
0681:             *
0682:             * @since ostermillerutils 1.00.00
0683:             */
0684:            public static String encode(String string, String enc)
0685:                    throws UnsupportedEncodingException {
0686:                return new String(encode(string.getBytes(enc)), enc);
0687:            }
0688:
0689:            /**
0690:             * Encode bytes in Base64.
0691:             * No line breaks or other white space are inserted into the encoded data.
0692:             *
0693:             * @param bytes The data to encode.
0694:             * @return String with Base64 encoded data.
0695:             *
0696:             * @since ostermillerutils 1.04.00
0697:             */
0698:            public static String encodeToString(byte[] bytes) {
0699:                return encodeToString(bytes, false);
0700:            }
0701:
0702:            /**
0703:             * Encode bytes in Base64.
0704:             *
0705:             * @param bytes The data to encode.
0706:             * @param lineBreaks  Whether to insert line breaks every 76 characters in the output.
0707:             * @return String with Base64 encoded data.
0708:             *
0709:             * @since ostermillerutils 1.04.00
0710:             */
0711:            public static String encodeToString(byte[] bytes, boolean lineBreaks) {
0712:                try {
0713:                    return new String(encode(bytes, lineBreaks), "ASCII");
0714:                } catch (UnsupportedEncodingException iex) {
0715:                    // ASCII should be supported
0716:                    throw new RuntimeException(iex);
0717:                }
0718:            }
0719:
0720:            /**
0721:             * Encode bytes in Base64.
0722:             * No line breaks or other white space are inserted into the encoded data.
0723:             *
0724:             * @param bytes The data to encode.
0725:             * @return Encoded bytes.
0726:             *
0727:             * @since ostermillerutils 1.00.00
0728:             */
0729:            public static byte[] encode(byte[] bytes) {
0730:                return encode(bytes, false);
0731:            }
0732:
0733:            /**
0734:             * Encode bytes in Base64.
0735:             *
0736:             * @param bytes The data to encode.
0737:             * @param lineBreaks  Whether to insert line breaks every 76 characters in the output.
0738:             * @return Encoded bytes.
0739:             *
0740:             * @since ostermillerutils 1.04.00
0741:             */
0742:            public static byte[] encode(byte[] bytes, boolean lineBreaks) {
0743:                ByteArrayInputStream in = new ByteArrayInputStream(bytes);
0744:                // calculate the length of the resulting output.
0745:                // in general it will be 4/3 the size of the input
0746:                // but the input length must be divisible by three.
0747:                // If it isn't the next largest size that is divisible
0748:                // by three is used.
0749:                int mod;
0750:                int length = bytes.length;
0751:                if ((mod = length % 3) != 0) {
0752:                    length += 3 - mod;
0753:                }
0754:                length = length * 4 / 3;
0755:                ByteArrayOutputStream out = new ByteArrayOutputStream(length);
0756:                try {
0757:                    encode(in, out, lineBreaks);
0758:                } catch (IOException x) {
0759:                    // This can't happen.
0760:                    // The input and output streams were constructed
0761:                    // on memory structures that don't actually use IO.
0762:                    throw new RuntimeException(x);
0763:                }
0764:                return out.toByteArray();
0765:            }
0766:
0767:            /**
0768:             * Encode this file in Base64.
0769:             * Line breaks will be inserted every 76 characters.
0770:             *
0771:             * @param fIn File to be encoded (will be overwritten).
0772:             * @throws IOException if an input or output error occurs.
0773:             *
0774:             * @since ostermillerutils 1.00.00
0775:             */
0776:            public static void encode(File fIn) throws IOException {
0777:                encode(fIn, fIn, true);
0778:            }
0779:
0780:            /**
0781:             * Encode this file in Base64.
0782:             *
0783:             * @param fIn File to be encoded (will be overwritten).
0784:             * @param lineBreaks  Whether to insert line breaks every 76 characters in the output.
0785:             * @throws IOException if an input or output error occurs.
0786:             *
0787:             * @since ostermillerutils 1.00.00
0788:             */
0789:            public static void encode(File fIn, boolean lineBreaks)
0790:                    throws IOException {
0791:                encode(fIn, fIn, lineBreaks);
0792:            }
0793:
0794:            /**
0795:             * Encode this file in Base64.
0796:             * Line breaks will be inserted every 76 characters.
0797:             *
0798:             * @param fIn File to be encoded.
0799:             * @param fOut File to which the results should be written (may be the same as fIn).
0800:             * @throws IOException if an input or output error occurs.
0801:             *
0802:             * @since ostermillerutils 1.00.00
0803:             */
0804:            public static void encode(File fIn, File fOut) throws IOException {
0805:                encode(fIn, fOut, true);
0806:            }
0807:
0808:            /**
0809:             * Encode this file in Base64.
0810:             *
0811:             * @param fIn File to be encoded.
0812:             * @param fOut File to which the results should be written (may be the same as fIn).
0813:             * @param lineBreaks  Whether to insert line breaks every 76 characters in the output.
0814:             * @throws IOException if an input or output error occurs.
0815:             *
0816:             * @since ostermillerutils 1.00.00
0817:             */
0818:            public static void encode(File fIn, File fOut, boolean lineBreaks)
0819:                    throws IOException {
0820:                File temp = null;
0821:                InputStream in = null;
0822:                OutputStream out = null;
0823:                try {
0824:                    in = new BufferedInputStream(new FileInputStream(fIn));
0825:                    temp = File.createTempFile("Base64", null, null);
0826:                    out = new BufferedOutputStream(new FileOutputStream(temp));
0827:                    encode(in, out, lineBreaks);
0828:                    in.close();
0829:                    in = null;
0830:                    out.flush();
0831:                    out.close();
0832:                    out = null;
0833:                    FileHelper.move(temp, fOut, true);
0834:                } finally {
0835:                    if (in != null) {
0836:                        in.close();
0837:                        in = null;
0838:                    }
0839:                    if (out != null) {
0840:                        out.flush();
0841:                        out.close();
0842:                        out = null;
0843:                    }
0844:                }
0845:            }
0846:
0847:            /**
0848:             * Encode data from the InputStream to the OutputStream in Base64.
0849:             * Line breaks are inserted every 76 characters in the output.
0850:             *
0851:             * @param in Stream from which to read data that needs to be encoded.
0852:             * @param out Stream to which to write encoded data.
0853:             * @throws IOException if there is a problem reading or writing.
0854:             *
0855:             * @since ostermillerutils 1.00.00
0856:             */
0857:            public static void encode(InputStream in, OutputStream out)
0858:                    throws IOException {
0859:                encode(in, out, true);
0860:            }
0861:
0862:            /**
0863:             * Encode data from the InputStream to the OutputStream in Base64.
0864:             *
0865:             * @param in Stream from which to read data that needs to be encoded.
0866:             * @param out Stream to which to write encoded data.
0867:             * @param lineBreaks Whether to insert line breaks every 76 characters in the output.
0868:             * @throws IOException if there is a problem reading or writing.
0869:             *
0870:             * @since ostermillerutils 1.00.00
0871:             */
0872:            public static void encode(InputStream in, OutputStream out,
0873:                    boolean lineBreaks) throws IOException {
0874:                // Base64 encoding converts three bytes of input to
0875:                // four bytes of output
0876:                int[] inBuffer = new int[3];
0877:                int lineCount = 0;
0878:
0879:                boolean done = false;
0880:                while (!done && (inBuffer[0] = in.read()) != END_OF_INPUT) {
0881:                    // Fill the buffer
0882:                    inBuffer[1] = in.read();
0883:                    inBuffer[2] = in.read();
0884:
0885:                    // Calculate the out Buffer
0886:                    // The first byte of our in buffer will always be valid
0887:                    // but we must check to make sure the other two bytes
0888:                    // are not END_OF_INPUT before using them.
0889:                    // The basic idea is that the three bytes get split into
0890:                    // four bytes along these lines:
0891:                    //      [AAAAAABB] [BBBBCCCC] [CCDDDDDD]
0892:                    // [xxAAAAAA] [xxBBBBBB] [xxCCCCCC] [xxDDDDDD]
0893:                    // bytes are considered to be zero when absent.
0894:                    // the four bytes are then mapped to common ASCII symbols
0895:
0896:                    // A's: first six bits of first byte
0897:                    out.write(base64Chars[inBuffer[0] >> 2]);
0898:                    if (inBuffer[1] != END_OF_INPUT) {
0899:                        // B's: last two bits of first byte, first four bits of second byte
0900:                        out.write(base64Chars[((inBuffer[0] << 4) & 0x30)
0901:                                | (inBuffer[1] >> 4)]);
0902:                        if (inBuffer[2] != END_OF_INPUT) {
0903:                            // C's: last four bits of second byte, first two bits of third byte
0904:                            out.write(base64Chars[((inBuffer[1] << 2) & 0x3c)
0905:                                    | (inBuffer[2] >> 6)]);
0906:                            // D's: last six bits of third byte
0907:                            out.write(base64Chars[inBuffer[2] & 0x3F]);
0908:                        } else {
0909:                            // C's: last four bits of second byte
0910:                            out.write(base64Chars[((inBuffer[1] << 2) & 0x3c)]);
0911:                            // an equals sign for a character that is not a Base64 character
0912:                            out.write('=');
0913:                            done = true;
0914:                        }
0915:                    } else {
0916:                        // B's: last two bits of first byte
0917:                        out.write(base64Chars[((inBuffer[0] << 4) & 0x30)]);
0918:                        // an equal signs for characters that is not a Base64 characters
0919:                        out.write('=');
0920:                        out.write('=');
0921:                        done = true;
0922:                    }
0923:                    lineCount += 4;
0924:                    if (lineBreaks && lineCount >= 76) {
0925:                        out.write('\n');
0926:                        lineCount = 0;
0927:                    }
0928:                }
0929:                if (lineBreaks && lineCount >= 1) {
0930:                    out.write('\n');
0931:                    lineCount = 0;
0932:                }
0933:                out.flush();
0934:            }
0935:
0936:            /**
0937:             * Decode a Base64 encoded String.
0938:             * Characters that are not part of the Base64 alphabet are ignored
0939:             * in the input.
0940:             * The String is converted to and from bytes according to the platform's
0941:             * default character encoding.
0942:             *
0943:             * @param string The data to decode.
0944:             * @return A decoded String.
0945:             *
0946:             * @since ostermillerutils 1.00.00
0947:             */
0948:            public static String decode(String string) {
0949:                return new String(decode(string.getBytes()));
0950:            }
0951:
0952:            /**
0953:             * Decode a Base64 encoded String.
0954:             * Characters that are not part of the Base64 alphabet are ignored
0955:             * in the input.
0956:             *
0957:             * @param string The data to decode.
0958:             * @param enc Character encoding to use when converting to and from bytes.
0959:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
0960:             * @return A decoded String.
0961:             *
0962:             * @since ostermillerutils 1.00.00
0963:             */
0964:            public static String decode(String string, String enc)
0965:                    throws UnsupportedEncodingException {
0966:                return new String(decode(string.getBytes(enc)), enc);
0967:            }
0968:
0969:            /**
0970:             * Decode a Base64 encoded String.
0971:             * Characters that are not part of the Base64 alphabet are ignored
0972:             * in the input.
0973:             *
0974:             * @param string The data to decode.
0975:             * @param encIn Character encoding to use when converting input to bytes (should not matter because Base64 data is designed to survive most character encodings)
0976:             * @param encOut Character encoding to use when converting decoded bytes to output.
0977:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
0978:             * @return A decoded String.
0979:             *
0980:             * @since ostermillerutils 1.00.00
0981:             */
0982:            public static String decode(String string, String encIn,
0983:                    String encOut) throws UnsupportedEncodingException {
0984:                return new String(decode(string.getBytes(encIn)), encOut);
0985:            }
0986:
0987:            /**
0988:             * Decode a Base64 encoded String.
0989:             * Characters that are not part of the Base64 alphabet are ignored
0990:             * in the input.
0991:             * The String is converted to and from bytes according to the platform's
0992:             * default character encoding.
0993:             *
0994:             * @param string The data to decode.
0995:             * @return A decoded String.
0996:             *
0997:             * @since ostermillerutils 1.02.16
0998:             */
0999:            public static String decodeToString(String string) {
1000:                return new String(decode(string.getBytes()));
1001:            }
1002:
1003:            /**
1004:             * Decode a Base64 encoded String.
1005:             * Characters that are not part of the Base64 alphabet are ignored
1006:             * in the input.
1007:             *
1008:             * @param string The data to decode.
1009:             * @param enc Character encoding to use when converting to and from bytes.
1010:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
1011:             * @return A decoded String.
1012:             *
1013:             * @since ostermillerutils 1.02.16
1014:             */
1015:            public static String decodeToString(String string, String enc)
1016:                    throws UnsupportedEncodingException {
1017:                return new String(decode(string.getBytes(enc)), enc);
1018:            }
1019:
1020:            /**
1021:             * Decode a Base64 encoded String.
1022:             * Characters that are not part of the Base64 alphabet are ignored
1023:             * in the input.
1024:             *
1025:             * @param string The data to decode.
1026:             * @param encIn Character encoding to use when converting input to bytes (should not matter because Base64 data is designed to survive most character encodings)
1027:             * @param encOut Character encoding to use when converting decoded bytes to output.
1028:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
1029:             * @return A decoded String.
1030:             *
1031:             * @since ostermillerutils 1.02.16
1032:             */
1033:            public static String decodeToString(String string, String encIn,
1034:                    String encOut) throws UnsupportedEncodingException {
1035:                return new String(decode(string.getBytes(encIn)), encOut);
1036:            }
1037:
1038:            /**
1039:             * Decode a Base64 encoded String to an OutputStream.
1040:             * Characters that are not part of the Base64 alphabet are ignored
1041:             * in the input.
1042:             * The String is converted from bytes according to the platform's
1043:             * default character encoding.
1044:             *
1045:             * @param string The data to decode.
1046:             * @param out Stream to which to write decoded data.
1047:             * @throws IOException if an IO error occurs.
1048:             *
1049:             * @since ostermillerutils 1.02.16
1050:             */
1051:            public static void decodeToStream(String string, OutputStream out)
1052:                    throws IOException {
1053:                decode(new ByteArrayInputStream(string.getBytes()), out);
1054:            }
1055:
1056:            /**
1057:             * Decode a Base64 encoded String to an OutputStream.
1058:             * Characters that are not part of the Base64 alphabet are ignored
1059:             * in the input.
1060:             *
1061:             * @param string The data to decode.
1062:             * @param enc Character encoding to use when converting to and from bytes.
1063:             * @param out Stream to which to write decoded data.
1064:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
1065:             * @throws IOException if an IO error occurs.
1066:             *
1067:             * @since ostermillerutils 1.02.16
1068:             */
1069:            public static void decodeToStream(String string, String enc,
1070:                    OutputStream out) throws UnsupportedEncodingException,
1071:                    IOException {
1072:                decode(new ByteArrayInputStream(string.getBytes(enc)), out);
1073:            }
1074:
1075:            /**
1076:             * Decode a Base64 encoded String.
1077:             * Characters that are not part of the Base64 alphabet are ignored
1078:             * in the input.
1079:             * The String is converted from bytes according to the platform's
1080:             * default character encoding.
1081:             *
1082:             * @param string The data to decode.
1083:             * @return decoded data.
1084:             *
1085:             * @since ostermillerutils 1.02.16
1086:             */
1087:            public static byte[] decodeToBytes(String string) {
1088:                return decode(string.getBytes());
1089:            }
1090:
1091:            /**
1092:             * Decode a Base64 encoded String.
1093:             * Characters that are not part of the Base64 alphabet are ignored
1094:             * in the input.
1095:             *
1096:             * @param string The data to decode.
1097:             * @param enc Character encoding to use when converting from bytes.
1098:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
1099:             * @return decoded data.
1100:             *
1101:             * @since ostermillerutils 1.02.16
1102:             */
1103:            public static byte[] decodeToBytes(String string, String enc)
1104:                    throws UnsupportedEncodingException {
1105:                return decode(string.getBytes(enc));
1106:            }
1107:
1108:            /**
1109:             * Decode Base64 encoded bytes.
1110:             * Characters that are not part of the Base64 alphabet are ignored
1111:             * in the input.
1112:             * The String is converted to bytes according to the platform's
1113:             * default character encoding.
1114:             *
1115:             * @param bytes The data to decode.
1116:             * @return A decoded String.
1117:             *
1118:             * @since ostermillerutils 1.02.16
1119:             */
1120:            public static String decodeToString(byte[] bytes) {
1121:                return new String(decode(bytes));
1122:            }
1123:
1124:            /**
1125:             * Decode Base64 encoded bytes.
1126:             * Characters that are not part of the Base64 alphabet are ignored
1127:             * in the input.
1128:             *
1129:             * @param bytes The data to decode.
1130:             * @param enc Character encoding to use when converting to and from bytes.
1131:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
1132:             * @return A decoded String.
1133:             *
1134:             * @since ostermillerutils 1.02.16
1135:             */
1136:            public static String decodeToString(byte[] bytes, String enc)
1137:                    throws UnsupportedEncodingException {
1138:                return new String(decode(bytes), enc);
1139:            }
1140:
1141:            /**
1142:             * Decode Base64 encoded bytes.
1143:             * Characters that are not part of the Base64 alphabet are ignored
1144:             * in the input.
1145:             *
1146:             * @param bytes The data to decode.
1147:             * @return Decoded bytes.
1148:             *
1149:             * @since ostermillerutils 1.02.16
1150:             */
1151:            public static byte[] decodeToBytes(byte[] bytes) {
1152:                return decode(bytes);
1153:            }
1154:
1155:            /**
1156:             * Decode Base64 encoded bytes.
1157:             * Characters that are not part of the Base64 alphabet are ignored
1158:             * in the input.
1159:             *
1160:             * @param bytes The data to decode.
1161:             * @return Decoded bytes.
1162:             *
1163:             * @since ostermillerutils 1.00.00
1164:             */
1165:            public static byte[] decode(byte[] bytes) {
1166:                ByteArrayInputStream in = new ByteArrayInputStream(bytes);
1167:                // calculate the length of the resulting output.
1168:                // in general it will be at most 3/4 the size of the input
1169:                // but the input length must be divisible by four.
1170:                // If it isn't the next largest size that is divisible
1171:                // by four is used.
1172:                int mod;
1173:                int length = bytes.length;
1174:                if ((mod = length % 4) != 0) {
1175:                    length += 4 - mod;
1176:                }
1177:                length = length * 3 / 4;
1178:                ByteArrayOutputStream out = new ByteArrayOutputStream(length);
1179:                try {
1180:                    decode(in, out, false);
1181:                } catch (IOException x) {
1182:                    // This can't happen.
1183:                    // The input and output streams were constructed
1184:                    // on memory structures that don't actually use IO.
1185:                    throw new RuntimeException(x);
1186:                }
1187:                return out.toByteArray();
1188:            }
1189:
1190:            /**
1191:             * Decode Base64 encoded bytes to the an OutputStream.
1192:             * Characters that are not part of the Base64 alphabet are ignored
1193:             * in the input.
1194:             *
1195:             * @param bytes The data to decode.
1196:             * @param out Stream to which to write decoded data.
1197:             * @throws IOException if an IO error occurs.
1198:             *
1199:             * @since ostermillerutils 1.00.00
1200:             */
1201:            public static void decode(byte[] bytes, OutputStream out)
1202:                    throws IOException {
1203:                ByteArrayInputStream in = new ByteArrayInputStream(bytes);
1204:                decode(in, out, false);
1205:            }
1206:
1207:            /**
1208:             * Decode Base64 encoded bytes to the an OutputStream.
1209:             * Characters that are not part of the Base64 alphabet are ignored
1210:             * in the input.
1211:             *
1212:             * @param bytes The data to decode.
1213:             * @param out Stream to which to write decoded data.
1214:             * @throws IOException if an IO error occurs.
1215:             *
1216:             * @since ostermillerutils 1.02.16
1217:             */
1218:            public static void decodeToStream(byte[] bytes, OutputStream out)
1219:                    throws IOException {
1220:                ByteArrayInputStream in = new ByteArrayInputStream(bytes);
1221:                decode(in, out, false);
1222:            }
1223:
1224:            /**
1225:             * Decode Base64 encoded data from one file to the other.
1226:             * Characters in the Base64 alphabet, white space and equals sign are
1227:             * expected to be in url encoded data.  The presence of other characters
1228:             * could be a sign that the data is corrupted.
1229:             *
1230:             * @param fIn File to be decoded (will be overwritten).
1231:             * @throws IOException if an IO error occurs.
1232:             * @throws Base64DecodingException if unexpected data is encountered.
1233:             *
1234:             * @since ostermillerutils 1.00.00
1235:             */
1236:            public static void decode(File fIn) throws IOException {
1237:                decode(fIn, fIn, true);
1238:            }
1239:
1240:            /**
1241:             * Decode Base64 encoded data from one file to the other.
1242:             * Characters in the Base64 alphabet, white space and equals sign are
1243:             * expected to be in url encoded data.  The presence of other characters
1244:             * could be a sign that the data is corrupted.
1245:             *
1246:             * @param fIn File to be decoded (will be overwritten).
1247:             * @param throwExceptions Whether to throw exceptions when unexpected data is encountered.
1248:             * @throws IOException if an IO error occurs.
1249:             * @throws Base64DecodingException if unexpected data is encountered when throwExceptions is specified.
1250:             *
1251:             * @since ostermillerutils 1.00.00
1252:             */
1253:            public static void decode(File fIn, boolean throwExceptions)
1254:                    throws IOException {
1255:                decode(fIn, fIn, throwExceptions);
1256:            }
1257:
1258:            /**
1259:             * Decode Base64 encoded data from one file to the other.
1260:             * Characters in the Base64 alphabet, white space and equals sign are
1261:             * expected to be in url encoded data.  The presence of other characters
1262:             * could be a sign that the data is corrupted.
1263:             *
1264:             * @param fIn File to be decoded.
1265:             * @param fOut File to which the results should be written (may be the same as fIn).
1266:             * @throws IOException if an IO error occurs.
1267:             * @throws Base64DecodingException if unexpected data is encountered.
1268:             *
1269:             * @since ostermillerutils 1.00.00
1270:             */
1271:            public static void decode(File fIn, File fOut) throws IOException {
1272:                decode(fIn, fOut, true);
1273:            }
1274:
1275:            /**
1276:             * Decode Base64 encoded data from one file to the other.
1277:             * Characters in the Base64 alphabet, white space and equals sign are
1278:             * expected to be in url encoded data.  The presence of other characters
1279:             * could be a sign that the data is corrupted.
1280:             *
1281:             * @param fIn File to be decoded.
1282:             * @param fOut File to which the results should be written (may be the same as fIn).
1283:             * @param throwExceptions Whether to throw exceptions when unexpected data is encountered.
1284:             * @throws IOException if an IO error occurs.
1285:             * @throws Base64DecodingException if unexpected data is encountered when throwExceptions is specified.
1286:             *
1287:             * @since ostermillerutils 1.00.00
1288:             */
1289:            public static void decode(File fIn, File fOut,
1290:                    boolean throwExceptions) throws IOException {
1291:                File temp = null;
1292:                InputStream in = null;
1293:                OutputStream out = null;
1294:                try {
1295:                    in = new BufferedInputStream(new FileInputStream(fIn));
1296:                    temp = File.createTempFile("Base64", null, null);
1297:                    out = new BufferedOutputStream(new FileOutputStream(temp));
1298:                    decode(in, out, throwExceptions);
1299:                    in.close();
1300:                    in = null;
1301:                    out.flush();
1302:                    out.close();
1303:                    out = null;
1304:                    FileHelper.move(temp, fOut, true);
1305:                } finally {
1306:                    if (in != null) {
1307:                        try {
1308:                            in.close();
1309:                        } catch (IOException ignore) {
1310:                            if (throwExceptions)
1311:                                throw ignore;
1312:                        }
1313:                        in = null;
1314:                    }
1315:                    if (out != null) {
1316:                        try {
1317:                            out.flush();
1318:                            out.close();
1319:                        } catch (IOException ignore) {
1320:                            if (throwExceptions)
1321:                                throw ignore;
1322:                        }
1323:                        out = null;
1324:                    }
1325:                }
1326:            }
1327:
1328:            /**
1329:             * Reads the next (decoded) Base64 character from the input stream.
1330:             * Non Base64 characters are skipped.
1331:             *
1332:             * @param in Stream from which bytes are read.
1333:             * @param throwExceptions Throw an exception if an unexpected character is encountered.
1334:             * @return the next Base64 character from the stream or -1 if there are no more Base64 characters on the stream.
1335:             * @throws IOException if an IO Error occurs.
1336:             * @throws Base64DecodingException if unexpected data is encountered when throwExceptions is specified.
1337:             *
1338:             * @since ostermillerutils 1.00.00
1339:             */
1340:            private static final int readBase64(InputStream in,
1341:                    boolean throwExceptions) throws IOException {
1342:                int read;
1343:                int numPadding = 0;
1344:                do {
1345:                    read = in.read();
1346:                    if (read == END_OF_INPUT)
1347:                        return END_OF_INPUT;
1348:                    read = reverseBase64Chars[(byte) read];
1349:                    if (throwExceptions
1350:                            && (read == NON_BASE_64 || (numPadding > 0 && read > NON_BASE_64))) {
1351:                        throw new Base64DecodingException(MessageFormat.format(
1352:                                labels.getString("unexpectedchar"),
1353:                                (Object[]) new String[] { "'" + (char) read
1354:                                        + "' (0x" + Integer.toHexString(read)
1355:                                        + ")" }), (char) read);
1356:                    }
1357:                    if (read == NON_BASE_64_PADDING) {
1358:                        numPadding++;
1359:                    }
1360:                } while (read <= NON_BASE_64);
1361:                return read;
1362:            }
1363:
1364:            /**
1365:             * Decode Base64 encoded data from the InputStream to a byte array.
1366:             * Characters that are not part of the Base64 alphabet are ignored
1367:             * in the input.
1368:             *
1369:             * @param in Stream from which to read data that needs to be decoded.
1370:             * @return decoded data.
1371:             * @throws IOException if an IO error occurs.
1372:             *
1373:             * @since ostermillerutils 1.00.00
1374:             */
1375:            public static byte[] decodeToBytes(InputStream in)
1376:                    throws IOException {
1377:                ByteArrayOutputStream out = new ByteArrayOutputStream();
1378:                decode(in, out, false);
1379:                return out.toByteArray();
1380:            }
1381:
1382:            /**
1383:             * Decode Base64 encoded data from the InputStream to a String.
1384:             * Characters that are not part of the Base64 alphabet are ignored
1385:             * in the input.
1386:             * Bytes are converted to characters in the output String according to the platform's
1387:             * default character encoding.
1388:             *
1389:             * @param in Stream from which to read data that needs to be decoded.
1390:             * @return decoded data.
1391:             * @throws IOException if an IO error occurs.
1392:             *
1393:             * @since ostermillerutils 1.02.16
1394:             */
1395:            public static String decodeToString(InputStream in)
1396:                    throws IOException {
1397:                return new String(decodeToBytes(in));
1398:            }
1399:
1400:            /**
1401:             * Decode Base64 encoded data from the InputStream to a String.
1402:             * Characters that are not part of the Base64 alphabet are ignored
1403:             * in the input.
1404:             *
1405:             * @param in Stream from which to read data that needs to be decoded.
1406:             * @param enc Character encoding to use when converting bytes to characters.
1407:             * @return decoded data.
1408:             * @throws IOException if an IO error occurs.Throws:
1409:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
1410:             *
1411:             * @since ostermillerutils 1.02.16
1412:             */
1413:            public static String decodeToString(InputStream in, String enc)
1414:                    throws IOException {
1415:                return new String(decodeToBytes(in), enc);
1416:            }
1417:
1418:            /**
1419:             * Decode Base64 encoded data from the InputStream to the OutputStream.
1420:             * Characters in the Base64 alphabet, white space and equals sign are
1421:             * expected to be in url encoded data.  The presence of other characters
1422:             * could be a sign that the data is corrupted.
1423:             *
1424:             * @param in Stream from which to read data that needs to be decoded.
1425:             * @param out Stream to which to write decoded data.
1426:             * @throws IOException if an IO error occurs.
1427:             * @throws Base64DecodingException if unexpected data is encountered.
1428:             *
1429:             * @since ostermillerutils 1.00.00
1430:             */
1431:            public static void decode(InputStream in, OutputStream out)
1432:                    throws IOException {
1433:                decode(in, out, true);
1434:            }
1435:
1436:            /**
1437:             * Decode Base64 encoded data from the InputStream to the OutputStream.
1438:             * Characters in the Base64 alphabet, white space and equals sign are
1439:             * expected to be in url encoded data.  The presence of other characters
1440:             * could be a sign that the data is corrupted.
1441:             *
1442:             * @param in Stream from which to read data that needs to be decoded.
1443:             * @param out Stream to which to write decoded data.
1444:             * @param throwExceptions Whether to throw exceptions when unexpected data is encountered.
1445:             * @throws IOException if an IO error occurs.
1446:             * @throws Base64DecodingException if unexpected data is encountered when throwExceptions is specified.
1447:             *
1448:             * @since ostermillerutils 1.00.00
1449:             */
1450:            public static void decode(InputStream in, OutputStream out,
1451:                    boolean throwExceptions) throws IOException {
1452:                // Base64 decoding converts four bytes of input to three bytes of output
1453:                int[] inBuffer = new int[4];
1454:
1455:                // read bytes unmapping them from their ASCII encoding in the process
1456:                // we must read at least two bytes to be able to output anything
1457:                boolean done = false;
1458:                while (!done
1459:                        && (inBuffer[0] = readBase64(in, throwExceptions)) != END_OF_INPUT
1460:                        && (inBuffer[1] = readBase64(in, throwExceptions)) != END_OF_INPUT) {
1461:                    // Fill the buffer
1462:                    inBuffer[2] = readBase64(in, throwExceptions);
1463:                    inBuffer[3] = readBase64(in, throwExceptions);
1464:
1465:                    // Calculate the output
1466:                    // The first two bytes of our in buffer will always be valid
1467:                    // but we must check to make sure the other two bytes
1468:                    // are not END_OF_INPUT before using them.
1469:                    // The basic idea is that the four bytes will get reconstituted
1470:                    // into three bytes along these lines:
1471:                    // [xxAAAAAA] [xxBBBBBB] [xxCCCCCC] [xxDDDDDD]
1472:                    //      [AAAAAABB] [BBBBCCCC] [CCDDDDDD]
1473:                    // bytes are considered to be zero when absent.
1474:
1475:                    // six A and two B
1476:                    out.write(inBuffer[0] << 2 | inBuffer[1] >> 4);
1477:                    if (inBuffer[2] != END_OF_INPUT) {
1478:                        // four B and four C
1479:                        out.write(inBuffer[1] << 4 | inBuffer[2] >> 2);
1480:                        if (inBuffer[3] != END_OF_INPUT) {
1481:                            // two C and six D
1482:                            out.write(inBuffer[2] << 6 | inBuffer[3]);
1483:                        } else {
1484:                            done = true;
1485:                        }
1486:                    } else {
1487:                        done = true;
1488:                    }
1489:                }
1490:                out.flush();
1491:            }
1492:
1493:            /**
1494:             * Determines if the byte array is in base64 format.
1495:             * <p>
1496:             * Data will be considered to be in base64 format if it contains
1497:             * only base64 characters and whitespace with equals sign padding
1498:             * on the end so that the number of base64 characters is divisible
1499:             * by four.
1500:             * <p>
1501:             * It is possible for data to be in base64 format but for it to not
1502:             * meet these stringent requirements.  It is also possible for data
1503:             * to meet these requirements even though decoding it would not make
1504:             * any sense.  This method should be used as a guide but it is not
1505:             * authoritative because of the possibility of these false positives
1506:             * and false negatives.
1507:             * <p>
1508:             * Additionally, extra data such as headers or footers may throw
1509:             * this method off the scent and cause it to return false.
1510:             *
1511:             * @param bytes data that could be in base64 format.
1512:             * @return true iff the array appears to be in base64 format
1513:             *
1514:             * @since ostermillerutils 1.00.00
1515:             */
1516:            public static boolean isBase64(byte[] bytes) {
1517:                try {
1518:                    return isBase64(new ByteArrayInputStream(bytes));
1519:                } catch (IOException x) {
1520:                    // This can't happen.
1521:                    // The input and output streams were constructed
1522:                    // on memory structures that don't actually use IO.
1523:                    return false;
1524:                }
1525:            }
1526:
1527:            /**
1528:             * Determines if the String is in base64 format.
1529:             * The String is converted to and from bytes according to the platform's
1530:             * default character encoding.
1531:             * <p>
1532:             * Data will be considered to be in base64 format if it contains
1533:             * only base64 characters and whitespace with equals sign padding
1534:             * on the end so that the number of base64 characters is divisible
1535:             * by four.
1536:             * <p>
1537:             * It is possible for data to be in base64 format but for it to not
1538:             * meet these stringent requirements.  It is also possible for data
1539:             * to meet these requirements even though decoding it would not make
1540:             * any sense.  This method should be used as a guide but it is not
1541:             * authoritative because of the possibility of these false positives
1542:             * and false negatives.
1543:             * <p>
1544:             * Additionally, extra data such as headers or footers may throw
1545:             * this method off the scent and cause it to return false.
1546:             *
1547:             * @param string String that may be in base64 format.
1548:             * @return Best guess as to whether the data is in base64 format.
1549:             *
1550:             * @since ostermillerutils 1.00.00
1551:             */
1552:            public static boolean isBase64(String string) {
1553:                return isBase64(string.getBytes());
1554:            }
1555:
1556:            /**
1557:             * Determines if the String is in base64 format.
1558:             * <p>
1559:             * Data will be considered to be in base64 format if it contains
1560:             * only base64 characters and whitespace with equals sign padding
1561:             * on the end so that the number of base64 characters is divisible
1562:             * by four.
1563:             * <p>
1564:             * It is possible for data to be in base64 format but for it to not
1565:             * meet these stringent requirements.  It is also possible for data
1566:             * to meet these requirements even though decoding it would not make
1567:             * any sense.  This method should be used as a guide but it is not
1568:             * authoritative because of the possibility of these false positives
1569:             * and false negatives.
1570:             * <p>
1571:             * Additionally, extra data such as headers or footers may throw
1572:             * this method off the scent and cause it to return false.
1573:             *
1574:             * @param string String that may be in base64 format.
1575:             * @param enc Character encoding to use when converting to bytes.
1576:             * @return Best guess as to whether the data is in base64 format.
1577:             * @throws UnsupportedEncodingException if the character encoding specified is not supported.
1578:             */
1579:            public static boolean isBase64(String string, String enc)
1580:                    throws UnsupportedEncodingException {
1581:                return isBase64(string.getBytes(enc));
1582:            }
1583:
1584:            /**
1585:             * Determines if the File is in base64 format.
1586:             * <p>
1587:             * Data will be considered to be in base64 format if it contains
1588:             * only base64 characters and whitespace with equals sign padding
1589:             * on the end so that the number of base64 characters is divisible
1590:             * by four.
1591:             * <p>
1592:             * It is possible for data to be in base64 format but for it to not
1593:             * meet these stringent requirements.  It is also possible for data
1594:             * to meet these requirements even though decoding it would not make
1595:             * any sense.  This method should be used as a guide but it is not
1596:             * authoritative because of the possibility of these false positives
1597:             * and false negatives.
1598:             * <p>
1599:             * Additionally, extra data such as headers or footers may throw
1600:             * this method off the scent and cause it to return false.
1601:             *
1602:             * @param fIn File that may be in base64 format.
1603:             * @return Best guess as to whether the data is in base64 format.
1604:             * @throws IOException if an IO error occurs.
1605:             *
1606:             * @since ostermillerutils 1.00.00
1607:             */
1608:            public static boolean isBase64(File fIn) throws IOException {
1609:                return isBase64(new BufferedInputStream(
1610:                        new FileInputStream(fIn)));
1611:            }
1612:
1613:            /**
1614:             * Reads data from the stream and determines if it is
1615:             * in base64 format.
1616:             * <p>
1617:             * Data will be considered to be in base64 format if it contains
1618:             * only base64 characters and whitespace with equals sign padding
1619:             * on the end so that the number of base64 characters is divisible
1620:             * by four.
1621:             * <p>
1622:             * It is possible for data to be in base64 format but for it to not
1623:             * meet these stringent requirements.  It is also possible for data
1624:             * to meet these requirements even though decoding it would not make
1625:             * any sense.  This method should be used as a guide but it is not
1626:             * authoritative because of the possibility of these false positives
1627:             * and false negatives.
1628:             * <p>
1629:             * Additionally, extra data such as headers or footers may throw
1630:             * this method off the scent and cause it to return false.
1631:             *
1632:             * @param in Stream from which to read data to be tested.
1633:             * @return Best guess as to whether the data is in base64 format.
1634:             * @throws IOException if an IO error occurs.
1635:             *
1636:             * @since ostermillerutils 1.00.00
1637:             */
1638:            public static boolean isBase64(InputStream in) throws IOException {
1639:                long numBase64Chars = 0;
1640:                int numPadding = 0;
1641:                int read;
1642:
1643:                while ((read = in.read()) != -1) {
1644:                    read = reverseBase64Chars[read];
1645:                    if (read == NON_BASE_64) {
1646:                        return false;
1647:                    } else if (read == NON_BASE_64_WHITESPACE) {
1648:                        // ignore white space
1649:                    } else if (read == NON_BASE_64_PADDING) {
1650:                        numPadding++;
1651:                        numBase64Chars++;
1652:                    } else if (numPadding > 0) {
1653:                        return false;
1654:                    } else {
1655:                        numBase64Chars++;
1656:                    }
1657:                }
1658:                if (numBase64Chars == 0)
1659:                    return false;
1660:                if (numBase64Chars % 4 != 0)
1661:                    return false;
1662:                return true;
1663:            }
1664:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.