mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 22:32:46 +00:00
1a97e11ffd
The mailto library is the mail compose code ripped out of the old Messenger libmsg library, then cleaned up somewhat (it could still use more cleaning). This library should only be built ifdef MOZ_MAIL_COMPOSE.
1042 lines
25 KiB
C
1042 lines
25 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public License
|
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
|
* http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
|
* for the specific language governing rights and limitations under the
|
|
* NPL.
|
|
*
|
|
* The Initial Developer of this code under the NPL is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
|
* Reserved.
|
|
*/
|
|
/*
|
|
*
|
|
* Mac_BinHex.c
|
|
* ------------
|
|
*
|
|
* The decode and encode for BinHex 4.0
|
|
*
|
|
* 09sep95 mym Created
|
|
* 18sep95 mym Added the functions to do encoding from
|
|
* the input stream instead of file.
|
|
*/
|
|
|
|
#include "msg.h"
|
|
#include "appledbl.h"
|
|
#include "m_binhex.h"
|
|
#include "ad_codes.h"
|
|
/* for XP_GetString() */
|
|
#include "xpgetstr.h"
|
|
|
|
#ifdef XP_MAC
|
|
#include <StandardFile.h>
|
|
#pragma warn_unusedarg off
|
|
#endif
|
|
|
|
extern int MK_MSG_SAVE_DECODED_AS;
|
|
|
|
extern int MK_UNABLE_TO_OPEN_TMP_FILE;
|
|
extern int MK_MIME_ERROR_WRITING_FILE;
|
|
extern int MK_MIME_DATA_CORRUPTED;
|
|
|
|
static char BinHexTable[64] =
|
|
{
|
|
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
|
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x30, 0x31, 0x32,
|
|
0x33, 0x34, 0x35, 0x36, 0x38, 0x39, 0x40, 0x41,
|
|
0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
|
|
0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x50, 0x51, 0x52,
|
|
0x53, 0x54, 0x55, 0x56, 0x58, 0x59, 0x5a, 0x5b,
|
|
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x68,
|
|
0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x70, 0x71, 0x72
|
|
};
|
|
|
|
/*
|
|
* The encode for bin hex format.
|
|
*/
|
|
|
|
PRIVATE int binhex_fill_data(
|
|
binhex_encode_object* p_bh_encode_obj, char c)
|
|
{
|
|
int i;
|
|
|
|
if (p_bh_encode_obj->pos_outbuff >= p_bh_encode_obj->s_outbuff)
|
|
{
|
|
p_bh_encode_obj->overflow[p_bh_encode_obj->s_overflow++] = c;
|
|
}
|
|
else
|
|
{
|
|
p_bh_encode_obj->outbuff[p_bh_encode_obj->pos_outbuff++] =c;
|
|
}
|
|
|
|
if (++p_bh_encode_obj->line_length == 64)
|
|
{
|
|
/*
|
|
** Incase the new line is 2 character. LRCR
|
|
*/
|
|
for(i = 1; i <= p_bh_encode_obj->newline[0]; i++)
|
|
binhex_fill_data(p_bh_encode_obj, p_bh_encode_obj->newline[i]);
|
|
|
|
p_bh_encode_obj->line_length = 0;
|
|
}
|
|
|
|
return p_bh_encode_obj->s_overflow ? errEOB : NOERR;
|
|
}
|
|
|
|
/************************************************************************
|
|
* EncodeDataChar - encode an 8-bit data char into a six-bit buffer
|
|
* returns the number of valid encoded characters generated
|
|
************************************************************************/
|
|
PRIVATE int binhex_encode_data_char(
|
|
binhex_encode_object *p_bh_encode_obj,
|
|
unsigned char c)
|
|
{
|
|
int status = 0;
|
|
|
|
switch (p_bh_encode_obj->state86++)
|
|
{
|
|
case 0:
|
|
status = binhex_fill_data(p_bh_encode_obj,
|
|
BinHexTable[(c>>2)&0x3f]);
|
|
p_bh_encode_obj->saved_bits = (c&0x3)<<4;
|
|
break;
|
|
case 1:
|
|
status = binhex_fill_data(p_bh_encode_obj,
|
|
BinHexTable[p_bh_encode_obj->saved_bits | ((c>>4)&0xf)]);
|
|
p_bh_encode_obj->saved_bits = (c&0xf)<<2;
|
|
break;
|
|
case 2:
|
|
status = binhex_fill_data(p_bh_encode_obj,
|
|
BinHexTable[p_bh_encode_obj->saved_bits | ((c>>6)&0x3)]);
|
|
if (status != NOERR)
|
|
break;
|
|
|
|
status = binhex_fill_data(p_bh_encode_obj,
|
|
BinHexTable[c&0x3f]);
|
|
p_bh_encode_obj->state86 = 0;
|
|
break;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
#define BYTEMASK 0xff
|
|
#define BYTEBIT 0x100
|
|
#define WORDMASK 0xffff
|
|
#define WORDBIT 0x10000
|
|
#define CRCCONSTANT 0x1021
|
|
|
|
#define WOW { \
|
|
c <<= 1; \
|
|
if ((temp <<= 1) & WORDBIT) \
|
|
temp = (temp & WORDMASK) ^ CRCCONSTANT; \
|
|
temp ^= (c >> 8); \
|
|
c &= BYTEMASK; \
|
|
}
|
|
|
|
PRIVATE void binhex_comp_q_crc_out(
|
|
binhex_encode_object *p_bh_encode_obj, uint16 c)
|
|
{
|
|
register uint32 temp = p_bh_encode_obj->CRC;
|
|
|
|
WOW;
|
|
WOW;
|
|
WOW;
|
|
WOW;
|
|
WOW;
|
|
WOW;
|
|
WOW;
|
|
WOW;
|
|
p_bh_encode_obj->CRC = temp;
|
|
}
|
|
|
|
PRIVATE int binhex_encode_buff(
|
|
binhex_encode_object *p_bh_encode_obj,
|
|
unsigned char* data,
|
|
int size)
|
|
{
|
|
int i, status = 0;
|
|
unsigned char dc;
|
|
|
|
for (i = 0; i < size; i++)
|
|
{
|
|
dc = *data++;
|
|
|
|
status = binhex_encode_data_char(p_bh_encode_obj, dc);
|
|
if ((char)dc == (char)0x90)
|
|
status = binhex_encode_data_char(p_bh_encode_obj, 0);
|
|
|
|
if (status != NOERR)
|
|
break;
|
|
|
|
binhex_comp_q_crc_out(p_bh_encode_obj, dc); /* and compute the CRC too */
|
|
}
|
|
return status;
|
|
}
|
|
|
|
PRIVATE int binhex_encode_end_a_part(
|
|
binhex_encode_object* p_bh_encode_obj)
|
|
{
|
|
int status;
|
|
uint16 tempCrc;
|
|
|
|
/*
|
|
** write the CRC to the encode.
|
|
*/
|
|
binhex_comp_q_crc_out(p_bh_encode_obj, 0);
|
|
binhex_comp_q_crc_out(p_bh_encode_obj, 0);
|
|
tempCrc = (uint16)(p_bh_encode_obj->CRC & 0xffff);
|
|
tempCrc = htons(tempCrc);
|
|
status = binhex_encode_buff(p_bh_encode_obj,
|
|
(unsigned char*)&tempCrc,
|
|
sizeof(uint16));
|
|
p_bh_encode_obj->CRC = 0;
|
|
return status;
|
|
}
|
|
|
|
PRIVATE int binhex_encode_finishing(
|
|
binhex_encode_object *p_bh_encode_obj)
|
|
{
|
|
int i, status = 0;
|
|
|
|
if (p_bh_encode_obj->state86)
|
|
status = binhex_encode_buff(p_bh_encode_obj, (unsigned char*)&status, 1);
|
|
|
|
/*
|
|
** The close token.
|
|
*/
|
|
status = binhex_fill_data(p_bh_encode_obj, ':');
|
|
|
|
for (i=1; i <= p_bh_encode_obj->newline[0]; i++)
|
|
status = binhex_fill_data(p_bh_encode_obj,
|
|
p_bh_encode_obj->newline[i]);
|
|
|
|
return errDone;
|
|
}
|
|
|
|
|
|
int binhex_encode_init(binhex_encode_object *p_bh_encode_obj)
|
|
{
|
|
/*
|
|
** init all the status.
|
|
*/
|
|
XP_MEMSET(p_bh_encode_obj, 0, sizeof(binhex_encode_object));
|
|
|
|
p_bh_encode_obj->line_length = 1;
|
|
|
|
p_bh_encode_obj->newline[0] = 2;
|
|
p_bh_encode_obj->newline[1] = CR;
|
|
p_bh_encode_obj->newline[2] = LF; /* to confirm with rfc822, use CRLF */
|
|
|
|
return NOERR;
|
|
}
|
|
|
|
int binhex_encode_next(
|
|
binhex_encode_object* p_bh_encode_obj,
|
|
char *in_buff,
|
|
int32 in_size,
|
|
char *out_buff,
|
|
int32 buff_size,
|
|
int32 *real_size)
|
|
{
|
|
int status = 0;
|
|
/*
|
|
** setup the buffer information.
|
|
*/
|
|
p_bh_encode_obj->outbuff = out_buff;
|
|
p_bh_encode_obj->s_outbuff = buff_size;
|
|
p_bh_encode_obj->pos_outbuff = 0;
|
|
|
|
/*
|
|
** copy over the left over from last time.
|
|
*/
|
|
if (p_bh_encode_obj->s_overflow)
|
|
{
|
|
XP_MEMCPY(p_bh_encode_obj->overflow,
|
|
p_bh_encode_obj->outbuff,
|
|
p_bh_encode_obj->s_overflow);
|
|
|
|
p_bh_encode_obj->pos_outbuff = p_bh_encode_obj->s_overflow;
|
|
p_bh_encode_obj->s_overflow = 0;
|
|
}
|
|
|
|
/*
|
|
** Jump to the right state.
|
|
*/
|
|
if ( p_bh_encode_obj->state < BINHEX_STATE_DONE)
|
|
{
|
|
if (in_buff == NULL && in_size == 0)
|
|
{
|
|
/* this is our special token of end of a part, time to append crc codes */
|
|
if (p_bh_encode_obj->state != BINHEX_STATE_FINISH)
|
|
status = binhex_encode_end_a_part(p_bh_encode_obj);
|
|
else
|
|
status = binhex_encode_finishing(p_bh_encode_obj);
|
|
|
|
p_bh_encode_obj->state += 2; /* so we can jump to the next state.*/
|
|
}
|
|
else
|
|
{
|
|
if (p_bh_encode_obj->state == BINHEX_STATE_START)
|
|
{
|
|
XP_STRCPY(p_bh_encode_obj->outbuff + p_bh_encode_obj->pos_outbuff,
|
|
"\r\n(This file must be converted with BinHex 4.0)\r\n\r\n:");
|
|
p_bh_encode_obj->pos_outbuff += 52;
|
|
|
|
p_bh_encode_obj->state = BINHEX_STATE_HEADER;
|
|
|
|
XP_MEMCPY(p_bh_encode_obj->name,
|
|
in_buff,
|
|
in_size);
|
|
}
|
|
else if (p_bh_encode_obj->state == BINHEX_STATE_HEADER)
|
|
{
|
|
XP_MEMCPY(&(p_bh_encode_obj->head),
|
|
in_buff,
|
|
sizeof(binhex_header));
|
|
|
|
if (in_size == 20) /* in the platform that alignment is 4-bytes. */
|
|
in_size = 18;
|
|
|
|
p_bh_encode_obj->head.dlen = 0; /* we just can't trust the dlen from */
|
|
/* apple double decoder told us. */
|
|
/* do our own counting. */
|
|
}
|
|
else if (p_bh_encode_obj->state == BINHEX_STATE_DFORK)
|
|
{
|
|
if (p_bh_encode_obj->head.dlen == 0)
|
|
{
|
|
p_bh_encode_obj->c[0] = in_buff[0]; /* save the first 2 bytes, in case */
|
|
p_bh_encode_obj->c[1] = in_buff[1]; /* head and data share 1 code block */
|
|
}
|
|
p_bh_encode_obj->head.dlen += in_size;
|
|
}
|
|
|
|
status = binhex_encode_buff(p_bh_encode_obj,
|
|
(unsigned char *)in_buff,
|
|
in_size);
|
|
}
|
|
}
|
|
*real_size = p_bh_encode_obj->pos_outbuff;
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
** Only generate the header part of the encoding,
|
|
** so we can fix up the
|
|
*/
|
|
int binhex_reencode_head(
|
|
binhex_encode_object *p_bh_encode_obj,
|
|
char* outbuff,
|
|
int32 buff_size,
|
|
int32* real_size)
|
|
{
|
|
int32 size, dlen;
|
|
int status;
|
|
char buff[64];
|
|
|
|
p_bh_encode_obj->state = 0;
|
|
p_bh_encode_obj->state86 = 0;
|
|
p_bh_encode_obj->CRC = 0;
|
|
p_bh_encode_obj->line_length= 1;
|
|
p_bh_encode_obj->saved_bits = 0;
|
|
p_bh_encode_obj->s_overflow = 0 ;
|
|
|
|
status = binhex_encode_next(
|
|
p_bh_encode_obj,
|
|
p_bh_encode_obj->name,
|
|
p_bh_encode_obj->name[0]+2, /* in_size */
|
|
outbuff,
|
|
buff_size,
|
|
real_size);
|
|
if (status != NOERR)
|
|
return status;
|
|
|
|
size = *real_size;
|
|
|
|
/* now we should have the right data length in the head structure, but don't */
|
|
/* forget convert it back to the net byte order (i.e., Motolora) before write it */
|
|
/* */
|
|
/* Note: since we don't change the size of rlen, so don't need to worry about it */
|
|
|
|
p_bh_encode_obj->head.dlen = htonl(dlen = p_bh_encode_obj->head.dlen);
|
|
|
|
/* make a copy before do the encoding, -- it may modify the head!!!. */
|
|
XP_MEMCPY(buff, (char*)&p_bh_encode_obj->head,
|
|
sizeof(binhex_header));
|
|
if (18 < sizeof(binhex_header))
|
|
{
|
|
/* we get an alignment problem here. */
|
|
XP_MEMCPY(buff + 10, buff + 12, 8);
|
|
}
|
|
|
|
status = binhex_encode_next(
|
|
p_bh_encode_obj,
|
|
(char*)buff,
|
|
18, /* sizeof(binhex_header),*/
|
|
outbuff + size,
|
|
buff_size - size,
|
|
real_size);
|
|
if (status != NOERR)
|
|
return status;
|
|
|
|
size += *real_size;
|
|
|
|
status = binhex_encode_next( /* for CRC */
|
|
p_bh_encode_obj,
|
|
NULL,
|
|
0, /* in_size */
|
|
outbuff + size,
|
|
buff_size - size,
|
|
real_size);
|
|
|
|
if (status != NOERR)
|
|
return status;
|
|
|
|
size += *real_size;
|
|
|
|
if (p_bh_encode_obj->state86 != 0)
|
|
{
|
|
/*
|
|
** Make sure we don't destroy the orignal valid coding.
|
|
**
|
|
** (Keep in mind that 3 characters share 4 coding chars,
|
|
** so it is possible for the head and data stream share one 4 code group.
|
|
**
|
|
** How about only one or zero character in the data fork?
|
|
** ---- just rerun the encoding, not a big deal.
|
|
*/
|
|
if (dlen <= 1)
|
|
{
|
|
/* why just rerun the encoding once more. */
|
|
status = binhex_encode_next(
|
|
p_bh_encode_obj,
|
|
p_bh_encode_obj->c,
|
|
dlen,
|
|
outbuff + size,
|
|
buff_size - size,
|
|
real_size);
|
|
if (status != NOERR)
|
|
return status;
|
|
|
|
size += *real_size; /* encode the data fork */
|
|
|
|
status = binhex_encode_next(
|
|
p_bh_encode_obj,
|
|
NULL,
|
|
0,
|
|
outbuff + size,
|
|
buff_size - size,
|
|
real_size);
|
|
if (status != NOERR)
|
|
return status;
|
|
|
|
size += *real_size; /* for the end up data fork */
|
|
|
|
status = binhex_encode_next(
|
|
p_bh_encode_obj,
|
|
NULL,
|
|
0,
|
|
outbuff + size,
|
|
buff_size - size,
|
|
real_size); /* for the end up encoding*/
|
|
}
|
|
else
|
|
{
|
|
status = binhex_encode_next(
|
|
p_bh_encode_obj,
|
|
p_bh_encode_obj->c,
|
|
3 - p_bh_encode_obj->state86, /* in_size */
|
|
outbuff + size,
|
|
buff_size - size,
|
|
real_size);
|
|
}
|
|
size += *real_size;
|
|
}
|
|
*real_size = size;
|
|
|
|
return status;
|
|
}
|
|
|
|
int binhex_encode_end (
|
|
binhex_encode_object *p_bh_encode_obj,
|
|
XP_Bool is_aborting)
|
|
{
|
|
return NOERR;
|
|
}
|
|
|
|
|
|
/*
|
|
** The decode's.
|
|
*/
|
|
static char binhex_decode[256] =
|
|
{
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, -1, -1,
|
|
13, 14, 15, 16, 17, 18, 19, -1, 20, 21, -1, -1, -1, -1, -1, -1,
|
|
22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, -1,
|
|
37, 38, 39, 40, 41, 42, 43, -1, 44, 45, 46, 47, -1, -1, -1, -1,
|
|
48, 49, 50, 51, 52, 53, 54, -1, 55, 56, 57, 58, 59, 60, -1, -1,
|
|
61, 62, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
|
|
};
|
|
|
|
#define BHEXVAL(c) (binhex_decode[(unsigned char) c])
|
|
|
|
/*
|
|
** the decode for bin hex format.
|
|
*/
|
|
int binhex_decode_init (
|
|
binhex_decode_object *p_bh_decode_obj,
|
|
MWContext *context)
|
|
{
|
|
XP_MEMSET(p_bh_decode_obj, 0, sizeof(binhex_decode_object));
|
|
|
|
p_bh_decode_obj->octetin = 26;
|
|
p_bh_decode_obj->donepos = 3;
|
|
p_bh_decode_obj->context = context;
|
|
|
|
return NOERR;
|
|
}
|
|
|
|
static void
|
|
simple_copy(MWContext* context, char* newFile, void* closure)
|
|
{
|
|
XP_STRCPY((char *)closure, newFile);
|
|
}
|
|
|
|
PRIVATE void binhex_process(
|
|
binhex_decode_object *p_bh_decode_obj)
|
|
{
|
|
int32 status;
|
|
uint16 tmpcrc, cval;
|
|
unsigned char ctmp, c = p_bh_decode_obj->rlebuf;
|
|
|
|
/* do CRC */
|
|
ctmp = p_bh_decode_obj->inCRC ? c : 0;
|
|
cval = p_bh_decode_obj->CRC & 0xf000;
|
|
tmpcrc = ((uint16) (p_bh_decode_obj->CRC << 4) |
|
|
(ctmp >> 4))
|
|
^ (cval | (cval >> 7) |
|
|
(cval >> 12));
|
|
cval = tmpcrc & 0xf000;
|
|
p_bh_decode_obj->CRC = ((uint16) (tmpcrc << 4) |
|
|
(ctmp & 0x0f))
|
|
^ (cval | (cval >> 7) |
|
|
(cval >> 12));
|
|
|
|
/* handle state */
|
|
switch (p_bh_decode_obj->state)
|
|
{
|
|
case BINHEX_STATE_START:
|
|
p_bh_decode_obj->state = BINHEX_STATE_FNAME;
|
|
p_bh_decode_obj->count = 1;
|
|
#ifndef XP_MAC
|
|
p_bh_decode_obj->name = XP_ALLOC(64);
|
|
#endif
|
|
*(p_bh_decode_obj->name) = (c & 63);
|
|
break;
|
|
|
|
case BINHEX_STATE_FNAME:
|
|
p_bh_decode_obj->name[p_bh_decode_obj->count] = c;
|
|
|
|
if (p_bh_decode_obj->count++ > *(p_bh_decode_obj->name))
|
|
{
|
|
#if 0
|
|
char* p;
|
|
/* convert it to the c-string too. */
|
|
c = *(p_bh_decode_obj->name);
|
|
p = p_bh_decode_obj->name;
|
|
|
|
while (c--)
|
|
{
|
|
*p = *(p+1); p++;
|
|
}
|
|
|
|
*p = '\0';
|
|
#endif
|
|
p_bh_decode_obj->state = BINHEX_STATE_HEADER;
|
|
p_bh_decode_obj->count = 0;
|
|
}
|
|
break;
|
|
|
|
case BINHEX_STATE_HEADER:
|
|
((char *)&p_bh_decode_obj->head)[p_bh_decode_obj->count] = c;
|
|
if (++p_bh_decode_obj->count == 18)
|
|
{
|
|
#ifndef XP_MAC
|
|
if (sizeof(binhex_header) != 18) /* fix the alignment problem in some OS */
|
|
{
|
|
char *p = (char *)&p_bh_decode_obj->head;
|
|
p += 19;
|
|
for (c = 0; c < 8; c++)
|
|
{
|
|
*p = *(p-2); p--;
|
|
}
|
|
}
|
|
#endif
|
|
p_bh_decode_obj->state = BINHEX_STATE_HCRC;
|
|
p_bh_decode_obj->inCRC = 1;
|
|
p_bh_decode_obj->count = 0;
|
|
}
|
|
break;
|
|
|
|
case BINHEX_STATE_DFORK:
|
|
case BINHEX_STATE_RFORK:
|
|
p_bh_decode_obj->outbuff[p_bh_decode_obj->pos_outbuff++] = c;
|
|
if (-- p_bh_decode_obj->count == 0)
|
|
{
|
|
#ifdef XP_MAC
|
|
long howMuch = p_bh_decode_obj->pos_outbuff;
|
|
status = FSWrite(p_bh_decode_obj->fileId,
|
|
&howMuch,
|
|
p_bh_decode_obj->outbuff);
|
|
FSClose(p_bh_decode_obj->fileId);
|
|
#else
|
|
/* only output data fork in the non-mac system. */
|
|
if (p_bh_decode_obj->state == BINHEX_STATE_DFORK)
|
|
{
|
|
status = XP_FileWrite(p_bh_decode_obj->outbuff,
|
|
p_bh_decode_obj->pos_outbuff,
|
|
p_bh_decode_obj->fileId)
|
|
== p_bh_decode_obj->pos_outbuff ? NOERR : errFileWrite;
|
|
|
|
XP_FileClose(p_bh_decode_obj->fileId);
|
|
}
|
|
else
|
|
{
|
|
status = NOERR; /* do nothing for resource fork. */
|
|
}
|
|
#endif
|
|
p_bh_decode_obj->pos_outbuff = 0;
|
|
|
|
if (status != NOERR)
|
|
p_bh_decode_obj->state = status;
|
|
else
|
|
{
|
|
p_bh_decode_obj->state ++;
|
|
p_bh_decode_obj->fileId = 0;
|
|
}
|
|
p_bh_decode_obj->inCRC = 1;
|
|
}
|
|
else if (p_bh_decode_obj->pos_outbuff >= MAX_BUFF_SIZE)
|
|
{
|
|
#ifdef XP_MAC
|
|
long howMuch = p_bh_decode_obj->pos_outbuff;
|
|
status = FSWrite(p_bh_decode_obj->fileId,
|
|
&howMuch,
|
|
p_bh_decode_obj->outbuff);
|
|
#else
|
|
if (p_bh_decode_obj->state == BINHEX_STATE_DFORK)
|
|
{
|
|
status = XP_FileWrite(p_bh_decode_obj->outbuff,
|
|
p_bh_decode_obj->pos_outbuff,
|
|
p_bh_decode_obj->fileId)
|
|
== p_bh_decode_obj->pos_outbuff ? NOERR : errFileWrite;
|
|
}
|
|
else
|
|
{
|
|
status = NOERR; /* don't care about the resource fork. */
|
|
}
|
|
#endif
|
|
if (status != NOERR)
|
|
p_bh_decode_obj->state = status;
|
|
|
|
p_bh_decode_obj->pos_outbuff = 0;
|
|
}
|
|
break;
|
|
|
|
case BINHEX_STATE_HCRC:
|
|
case BINHEX_STATE_DCRC:
|
|
case BINHEX_STATE_RCRC:
|
|
if (!p_bh_decode_obj->count++)
|
|
{
|
|
p_bh_decode_obj->fileCRC = (unsigned short) c << 8;
|
|
}
|
|
else
|
|
{
|
|
if ((p_bh_decode_obj->fileCRC | c) != p_bh_decode_obj->CRC)
|
|
{
|
|
if (p_bh_decode_obj->state > BINHEX_STATE_HCRC)
|
|
{
|
|
#ifdef XP_MAC
|
|
HDelete(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
(unsigned char*)p_bh_decode_obj->name);
|
|
#else
|
|
XP_FileRemove(p_bh_decode_obj->name, xpURL);
|
|
#endif
|
|
}
|
|
p_bh_decode_obj->state = errDecoding;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
** passed the CRC check!!!
|
|
*/
|
|
p_bh_decode_obj->CRC = 0;
|
|
if (++ p_bh_decode_obj->state == BINHEX_STATE_FINISH)
|
|
{
|
|
#ifdef XP_MAC
|
|
FInfo finfo;
|
|
|
|
/* set back the file information.before we declare done ! */
|
|
finfo.fdType = p_bh_decode_obj->head.type;
|
|
finfo.fdCreator = p_bh_decode_obj->head.creator;
|
|
finfo.fdFlags = p_bh_decode_obj->head.flags & 0xf800;
|
|
|
|
HSetFInfo(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
(unsigned char *)p_bh_decode_obj->name,
|
|
&finfo);
|
|
#endif
|
|
/* now We are done with everything. */
|
|
p_bh_decode_obj->state++;
|
|
break;
|
|
}
|
|
|
|
if (p_bh_decode_obj->state == BINHEX_STATE_DFORK)
|
|
{
|
|
#ifdef XP_MAC
|
|
StandardFileReply reply;
|
|
if( !p_bh_decode_obj->mSpec )
|
|
{
|
|
StandardPutFile("\pSave decoded file as:",
|
|
(unsigned char *)p_bh_decode_obj->name,
|
|
&reply);
|
|
|
|
if (!reply.sfGood)
|
|
{
|
|
p_bh_decode_obj->state = errUsrCancel;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
reply.sfFile.vRefNum = p_bh_decode_obj->mSpec->vRefNum;
|
|
reply.sfFile.parID = p_bh_decode_obj->mSpec->parID;
|
|
XP_MEMCPY(&reply.sfFile.name, p_bh_decode_obj->mSpec->name , 63 );
|
|
}
|
|
|
|
XP_MEMCPY(p_bh_decode_obj->name,
|
|
reply.sfFile.name,
|
|
*(reply.sfFile.name)+1); /* save the new file name. */
|
|
|
|
p_bh_decode_obj->vRefNum = reply.sfFile.vRefNum;
|
|
p_bh_decode_obj->parID = reply.sfFile.parID;
|
|
|
|
HDelete(reply.sfFile.vRefNum,
|
|
reply.sfFile.parID,
|
|
reply.sfFile.name);
|
|
|
|
status = HCreate(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
reply.sfFile.name,
|
|
p_bh_decode_obj->head.creator,
|
|
p_bh_decode_obj->head.type);
|
|
#else /* non-mac OS case */
|
|
char* filename;
|
|
|
|
filename = XP_ALLOC(1024);
|
|
if (filename == NULL ||
|
|
FE_PromptForFileName(p_bh_decode_obj->context,
|
|
XP_GetString(MK_MSG_SAVE_DECODED_AS),
|
|
0,
|
|
FALSE,
|
|
FALSE,
|
|
simple_copy,
|
|
filename) == -1)
|
|
{
|
|
FREEIF(filename);
|
|
p_bh_decode_obj->state = errUsrCancel;
|
|
break;
|
|
}
|
|
|
|
FREEIF(p_bh_decode_obj->name);
|
|
p_bh_decode_obj->name = XP_STRDUP(filename);
|
|
p_bh_decode_obj->fileId
|
|
= XP_FileOpen(filename,
|
|
xpURL,
|
|
XP_FILE_TRUNCATE_BIN);
|
|
if (p_bh_decode_obj->fileId == NULL)
|
|
status = errFileOpen;
|
|
else
|
|
status = NOERR;
|
|
|
|
XP_FREE(filename);
|
|
|
|
#endif
|
|
if (status != NOERR)
|
|
p_bh_decode_obj->state = status;
|
|
|
|
p_bh_decode_obj->count
|
|
= ntohl(p_bh_decode_obj->head.dlen);
|
|
}
|
|
else
|
|
{
|
|
p_bh_decode_obj->count
|
|
= ntohl(p_bh_decode_obj->head.rlen); /* it should in host byte order */
|
|
}
|
|
|
|
if (p_bh_decode_obj->count)
|
|
{
|
|
p_bh_decode_obj->inCRC = 0;
|
|
#ifdef XP_MAC
|
|
if (p_bh_decode_obj->state == BINHEX_STATE_DFORK)
|
|
status = HOpen(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
(unsigned char*)p_bh_decode_obj->name,
|
|
fsWrPerm,
|
|
&(p_bh_decode_obj->fileId));
|
|
else
|
|
status = HOpenRF(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
(unsigned char*)p_bh_decode_obj->name,
|
|
fsWrPerm,
|
|
&(p_bh_decode_obj->fileId));
|
|
if (status != NOERR)
|
|
{
|
|
p_bh_decode_obj->state = errFileOpen;
|
|
HDelete(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
(unsigned char*)p_bh_decode_obj->name);
|
|
break;
|
|
}
|
|
#else
|
|
/* for None Mac OS -- nothing is required, file already open. */
|
|
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
/* nothing inside, so skip to the next state. */
|
|
p_bh_decode_obj->state ++;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static int get_next_char(binhex_decode_object *p_bh_decode_obj)
|
|
{
|
|
char c = 0;
|
|
|
|
while (p_bh_decode_obj->pos_inbuff < p_bh_decode_obj->s_inbuff)
|
|
{
|
|
c = p_bh_decode_obj->inbuff[p_bh_decode_obj->pos_inbuff++];
|
|
if (c != LF && c != CR)
|
|
break;
|
|
}
|
|
return (c == LF || c == CR) ? 0 : (int) c;
|
|
}
|
|
|
|
int binhex_decode_next (
|
|
binhex_decode_object *p_bh_decode_obj,
|
|
const char *in_buff,
|
|
int32 buff_size)
|
|
{
|
|
int found_start;
|
|
int octetpos, c = 0;
|
|
uint32 val;
|
|
|
|
/*
|
|
** reset the buff first.
|
|
*/
|
|
p_bh_decode_obj->inbuff = (char*)in_buff;
|
|
p_bh_decode_obj->s_inbuff = buff_size;
|
|
p_bh_decode_obj->pos_inbuff = 0;
|
|
|
|
/*
|
|
** if it is the first time, seek to the right start place.
|
|
*/
|
|
if (p_bh_decode_obj->state == BINHEX_STATE_START)
|
|
{
|
|
found_start = FALSE;
|
|
/*
|
|
** go through the line, until we get a ':'
|
|
*/
|
|
while (p_bh_decode_obj->pos_inbuff < p_bh_decode_obj->s_inbuff)
|
|
{
|
|
c = p_bh_decode_obj->inbuff[p_bh_decode_obj->pos_inbuff++];
|
|
while (c == CR || c == LF)
|
|
{
|
|
if (p_bh_decode_obj->pos_inbuff >= p_bh_decode_obj->s_inbuff)
|
|
break;
|
|
|
|
c = p_bh_decode_obj->inbuff[p_bh_decode_obj->pos_inbuff++];
|
|
if (c == ':')
|
|
{
|
|
found_start = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (found_start) break; /* we got the start point. */
|
|
}
|
|
|
|
if (p_bh_decode_obj->pos_inbuff >= p_bh_decode_obj->s_inbuff)
|
|
return NOERR; /* we meet buff end before we get the */
|
|
/* start point, wait till next fills. */
|
|
|
|
if (c != ':')
|
|
return errDecoding; /* can't find the start character. */
|
|
}
|
|
|
|
/*
|
|
** run - through the in-stream now.
|
|
*/
|
|
while (p_bh_decode_obj->state >= 0 &&
|
|
p_bh_decode_obj->state < BINHEX_STATE_DONE)
|
|
{
|
|
/* fill in octetbuf */
|
|
do
|
|
{
|
|
if (p_bh_decode_obj->pos_inbuff >= p_bh_decode_obj->s_inbuff)
|
|
return NOERR; /* end of buff, go on for the nxet calls. */
|
|
|
|
c = get_next_char(p_bh_decode_obj);
|
|
if (c == 0)
|
|
return NOERR;
|
|
|
|
if ((val = BHEXVAL(c)) == -1)
|
|
{
|
|
/*
|
|
** we incount an invalid character.
|
|
*/
|
|
if (c)
|
|
{
|
|
/*
|
|
** rolling back.
|
|
*/
|
|
p_bh_decode_obj->donepos --;
|
|
if (p_bh_decode_obj->octetin >= 14) p_bh_decode_obj->donepos--;
|
|
if (p_bh_decode_obj->octetin >= 20) p_bh_decode_obj->donepos--;
|
|
}
|
|
break;
|
|
}
|
|
p_bh_decode_obj->octetbuf.val |= val << p_bh_decode_obj->octetin;
|
|
}
|
|
while ((p_bh_decode_obj->octetin -= 6) > 2);
|
|
|
|
/* handle decoded characters -- run length encoding (rle) detection */
|
|
|
|
#ifndef XP_MAC
|
|
p_bh_decode_obj->octetbuf.val
|
|
= ntohl(p_bh_decode_obj->octetbuf.val);
|
|
#endif
|
|
|
|
for (octetpos = 0; octetpos < p_bh_decode_obj->donepos; ++octetpos)
|
|
{
|
|
c = p_bh_decode_obj->octetbuf.c[octetpos];
|
|
|
|
if (c == 0x90 && !p_bh_decode_obj->marker++)
|
|
continue;
|
|
|
|
if (p_bh_decode_obj->marker)
|
|
{
|
|
if (c == 0)
|
|
{
|
|
p_bh_decode_obj->rlebuf = 0x90;
|
|
binhex_process(p_bh_decode_obj);
|
|
}
|
|
else
|
|
{
|
|
while (--c > 0) /* we are in the run lenght mode */
|
|
{
|
|
binhex_process(p_bh_decode_obj);
|
|
}
|
|
}
|
|
p_bh_decode_obj->marker = 0;
|
|
}
|
|
else
|
|
{
|
|
p_bh_decode_obj->rlebuf = (unsigned char) c;
|
|
binhex_process(p_bh_decode_obj);
|
|
}
|
|
|
|
|
|
if (p_bh_decode_obj->state >= BINHEX_STATE_FINISH)
|
|
break;
|
|
}
|
|
|
|
/* prepare for next 3 characters. */
|
|
if (p_bh_decode_obj->donepos < 3 && p_bh_decode_obj->state < BINHEX_STATE_FINISH)
|
|
p_bh_decode_obj->state = errDecoding;
|
|
|
|
p_bh_decode_obj->octetin = 26;
|
|
p_bh_decode_obj->octetbuf.val = 0;
|
|
}
|
|
|
|
/*
|
|
** Error clean-ups
|
|
*/
|
|
if (p_bh_decode_obj->state < 0 && p_bh_decode_obj->fileId)
|
|
{
|
|
#ifdef XP_MAC
|
|
FSClose(p_bh_decode_obj->fileId);
|
|
p_bh_decode_obj->fileId = 0;
|
|
HDelete(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
(unsigned char*)p_bh_decode_obj->name);
|
|
#else
|
|
XP_FileClose(p_bh_decode_obj->fileId);
|
|
p_bh_decode_obj->fileId = 0;
|
|
XP_FileRemove(p_bh_decode_obj->name, xpURL);
|
|
#endif
|
|
}
|
|
|
|
|
|
return p_bh_decode_obj->state < 0 ? (p_bh_decode_obj->state) :
|
|
p_bh_decode_obj->state >= BINHEX_STATE_FINISH ? errDone : NOERR;
|
|
}
|
|
|
|
int binhex_decode_end (
|
|
binhex_decode_object *p_bh_decode_obj,
|
|
XP_Bool is_aborting)
|
|
{
|
|
#ifdef XP_MAC
|
|
if (p_bh_decode_obj->fileId)
|
|
{
|
|
FSClose(p_bh_decode_obj->fileId);
|
|
p_bh_decode_obj->fileId = 0;
|
|
|
|
if (is_aborting)
|
|
{
|
|
HDelete(p_bh_decode_obj->vRefNum,
|
|
p_bh_decode_obj->parID,
|
|
(unsigned char*)p_bh_decode_obj->name);
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
if (p_bh_decode_obj->fileId)
|
|
{
|
|
XP_FileClose(p_bh_decode_obj->fileId);
|
|
p_bh_decode_obj->fileId = NULL;
|
|
|
|
if (is_aborting)
|
|
XP_FileRemove(p_bh_decode_obj->name, xpURL);
|
|
}
|
|
FREEIF(p_bh_decode_obj->name);
|
|
#endif
|
|
|
|
return NOERR;
|
|
}
|
|
|
|
|