Browse Source
MFH Update fileinfo to libmagic 5.00 and remove dependency on dirent.h on Windows
experimental/5.3-FPM
MFH Update fileinfo to libmagic 5.00 and remove dependency on dirent.h on Windows
experimental/5.3-FPM
27 changed files with 43144 additions and 36820 deletions
-
5ext/fileinfo/config.m4
-
26ext/fileinfo/config.w32
-
76157ext/fileinfo/data_file.c
-
2ext/fileinfo/fileinfo.c
-
126ext/fileinfo/libmagic/apprentice.c
-
9ext/fileinfo/libmagic/apptype.c
-
545ext/fileinfo/libmagic/ascmagic.c
-
1111ext/fileinfo/libmagic/cdf.c
-
298ext/fileinfo/libmagic/cdf.h
-
183ext/fileinfo/libmagic/cdf_time.c
-
12ext/fileinfo/libmagic/compress.c
-
484ext/fileinfo/libmagic/encoding.c
-
57ext/fileinfo/libmagic/file.h
-
114ext/fileinfo/libmagic/fsmagic.c
-
156ext/fileinfo/libmagic/funcs.c
-
19ext/fileinfo/libmagic/is_tar.c
-
18ext/fileinfo/libmagic/magic.c
-
16ext/fileinfo/libmagic/magic.h
-
7ext/fileinfo/libmagic/patchlevel.h
-
11ext/fileinfo/libmagic/print.c
-
262ext/fileinfo/libmagic/readcdf.c
-
27ext/fileinfo/libmagic/readelf.c
-
309ext/fileinfo/libmagic/softmagic.c
-
2ext/fileinfo/tests/finfo_buffer_basic.phpt
-
2ext/fileinfo/tests/finfo_buffer_variation1.phpt
-
2ext/fileinfo/tests/finfo_file_002.phpt
-
4ext/fileinfo/tests/finfo_file_basic.phpt
76157
ext/fileinfo/data_file.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
1111
ext/fileinfo/libmagic/cdf.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,298 @@ |
|||
/*- |
|||
* Copyright (c) 2008 Christos Zoulas |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions |
|||
* are met: |
|||
* 1. Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
|||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
|||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
/* |
|||
* Info from: http://sc.openoffice.org/compdocfileformat.pdf |
|||
*/ |
|||
|
|||
#ifndef _H_CDF_ |
|||
#define _H_CDF_ |
|||
|
|||
typedef int32_t cdf_secid_t; |
|||
|
|||
#define CDF_LOOP_LIMIT 10000 |
|||
|
|||
#define CDF_SECID_NULL 0 |
|||
#define CDF_SECID_FREE -1 |
|||
#define CDF_SECID_END_OF_CHAIN -2 |
|||
#define CDF_SECID_SECTOR_ALLOCATION_TABLE -3 |
|||
#define CDF_SECID_MASTER_SECTOR_ALLOCATION_TABLE -4 |
|||
|
|||
typedef struct { |
|||
uint64_t h_magic; |
|||
#define CDF_MAGIC 0xE11AB1A1E011CFD0LL |
|||
uint64_t h_uuid[2]; |
|||
uint16_t h_revision; |
|||
uint16_t h_version; |
|||
uint16_t h_byte_order; |
|||
uint16_t h_sec_size_p2; |
|||
uint16_t h_short_sec_size_p2; |
|||
uint8_t h_unused0[10]; |
|||
uint32_t h_num_sectors_in_sat; |
|||
uint32_t h_secid_first_directory; |
|||
uint8_t h_unused1[4]; |
|||
uint32_t h_min_size_standard_stream; |
|||
cdf_secid_t h_secid_first_sector_in_short_sat; |
|||
uint32_t h_num_sectors_in_short_sat; |
|||
cdf_secid_t h_secid_first_sector_in_master_sat; |
|||
uint32_t h_num_sectors_in_master_sat; |
|||
cdf_secid_t h_master_sat[436/4]; |
|||
} cdf_header_t; |
|||
|
|||
#define CDF_SEC_SIZE(h) (1 << (h)->h_sec_size_p2) |
|||
#define CDF_SEC_POS(h, secid) (CDF_SEC_SIZE(h) + (secid) * CDF_SEC_SIZE(h)) |
|||
#define CDF_SHORT_SEC_SIZE(h) (1 << (h)->h_short_sec_size_p2) |
|||
#define CDF_SHORT_SEC_POS(h, secid) ((secid) * CDF_SHORT_SEC_SIZE(h)) |
|||
|
|||
typedef int32_t cdf_dirid_t; |
|||
#define CDF_DIRID_NULL -1 |
|||
|
|||
typedef int64_t cdf_timestamp_t; |
|||
#define CDF_BASE_YEAR 1601 |
|||
#define CDF_TIME_PREC 10000000 |
|||
|
|||
typedef struct { |
|||
uint16_t d_name[32]; |
|||
uint16_t d_namelen; |
|||
uint8_t d_type; |
|||
#define CDF_DIR_TYPE_EMPTY 0 |
|||
#define CDF_DIR_TYPE_USER_STORAGE 1 |
|||
#define CDF_DIR_TYPE_USER_STREAM 2 |
|||
#define CDF_DIR_TYPE_LOCKBYTES 3 |
|||
#define CDF_DIR_TYPE_PROPERTY 4 |
|||
#define CDF_DIR_TYPE_ROOT_STORAGE 5 |
|||
uint8_t d_color; |
|||
#define CDF_DIR_COLOR_READ 0 |
|||
#define CDF_DIR_COLOR_BLACK 1 |
|||
cdf_dirid_t d_left_child; |
|||
cdf_dirid_t d_right_child; |
|||
cdf_dirid_t d_storage; |
|||
uint64_t d_storage_uuid[2]; |
|||
uint32_t d_flags; |
|||
cdf_timestamp_t d_created; |
|||
cdf_timestamp_t d_modified; |
|||
cdf_secid_t d_stream_first_sector; |
|||
uint32_t d_size; |
|||
uint32_t d_unused0; |
|||
} cdf_directory_t; |
|||
|
|||
#define CDF_DIRECTORY_SIZE 128 |
|||
|
|||
typedef struct { |
|||
cdf_secid_t *sat_tab; |
|||
size_t sat_len; |
|||
} cdf_sat_t; |
|||
|
|||
typedef struct { |
|||
cdf_directory_t *dir_tab; |
|||
size_t dir_len; |
|||
} cdf_dir_t; |
|||
|
|||
typedef struct { |
|||
void *sst_tab; |
|||
size_t sst_len; |
|||
size_t sst_dirlen; |
|||
} cdf_stream_t; |
|||
|
|||
typedef struct { |
|||
uint32_t cl_dword; |
|||
uint16_t cl_word[2]; |
|||
uint8_t cl_two[2]; |
|||
uint8_t cl_six[6]; |
|||
} cdf_classid_t; |
|||
|
|||
typedef struct { |
|||
uint16_t si_byte_order; |
|||
uint16_t si_zero; |
|||
uint16_t si_os_version; |
|||
uint16_t si_os; |
|||
cdf_classid_t si_class; |
|||
uint32_t si_count; |
|||
} cdf_summary_info_header_t; |
|||
|
|||
#define CDF_SECTION_DECLARATION_OFFSET 0x1c |
|||
|
|||
typedef struct { |
|||
cdf_classid_t sd_class; |
|||
uint32_t sd_offset; |
|||
} cdf_section_declaration_t; |
|||
|
|||
typedef struct { |
|||
uint32_t sh_len; |
|||
uint32_t sh_properties; |
|||
} cdf_section_header_t; |
|||
|
|||
typedef struct { |
|||
uint32_t pi_id; |
|||
uint32_t pi_type; |
|||
union { |
|||
uint16_t _pi_u16; |
|||
int16_t _pi_s16; |
|||
uint32_t _pi_u32; |
|||
int32_t _pi_s32; |
|||
uint64_t _pi_u64; |
|||
int64_t _pi_s64; |
|||
cdf_timestamp_t _pi_tp; |
|||
struct { |
|||
uint32_t s_len; |
|||
const char *s_buf; |
|||
} _pi_str; |
|||
} pi_val; |
|||
#define pi_u64 pi_val._pi_u64 |
|||
#define pi_s64 pi_val._pi_s64 |
|||
#define pi_u32 pi_val._pi_u32 |
|||
#define pi_s32 pi_val._pi_s32 |
|||
#define pi_u16 pi_val._pi_u16 |
|||
#define pi_s16 pi_val._pi_s16 |
|||
#define pi_tp pi_val._pi_tp |
|||
#define pi_str pi_val._pi_str |
|||
} cdf_property_info_t; |
|||
|
|||
#define CDF_ROUND(val, by) (((val) + (by) - 1) & ~((by) - 1)) |
|||
|
|||
/* Variant type definitions */ |
|||
#define CDF_EMPTY 0x00000000 |
|||
#define CDF_NULL 0x00000001 |
|||
#define CDF_SIGNED16 0x00000002 |
|||
#define CDF_SIGNED32 0x00000003 |
|||
#define CDF_FLOAT 0x00000004 |
|||
#define CDF_DOUBLE 0x00000005 |
|||
#define CDF_CY 0x00000006 |
|||
#define CDF_DATE 0x00000007 |
|||
#define CDF_BSTR 0x00000008 |
|||
#define CDF_DISPATCH 0x00000009 |
|||
#define CDF_ERROR 0x0000000a |
|||
#define CDF_BOOL 0x0000000b |
|||
#define CDF_VARIANT 0x0000000c |
|||
#define CDF_UNKNOWN 0x0000000d |
|||
#define CDF_DECIMAL 0x0000000e |
|||
#define CDF_SIGNED8 0x00000010 |
|||
#define CDF_UNSIGNED8 0x00000011 |
|||
#define CDF_UNSIGNED16 0x00000012 |
|||
#define CDF_UNSIGNED32 0x00000013 |
|||
#define CDF_SIGNED64 0x00000014 |
|||
#define CDF_UNSIGNED64 0x00000015 |
|||
#define CDF_INT 0x00000016 |
|||
#define CDF_UINT 0x00000017 |
|||
#define CDF_VOID 0x00000018 |
|||
#define CDF_HRESULT 0x00000019 |
|||
#define CDF_PTR 0x0000001a |
|||
#define CDF_SAFEARRAY 0x0000001b |
|||
#define CDF_CARRAY 0x0000001c |
|||
#define CDF_USERDEFINED 0x0000001d |
|||
#define CDF_LENGTH32_STRING 0x0000001e |
|||
#define CDF_LENGTH32_WSTRING 0x0000001f |
|||
#define CDF_FILETIME 0x00000040 |
|||
#define CDF_BLOB 0x00000041 |
|||
#define CDF_STREAM 0x00000042 |
|||
#define CDF_STORAGE 0x00000043 |
|||
#define CDF_STREAMED_OBJECT 0x00000044 |
|||
#define CDF_STORED_OBJECT 0x00000045 |
|||
#define CDF_BLOB_OBJECT 0x00000046 |
|||
#define CDF_CLIPBOARD 0x00000047 |
|||
#define CDF_CLSID 0x00000048 |
|||
#define CDF_VECTOR 0x00001000 |
|||
#define CDF_ARRAY 0x00002000 |
|||
#define CDF_BYREF 0x00004000 |
|||
#define CDF_RESERVED 0x00008000 |
|||
#define CDF_ILLEGAL 0x0000ffff |
|||
#define CDF_ILLEGALMASKED 0x00000fff |
|||
#define CDF_TYPEMASK 0x00000fff |
|||
|
|||
#define CDF_PROPERTY_CODE_PAGE 0x00000001 |
|||
#define CDF_PROPERTY_TITLE 0x00000002 |
|||
#define CDF_PROPERTY_SUBJECT 0x00000003 |
|||
#define CDF_PROPERTY_AUTHOR 0x00000004 |
|||
#define CDF_PROPERTY_KEYWORDS 0x00000005 |
|||
#define CDF_PROPERTY_COMMENTS 0x00000006 |
|||
#define CDF_PROPERTY_TEMPLATE 0x00000007 |
|||
#define CDF_PROPERTY_LAST_SAVED_BY 0x00000008 |
|||
#define CDF_PROPERTY_REVISION_NUMBER 0x00000009 |
|||
#define CDF_PROPERTY_TOTAL_EDITING_TIME 0x0000000a |
|||
#define CDF_PROPERTY_LAST_PRINTED 0X0000000b |
|||
#define CDF_PROPERTY_CREATE_TIME 0x0000000c |
|||
#define CDF_PROPERTY_LAST_SAVED_TIME 0x0000000d |
|||
#define CDF_PROPERTY_NUMBER_OF_PAGES 0x0000000e |
|||
#define CDF_PROPERTY_NUMBER_OF_WORDS 0x0000000f |
|||
#define CDF_PROPERTY_NUMBER_OF_CHARACTERS 0x00000010 |
|||
#define CDF_PROPERTY_THUMBNAIL 0x00000011 |
|||
#define CDF_PROPERTY_NAME_OF_APPLICATION 0x00000012 |
|||
#define CDF_PROPERTY_SECURITY 0x00000013 |
|||
#define CDF_PROPERTY_LOCALE_ID 0x80000000 |
|||
|
|||
struct timeval; |
|||
int cdf_timestamp_to_timespec(struct timeval *, cdf_timestamp_t); |
|||
int cdf_timespec_to_timestamp(cdf_timestamp_t *, const struct timeval *); |
|||
int cdf_read_header(int, cdf_header_t *); |
|||
void cdf_swap_header(cdf_header_t *); |
|||
void cdf_unpack_header(cdf_header_t *, char *); |
|||
void cdf_swap_dir(cdf_directory_t *); |
|||
void cdf_unpack_dir(cdf_directory_t *, char *); |
|||
void cdf_swap_class(cdf_classid_t *); |
|||
ssize_t cdf_read_sector(int, void *, size_t, size_t, const cdf_header_t *, |
|||
cdf_secid_t); |
|||
ssize_t cdf_read_short_sector(const cdf_stream_t *, void *, size_t, size_t, |
|||
const cdf_header_t *, cdf_secid_t); |
|||
int cdf_read_sat(int, cdf_header_t *, cdf_sat_t *); |
|||
size_t cdf_count_chain(const cdf_header_t *, const cdf_sat_t *, |
|||
cdf_secid_t); |
|||
int cdf_read_long_sector_chain(int, const cdf_header_t *, |
|||
const cdf_sat_t *, cdf_secid_t, size_t, cdf_stream_t *); |
|||
int cdf_read_short_sector_chain(const cdf_header_t *, const cdf_sat_t *, |
|||
const cdf_stream_t *, cdf_secid_t, size_t, cdf_stream_t *); |
|||
int cdf_read_sector_chain(int, const cdf_header_t *, |
|||
const cdf_sat_t *, const cdf_sat_t *, const cdf_stream_t *, cdf_secid_t, |
|||
size_t, cdf_stream_t *); |
|||
int cdf_read_dir(int, const cdf_header_t *, const cdf_sat_t *, cdf_dir_t *); |
|||
int cdf_read_ssat(int, const cdf_header_t *, const cdf_sat_t *, cdf_sat_t *); |
|||
int cdf_read_short_stream(int, const cdf_header_t *, const cdf_sat_t *, |
|||
const cdf_dir_t *, cdf_stream_t *); |
|||
int cdf_read_property_info(const cdf_stream_t *, uint32_t, |
|||
cdf_property_info_t **, size_t *, size_t *); |
|||
int cdf_read_summary_info(int, const cdf_header_t *, const cdf_sat_t *, |
|||
const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *, |
|||
cdf_stream_t *); |
|||
int cdf_unpack_summary_info(const cdf_stream_t *, cdf_summary_info_header_t *, |
|||
cdf_property_info_t **, size_t *); |
|||
int cdf_print_classid(char *, size_t, const cdf_classid_t *); |
|||
int cdf_print_property_name(char *, size_t, uint32_t); |
|||
int cdf_print_elapsed_time(char *, size_t, cdf_timestamp_t); |
|||
uint16_t cdf_tole2(uint16_t); |
|||
uint32_t cdf_tole4(uint32_t); |
|||
uint64_t cdf_tole8(uint64_t); |
|||
|
|||
#ifdef CDF_DEBUG |
|||
void cdf_dump_header(const cdf_header_t *); |
|||
void cdf_dump_sat(const char *, const cdf_header_t *, const cdf_sat_t *); |
|||
void cdf_dump(void *, size_t); |
|||
void cdf_dump_stream(const cdf_header_t *, const cdf_stream_t *); |
|||
void cdf_dump_dir(int, const cdf_header_t *, const cdf_sat_t *, |
|||
const cdf_sat_t *, const cdf_stream_t *, const cdf_dir_t *); |
|||
void cdf_dump_property_info(const cdf_property_info_t *, size_t); |
|||
void cdf_dump_summary_info(const cdf_header_t *, const cdf_stream_t *); |
|||
#endif |
|||
|
|||
|
|||
#endif /* _H_CDF_ */ |
|||
@ -0,0 +1,183 @@ |
|||
/*- |
|||
* Copyright (c) 2008 Christos Zoulas |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions |
|||
* are met: |
|||
* 1. Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
|||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
|||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: cdf_time.c,v 1.5 2009/02/03 20:27:51 christos Exp $") |
|||
#endif |
|||
|
|||
#include <time.h> |
|||
#ifdef TEST |
|||
#include <err.h> |
|||
#endif |
|||
#include <string.h> |
|||
|
|||
#include "cdf.h" |
|||
|
|||
#define isleap(y) ((((y) % 4) == 0) && \ |
|||
((((y) % 100) != 0) || (((y) % 400) == 0))) |
|||
|
|||
static const int mdays[] = { |
|||
31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
|||
}; |
|||
|
|||
/* |
|||
* Return the number of days between jan 01 1601 and jan 01 of year. |
|||
*/ |
|||
static int |
|||
cdf_getdays(int year) |
|||
{ |
|||
int days = 0; |
|||
int y; |
|||
|
|||
for (y = CDF_BASE_YEAR; y < year; y++) |
|||
days += isleap(y) + 365; |
|||
|
|||
return days; |
|||
} |
|||
|
|||
/* |
|||
* Return the day within the month |
|||
*/ |
|||
static int |
|||
cdf_getday(int year, int days) |
|||
{ |
|||
size_t m; |
|||
|
|||
for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) { |
|||
int sub = mdays[m] + (m == 1 && isleap(year)); |
|||
if (days < sub) |
|||
return days; |
|||
days -= sub; |
|||
} |
|||
return days; |
|||
} |
|||
|
|||
/* |
|||
* Return the 0...11 month number. |
|||
*/ |
|||
static int |
|||
cdf_getmonth(int year, int days) |
|||
{ |
|||
size_t m; |
|||
|
|||
for (m = 0; m < sizeof(mdays) / sizeof(mdays[0]); m++) { |
|||
days -= mdays[m]; |
|||
if (m == 1 && isleap(year)) |
|||
days--; |
|||
if (days <= 0) |
|||
return (int)m; |
|||
} |
|||
return (int)m; |
|||
} |
|||
|
|||
int |
|||
cdf_timestamp_to_timespec(struct timeval *ts, cdf_timestamp_t t) |
|||
{ |
|||
struct tm tm; |
|||
#ifdef HAVE_STRUCT_TM_TM_ZONE |
|||
static char UTC[] = "UTC"; |
|||
#endif |
|||
int rdays; |
|||
|
|||
/* Unit is 100's of nanoseconds */ |
|||
ts->tv_usec = (t % CDF_TIME_PREC) * 1000000; |
|||
|
|||
t /= CDF_TIME_PREC; |
|||
tm.tm_sec = t % 60; |
|||
t /= 60; |
|||
|
|||
tm.tm_min = t % 60; |
|||
t /= 60; |
|||
|
|||
tm.tm_hour = t % 24; |
|||
t /= 24; |
|||
|
|||
// XXX: Approx |
|||
tm.tm_year = CDF_BASE_YEAR + (t / 365); |
|||
|
|||
rdays = cdf_getdays(tm.tm_year); |
|||
t -= rdays; |
|||
tm.tm_mday = cdf_getday(tm.tm_year, t); |
|||
tm.tm_mon = cdf_getmonth(tm.tm_year, t); |
|||
tm.tm_wday = 0; |
|||
tm.tm_yday = 0; |
|||
tm.tm_isdst = 0; |
|||
#ifdef HAVE_STRUCT_TM_TM_GMTOFF |
|||
tm.tm_gmtoff = 0; |
|||
#endif |
|||
#ifdef HAVE_STRUCT_TM_TM_ZONE |
|||
tm.tm_zone = UTC; |
|||
#endif |
|||
tm.tm_year -= 1900; |
|||
ts->tv_sec = mktime(&tm); |
|||
if (ts->tv_sec == -1) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
int |
|||
cdf_timespec_to_timestamp(cdf_timestamp_t *t, const struct timeval *ts) |
|||
{ |
|||
(void)&t; |
|||
(void)&ts; |
|||
#ifdef notyet |
|||
struct tm tm; |
|||
if (gmtime_r(&ts->ts_sec, &tm) == NULL) { |
|||
errno = EINVAL; |
|||
return -1; |
|||
} |
|||
*t = (ts->ts_usec / 1000000) * CDF_TIME_PREC; |
|||
*t = tm.tm_sec; |
|||
*t += tm.tm_min * 60; |
|||
*t += tm.tm_hour * 60 * 60; |
|||
*t += tm.tm_mday * 60 * 60 * 24; |
|||
#endif |
|||
return 0; |
|||
} |
|||
|
|||
|
|||
#ifdef TEST |
|||
int |
|||
main(int argc, char *argv[]) |
|||
{ |
|||
struct timeval ts; |
|||
static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL; |
|||
static const char *ref = "Sat Apr 23 01:30:00 1977"; |
|||
char *p, *q; |
|||
|
|||
cdf_timestamp_to_timespec(&ts, tst); |
|||
p = ctime(&ts.tv_sec); |
|||
if ((q = strchr(p, '\n')) != NULL) |
|||
*q = '\0'; |
|||
if (strcmp(ref, p) != 0) |
|||
errx(1, "Error date %s != %s\n", ref, p); |
|||
return 0; |
|||
} |
|||
#endif |
|||
@ -0,0 +1,484 @@ |
|||
/* |
|||
* Copyright (c) Ian F. Darwin 1986-1995. |
|||
* Software written by Ian F. Darwin and others; |
|||
* maintained 1995-present by Christos Zoulas and others. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions |
|||
* are met: |
|||
* 1. Redistributions of source code must retain the above copyright |
|||
* notice immediately at the beginning of the file, without modification, |
|||
* this list of conditions, and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
|||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR |
|||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|||
* SUCH DAMAGE. |
|||
*/ |
|||
/* |
|||
* Encoding -- determine the character encoding of a text file. |
|||
* |
|||
* Joerg Wunsch <joerg@freebsd.org> wrote the original support for 8-bit |
|||
* international characters. |
|||
*/ |
|||
|
|||
#include "file.h" |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: encoding.c,v 1.3 2009/02/03 20:27:51 christos Exp $") |
|||
#endif /* lint */ |
|||
|
|||
#include "magic.h" |
|||
#include <string.h> |
|||
#include <memory.h> |
|||
#include <stdlib.h> |
|||
|
|||
|
|||
private int looks_ascii(const unsigned char *, size_t, unichar *, size_t *); |
|||
private int looks_utf8_with_BOM(const unsigned char *, size_t, unichar *, |
|||
size_t *); |
|||
private int looks_ucs16(const unsigned char *, size_t, unichar *, size_t *); |
|||
private int looks_latin1(const unsigned char *, size_t, unichar *, size_t *); |
|||
private int looks_extended(const unsigned char *, size_t, unichar *, size_t *); |
|||
private void from_ebcdic(const unsigned char *, size_t, unsigned char *); |
|||
|
|||
/* |
|||
* Try to determine whether text is in some character code we can |
|||
* identify. Each of these tests, if it succeeds, will leave |
|||
* the text converted into one-unichar-per-character Unicode in |
|||
* ubuf, and the number of characters converted in ulen. |
|||
*/ |
|||
protected int |
|||
file_encoding(struct magic_set *ms, const unsigned char *buf, size_t nbytes, unichar **ubuf, size_t *ulen, const char **code, const char **code_mime, const char **type) |
|||
{ |
|||
size_t mlen; |
|||
int rv = 1, ucs_type; |
|||
unsigned char *nbuf = NULL; |
|||
|
|||
mlen = (nbytes + 1) * sizeof(nbuf[0]); |
|||
if ((nbuf = CAST(unsigned char *, calloc((size_t)1, mlen))) == NULL) { |
|||
file_oomem(ms, mlen); |
|||
goto done; |
|||
} |
|||
mlen = (nbytes + 1) * sizeof((*ubuf)[0]); |
|||
if ((*ubuf = CAST(unichar *, calloc((size_t)1, mlen))) == NULL) { |
|||
file_oomem(ms, mlen); |
|||
goto done; |
|||
} |
|||
|
|||
*type = "text"; |
|||
if (looks_ascii(buf, nbytes, *ubuf, ulen)) { |
|||
*code = "ASCII"; |
|||
*code_mime = "us-ascii"; |
|||
} else if (looks_utf8_with_BOM(buf, nbytes, *ubuf, ulen) > 0) { |
|||
*code = "UTF-8 Unicode (with BOM)"; |
|||
*code_mime = "utf-8"; |
|||
} else if (file_looks_utf8(buf, nbytes, *ubuf, ulen) > 1) { |
|||
*code = "UTF-8 Unicode"; |
|||
*code_mime = "utf-8"; |
|||
} else if ((ucs_type = looks_ucs16(buf, nbytes, *ubuf, ulen)) != 0) { |
|||
if (ucs_type == 1) { |
|||
*code = "Little-endian UTF-16 Unicode"; |
|||
*code_mime = "utf-16le"; |
|||
} else { |
|||
*code = "Big-endian UTF-16 Unicode"; |
|||
*code_mime = "utf-16be"; |
|||
} |
|||
} else if (looks_latin1(buf, nbytes, *ubuf, ulen)) { |
|||
*code = "ISO-8859"; |
|||
*code_mime = "iso-8859-1"; |
|||
} else if (looks_extended(buf, nbytes, *ubuf, ulen)) { |
|||
*code = "Non-ISO extended-ASCII"; |
|||
*code_mime = "unknown-8bit"; |
|||
} else { |
|||
from_ebcdic(buf, nbytes, nbuf); |
|||
|
|||
if (looks_ascii(nbuf, nbytes, *ubuf, ulen)) { |
|||
*code = "EBCDIC"; |
|||
*code_mime = "ebcdic"; |
|||
} else if (looks_latin1(nbuf, nbytes, *ubuf, ulen)) { |
|||
*code = "International EBCDIC"; |
|||
*code_mime = "ebcdic"; |
|||
} else { /* Doesn't look like text at all */ |
|||
rv = 0; |
|||
*type = "binary"; |
|||
} |
|||
} |
|||
|
|||
done: |
|||
if (nbuf) |
|||
free(nbuf); |
|||
|
|||
return rv; |
|||
} |
|||
|
|||
/* |
|||
* This table reflects a particular philosophy about what constitutes |
|||
* "text," and there is room for disagreement about it. |
|||
* |
|||
* Version 3.31 of the file command considered a file to be ASCII if |
|||
* each of its characters was approved by either the isascii() or |
|||
* isalpha() function. On most systems, this would mean that any |
|||
* file consisting only of characters in the range 0x00 ... 0x7F |
|||
* would be called ASCII text, but many systems might reasonably |
|||
* consider some characters outside this range to be alphabetic, |
|||
* so the file command would call such characters ASCII. It might |
|||
* have been more accurate to call this "considered textual on the |
|||
* local system" than "ASCII." |
|||
* |
|||
* It considered a file to be "International language text" if each |
|||
* of its characters was either an ASCII printing character (according |
|||
* to the real ASCII standard, not the above test), a character in |
|||
* the range 0x80 ... 0xFF, or one of the following control characters: |
|||
* backspace, tab, line feed, vertical tab, form feed, carriage return, |
|||
* escape. No attempt was made to determine the language in which files |
|||
* of this type were written. |
|||
* |
|||
* |
|||
* The table below considers a file to be ASCII if all of its characters |
|||
* are either ASCII printing characters (again, according to the X3.4 |
|||
* standard, not isascii()) or any of the following controls: bell, |
|||
* backspace, tab, line feed, form feed, carriage return, esc, nextline. |
|||
* |
|||
* I include bell because some programs (particularly shell scripts) |
|||
* use it literally, even though it is rare in normal text. I exclude |
|||
* vertical tab because it never seems to be used in real text. I also |
|||
* include, with hesitation, the X3.64/ECMA-43 control nextline (0x85), |
|||
* because that's what the dd EBCDIC->ASCII table maps the EBCDIC newline |
|||
* character to. It might be more appropriate to include it in the 8859 |
|||
* set instead of the ASCII set, but it's got to be included in *something* |
|||
* we recognize or EBCDIC files aren't going to be considered textual. |
|||
* Some old Unix source files use SO/SI (^N/^O) to shift between Greek |
|||
* and Latin characters, so these should possibly be allowed. But they |
|||
* make a real mess on VT100-style displays if they're not paired properly, |
|||
* so we are probably better off not calling them text. |
|||
* |
|||
* A file is considered to be ISO-8859 text if its characters are all |
|||
* either ASCII, according to the above definition, or printing characters |
|||
* from the ISO-8859 8-bit extension, characters 0xA0 ... 0xFF. |
|||
* |
|||
* Finally, a file is considered to be international text from some other |
|||
* character code if its characters are all either ISO-8859 (according to |
|||
* the above definition) or characters in the range 0x80 ... 0x9F, which |
|||
* ISO-8859 considers to be control characters but the IBM PC and Macintosh |
|||
* consider to be printing characters. |
|||
*/ |
|||
|
|||
#define F 0 /* character never appears in text */ |
|||
#define T 1 /* character appears in plain ASCII text */ |
|||
#define I 2 /* character appears in ISO-8859 text */ |
|||
#define X 3 /* character appears in non-ISO extended ASCII (Mac, IBM PC) */ |
|||
|
|||
private char text_chars[256] = { |
|||
/* BEL BS HT LF FF CR */ |
|||
F, F, F, F, F, F, F, T, T, T, T, F, T, T, F, F, /* 0x0X */ |
|||
/* ESC */ |
|||
F, F, F, F, F, F, F, F, F, F, F, T, F, F, F, F, /* 0x1X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x2X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x3X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x4X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x5X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, /* 0x6X */ |
|||
T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, F, /* 0x7X */ |
|||
/* NEL */ |
|||
X, X, X, X, X, T, X, X, X, X, X, X, X, X, X, X, /* 0x8X */ |
|||
X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, X, /* 0x9X */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xaX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xbX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xcX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xdX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, /* 0xeX */ |
|||
I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I /* 0xfX */ |
|||
}; |
|||
|
|||
private int |
|||
looks_ascii(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
int t = text_chars[buf[i]]; |
|||
|
|||
if (t != T) |
|||
return 0; |
|||
|
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
private int |
|||
looks_latin1(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
int t = text_chars[buf[i]]; |
|||
|
|||
if (t != T && t != I) |
|||
return 0; |
|||
|
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
private int |
|||
looks_extended(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
int t = text_chars[buf[i]]; |
|||
|
|||
if (t != T && t != I && t != X) |
|||
return 0; |
|||
|
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} |
|||
|
|||
return 1; |
|||
} |
|||
|
|||
/* |
|||
* Decide whether some text looks like UTF-8. Returns: |
|||
* |
|||
* -1: invalid UTF-8 |
|||
* 0: uses odd control characters, so doesn't look like text |
|||
* 1: 7-bit text |
|||
* 2: definitely UTF-8 text (valid high-bit set bytes) |
|||
* |
|||
* If ubuf is non-NULL on entry, text is decoded into ubuf, *ulen; |
|||
* ubuf must be big enough! |
|||
*/ |
|||
protected int |
|||
file_looks_utf8(const unsigned char *buf, size_t nbytes, unichar *ubuf, size_t *ulen) |
|||
{ |
|||
size_t i; |
|||
int n; |
|||
unichar c; |
|||
int gotone = 0, ctrl = 0; |
|||
|
|||
if (ubuf) |
|||
*ulen = 0; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
if ((buf[i] & 0x80) == 0) { /* 0xxxxxxx is plain ASCII */ |
|||
/* |
|||
* Even if the whole file is valid UTF-8 sequences, |
|||
* still reject it if it uses weird control characters. |
|||
*/ |
|||
|
|||
if (text_chars[buf[i]] != T) |
|||
ctrl = 1; |
|||
|
|||
if (ubuf) |
|||
ubuf[(*ulen)++] = buf[i]; |
|||
} else if ((buf[i] & 0x40) == 0) { /* 10xxxxxx never 1st byte */ |
|||
return -1; |
|||
} else { /* 11xxxxxx begins UTF-8 */ |
|||
int following; |
|||
|
|||
if ((buf[i] & 0x20) == 0) { /* 110xxxxx */ |
|||
c = buf[i] & 0x1f; |
|||
following = 1; |
|||
} else if ((buf[i] & 0x10) == 0) { /* 1110xxxx */ |
|||
c = buf[i] & 0x0f; |
|||
following = 2; |
|||
} else if ((buf[i] & 0x08) == 0) { /* 11110xxx */ |
|||
c = buf[i] & 0x07; |
|||
following = 3; |
|||
} else if ((buf[i] & 0x04) == 0) { /* 111110xx */ |
|||
c = buf[i] & 0x03; |
|||
following = 4; |
|||
} else if ((buf[i] & 0x02) == 0) { /* 1111110x */ |
|||
c = buf[i] & 0x01; |
|||
following = 5; |
|||
} else |
|||
return -1; |
|||
|
|||
for (n = 0; n < following; n++) { |
|||
i++; |
|||
if (i >= nbytes) |
|||
goto done; |
|||
|
|||
if ((buf[i] & 0x80) == 0 || (buf[i] & 0x40)) |
|||
return -1; |
|||
|
|||
c = (c << 6) + (buf[i] & 0x3f); |
|||
} |
|||
|
|||
if (ubuf) |
|||
ubuf[(*ulen)++] = c; |
|||
gotone = 1; |
|||
} |
|||
} |
|||
done: |
|||
return ctrl ? 0 : (gotone ? 2 : 1); |
|||
} |
|||
|
|||
/* |
|||
* Decide whether some text looks like UTF-8 with BOM. If there is no |
|||
* BOM, return -1; otherwise return the result of looks_utf8 on the |
|||
* rest of the text. |
|||
*/ |
|||
private int |
|||
looks_utf8_with_BOM(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
if (nbytes > 3 && buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf) |
|||
return file_looks_utf8(buf + 3, nbytes - 3, ubuf, ulen); |
|||
else |
|||
return -1; |
|||
} |
|||
|
|||
private int |
|||
looks_ucs16(const unsigned char *buf, size_t nbytes, unichar *ubuf, |
|||
size_t *ulen) |
|||
{ |
|||
int bigend; |
|||
size_t i; |
|||
|
|||
if (nbytes < 2) |
|||
return 0; |
|||
|
|||
if (buf[0] == 0xff && buf[1] == 0xfe) |
|||
bigend = 0; |
|||
else if (buf[0] == 0xfe && buf[1] == 0xff) |
|||
bigend = 1; |
|||
else |
|||
return 0; |
|||
|
|||
*ulen = 0; |
|||
|
|||
for (i = 2; i + 1 < nbytes; i += 2) { |
|||
/* XXX fix to properly handle chars > 65536 */ |
|||
|
|||
if (bigend) |
|||
ubuf[(*ulen)++] = buf[i + 1] + 256 * buf[i]; |
|||
else |
|||
ubuf[(*ulen)++] = buf[i] + 256 * buf[i + 1]; |
|||
|
|||
if (ubuf[*ulen - 1] == 0xfffe) |
|||
return 0; |
|||
if (ubuf[*ulen - 1] < 128 && |
|||
text_chars[(size_t)ubuf[*ulen - 1]] != T) |
|||
return 0; |
|||
} |
|||
|
|||
return 1 + bigend; |
|||
} |
|||
|
|||
#undef F |
|||
#undef T |
|||
#undef I |
|||
#undef X |
|||
|
|||
/* |
|||
* This table maps each EBCDIC character to an (8-bit extended) ASCII |
|||
* character, as specified in the rationale for the dd(1) command in |
|||
* draft 11.2 (September, 1991) of the POSIX P1003.2 standard. |
|||
* |
|||
* Unfortunately it does not seem to correspond exactly to any of the |
|||
* five variants of EBCDIC documented in IBM's _Enterprise Systems |
|||
* Architecture/390: Principles of Operation_, SA22-7201-06, Seventh |
|||
* Edition, July, 1999, pp. I-1 - I-4. |
|||
* |
|||
* Fortunately, though, all versions of EBCDIC, including this one, agree |
|||
* on most of the printing characters that also appear in (7-bit) ASCII. |
|||
* Of these, only '|', '!', '~', '^', '[', and ']' are in question at all. |
|||
* |
|||
* Fortunately too, there is general agreement that codes 0x00 through |
|||
* 0x3F represent control characters, 0x41 a nonbreaking space, and the |
|||
* remainder printing characters. |
|||
* |
|||
* This is sufficient to allow us to identify EBCDIC text and to distinguish |
|||
* between old-style and internationalized examples of text. |
|||
*/ |
|||
|
|||
private unsigned char ebcdic_to_ascii[] = { |
|||
0, 1, 2, 3, 156, 9, 134, 127, 151, 141, 142, 11, 12, 13, 14, 15, |
|||
16, 17, 18, 19, 157, 133, 8, 135, 24, 25, 146, 143, 28, 29, 30, 31, |
|||
128, 129, 130, 131, 132, 10, 23, 27, 136, 137, 138, 139, 140, 5, 6, 7, |
|||
144, 145, 22, 147, 148, 149, 150, 4, 152, 153, 154, 155, 20, 21, 158, 26, |
|||
' ', 160, 161, 162, 163, 164, 165, 166, 167, 168, 213, '.', '<', '(', '+', '|', |
|||
'&', 169, 170, 171, 172, 173, 174, 175, 176, 177, '!', '$', '*', ')', ';', '~', |
|||
'-', '/', 178, 179, 180, 181, 182, 183, 184, 185, 203, ',', '%', '_', '>', '?', |
|||
186, 187, 188, 189, 190, 191, 192, 193, 194, '`', ':', '#', '@', '\'','=', '"', |
|||
195, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 196, 197, 198, 199, 200, 201, |
|||
202, 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', '^', 204, 205, 206, 207, 208, |
|||
209, 229, 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 210, 211, 212, '[', 214, 215, |
|||
216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, ']', 230, 231, |
|||
'{', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 232, 233, 234, 235, 236, 237, |
|||
'}', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 238, 239, 240, 241, 242, 243, |
|||
'\\',159, 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 244, 245, 246, 247, 248, 249, |
|||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 250, 251, 252, 253, 254, 255 |
|||
}; |
|||
|
|||
#ifdef notdef |
|||
/* |
|||
* The following EBCDIC-to-ASCII table may relate more closely to reality, |
|||
* or at least to modern reality. It comes from |
|||
* |
|||
* http://ftp.s390.ibm.com/products/oe/bpxqp9.html |
|||
* |
|||
* and maps the characters of EBCDIC code page 1047 (the code used for |
|||
* Unix-derived software on IBM's 390 systems) to the corresponding |
|||
* characters from ISO 8859-1. |
|||
* |
|||
* If this table is used instead of the above one, some of the special |
|||
* cases for the NEL character can be taken out of the code. |
|||
*/ |
|||
|
|||
private unsigned char ebcdic_1047_to_8859[] = { |
|||
0x00,0x01,0x02,0x03,0x9C,0x09,0x86,0x7F,0x97,0x8D,0x8E,0x0B,0x0C,0x0D,0x0E,0x0F, |
|||
0x10,0x11,0x12,0x13,0x9D,0x0A,0x08,0x87,0x18,0x19,0x92,0x8F,0x1C,0x1D,0x1E,0x1F, |
|||
0x80,0x81,0x82,0x83,0x84,0x85,0x17,0x1B,0x88,0x89,0x8A,0x8B,0x8C,0x05,0x06,0x07, |
|||
0x90,0x91,0x16,0x93,0x94,0x95,0x96,0x04,0x98,0x99,0x9A,0x9B,0x14,0x15,0x9E,0x1A, |
|||
0x20,0xA0,0xE2,0xE4,0xE0,0xE1,0xE3,0xE5,0xE7,0xF1,0xA2,0x2E,0x3C,0x28,0x2B,0x7C, |
|||
0x26,0xE9,0xEA,0xEB,0xE8,0xED,0xEE,0xEF,0xEC,0xDF,0x21,0x24,0x2A,0x29,0x3B,0x5E, |
|||
0x2D,0x2F,0xC2,0xC4,0xC0,0xC1,0xC3,0xC5,0xC7,0xD1,0xA6,0x2C,0x25,0x5F,0x3E,0x3F, |
|||
0xF8,0xC9,0xCA,0xCB,0xC8,0xCD,0xCE,0xCF,0xCC,0x60,0x3A,0x23,0x40,0x27,0x3D,0x22, |
|||
0xD8,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0xAB,0xBB,0xF0,0xFD,0xFE,0xB1, |
|||
0xB0,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,0x70,0x71,0x72,0xAA,0xBA,0xE6,0xB8,0xC6,0xA4, |
|||
0xB5,0x7E,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0xA1,0xBF,0xD0,0x5B,0xDE,0xAE, |
|||
0xAC,0xA3,0xA5,0xB7,0xA9,0xA7,0xB6,0xBC,0xBD,0xBE,0xDD,0xA8,0xAF,0x5D,0xB4,0xD7, |
|||
0x7B,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0xAD,0xF4,0xF6,0xF2,0xF3,0xF5, |
|||
0x7D,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0xB9,0xFB,0xFC,0xF9,0xFA,0xFF, |
|||
0x5C,0xF7,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0xB2,0xD4,0xD6,0xD2,0xD3,0xD5, |
|||
0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0xB3,0xDB,0xDC,0xD9,0xDA,0x9F |
|||
}; |
|||
#endif |
|||
|
|||
/* |
|||
* Copy buf[0 ... nbytes-1] into out[], translating EBCDIC to ASCII. |
|||
*/ |
|||
private void |
|||
from_ebcdic(const unsigned char *buf, size_t nbytes, unsigned char *out) |
|||
{ |
|||
size_t i; |
|||
|
|||
for (i = 0; i < nbytes; i++) { |
|||
out[i] = ebcdic_to_ascii[buf[i]]; |
|||
} |
|||
} |
|||
@ -0,0 +1,262 @@ |
|||
/*- |
|||
* Copyright (c) 2008 Christos Zoulas |
|||
* All rights reserved. |
|||
* |
|||
* Redistribution and use in source and binary forms, with or without |
|||
* modification, are permitted provided that the following conditions |
|||
* are met: |
|||
* 1. Redistributions of source code must retain the above copyright |
|||
* notice, this list of conditions and the following disclaimer. |
|||
* 2. Redistributions in binary form must reproduce the above copyright |
|||
* notice, this list of conditions and the following disclaimer in the |
|||
* documentation and/or other materials provided with the distribution. |
|||
* |
|||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
|||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
|||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
|||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
|||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|||
* POSSIBILITY OF SUCH DAMAGE. |
|||
*/ |
|||
#include "file.h" |
|||
|
|||
#ifndef lint |
|||
FILE_RCSID("@(#)$File: readcdf.c,v 1.11 2009/02/03 20:27:51 christos Exp $") |
|||
#endif |
|||
|
|||
#include <stdlib.h> |
|||
|
|||
#ifdef PHP_WIN32 |
|||
#include "win32/unistd.h" |
|||
#else |
|||
#include <unistd.h> |
|||
#endif |
|||
|
|||
#include <string.h> |
|||
#include <time.h> |
|||
#include <ctype.h> |
|||
|
|||
#include "cdf.h" |
|||
#include "magic.h" |
|||
|
|||
#define NOTMIME(ms) (((ms)->flags & MAGIC_MIME) == 0) |
|||
|
|||
private int |
|||
cdf_file_property_info(struct magic_set *ms, const cdf_property_info_t *info, |
|||
size_t count) |
|||
{ |
|||
size_t i; |
|||
cdf_timestamp_t tp; |
|||
struct timeval ts; |
|||
char buf[64]; |
|||
const char *str = "vnd.ms-office"; |
|||
const char *s; |
|||
int len; |
|||
|
|||
for (i = 0; i < count; i++) { |
|||
cdf_print_property_name(buf, sizeof(buf), info[i].pi_id); |
|||
switch (info[i].pi_type) { |
|||
case CDF_SIGNED16: |
|||
if (NOTMIME(ms) && file_printf(ms, ", %s: %hd", buf, |
|||
info[i].pi_s16) == -1) |
|||
return -1; |
|||
break; |
|||
case CDF_SIGNED32: |
|||
if (NOTMIME(ms) && file_printf(ms, ", %s: %d", buf, |
|||
info[i].pi_s32) == -1) |
|||
return -1; |
|||
break; |
|||
case CDF_UNSIGNED32: |
|||
if (NOTMIME(ms) && file_printf(ms, ", %s: %u", buf, |
|||
info[i].pi_u32) == -1) |
|||
return -1; |
|||
break; |
|||
case CDF_LENGTH32_STRING: |
|||
len = info[i].pi_str.s_len; |
|||
if (len > 1) { |
|||
s = info[i].pi_str.s_buf; |
|||
if (NOTMIME(ms)) { |
|||
if (file_printf(ms, ", %s: %.*s", buf, |
|||
len, s) == -1) |
|||
return -1; |
|||
} else if (info[i].pi_id == |
|||
CDF_PROPERTY_NAME_OF_APPLICATION) { |
|||
if (strstr(s, "Word")) |
|||
str = "msword"; |
|||
else if (strstr(s, "Excel")) |
|||
str = "vnd.ms-excel"; |
|||
else if (strstr(s, "Powerpoint")) |
|||
str = "vnd.ms-powerpoint"; |
|||
} |
|||
} |
|||
break; |
|||
case CDF_FILETIME: |
|||
tp = info[i].pi_tp; |
|||
if (tp != 0) { |
|||
if (tp < 1000000000000000LL) { |
|||
char tbuf[64]; |
|||
cdf_print_elapsed_time(tbuf, |
|||
sizeof(tbuf), tp); |
|||
if (NOTMIME(ms) && file_printf(ms, |
|||
", %s: %s", buf, tbuf) == -1) |
|||
return -1; |
|||
} else { |
|||
char *c, *ec; |
|||
cdf_timestamp_to_timespec(&ts, tp); |
|||
c = ctime(&ts.tv_sec); |
|||
if ((ec = strchr(c, '\n')) != NULL) |
|||
*ec = '\0'; |
|||
|
|||
if (NOTMIME(ms) && file_printf(ms, |
|||
", %s: %s", buf, c) == -1) |
|||
return -1; |
|||
} |
|||
} |
|||
break; |
|||
case CDF_CLIPBOARD: |
|||
break; |
|||
default: |
|||
file_error(ms, 0, "Internal parsing error"); |
|||
return -1; |
|||
} |
|||
} |
|||
if (!NOTMIME(ms)) { |
|||
if (file_printf(ms, "application/%s", str) == -1) |
|||
return -1; |
|||
} |
|||
return 1; |
|||
} |
|||
|
|||
private int |
|||
cdf_file_summary_info(struct magic_set *ms, const cdf_stream_t *sst) |
|||
{ |
|||
cdf_summary_info_header_t si; |
|||
cdf_property_info_t *info; |
|||
size_t count; |
|||
int m; |
|||
|
|||
if (cdf_unpack_summary_info(sst, &si, &info, &count) == -1) { |
|||
if (si.si_byte_order != 0xfffe) |
|||
return 0; |
|||
else |
|||
return -1; |
|||
} |
|||
|
|||
if (si.si_byte_order != 0xfffe) |
|||
return 0; |
|||
|
|||
if (NOTMIME(ms)) { |
|||
if (file_printf(ms, "CDF V2 Document") == -1) |
|||
return -1; |
|||
|
|||
if (file_printf(ms, ", %s Endian", |
|||
si.si_byte_order == 0xfffe ? "Little" : "Big") == -1) |
|||
return -1; |
|||
switch (si.si_os) { |
|||
case 2: |
|||
if (file_printf(ms, ", Os: Windows, Version %d.%d", |
|||
si.si_os_version & 0xff, si.si_os_version >> 8) |
|||
== -1) |
|||
return -1; |
|||
break; |
|||
case 1: |
|||
if (file_printf(ms, ", Os: MacOS, Version %d.%d", |
|||
si.si_os_version >> 8, si.si_os_version & 0xff) |
|||
== -1) |
|||
return -1; |
|||
break; |
|||
default: |
|||
if (file_printf(ms, ", Os %d, Version: %d.%d", si.si_os, |
|||
si.si_os_version & 0xff, si.si_os_version >> 8) |
|||
== -1) |
|||
return -1; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
m = cdf_file_property_info(ms, info, count); |
|||
free(info); |
|||
|
|||
return m; |
|||
} |
|||
|
|||
protected int |
|||
file_trycdf(struct magic_set *ms, int fd, const unsigned char *buf, |
|||
size_t nbytes) |
|||
{ |
|||
cdf_header_t h; |
|||
cdf_sat_t sat, ssat; |
|||
cdf_stream_t sst, scn; |
|||
cdf_dir_t dir; |
|||
int i; |
|||
(void)&nbytes; |
|||
(void)&buf; |
|||
|
|||
if (ms->flags & MAGIC_APPLE) |
|||
return 0; |
|||
if (cdf_read_header(fd, &h) == -1) |
|||
return 0; |
|||
#ifdef CDF_DEBUG |
|||
cdf_dump_header(&h); |
|||
#endif |
|||
|
|||
if (cdf_read_sat(fd, &h, &sat) == -1) { |
|||
file_error(ms, errno, "Can't read SAT"); |
|||
return -1; |
|||
} |
|||
#ifdef CDF_DEBUG |
|||
cdf_dump_sat("SAT", &h, &sat); |
|||
#endif |
|||
|
|||
if ((i = cdf_read_ssat(fd, &h, &sat, &ssat)) == -1) { |
|||
file_error(ms, errno, "Can't read SAT"); |
|||
goto out1; |
|||
} |
|||
#ifdef CDF_DEBUG |
|||
cdf_dump_sat("SSAT", &h, &ssat); |
|||
#endif |
|||
|
|||
if ((i = cdf_read_dir(fd, &h, &sat, &dir)) == -1) { |
|||
file_error(ms, errno, "Can't read directory"); |
|||
goto out2; |
|||
} |
|||
|
|||
if ((i = cdf_read_short_stream(fd, &h, &sat, &dir, &sst)) == -1) { |
|||
file_error(ms, errno, "Cannot read short stream"); |
|||
goto out3; |
|||
} |
|||
|
|||
#ifdef CDF_DEBUG |
|||
cdf_dump_dir(fd, &h, &sat, &ssat, &sst, &dir); |
|||
#endif |
|||
if ((i = cdf_read_summary_info(fd, &h, &sat, &ssat, &sst, &dir, &scn)) |
|||
== -1) { |
|||
/* Some files don't have summary info! */ |
|||
#ifdef notyet |
|||
file_error(ms, errno, "Can't read summary_info"); |
|||
#else |
|||
i = 0; |
|||
#endif |
|||
goto out4; |
|||
} |
|||
#ifdef CDF_DEBUG |
|||
cdf_dump_summary_info(&h, &scn); |
|||
#endif |
|||
if ((i = cdf_file_summary_info(ms, &scn)) == -1) |
|||
file_error(ms, errno, "Can't expand summary_info"); |
|||
free(scn.sst_tab); |
|||
out4: |
|||
free(sst.sst_tab); |
|||
out3: |
|||
free(dir.dir_tab); |
|||
out2: |
|||
free(ssat.sat_tab); |
|||
out1: |
|||
free(sat.sat_tab); |
|||
return i; |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue