static int read_central_dir_values(Zipfile* file, const unsigned char* buf, int len) { if (len < EOCD_LEN) { // looks like ZIP file got truncated fprintf(stderr, " Zip EOCD: expected >= %d bytes, found %d\n", EOCD_LEN, len); return -1; } file->disknum = read_le_short(&buf[0x04]); file->diskWithCentralDir = read_le_short(&buf[0x06]); file->entryCount = read_le_short(&buf[0x08]); file->totalEntryCount = read_le_short(&buf[0x0a]); file->centralDirSize = read_le_int(&buf[0x0c]); file->centralDirOffest = read_le_int(&buf[0x10]); file->commentLen = read_le_short(&buf[0x14]); if (file->commentLen > 0) { if (EOCD_LEN + file->commentLen > len) { fprintf(stderr, "EOCD(%d) + comment(%d) exceeds len (%d)\n", EOCD_LEN, file->commentLen, len); return -1; } file->comment = buf + EOCD_LEN; } return 0; }
static int read_central_directory_entry(Zipfile* file, Zipentry* entry, const unsigned char** buf, ssize_t* len) { const unsigned char* p; unsigned short versionMadeBy; unsigned short versionToExtract; unsigned short gpBitFlag; unsigned short compressionMethod; unsigned short lastModFileTime; unsigned short lastModFileDate; unsigned long crc32; unsigned short extraFieldLength; unsigned short fileCommentLength; unsigned short diskNumberStart; unsigned short internalAttrs; unsigned long externalAttrs; unsigned long localHeaderRelOffset; const unsigned char* extraField; const unsigned char* fileComment; unsigned int dataOffset; unsigned short lfhExtraFieldSize; p = *buf; if (*len < ENTRY_LEN) { fprintf(stderr, "cde entry not large enough\n"); return -1; } if (read_le_int(&p[0x00]) != ENTRY_SIGNATURE) { fprintf(stderr, "Whoops: didn't find expected signature\n"); return -1; } versionMadeBy = read_le_short(&p[0x04]); versionToExtract = read_le_short(&p[0x06]); gpBitFlag = read_le_short(&p[0x08]); entry->compressionMethod = read_le_short(&p[0x0a]); lastModFileTime = read_le_short(&p[0x0c]); lastModFileDate = read_le_short(&p[0x0e]); crc32 = read_le_int(&p[0x10]); entry->compressedSize = read_le_int(&p[0x14]); entry->uncompressedSize = read_le_int(&p[0x18]); entry->fileNameLength = read_le_short(&p[0x1c]); extraFieldLength = read_le_short(&p[0x1e]); fileCommentLength = read_le_short(&p[0x20]); diskNumberStart = read_le_short(&p[0x22]); internalAttrs = read_le_short(&p[0x24]); externalAttrs = read_le_int(&p[0x26]); localHeaderRelOffset = read_le_int(&p[0x2a]); p += ENTRY_LEN; // filename if (entry->fileNameLength != 0) { entry->fileName = p; } else { entry->fileName = NULL; } p += entry->fileNameLength; // extra field if (extraFieldLength != 0) { extraField = p; } else { extraField = NULL; } p += extraFieldLength; // comment, if any if (fileCommentLength != 0) { fileComment = p; } else { fileComment = NULL; } p += fileCommentLength; *buf = p; // the size of the extraField in the central dir is how much data there is, // but the one in the local file header also contains some padding. p = file->buf + localHeaderRelOffset; extraFieldLength = read_le_short(&p[0x1c]); dataOffset = localHeaderRelOffset + LFH_SIZE + entry->fileNameLength + extraFieldLength; entry->data = file->buf + dataOffset; #if 0 printf("file->buf=%p entry->data=%p dataOffset=%x localHeaderRelOffset=%d " "entry->fileNameLength=%d extraFieldLength=%d\n", file->buf, entry->data, dataOffset, localHeaderRelOffset, entry->fileNameLength, extraFieldLength); #endif return 0; }
Track *wav_get_file_info(const gchar *filename, GError **error) { Track *track = NULL; gchar *fn; gchar magic[4]; gulong len; WaveFile *wav_file; wav_file = g_malloc(sizeof(WaveFile)); memset(wav_file, 0, sizeof(WaveFile)); if (!(wav_file->file = fopen(filename, "rb"))) { gchar *fn = charset_to_utf8(filename); gtkpod_log_error(error, g_strdup_printf(_("Could not open '%s' for reading.\n"), fn)); g_free(fn); g_free(wav_file); wav_file = NULL; return NULL; } fread(magic, 1, 4, wav_file->file); if (strncmp(magic, "RIFF", 4) != 0) goto file_error; read_le_long(wav_file->file, &len); fread(magic, 1, 4, wav_file->file); if (strncmp(magic, "WAVE", 4) != 0) goto file_error; for (;;) { fread(magic, 1, 4, wav_file->file); if (!read_le_long(wav_file->file, &len)) goto file_error; if (!strncmp("fmt ", magic, 4)) break; fseek(wav_file->file, len, SEEK_CUR); } if (len < 16) goto file_error; read_le_short(wav_file->file, &wav_file->format_tag); switch (wav_file->format_tag) { case WAVE_FORMAT_UNKNOWN: case WAVE_FORMAT_ALAW: case WAVE_FORMAT_MULAW: case WAVE_FORMAT_ADPCM: case WAVE_FORMAT_OKI_ADPCM: case WAVE_FORMAT_DIGISTD: case WAVE_FORMAT_DIGIFIX: case IBM_FORMAT_MULAW: case IBM_FORMAT_ALAW: case IBM_FORMAT_ADPCM: goto file_error; } read_le_short(wav_file->file, &wav_file->channels); read_le_long(wav_file->file, &wav_file->samples_per_sec); read_le_long(wav_file->file, &wav_file->avg_bytes_per_sec); read_le_short(wav_file->file, &wav_file->block_align); read_le_short(wav_file->file, &wav_file->bits_per_sample); /* if (wav_file->bits_per_sample != 8 && wav_file->bits_per_sample != 16) goto file_error;*/ len -= 16; if (len) fseek(wav_file->file, len, SEEK_CUR); for (;;) { fread(magic, 4, 1, wav_file->file); if (!read_le_long(wav_file->file, &len)) goto file_error; if (!strncmp("data", magic, 4)) break; fseek(wav_file->file, len, SEEK_CUR); } track = gp_track_new(); track->mediatype = ITDB_MEDIATYPE_AUDIO; track->bitrate = wav_file->samples_per_sec * wav_file->channels * wav_file->bits_per_sample; track->samplerate = wav_file->samples_per_sec; track->tracklen = 1000 * ((double) 8 * len / track->bitrate); track->bitrate /= 1000; /* change to kbps */ track->filetype = g_strdup(_("WAV audio file")); fclose(wav_file->file); g_free(wav_file); wav_file = NULL; return track; file_error: fclose(wav_file->file); g_free(wav_file); wav_file = NULL; fn = charset_to_utf8(filename); gtkpod_log_error(error, g_strdup_printf(_("%s does not appear to be a supported wav file.\n"), fn)); g_free(fn); return NULL; }
static int read_central_directory_entry(Zipfile* file, Zipentry* entry, const unsigned char** buf, ssize_t* len) { const unsigned char* p; unsigned short extraFieldLength; unsigned short fileCommentLength; unsigned long localHeaderRelOffset; unsigned int dataOffset; p = *buf; if (*len < ENTRY_LEN) { fprintf(stderr, "cde entry not large enough\n"); return -1; } if (read_le_int(&p[0x00]) != ENTRY_SIGNATURE) { fprintf(stderr, "Whoops: didn't find expected signature\n"); return -1; } entry->compressionMethod = read_le_short(&p[0x0a]); entry->compressedSize = read_le_int(&p[0x14]); entry->uncompressedSize = read_le_int(&p[0x18]); entry->fileNameLength = read_le_short(&p[0x1c]); extraFieldLength = read_le_short(&p[0x1e]); fileCommentLength = read_le_short(&p[0x20]); localHeaderRelOffset = read_le_int(&p[0x2a]); p += ENTRY_LEN; // filename if (entry->fileNameLength != 0) { entry->fileName = p; } else { entry->fileName = NULL; } p += entry->fileNameLength; // extra field p += extraFieldLength; // comment, if any p += fileCommentLength; *buf = p; // the size of the extraField in the central dir is how much data there is, // but the one in the local file header also contains some padding. p = file->buf + localHeaderRelOffset; extraFieldLength = read_le_short(&p[0x1c]); dataOffset = localHeaderRelOffset + LFH_SIZE + entry->fileNameLength + extraFieldLength; entry->data = file->buf + dataOffset; #if 0 printf("file->buf=%p entry->data=%p dataOffset=%x localHeaderRelOffset=%d " "entry->fileNameLength=%d extraFieldLength=%d\n", file->buf, entry->data, dataOffset, localHeaderRelOffset, entry->fileNameLength, extraFieldLength); #endif return 0; }