Skip to content

Commit e44faf9

Browse files
author
Nicola Ken Barozzi
committed
New zip classes from Avalon excalibur.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/io/trunk@140304 13f79535-47bb-0310-9956-ffa450edef68
1 parent 70492fe commit e44faf9

10 files changed

Lines changed: 2311 additions & 0 deletions

File tree

Lines changed: 398 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,398 @@
1+
/*
2+
* Copyright (C) The Apache Software Foundation. All rights reserved.
3+
*
4+
* This software is published under the terms of the Apache Software License
5+
* version 1.1, a copy of which has been included with this distribution in
6+
* the LICENSE.txt file.
7+
*/
8+
package org.apache.commons.io.compress.zip;
9+
10+
import java.util.zip.CRC32;
11+
import java.util.zip.ZipException;
12+
13+
/**
14+
* Adds Unix file permission and UID/GID fields as well as symbolic link
15+
* handling. <p>
16+
*
17+
* This class uses the ASi extra field in the format: <pre>
18+
* Value Size Description
19+
* ----- ---- -----------
20+
* (Unix3) 0x756e Short tag for this extra block type
21+
* TSize Short total data size for this block
22+
* CRC Long CRC-32 of the remaining data
23+
* Mode Short file permissions
24+
* SizDev Long symlink'd size OR major/minor dev num
25+
* UID Short user ID
26+
* GID Short group ID
27+
* (var.) variable symbolic link filename
28+
* </pre> taken from appnote.iz (Info-ZIP note, 981119) found at <a
29+
* href="ftp://ftp.uu.net/pub/archiving/zip/doc/">
30+
* ftp://ftp.uu.net/pub/archiving/zip/doc/</a> </p> <p>
31+
*
32+
* Short is two bytes and Long is four bytes in big endian byte and word order,
33+
* device numbers are currently not supported.</p>
34+
*
35+
* @author <a href="stefan.bodewig@epost.de">Stefan Bodewig</a>
36+
* @version $Revision: 1.1 $
37+
*/
38+
public class AsiExtraField
39+
implements ZipExtraField, UnixStat, Cloneable
40+
{
41+
private static final ZipShort HEADER_ID = new ZipShort( 0x756E );
42+
43+
/**
44+
* Standard Unix stat(2) file mode.
45+
*
46+
* @since 1.1
47+
*/
48+
private int m_mode;
49+
50+
/**
51+
* User ID.
52+
*
53+
* @since 1.1
54+
*/
55+
private int m_uid;
56+
57+
/**
58+
* Group ID.
59+
*
60+
* @since 1.1
61+
*/
62+
private int m_gid;
63+
64+
/**
65+
* File this entry points to, if it is a symbolic link. <p>
66+
*
67+
* empty string - if entry is not a symbolic link.</p>
68+
*
69+
* @since 1.1
70+
*/
71+
private String m_link = "";
72+
73+
/**
74+
* Is this an entry for a directory?
75+
*
76+
* @since 1.1
77+
*/
78+
private boolean m_dirFlag;
79+
80+
/**
81+
* Instance used to calculate checksums.
82+
*
83+
* @since 1.1
84+
*/
85+
private CRC32 m_crc = new CRC32();
86+
87+
/**
88+
* Indicate whether this entry is a directory.
89+
*
90+
* @param dirFlag The new Directory value
91+
* @since 1.1
92+
*/
93+
public void setDirectory( final boolean dirFlag )
94+
{
95+
m_dirFlag = dirFlag;
96+
m_mode = getMode( m_mode );
97+
}
98+
99+
/**
100+
* Set the group id.
101+
*
102+
* @param gid The new GroupId value
103+
* @since 1.1
104+
*/
105+
public void setGroupId( int gid )
106+
{
107+
m_gid = gid;
108+
}
109+
110+
/**
111+
* Indicate that this entry is a symbolic link to the given filename.
112+
*
113+
* @param name Name of the file this entry links to, empty String if it is
114+
* not a symbolic link.
115+
* @since 1.1
116+
*/
117+
public void setLinkedFile( final String name )
118+
{
119+
m_link = name;
120+
m_mode = getMode( m_mode );
121+
}
122+
123+
/**
124+
* File mode of this file.
125+
*
126+
* @param mode The new Mode value
127+
* @since 1.1
128+
*/
129+
public void setMode( final int mode )
130+
{
131+
m_mode = getMode( mode );
132+
}
133+
134+
/**
135+
* Set the user id.
136+
*
137+
* @param uid The new UserId value
138+
* @since 1.1
139+
* @deprecated Use setUserID(int)
140+
* @see #setUserID(int)
141+
*/
142+
public void setUserId( final int uid )
143+
{
144+
m_uid = uid;
145+
}
146+
147+
/**
148+
* Set the user id.
149+
*
150+
* @param uid The new UserId value
151+
*/
152+
public void setUserID( final int uid )
153+
{
154+
m_uid = uid;
155+
}
156+
157+
/**
158+
* Delegate to local file data.
159+
*
160+
* @return The CentralDirectoryData value
161+
* @since 1.1
162+
*/
163+
public byte[] getCentralDirectoryData()
164+
{
165+
return getLocalFileDataData();
166+
}
167+
168+
/**
169+
* Delegate to local file data.
170+
*
171+
* @return The CentralDirectoryLength value
172+
* @since 1.1
173+
*/
174+
public ZipShort getCentralDirectoryLength()
175+
{
176+
return getLocalFileDataLength();
177+
}
178+
179+
/**
180+
* Get the group id.
181+
*
182+
* @return The GroupId value
183+
* @since 1.1
184+
*/
185+
public int getGroupID()
186+
{
187+
return m_gid;
188+
}
189+
190+
/**
191+
* Get the group id.
192+
*
193+
* @return The GroupId value
194+
* @since 1.1
195+
* @deprecated Use getGroupID() instead
196+
* @see #getGroupID()
197+
*/
198+
public int getGroupId()
199+
{
200+
return m_gid;
201+
}
202+
203+
/**
204+
* The Header-ID.
205+
*
206+
* @return The HeaderId value
207+
* @since 1.1
208+
*/
209+
public ZipShort getHeaderID()
210+
{
211+
return HEADER_ID;
212+
}
213+
214+
/**
215+
* Name of linked file
216+
*
217+
* @return name of the file this entry links to if it is a symbolic link,
218+
* the empty string otherwise.
219+
* @since 1.1
220+
*/
221+
public String getLinkedFile()
222+
{
223+
return m_link;
224+
}
225+
226+
/**
227+
* The actual data to put into local file data - without Header-ID or length
228+
* specifier.
229+
*
230+
* @return The LocalFileDataData value
231+
* @since 1.1
232+
*/
233+
public byte[] getLocalFileDataData()
234+
{
235+
// CRC will be added later
236+
byte[] data = new byte[ getLocalFileDataLength().getValue() - 4 ];
237+
System.arraycopy( ( new ZipShort( getMode() ) ).getBytes(), 0, data, 0, 2 );
238+
239+
byte[] linkArray = getLinkedFile().getBytes();
240+
System.arraycopy( ( new ZipLong( linkArray.length ) ).getBytes(),
241+
0, data, 2, 4 );
242+
243+
System.arraycopy( ( new ZipShort( getUserID() ) ).getBytes(),
244+
0, data, 6, 2 );
245+
System.arraycopy( ( new ZipShort( getGroupID() ) ).getBytes(),
246+
0, data, 8, 2 );
247+
248+
System.arraycopy( linkArray, 0, data, 10, linkArray.length );
249+
250+
m_crc.reset();
251+
m_crc.update( data );
252+
long checksum = m_crc.getValue();
253+
254+
byte[] result = new byte[ data.length + 4 ];
255+
System.arraycopy( ( new ZipLong( checksum ) ).getBytes(), 0, result, 0, 4 );
256+
System.arraycopy( data, 0, result, 4, data.length );
257+
return result;
258+
}
259+
260+
/**
261+
* Length of the extra field in the local file data - without Header-ID or
262+
* length specifier.
263+
*
264+
* @return The LocalFileDataLength value
265+
* @since 1.1
266+
*/
267+
public ZipShort getLocalFileDataLength()
268+
{
269+
return new ZipShort( 4 + // CRC
270+
2 + // Mode
271+
4 + // SizDev
272+
2 + // UID
273+
2 + // GID
274+
getLinkedFile().getBytes().length );
275+
}
276+
277+
/**
278+
* File mode of this file.
279+
*
280+
* @return The Mode value
281+
* @since 1.1
282+
*/
283+
public int getMode()
284+
{
285+
return m_mode;
286+
}
287+
288+
/**
289+
* Get the user id.
290+
*
291+
* @return The UserId value
292+
* @since 1.1
293+
* @deprecated Use getUserID()
294+
* @see #getUserID()
295+
*/
296+
public int getUserId()
297+
{
298+
return m_uid;
299+
}
300+
301+
/**
302+
* Get the user id.
303+
*
304+
* @return The UserID value
305+
*/
306+
public int getUserID()
307+
{
308+
return m_uid;
309+
}
310+
311+
/**
312+
* Is this entry a directory?
313+
*
314+
* @return The Directory value
315+
* @since 1.1
316+
*/
317+
public boolean isDirectory()
318+
{
319+
return m_dirFlag && !isLink();
320+
}
321+
322+
/**
323+
* Is this entry a symbolic link?
324+
*
325+
* @return The Link value
326+
* @since 1.1
327+
*/
328+
public boolean isLink()
329+
{
330+
return getLinkedFile().length() != 0;
331+
}
332+
333+
/**
334+
* Populate data from this array as if it was in local file data.
335+
*
336+
* @param buffer the buffer
337+
* @param offset the offset into buffer
338+
* @param length the length of data in buffer
339+
* @throws ZipException on error
340+
* @since 1.1
341+
*/
342+
public void parseFromLocalFileData( final byte[] buffer,
343+
final int offset,
344+
final int length )
345+
throws ZipException
346+
{
347+
348+
long givenChecksum = ( new ZipLong( buffer, offset ) ).getValue();
349+
byte[] tmp = new byte[ length - 4 ];
350+
System.arraycopy( buffer, offset + 4, tmp, 0, length - 4 );
351+
m_crc.reset();
352+
m_crc.update( tmp );
353+
long realChecksum = m_crc.getValue();
354+
if( givenChecksum != realChecksum )
355+
{
356+
throw new ZipException( "bad CRC checksum " + Long.toHexString( givenChecksum ) +
357+
" instead of " + Long.toHexString( realChecksum ) );
358+
}
359+
360+
int newMode = ( new ZipShort( tmp, 0 ) ).getValue();
361+
byte[] linkArray = new byte[ (int)( new ZipLong( tmp, 2 ) ).getValue() ];
362+
m_uid = ( new ZipShort( tmp, 6 ) ).getValue();
363+
m_gid = ( new ZipShort( tmp, 8 ) ).getValue();
364+
365+
if( linkArray.length == 0 )
366+
{
367+
m_link = "";
368+
}
369+
else
370+
{
371+
System.arraycopy( tmp, 10, linkArray, 0, linkArray.length );
372+
m_link = new String( linkArray );
373+
}
374+
setDirectory( ( newMode & DIR_FLAG ) != 0 );
375+
setMode( newMode );
376+
}
377+
378+
/**
379+
* Get the file mode for given permissions with the correct file type.
380+
*
381+
* @param mode Description of Parameter
382+
* @return The Mode value
383+
* @since 1.1
384+
*/
385+
protected int getMode( final int mode )
386+
{
387+
int type = FILE_FLAG;
388+
if( isLink() )
389+
{
390+
type = LINK_FLAG;
391+
}
392+
else if( isDirectory() )
393+
{
394+
type = DIR_FLAG;
395+
}
396+
return type | ( mode & PERM_MASK );
397+
}
398+
}

0 commit comments

Comments
 (0)