001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 */ 018 019package org.apache.commons.compress.archivers.zip; 020 021import java.nio.Buffer; 022import java.nio.ByteBuffer; 023import java.nio.charset.Charset; 024import java.nio.charset.StandardCharsets; 025import java.nio.charset.UnsupportedCharsetException; 026 027/** 028 * Static helper functions for robustly encoding file names in zip files. 029 */ 030public abstract class ZipEncodingHelper { 031 032 033 /** 034 * name of the encoding UTF-8 035 */ 036 static final String UTF8 = "UTF8"; 037 038 /** 039 * the encoding UTF-8 040 */ 041 static final ZipEncoding UTF8_ZIP_ENCODING = getZipEncoding(UTF8); 042 043 /** 044 * Instantiates a zip encoding. An NIO based character set encoder/decoder will be returned. 045 * As a special case, if the character set is UTF-8, the nio encoder will be configured replace malformed and 046 * unmappable characters with '?'. This matches existing behavior from the older fallback encoder. 047 * <p> 048 * If the requested characer set cannot be found, the platform default will 049 * be used instead. 050 * </p> 051 * @param name The name of the zip encoding. Specify {@code null} for 052 * the platform's default encoding. 053 * @return A zip encoding for the given encoding name. 054 */ 055 public static ZipEncoding getZipEncoding(final String name) { 056 Charset cs = Charset.defaultCharset(); 057 if (name != null) { 058 try { 059 cs = Charset.forName(name); 060 } catch (UnsupportedCharsetException e) { // NOSONAR we use the default encoding instead 061 } 062 } 063 boolean useReplacement = isUTF8(cs.name()); 064 return new NioZipEncoding(cs, useReplacement); 065 } 066 067 /** 068 * Returns whether a given encoding is UTF-8. If the given name is null, then check the platform's default encoding. 069 * 070 * @param charsetName If the given name is null, then check the platform's default encoding. 071 */ 072 static boolean isUTF8(String charsetName) { 073 if (charsetName == null) { 074 // check platform's default encoding 075 charsetName = Charset.defaultCharset().name(); 076 } 077 if (StandardCharsets.UTF_8.name().equalsIgnoreCase(charsetName)) { 078 return true; 079 } 080 for (final String alias : StandardCharsets.UTF_8.aliases()) { 081 if (alias.equalsIgnoreCase(charsetName)) { 082 return true; 083 } 084 } 085 return false; 086 } 087 088 static ByteBuffer growBufferBy(ByteBuffer buffer, int increment) { 089 ((Buffer)buffer).limit(buffer.position()); 090 ((Buffer)buffer).rewind(); 091 092 final ByteBuffer on = ByteBuffer.allocate(buffer.capacity() + increment); 093 094 on.put(buffer); 095 return on; 096 } 097}