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:
parent
a3faa41696
commit
13d87e3d40
5 changed files with 67 additions and 100 deletions
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
48
source/org/jivesoftware/smack/util/Base64FileUrlEncoder.java
Normal file
48
source/org/jivesoftware/smack/util/Base64FileUrlEncoder.java
Normal 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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue