"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "odt2txt-0.4/kunzip/zipfile.c" of archive odt2txt-0.4.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 #include <stdio.h>
    2 #include <stdlib.h>
    3 #include <string.h>
    4 #include <sys/stat.h>
    5 #include <sys/types.h>
    6 #include <utime.h>
    7 #include <time.h>
    8 #include <unistd.h>
    9 
   10 #include "fileio.h"
   11 #include "zipfile.h"
   12 #include "kunzip.h"
   13 #include "../strbuf.h"
   14 #include "../mem.h"
   15 
   16 /*
   17 
   18 This code is Copyright 2005-2006 by Michael Kohn
   19 
   20 This program is free software; you can redistribute it and/or
   21 modify it under the terms of the GNU General Public License,
   22 version 2 as published by the Free Software Foundation
   23 
   24 */
   25 
   26 #define BUFFER_SIZE 16738
   27 
   28 /* #define _GNU_SOURCE */
   29 
   30 unsigned int copy_file_tobuf(FILE *in, STRBUF *out, int len)
   31 {
   32 	unsigned char buffer[BUFFER_SIZE];
   33 	uLong checksum;
   34 	int t, r;
   35 
   36 	checksum = crc32(0L, Z_NULL, 0);
   37 
   38 	t = 0;
   39 
   40 	while (t < len) {
   41 		if (t + BUFFER_SIZE < len) {
   42 			r = BUFFER_SIZE;
   43 		} else {
   44 			r = len - t;
   45 		}
   46 
   47 		read_buffer(in, buffer, r);
   48 		strbuf_append_n(out, (char *)buffer, r);
   49 		checksum = crc32(checksum, buffer, r);
   50 		t = t + r;
   51 	}
   52 
   53 	return checksum;
   54 }
   55 
   56 int read_zip_header(FILE *in,
   57 		    struct zip_local_file_header_t *local_file_header)
   58 {
   59 	local_file_header->signature = read_int(in);
   60 	if (local_file_header->signature != 0x04034b50)
   61 		return -1;
   62 
   63 	local_file_header->version = read_word(in);
   64 	local_file_header->general_purpose_bit_flag = read_word(in);
   65 	local_file_header->compression_method = read_word(in);
   66 	local_file_header->last_mod_file_time = read_word(in);
   67 	local_file_header->last_mod_file_date = read_word(in);
   68 	local_file_header->crc_32 = read_int(in);
   69 	local_file_header->compressed_size = read_int(in);
   70 	local_file_header->uncompressed_size = read_int(in);
   71 	local_file_header->file_name_length = read_word(in);
   72 	local_file_header->extra_field_length = read_word(in);
   73 	local_file_header->descriptor_length = 0;
   74 
   75 	/* if the 4th bit in the general_purpose_bit_flag is set,
   76 	   crc32, compressed_size and uncompressed_size are written
   77 	   into a data descriptor that follows the compressed
   78 	   data */
   79 	if (local_file_header->general_purpose_bit_flag & 8) {
   80 		long data_start = ftell(in);
   81 		unsigned int signature;
   82 
   83 		while (1) {
   84 			signature = read_int(in);
   85 
   86 			if (feof(in)) {
   87 				fseek(in, data_start, SEEK_SET);
   88 				return -1;
   89 			}
   90 
   91 			if (signature == 0x08074b50) {
   92 				local_file_header->crc_32 = read_int(in);
   93 				local_file_header->compressed_size =
   94 					read_int(in);
   95 				local_file_header->uncompressed_size =
   96 					read_int(in);
   97 				local_file_header->descriptor_length = 16;
   98 				fseek(in, data_start, SEEK_SET);
   99 				return 0;
  100 			}
  101 
  102 			fseek(in, -3, SEEK_CUR);
  103 		}
  104 
  105 	}
  106 	return 0;
  107 }
  108 
  109 #ifdef DEBUG
  110 int print_zip_header(struct zip_local_file_header_t *local_file_header)
  111 {
  112 	printf("ZIP LOCAL FILE HEADER\n");
  113 	printf("----------------------------------\n");
  114 	printf("Signature: %02x%02x%02x%02x\n",
  115 	       ((local_file_header->signature >> 24) & 255),
  116 	       ((local_file_header->signature >> 16) & 255),
  117 	       ((local_file_header->signature >> 8) & 255),
  118 	       (local_file_header->signature & 255));
  119 	printf("Version: %d\n", local_file_header->version);
  120 	printf("General Purpose Bit Flag: %d\n",
  121 	       local_file_header->general_purpose_bit_flag);
  122 	printf("Compression Method: %d\n",
  123 	       local_file_header->compression_method);
  124 	printf("Last Mod File Time: %d\n",
  125 	       local_file_header->last_mod_file_time);
  126 	printf("Last Mod File Date: %d\n",
  127 	       local_file_header->last_mod_file_date);
  128 	printf("CRC-32: %d\n", local_file_header->crc_32);
  129 	printf("Compressed Size: %d\n", local_file_header->compressed_size);
  130 	printf("Uncompressed Size: %d\n", local_file_header->uncompressed_size);
  131 	printf("File Name Length: %d\n", local_file_header->file_name_length);
  132 	printf("Extra Field Length: %d\n",
  133 	       local_file_header->extra_field_length);
  134 	printf("File Name: %s\n", local_file_header->file_name);
  135 
  136 	return 0;
  137 }
  138 #endif
  139 
  140 STRBUF *kunzip_file_tobuf(FILE *in)
  141 {
  142 	STRBUF *out;
  143 	struct zip_local_file_header_t local_file_header;
  144 	int ret_code;
  145 	int checksum;
  146 	long marker;
  147 
  148 	ret_code = 0;
  149 
  150 	if (read_zip_header(in, &local_file_header) == -1)
  151 		return NULL;
  152 
  153 	local_file_header.file_name =
  154 		(char *)ymalloc(local_file_header.file_name_length + 1);
  155 	local_file_header.extra_field =
  156 		(unsigned char *)ymalloc(local_file_header.extra_field_length + 1);
  157 
  158 	read_chars(in, local_file_header.file_name,
  159 		   local_file_header.file_name_length);
  160 	read_chars(in, (char *)local_file_header.extra_field,
  161 		   local_file_header.extra_field_length);
  162 
  163 	marker = ftell(in);
  164 
  165 #ifdef DEBUG
  166 	print_zip_header(&local_file_header);
  167 #endif
  168 
  169 	out = strbuf_new();
  170 
  171 	if (local_file_header.compression_method == 0) {
  172 		checksum =
  173 			copy_file_tobuf(in, out,
  174 					local_file_header.uncompressed_size);
  175 	} else if (local_file_header.compression_method == Z_DEFLATED) {
  176 		(void)strbuf_append_inflate(out, in);
  177 		checksum = strbuf_crc32(out);
  178 	} else {
  179 		fprintf(stderr, "Unknown compression method\n");
  180 		exit(EXIT_FAILURE);
  181 	}
  182 
  183 	if ((unsigned int)checksum != local_file_header.crc_32
  184 	    && local_file_header.crc_32 != 0) {
  185 		fprintf(stderr,
  186 			"Warning: Checksum does not match: %d %d.\nPossibly the file"
  187 			" is corrupted otr truncated.\n", checksum,
  188 			local_file_header.crc_32);
  189 		ret_code = -4;
  190 	}
  191 
  192 	yfree(local_file_header.file_name);
  193 	yfree(local_file_header.extra_field);
  194 
  195 	fseek(in, marker + local_file_header.compressed_size, SEEK_SET);
  196 
  197 	if ((local_file_header.general_purpose_bit_flag & 8) != 0) {
  198 		read_int(in);
  199 		read_int(in);
  200 		read_int(in);
  201 	}
  202 
  203 	return out;
  204 }
  205 
  206 STRBUF *kunzip_next_tobuf(char *zip_filename, int offset)
  207 {
  208 	FILE *in;
  209 	STRBUF *buf;
  210 	long marker;
  211 
  212 	in = fopen(zip_filename, "rb");
  213 	if (in == 0) {
  214 		return NULL;
  215 	}
  216 
  217 	fseek(in, offset, SEEK_SET);
  218 
  219 	buf = kunzip_file_tobuf(in);
  220 	marker = ftell(in);
  221 	fclose(in);
  222 
  223 	return buf;
  224 }
  225 
  226 /*
  227   Match Flags:
  228   bit 0: set to 1 if it should be exact filename match
  229   set to 0 if the archived filename only needs to contain that word
  230   bit 1: set to 1 if it should be case sensitive
  231   set to 0 if it should be case insensitive
  232 */
  233 
  234 int kunzip_get_offset_by_name(char *zip_filename, char *compressed_filename,
  235 			      int match_flags, int skip_offset)
  236 {
  237 	FILE *in;
  238 	struct zip_local_file_header_t local_file_header;
  239 	int i = 0, curr;
  240 	char *name = 0;
  241 	int name_size = 0;
  242 	long marker;
  243 
  244 	in = fopen(zip_filename, "rb");
  245 	if (in == 0) {
  246 		return -1;
  247 	}
  248 
  249 	if (skip_offset != -1) {
  250 		fseek(in, skip_offset, SEEK_SET);
  251 	}
  252 
  253 	while (1) {
  254 		curr = ftell(in);
  255 		i = read_zip_header(in, &local_file_header);
  256 		if (i == -1)
  257 			break;
  258 
  259 		if (skip_offset < 0 || curr > skip_offset) {
  260 			marker = ftell(in);	/* nasty code.. please make it nice later */
  261 
  262 			if (name_size < local_file_header.file_name_length + 1) {
  263 				if (name_size != 0)
  264 					yfree(name);
  265 				name_size =
  266 					local_file_header.file_name_length + 1;
  267 				name = ymalloc(name_size);
  268 			}
  269 
  270 			read_chars(in, name,
  271 				   local_file_header.file_name_length);
  272 			name[local_file_header.file_name_length] = 0;
  273 
  274 			fseek(in, marker, SEEK_SET);	/* and part 2 of nasty code */
  275 
  276 			if ((match_flags & 1) == 1) {
  277 				if (strcmp(compressed_filename, name) == 0)
  278 					break;
  279 			} else {
  280 				if (strstr(name, compressed_filename) != 0)
  281 					break;
  282 			}
  283 		}
  284 
  285 		fseek(in, local_file_header.compressed_size +
  286 		      local_file_header.file_name_length +
  287 		      local_file_header.extra_field_length +
  288 		      local_file_header.descriptor_length, SEEK_CUR);
  289 
  290 	}
  291 
  292 	if (name_size != 0)
  293 		yfree(name);
  294 
  295 	fclose(in);
  296 
  297 	if (i != -1) {
  298 		return curr;
  299 	} else {
  300 		return -1;
  301 	}
  302 }