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 018package org.apache.commons.compress.archivers.zip; 019 020import static java.nio.charset.StandardCharsets.UTF_8; 021 022import java.nio.ByteBuffer; 023import java.nio.charset.Charset; 024import java.nio.charset.UnsupportedCharsetException; 025 026/** 027 * Static helper functions for robustly encoding file names in ZIP files. 028 */ 029public abstract class ZipEncodingHelper { 030 031 032 /** 033 * name of the encoding UTF-8 034 */ 035 static final String UTF8 = "UTF8"; 036 037 /** 038 * the encoding UTF-8 039 */ 040 static final ZipEncoding UTF8_ZIP_ENCODING = getZipEncoding(UTF8); 041 042 /** 043 * Instantiates a ZIP encoding. An NIO based character set encoder/decoder will be returned. 044 * As a special case, if the character set is UTF-8, the nio encoder will be configured replace malformed and 045 * unmappable characters with '?'. This matches existing behavior from the older fallback encoder. 046 * <p> 047 * If the requested character set cannot be found, the platform default will 048 * be used instead. 049 * </p> 050 * @param name The name of the ZIP encoding. Specify {@code null} for 051 * the platform's default encoding. 052 * @return A ZIP encoding for the given encoding name. 053 */ 054 public static ZipEncoding getZipEncoding(final String name) { 055 Charset cs = Charset.defaultCharset(); 056 if (name != null) { 057 try { 058 cs = Charset.forName(name); 059 } catch (final UnsupportedCharsetException e) { // NOSONAR we use the default encoding instead 060 } 061 } 062 final boolean useReplacement = isUTF8(cs.name()); 063 return new NioZipEncoding(cs, useReplacement); 064 } 065 066 static ByteBuffer growBufferBy(final ByteBuffer buffer, final int increment) { 067 buffer.limit(buffer.position()); 068 buffer.rewind(); 069 070 final ByteBuffer on = ByteBuffer.allocate(buffer.capacity() + increment); 071 072 on.put(buffer); 073 return on; 074 } 075 076 /** 077 * Returns whether a given encoding is UTF-8. If the given name is null, then check the platform's default encoding. 078 * 079 * @param charsetName If the given name is null, then check the platform's default encoding. 080 */ 081 static boolean isUTF8(final String charsetName) { 082 final String actual = charsetName != null ? charsetName : Charset.defaultCharset().name(); 083 if (UTF_8.name().equalsIgnoreCase(actual)) { 084 return true; 085 } 086 return UTF_8.aliases().stream().anyMatch(alias -> alias.equalsIgnoreCase(actual)); 087 } 088}