/* -*- 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.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): */ /* * * 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 #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; }