1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-27 00:32:07 +01:00

SMACK-361 Changed default for filename encoding to Base 32 (which should work on all file systems) and added a Base 64 filename and url safe implementation of the StringEncoder.

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/branches/smack_3_3_0@13619 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
rcollier 2013-04-20 21:55:27 +00:00
parent a3faa41696
commit 13d87e3d40
5 changed files with 67 additions and 100 deletions

View file

@ -8,65 +8,8 @@ package org.jivesoftware.smack.util;
/** /**
* <p>Encodes and decodes to and from Base64 notation.</p> * <p>Encodes and decodes to and from Base64 notation.</p>
* <p>Homepage: <a href="http://iharder.net/base64">http://iharder.net/base64</a>.</p> * This code was obtained from <a href="http://iharder.net/base64">http://iharder.net/base64</a></p>
* *
* <p>
* Change Log:
* </p>
* <ul>
* <li>v2.2.1 - Fixed bug using URL_SAFE and ORDERED encodings. Fixed bug
* when using very small files (~< 40 bytes).</li>
* <li>v2.2 - Added some helper methods for encoding/decoding directly from
* one file to the next. Also added a main() method to support command line
* encoding/decoding from one file to the next. Also added these Base64 dialects:
* <ol>
* <li>The default is RFC3548 format.</li>
* <li>Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates
* URL and file name friendly format as described in Section 4 of RFC3548.
* http://www.faqs.org/rfcs/rfc3548.html</li>
* <li>Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates
* URL and file name friendly format that preserves lexical ordering as described
* in http://www.faqs.org/qa/rfcc-1940.html</li>
* </ol>
* Special thanks to Jim Kellerman at <a href="http://www.powerset.com/">http://www.powerset.com/</a>
* for contributing the new Base64 dialects.
* </li>
*
* <li>v2.1 - Cleaned up javadoc comments and unused variables and methods. Added
* some convenience methods for reading and writing to and from files.</li>
* <li>v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems
* with other encodings (like EBCDIC).</li>
* <li>v2.0.1 - Fixed an error when decoding a single byte, that is, when the
* encoded data was a single byte.</li>
* <li>v2.0 - I got rid of methods that used booleans to set options.
* Now everything is more consolidated and cleaner. The code now detects
* when data that's being decoded is gzip-compressed and will decompress it
* automatically. Generally things are cleaner. You'll probably have to
* change some method calls that you were making to support the new
* options format (<tt>int</tt>s that you "OR" together).</li>
* <li>v1.5.1 - Fixed bug when decompressing and decoding to a
* byte[] using <tt>decode( String s, boolean gzipCompressed )</tt>.
* Added the ability to "suspend" encoding in the Output Stream so
* you can turn on and off the encoding if you need to embed base64
* data in an otherwise "normal" stream (like an XML file).</li>
* <li>v1.5 - Output stream pases on flush() command but doesn't do anything itself.
* This helps when using GZIP streams.
* Added the ability to GZip-compress objects before encoding them.</li>
* <li>v1.4 - Added helper methods to read/write files.</li>
* <li>v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.</li>
* <li>v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream
* where last buffer being read, if not completely full, was not returned.</li>
* <li>v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.</li>
* <li>v1.3.3 - Fixed I/O streams which were totally messed up.</li>
* </ul>
*
* <p>
* I am placing this code in the Public Domain. Do with it as you will.
* This software comes with no guarantees or warranties but with
* plenty of well-wishing instead!
* Please visit <a href="http://iharder.net/base64">http://iharder.net/base64</a>
* periodically to check for updates or to contribute improvements.
* </p>
* *
* @author Robert Harder * @author Robert Harder
* @author rob@iharder.net * @author rob@iharder.net
@ -368,33 +311,6 @@ public class Base64
/** Defeats instantiation. */ /** Defeats instantiation. */
private Base64(){} private Base64(){}
/**
* Encodes or decodes two files from the command line;
* <strong>feel free to delete this method (in fact you probably should)
* if you're embedding this code into a larger program.</strong>
*/
public final static void main( String[] args )
{
if( args.length < 3 ){
usage("Not enough arguments.");
} // end if: args.length < 3
else {
String flag = args[0];
String infile = args[1];
String outfile = args[2];
if( flag.equals( "-e" ) ){
Base64.encodeFileToFile( infile, outfile );
} // end if: encode
else if( flag.equals( "-d" ) ) {
Base64.decodeFileToFile( infile, outfile );
} // end else if: decode
else {
usage( "Unknown flag: " + flag );
} // end else
} // end else
} // end main
/** /**
* Prints command line usage. * Prints command line usage.
* *

View file

@ -16,6 +16,7 @@ package org.jivesoftware.smack.util;
/** /**
* A Base 64 encoding implementation.
* @author Florian Schmaus * @author Florian Schmaus
*/ */
public class Base64Encoder implements StringEncoder { public class Base64Encoder implements StringEncoder {

View file

@ -0,0 +1,48 @@
/**
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.util;
/**
* A Base 64 encoding implementation that generates filename and Url safe encodings.
*
* <p>
* Note: This does NOT produce standard Base 64 encodings, but a variant as defined in
* Section 4 of RFC3548:
* <a href="http://www.faqs.org/rfcs/rfc3548.html">http://www.faqs.org/rfcs/rfc3548.html</a>.
*
* @author Robin Collier
*/
public class Base64FileUrlEncoder implements StringEncoder {
private static Base64FileUrlEncoder instance = new Base64FileUrlEncoder();
private Base64FileUrlEncoder() {
// Use getInstance()
}
public static Base64FileUrlEncoder getInstance() {
return instance;
}
public String encode(String s) {
return Base64.encodeBytes(s.getBytes(), Base64.URL_SAFE);
}
public String decode(String s) {
return new String(Base64.decode(s, Base64.URL_SAFE));
}
}

View file

@ -27,6 +27,7 @@ import java.io.StringReader;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider; import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.Base32Encoder;
import org.jivesoftware.smack.util.Base64Encoder; import org.jivesoftware.smack.util.Base64Encoder;
import org.jivesoftware.smack.util.StringEncoder; import org.jivesoftware.smack.util.StringEncoder;
import org.jivesoftware.smackx.entitycaps.EntityCapsManager; import org.jivesoftware.smackx.entitycaps.EntityCapsManager;
@ -47,19 +48,20 @@ import org.xmlpull.v1.XmlPullParserException;
public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache { public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache {
private File cacheDir; private File cacheDir;
private StringEncoder stringEncoder; private StringEncoder filenameEncoder;
/** /**
* Creates a new SimpleDirectoryPersistentCache Object. Make sure that the * Creates a new SimpleDirectoryPersistentCache Object. Make sure that the
* cacheDir exists and that it's an directory. * cacheDir exists and that it's an directory.
* * <p>
* If your cacheDir is case insensitive then make sure to set the * Default filename encoder {@link Base32Encoder}, as this will work on all
* StringEncoder to Base32. * filesystems, both case sensitive and case insensitive. It does however
* produce longer filenames.
* *
* @param cacheDir * @param cacheDir
*/ */
public SimpleDirectoryPersistentCache(File cacheDir) { public SimpleDirectoryPersistentCache(File cacheDir) {
this(cacheDir, Base64Encoder.getInstance()); this(cacheDir, Base32Encoder.getInstance());
} }
/** /**
@ -67,26 +69,25 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache
* cacheDir exists and that it's an directory. * cacheDir exists and that it's an directory.
* *
* If your cacheDir is case insensitive then make sure to set the * If your cacheDir is case insensitive then make sure to set the
* StringEncoder to Base32. * StringEncoder to {@link Base32Encoder} (which is the default).
* *
* @param cacheDir * @param cacheDir The directory where the cache will be stored.
* @param stringEncoder * @param filenameEncoder Encodes the node string into a filename.
*/ */
public SimpleDirectoryPersistentCache(File cacheDir, StringEncoder stringEncoder) { public SimpleDirectoryPersistentCache(File cacheDir, StringEncoder filenameEncoder) {
if (!cacheDir.exists()) if (!cacheDir.exists())
throw new IllegalStateException("Cache directory \"" + cacheDir + "\" does not exist"); throw new IllegalStateException("Cache directory \"" + cacheDir + "\" does not exist");
if (!cacheDir.isDirectory()) if (!cacheDir.isDirectory())
throw new IllegalStateException("Cache directory \"" + cacheDir + "\" is not a directory"); throw new IllegalStateException("Cache directory \"" + cacheDir + "\" is not a directory");
this.cacheDir = cacheDir; this.cacheDir = cacheDir;
this.stringEncoder = stringEncoder; this.filenameEncoder = filenameEncoder;
} }
@Override @Override
public void addDiscoverInfoByNodePersistent(String node, DiscoverInfo info) { public void addDiscoverInfoByNodePersistent(String node, DiscoverInfo info) {
String filename = stringEncoder.encode(node); String filename = filenameEncoder.encode(node);
File nodeFile = new File(cacheDir, filename); File nodeFile = new File(cacheDir, filename);
try { try {
if (nodeFile.createNewFile()) if (nodeFile.createNewFile())
writeInfoToFile(nodeFile, info); writeInfoToFile(nodeFile, info);
@ -99,7 +100,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache
public void replay() throws IOException { public void replay() throws IOException {
File[] files = cacheDir.listFiles(); File[] files = cacheDir.listFiles();
for (File f : files) { for (File f : files) {
String node = stringEncoder.decode(f.getName()); String node = filenameEncoder.decode(f.getName());
DiscoverInfo info = restoreInfoFromFile(f); DiscoverInfo info = restoreInfoFromFile(f);
if (info == null) if (info == null)
continue; continue;

View file

@ -10,6 +10,7 @@ import java.util.LinkedList;
import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.util.Base32Encoder; import org.jivesoftware.smack.util.Base32Encoder;
import org.jivesoftware.smack.util.Base64Encoder; import org.jivesoftware.smack.util.Base64Encoder;
import org.jivesoftware.smack.util.Base64FileUrlEncoder;
import org.jivesoftware.smack.util.StringEncoder; import org.jivesoftware.smack.util.StringEncoder;
import org.jivesoftware.smackx.FormField; import org.jivesoftware.smackx.FormField;
import org.jivesoftware.smackx.entitycaps.EntityCapsManager; import org.jivesoftware.smackx.entitycaps.EntityCapsManager;
@ -37,7 +38,7 @@ public class EntityCapsManagerTest {
@Test @Test
public void testSimpleDirectoryCacheBase64() throws IOException { public void testSimpleDirectoryCacheBase64() throws IOException {
EntityCapsManager.persistentCache = null; EntityCapsManager.persistentCache = null;
testSimpleDirectoryCache(Base64Encoder.getInstance()); testSimpleDirectoryCache(Base64FileUrlEncoder.getInstance());
} }
@Test @Test