|  | @@ -850,29 +850,33 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
 | 
	
		
			
				|  |  |  		zip_entry->mode |= AE_IFREG;
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	if ((zip_entry->mode & AE_IFMT) == 0) {
 | 
	
		
			
				|  |  | -		/* Especially in streaming mode, we can end up
 | 
	
		
			
				|  |  | -		   here without having seen proper mode information.
 | 
	
		
			
				|  |  | -		   Guess from the filename. */
 | 
	
		
			
				|  |  | +	/* If the mode is totally empty, set some sane default. */
 | 
	
		
			
				|  |  | +	if (zip_entry->mode == 0) {
 | 
	
		
			
				|  |  | +		zip_entry->mode |= 0664;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	/* Make sure that entries with a trailing '/' are marked as directories
 | 
	
		
			
				|  |  | +	 * even if the External File Attributes contains bogus values.  If this
 | 
	
		
			
				|  |  | +	 * is not a directory and there is no type, assume regularfile. */
 | 
	
		
			
				|  |  | +	if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
 | 
	
		
			
				|  |  | +		int has_slash;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  		wp = archive_entry_pathname_w(entry);
 | 
	
		
			
				|  |  |  		if (wp != NULL) {
 | 
	
		
			
				|  |  |  			len = wcslen(wp);
 | 
	
		
			
				|  |  | -			if (len > 0 && wp[len - 1] == L'/')
 | 
	
		
			
				|  |  | -				zip_entry->mode |= AE_IFDIR;
 | 
	
		
			
				|  |  | -			else
 | 
	
		
			
				|  |  | -				zip_entry->mode |= AE_IFREG;
 | 
	
		
			
				|  |  | +			has_slash = len > 0 && wp[len - 1] == L'/';
 | 
	
		
			
				|  |  |  		} else {
 | 
	
		
			
				|  |  |  			cp = archive_entry_pathname(entry);
 | 
	
		
			
				|  |  |  			len = (cp != NULL)?strlen(cp):0;
 | 
	
		
			
				|  |  | -			if (len > 0 && cp[len - 1] == '/')
 | 
	
		
			
				|  |  | -				zip_entry->mode |= AE_IFDIR;
 | 
	
		
			
				|  |  | -			else
 | 
	
		
			
				|  |  | -				zip_entry->mode |= AE_IFREG;
 | 
	
		
			
				|  |  | +			has_slash = len > 0 && cp[len - 1] == '/';
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  | -		if (zip_entry->mode == AE_IFDIR) {
 | 
	
		
			
				|  |  | -			zip_entry->mode |= 0775;
 | 
	
		
			
				|  |  | -		} else if (zip_entry->mode == AE_IFREG) {
 | 
	
		
			
				|  |  | -			zip_entry->mode |= 0664;
 | 
	
		
			
				|  |  | +		/* Correct file type as needed. */
 | 
	
		
			
				|  |  | +		if (has_slash) {
 | 
	
		
			
				|  |  | +			zip_entry->mode &= ~AE_IFMT;
 | 
	
		
			
				|  |  | +			zip_entry->mode |= AE_IFDIR;
 | 
	
		
			
				|  |  | +			zip_entry->mode |= 0111;
 | 
	
		
			
				|  |  | +		} else if ((zip_entry->mode & AE_IFMT) == 0) {
 | 
	
		
			
				|  |  | +			zip_entry->mode |= AE_IFREG;
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 |