Commit 7c72f5c4 authored by Michael Meeks's avatar Michael Meeks

Frank's new summary work.

parent f85d87c1
No preview for this file type
......@@ -27,6 +27,10 @@ Federico:
Robert:
* Primitive oleo import : supports numbers and text.
Frank:
* Huge chunk of summary-info re-structuring.
* Import and export lots of new summary fields.
--------------------------------------------------------------------------
Gnumeric 0.39
......
No preview for this file type
1999-11-08 Michael Meeks <mmeeks@gnu.org>
* ms-summary.c (ms_summary_read): quieten.
1999-11-08 Frank Chiulli <fchiulli@home.com>
* ms-summary.c : Added support for DocumentSummaryInformation stream.
Added new field, ps_id (Property Set ID), to mapping_t structure and
initialized excel_to_gnum_mapping[] appropriately.
* ms-summary.c (sum_name_to_excel) : New function to convert a summary
name to a MsOleSummaryPID.
* ms-summary.c (read_summary_items) : Added new argument - psid (Property
Set ID). It also checks to see that the summary item is in current
Summary stream as identified by psid. Added support for additional
summary types (boolean, short, time).
* ms-summary.c (ms_summary_read) : Reads DocumentSummaryInformation
stream and summary items therein.
* ms-summary.c (set_summary_item) : Processes additional summary types
(boolean, int, short, time).
* ms-summary.c (ms_summary_write) : Now also writes out the
DocumentSummaryInformation stream.
1999-11-07 Michael Meeks <mmeeks@gnu.org>
* boot.c (excel_save): Invert sense of return value to reflect success.
......
1999-11-08 Michael Meeks <mmeeks@gnu.org>
* ms-ole-summary.c (ms_ole_docsummary_open): quieten.
1999-11-xx Frank Chiulli <fchiulli@home.com>
* ms-ole-summary.c : Added new field (ps_id, Property Set ID) to the
structure item_t. Define the Summary FMTIDs as constants. Define
new TYPE_* s to handle additional items.
* ms-ole-summary.c (read_items) : Add a new argument - psid (Property
Set ID). Use this to set the new ps_id field in item_t.
* ms-ole-summary.c (write_items) : Correct an error when calculating
the offset of an item.
* ms-ole-summary.c (ms_ole_summary_open_stream) : Add a new argument -
psid (Property Set ID). Change references to FMTIDs from magic
numbers to references to constants. Set ps_id in SummaryInfo
accordingly. Change call to read_items.
* ms-ole-summary.c (ms_ole_summary_open) : Add argument in call to
ms_ole_summary_open_stream.
* ms-ole-summary.c (ms_ole_docsummary_open) : New function - opens the
DocumentSummaryInformation stream.
* ms-ole-summary.c (ms_ole_summary_create_stream) : Add new argument -
psid (Property Set ID). Change references to FMTIDs from magic
numbers to references to constants. Segregrate the processing for the
different Summary streams. Although they are identical now they
should change in the future because DocumentSummaryInformation can
contain two streams. Add new argument in call to
ms_ole_summary_open_stream.
* ms-ole-summary.c (ms_ole_summary_create) : Add new argument in call to
ms_ole_summary_create_stream.
* ms-ole-summary.c (ms_ole_docsummary_create) : New function to create
the DocumentSummaryInformation stream.
* ms-ole-summary.c (ms_ole_summary_get_short) : New function to read/get
items which are typed as short integers.
* ms-ole-summary.c (ms_ole_summary_get_boolean) : New function to read/
get items which are typed as booleans.
* ms-ole-summary.c (filetime_to_unixtime) : New function to convert DOS
filetime to UNIX time. This function was adapted from a similiar
function in 'wv' by Caolan McNamara (Caolan.McNamara@ul.ie).
* ms-ole-summary.c (unixtime_to_filetime) : New function to convert UNIX
time to DOS filetime.
* ms-ole-summary.c (ms_ole_summary_get_time) : Rewritten function to
get/read items which are typed as time.
* ms-ole-summary.c (ms_ole_summary_get_boolean) : Corrected a test.
* ms-ole-summary.c (ms_ole_summary_set_time) : Rewritten function to
set items which are typed as time.
* ms-ole-summary.c (ms_ole_summary_set_boolean) : Rewritten function to
set items which are typed as boolean.
* ms-ole-summary.c (ms_ole_summary_set_short) : New function to set
items which are typed as short.
* ms-ole-summary.c (ms_ole_summary_set_long) : Corrected a test.
* ms-ole-summary.h : Added new enum - MsOlePropertySetID. Added new
field (ps_id, Property Set ID) to the MsOleSummary structure. Added
prototypes for the following new public functions:
ms_ole_docsummary_open
ms_ole_docsummary_create
ms_ole_summary_get_boolean
ms_ole_summary_get_short
ms_ole_summary_set_boolean
ms_ole_summary_set_short
filetime_to_unixtime
unixtime_to_filetime
Modified prototypes where arguments were added. Added new types to
MsOleSummaryType. Added new enums to MsOleSummaryPID to reflect new
items in DocumentSummaryInformation and additional ones in
SummaryInformation.
1999-11-08 Arturo Tena <arturo@directmail.org>
* ms-ole.c: Fixed some OLE_DEBUG #if's.
......
......@@ -24,4 +24,7 @@ for homogeneity.
summary info from OLE 2.0 document files, named CPPSUM available from
the Somar Software WWW site at http://www.somar.com.
The summary information code was extensively updated and re -
written by Frank Chiulli incorporating both DocumentSummaryInformation
and SummaryInformation streams, and implementing several new types.
......@@ -25,12 +25,36 @@ typedef struct {
} section_t;
typedef struct {
guint32 offset;
guint32 id;
guint32 offset;
guint32 id;
MsOlePropertySetID ps_id;
} item_t;
const guint32 sum_fmtid[4] = {
0XF29F85E0,
0X10684FF9,
0X000891AB,
0XD9B3272B
};
const guint32 doc_fmtid[4] = {
0XD5CDD502,
0X101B2E9C,
0X00089793,
0XAEF92C2B
};
const guint32 user_fmtid[4] = {
0XD5CDD505,
0X101B2E9C,
0X00089793,
0XAEF92C2B
};
static gboolean
read_items (MsOleSummary *si)
read_items (MsOleSummary *si, MsOlePropertySetID psid)
{
gint sect;
......@@ -57,6 +81,7 @@ read_items (MsOleSummary *si)
item.id = MS_OLE_GET_GUINT32 (data);
item.offset = MS_OLE_GET_GUINT32 (data + 4);
item.offset = item.offset + st.offset;
item.ps_id = psid;
g_array_append_val (si->items, item);
}
}
......@@ -100,13 +125,13 @@ write_items (MsOleSummary *si)
/*
* The offset is calculated from the start of the
* properties header. The offset must be on a
* 4-byte boundary.
* 4-byte boundary.
*/
offset = bytes + num * PROPERTY_DESC_LEN;
fill = 0;
if ((offset & 0x3) > 0) {
offset += 4 - (offset & 0x3);
fill = 4 - (offset & 0x3);
offset += fill;
}
MS_OLE_SET_GUINT32 (data + 0, w->id & 0xff);
......@@ -149,14 +174,14 @@ write_items (MsOleSummary *si)
}
MsOleSummary *
ms_ole_summary_open_stream (MsOleStream *s)
ms_ole_summary_open_stream (MsOleStream *s, const MsOlePropertySetID psid)
{
guint8 data[64];
guint16 byte_order;
gboolean panic = FALSE;
guint32 os_version;
MsOleSummary *si;
gint i, sections;
guint8 data[64];
guint16 byte_order;
gboolean panic = FALSE;
guint32 os_version;
MsOleSummary *si;
gint i, sections;
g_return_val_if_fail (s != NULL, NULL);
......@@ -198,13 +223,38 @@ ms_ole_summary_open_stream (MsOleStream *s)
ms_ole_summary_close (si);
return NULL;
}
if (MS_OLE_GET_GUINT32 (data + 0) != 0XF29F85E0 ||
MS_OLE_GET_GUINT32 (data + 4) != 0X10684FF9 ||
MS_OLE_GET_GUINT32 (data + 8) != 0X000891AB ||
MS_OLE_GET_GUINT32 (data + 12) != 0XD9B3272B) {
ms_ole_summary_close (si);
return NULL;
if (psid == MS_OLE_PS_SUMMARY_INFO) {
if (MS_OLE_GET_GUINT32 (data + 0) == sum_fmtid[0] &&
MS_OLE_GET_GUINT32 (data + 4) == sum_fmtid[1] &&
MS_OLE_GET_GUINT32 (data + 8) == sum_fmtid[2] &&
MS_OLE_GET_GUINT32 (data + 12) == sum_fmtid[3] ) {
si->ps_id = MS_OLE_PS_SUMMARY_INFO;
} else {
ms_ole_summary_close (si);
return NULL;
}
} else if (psid == MS_OLE_PS_DOCUMENT_SUMMARY_INFO) {
if (MS_OLE_GET_GUINT32 (data + 0) == doc_fmtid[0] &&
MS_OLE_GET_GUINT32 (data + 4) == doc_fmtid[1] &&
MS_OLE_GET_GUINT32 (data + 8) == doc_fmtid[2] &&
MS_OLE_GET_GUINT32 (data + 12) == doc_fmtid[3] ) {
si->ps_id = MS_OLE_PS_DOCUMENT_SUMMARY_INFO;
} else if (MS_OLE_GET_GUINT32 (data + 0) == user_fmtid[0] &&
MS_OLE_GET_GUINT32 (data + 4) == user_fmtid[1] &&
MS_OLE_GET_GUINT32 (data + 8) == user_fmtid[2] &&
MS_OLE_GET_GUINT32 (data + 12) == user_fmtid[3] ) {
si->ps_id = MS_OLE_PS_DOCUMENT_SUMMARY_INFO;
} else {
ms_ole_summary_close (si);
return NULL;
}
}
sect.offset = MS_OLE_GET_GUINT32 (data + 16);
g_array_append_val (si->sections, sect);
/* We want to read the offsets of the items here into si->items */
......@@ -212,7 +262,7 @@ ms_ole_summary_open_stream (MsOleStream *s)
si->items = g_array_new (FALSE, FALSE, sizeof (item_t));
if (!read_items (si)) {
if (!read_items (si, si->ps_id)) {
g_warning ("Serious error reading items");
ms_ole_summary_close (si);
return NULL;
......@@ -221,6 +271,10 @@ ms_ole_summary_open_stream (MsOleStream *s)
return si;
}
/*
* ms_ole_summary_open:
* Opens the SummaryInformation stream.
*/
MsOleSummary *
ms_ole_summary_open (MsOle *f)
{
......@@ -233,16 +287,36 @@ ms_ole_summary_open (MsOle *f)
if (result != MS_OLE_ERR_OK || !s)
return NULL;
return ms_ole_summary_open_stream (s);
return ms_ole_summary_open_stream (s, MS_OLE_PS_SUMMARY_INFO);
}
/*
* ms_ole_docsummary_open:
* Opens the DocumentSummaryInformation stream.
*/
MsOleSummary *
ms_ole_docsummary_open (MsOle *f)
{
MsOleStream *s;
MsOleErr result;
g_return_val_if_fail (f != NULL, NULL);
result = ms_ole_stream_open (&s, f, "/",
"DocumentSummaryInformation", 'r');
if (result != MS_OLE_ERR_OK || !s)
return NULL;
return ms_ole_summary_open_stream (s, MS_OLE_PS_DOCUMENT_SUMMARY_INFO);
}
/*
* Cheat by hard coding magic numbers and chaining on.
*/
MsOleSummary *
ms_ole_summary_create_stream (MsOleStream *s)
ms_ole_summary_create_stream (MsOleStream *s, const MsOlePropertySetID psid)
{
guint8 data[64];
guint8 data[78];
MsOleSummary *si;
g_return_val_if_fail (s != NULL, NULL);
......@@ -255,23 +329,42 @@ ms_ole_summary_create_stream (MsOleStream *s)
MS_OLE_SET_GUINT32 (data + 12, 0x0000);
MS_OLE_SET_GUINT32 (data + 16, 0x0000);
MS_OLE_SET_GUINT32 (data + 20, 0x0000);
MS_OLE_SET_GUINT32 (data + 24, 0x0001); /* Sections */
MS_OLE_SET_GUINT32 (data + 28, 0xF29F85E0); /* ID */
MS_OLE_SET_GUINT32 (data + 32, 0x10684FF9);
MS_OLE_SET_GUINT32 (data + 36, 0x000891AB);
MS_OLE_SET_GUINT32 (data + 40, 0xD9B3272B);
if (psid == MS_OLE_PS_SUMMARY_INFO) {
MS_OLE_SET_GUINT32 (data + 24, 0x0001); /* Sections */
MS_OLE_SET_GUINT32 (data + 28, sum_fmtid[0]); /* ID */
MS_OLE_SET_GUINT32 (data + 32, sum_fmtid[1]);
MS_OLE_SET_GUINT32 (data + 36, sum_fmtid[2]);
MS_OLE_SET_GUINT32 (data + 40, sum_fmtid[3]);
MS_OLE_SET_GUINT32 (data + 44, 0x30); /* Section offset = 48 */
MS_OLE_SET_GUINT32 (data + 48, 0); /* bytes */
MS_OLE_SET_GUINT32 (data + 52, 0); /* properties */
s->write (s, data, 56);
} else if (psid == MS_OLE_PS_DOCUMENT_SUMMARY_INFO) {
MS_OLE_SET_GUINT32 (data + 24, 0x0001); /* Sections */
MS_OLE_SET_GUINT32 (data + 44, 48); /* Section offset */
MS_OLE_SET_GUINT32 (data + 28, doc_fmtid[0]); /* ID */
MS_OLE_SET_GUINT32 (data + 32, doc_fmtid[1]);
MS_OLE_SET_GUINT32 (data + 36, doc_fmtid[2]);
MS_OLE_SET_GUINT32 (data + 40, doc_fmtid[3]);
MS_OLE_SET_GUINT32 (data + 48, 0); /* bytes */
MS_OLE_SET_GUINT32 (data + 52, 0); /* properties */
s->write (s, data, 56);
MS_OLE_SET_GUINT32 (data + 44, 0x30); /* Section offset = 48 */
MS_OLE_SET_GUINT32 (data + 48, 0); /* bytes */
MS_OLE_SET_GUINT32 (data + 52, 0); /* properties */
s->write (s, data, 56);
}
s->lseek (s, 0, MsOleSeekSet);
si = ms_ole_summary_open_stream (s);
si = ms_ole_summary_open_stream (s, psid);
si->read_mode = FALSE;
return si;
......@@ -299,7 +392,32 @@ ms_ole_summary_create (MsOle *f)
return NULL;
}
return ms_ole_summary_create_stream (s);
return ms_ole_summary_create_stream (s, MS_OLE_PS_SUMMARY_INFO);
}
/**
* ms_ole_docsummary_create
*
* Create a MS DocumentSummaryInformation stream.
*
**/
MsOleSummary *
ms_ole_docsummary_create (MsOle *f)
{
MsOleStream *s;
MsOleErr result;
g_return_val_if_fail (f != NULL, NULL);
result = ms_ole_stream_open (&s, f, "/",
"DocumentSummaryInformation", 'w');
if (result != MS_OLE_ERR_OK || !s) {
printf ("ms_ole_docsummary_create: Can't open stream for writing\n");
return NULL;
}
return ms_ole_summary_create_stream (s, MS_OLE_PS_DOCUMENT_SUMMARY_INFO);
}
......@@ -347,11 +465,12 @@ void ms_ole_summary_close (MsOleSummary *si)
/*
* Record handling code
*/
#define TYPE_STRING 0x1e
#define TYPE_LONG 0x03
#define TYPE_PREVIEW 0x47
#define TYPE_TIME 0x1e
#define TYPE_SHORT 0x02 /* 2, VT_I2, 2-byte signed integer */
#define TYPE_LONG 0x03 /* 3, VT_I4, 4-byte signed integer */
#define TYPE_BOOLEAN 0x0b /* 11, VT_BOOL, Boolean value */
#define TYPE_STRING 0x1e /* 30, VT_LPSTR, Pointer to null terminated ANSI string */
#define TYPE_TIME 0x40 /* 64, VT_FILETIME, 64-bit FILETIME structure */
#define TYPE_PREVIEW 0x47 /* 71, VT_CF, Pointer to a CLIPDATA structure */
/* Seeks to the correct place, and returns a handle or NULL on failure */
static item_t *
......@@ -415,7 +534,79 @@ ms_ole_summary_get_string (MsOleSummary *si, MsOleSummaryPID id,
return ans;
}
guint32
guint16
ms_ole_summary_get_short (MsOleSummary *si, MsOleSummaryPID id,
gboolean *available)
{
guint8 data[8];
guint32 type;
guint32 value;
item_t *item;
g_return_val_if_fail (available != NULL, 0);
*available = FALSE;
g_return_val_if_fail (si != NULL, 0);
g_return_val_if_fail (si->read_mode, 0);
g_return_val_if_fail (MS_OLE_SUMMARY_TYPE (id) ==
MS_OLE_SUMMARY_TYPE_SHORT, 0);
if (!(item = seek_to_record (si, id)))
return 0;
if (!si->s->read_copy (si->s, data, 8))
return 0;
type = MS_OLE_GET_GUINT32 (data);
value = MS_OLE_GET_GUINT16 (data + 4);
if (type != TYPE_SHORT) { /* Very odd */
g_warning ("Summary short type mismatch");
printf ("Type expected: %#4.4x\n", TYPE_SHORT);
printf ("Type found : %#4.4x\n", type);
return 0;
}
*available = TRUE;
return value;
}
gboolean
ms_ole_summary_get_boolean (MsOleSummary *si, MsOleSummaryPID id,
gboolean *available)
{
guint8 data[8];
guint32 type;
gboolean value;
item_t *item;
g_return_val_if_fail (available != NULL, 0);
*available = FALSE;
g_return_val_if_fail (si != NULL, 0);
g_return_val_if_fail (si->read_mode, 0);
g_return_val_if_fail (MS_OLE_SUMMARY_TYPE (id) ==
MS_OLE_SUMMARY_TYPE_BOOLEAN, 0);
if (!(item = seek_to_record (si, id)))
return 0;
if (!si->s->read_copy (si->s, data, 8))
return 0;
type = MS_OLE_GET_GUINT32 (data);
value = MS_OLE_GET_GUINT16 (data + 4);
if (type != TYPE_BOOLEAN) { /* Very odd */
g_warning ("Summary boolean type mismatch");
printf ("Type expected: %#4.4x\n", TYPE_BOOLEAN);
printf ("Type found : %#4.4x\n", type);
return 0;
}
*available = TRUE;
return value;
}
guint32
ms_ole_summary_get_long (MsOleSummary *si, MsOleSummaryPID id,
gboolean *available)
{
......@@ -448,25 +639,178 @@ ms_ole_summary_get_long (MsOleSummary *si, MsOleSummaryPID id,
return value;
}
static void
demangle_datetime (guint32 low, guint32 high, MsOleSummaryTime *time)
/*
* filetime_to_unixtime
*
* Convert a FILETIME format to unixtime
* FILETIME is the number of 100ns units since January 1, 1601.
* unixtime is the number of seconds since January 1, 1970.
*
* The difference in 100ns units between the two dates is:
* 116,444,736,000,000,000 (TIMEDIF)
* (I'll let you do the math)
* If we divide this into pieces,
* high 32-bits = 27111902 or TIMEDIF / 16^8
* mid 16-bits = 54590 or (TIMEDIF - (high 32-bits * 16^8)) / 16^4
* low 16-bits = 32768 or (TIMEDIF - (high 32-bits * 16^8) - (mid 16-bits * 16^4)
*
* where all math is integer.
*
* Adapted from work in 'wv' by:
* Caolan McNamara (Caolan.McNamara@ul.ie)
*/
#define HIGH32_DELTA 27111902
#define MID16_DELTA 54590
#define LOW16_DELTA 32768
glong
filetime_to_unixtime (guint32 low_time, guint32 high_time)
{
/* See 'wv' for details */
g_warning ("FIXME: a vile mess...");
guint32 low16; /* 16 bit, low bits */
guint32 mid16; /* 16 bit, medium bits */
guint32 hi32; /* 32 bit, high bits */
unsigned int carry; /* carry bit for subtraction */
int negative; /* whether a represents a negative value */
/* Copy the time values to hi32/mid16/low16 */
hi32 = high_time;
mid16 = low_time >> 16;
low16 = low_time & 0xffff;
/* Subtract the time difference */
if (low16 >= LOW16_DELTA )
low16 -= LOW16_DELTA , carry = 0;
else
low16 += (1 << 16) - LOW16_DELTA , carry = 1;
if (mid16 >= MID16_DELTA + carry)
mid16 -= MID16_DELTA + carry, carry = 0;
else
mid16 += (1 << 16) - MID16_DELTA - carry, carry = 1;
hi32 -= HIGH32_DELTA + carry;
/* If a is negative, replace a by (-1-a) */
negative = (hi32 >= ((guint32)1) << 31);
if (negative) {
/* Set a to -a - 1 (a is hi32/mid16/low16) */
low16 = 0xffff - low16;
mid16 = 0xffff - mid16;
hi32 = ~hi32;
}
/*
* Divide a by 10000000 (a = hi32/mid16/low16), put the rest into r.
* Split the divisor into 10000 * 1000 which are both less than 0xffff.
*/
mid16 += (hi32 % 10000) << 16;
hi32 /= 10000;
low16 += (mid16 % 10000) << 16;
mid16 /= 10000;
low16 /= 10000;
mid16 += (hi32 % 1000) << 16;
hi32 /= 1000;
low16 += (mid16 % 1000) << 16;
mid16 /= 1000;
low16 /= 1000;
/* If a was negative, replace a by (-1-a) and r by (9999999 - r) */
if (negative) {
/* Set a to -a - 1 (a is hi32/mid16/low16) */
low16 = 0xffff - low16;
mid16 = 0xffff - mid16;
hi32 = ~hi32;
}
/* Do not replace this by << 32, it gives a compiler warning and
* it does not work
*/
return ((((glong)hi32) << 16) << 16) + (mid16 << 16) + low16;
}
MsOleSummaryTime
void
unixtime_to_filetime (time_t unix_time, unsigned int *time_high, unsigned int *time_low)
{
unsigned int low_16;
unsigned int mid_16;
unsigned int high32;
unsigned int carry;
/*
* First split unix_time up.
*/
high32 = (unix_time >> 16) >> 16;
mid_16 = unix_time >> 16;
low_16 = unix_time & 0xffff;
/*
* Convert seconds to 100 ns units by multipling by 10,000,000.
* Do this in two steps, 10,000 and 1,000.
*/
low_16 *= 10000;
carry = (low_16) >> 16;
low_16 = low_16 & 0xffff;
mid_16 *= 10000;
mid_16 += carry;
carry = (mid_16 >> 16);