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