/*
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 1, or (at your option)
** any later version.
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Author : Alexandre Parenteau <aubonbeurre@hotmail.com> --- December 1997
*/
#ifdef __MACH__
#include "cvs.h"
#include "system.h"
#include "error.h"
#include <Carbon/Carbon.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include "hqx.h"
#include "cvs_hqx.h"
#include "apsingle.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int quiet;
extern int really_quiet;
extern int cvs_output(const char*, size_t);
OSStatus PathToFSRef(const char *filename, FSRef * res)
{
return FSPathMakeRef((UInt8 *)filename, res, 0L);
}
OSStatus StrToUnicode(const char *str, UniChar *ustr, SInt32 *uniLen,
TextEncoding *outEncoder)
{
TextEncoding encoder = kTextEncodingMacRoman;
TextToUnicodeInfo textToUnicodeInfo;
ByteCount oUnicodeLen;
OSStatus status;
Str255 pstr;
c2pstrcpy(pstr, str);
status = CreateTextToUnicodeInfoByEncoding(encoder, &textToUnicodeInfo);
if(status != noErr)
return status;
status = ConvertFromPStringToUnicode(textToUnicodeInfo, pstr, *uniLen * sizeof(UniChar), &oUnicodeLen, ustr);
DisposeTextToUnicodeInfo(&textToUnicodeInfo);
if(status == noErr)
{
*uniLen = oUnicodeLen / sizeof(UniChar);
if(outEncoder != 0L)
*outEncoder = encoder;
}
return status;
}
struct TypeEntry {
OSType type;
CFStringRef ext;
};
static void fillSemiColonTypes(const char *envVar, TypeEntry *& allTypes, int & numTypes, const char* defaults)
{
allTypes = 0L;
numTypes = 0;
const char *envRes = CProtocolLibrary::GetEnvironment(envVar);
if ( envRes == 0L )
envRes = defaults;
if(envRes == 0L)
return;
char *tmpStr = (char *)malloc(strlen(envRes) + 1);
if(tmpStr == 0L)
error (1, errno, "Running out of memory !");
strcpy(tmpStr, envRes);
char *tmp = tmpStr, *colon = 0L, *start = tmpStr;
while((tmp = strchr(tmp, ';')) != 0L)
{
*tmp = '\0';
if((tmp - start) == 4)
{
if(allTypes == 0L)
allTypes = (TypeEntry *)malloc(sizeof(TypeEntry));
else
allTypes = (TypeEntry *)realloc(allTypes, (numTypes + 1) * sizeof(TypeEntry));
if(allTypes == 0L)
error (1, errno, "Running out of memory !");
OSType atype;
((char *)&atype)[0] = *start++;
((char *)&atype)[1] = *start++;
((char *)&atype)[2] = *start++;
((char *)&atype)[3] = *start;
allTypes[numTypes].type = atype;
allTypes[numTypes].ext = NULL;
numTypes++;
}
else if((tmp - start) > 4 && start[4] == '/')
{
if(allTypes == 0L)
allTypes = (TypeEntry *)malloc(sizeof(TypeEntry));
else
allTypes = (TypeEntry *)realloc(allTypes, (numTypes + 1) * sizeof(TypeEntry));
if(allTypes == 0L)
error (1, errno, "Running out of memory !");
OSType atype;
((char *)&atype)[0] = *start++;
((char *)&atype)[1] = *start++;
((char *)&atype)[2] = *start++;
((char *)&atype)[3] = *start++;
++start; // skip delimiter '/'
allTypes[numTypes].type = atype;
if ( *start != 0 )
{
allTypes[numTypes].ext = CFStringCreateWithCString(NULL, start, kCFStringEncodingUTF8);
if ( allTypes[numTypes].ext == NULL )
error(0, coreFoundationUnknownErr, "Warning: can't create CFStringRef for extension %s (variable : %s) !", start, envRes);
}
else allTypes[numTypes].ext = NULL;
numTypes++;
}
else
{
error (0, errno, "Warning unknown signature %s (variable : %s) !",
start, envRes);
}
start = ++tmp;
}
}
static bool isTypeInList(OSType inFileType,
CFStringRef inFileExtension,
const TypeEntry* inTypeList,
int inNumTypes,
const char* mappingsName)
{
if ( inTypeList == NULL ) return false;
// check for type _and_ extension match
if ( inFileType != 0 && inFileType != '\?\?\?\?' && inFileExtension != NULL )
for(int i = 0; i < inNumTypes; i++)
{
if ( inTypeList[i].ext != NULL && inTypeList[i].type != '\?\?\?\?' )
if ( inTypeList[i].type == inFileType &&
CFStringCompare(inFileExtension, inTypeList[i].ext, kCFCompareCaseInsensitive|kCFCompareNonliteral) == kCFCompareEqualTo )
return true;
}
// check for extension only match
if ( inFileExtension != NULL )
for(int i = 0; i < inNumTypes; i++)
{
if ( inTypeList[i].ext != NULL && inTypeList[i].type == '\?\?\?\?')
if (CFStringCompare(inFileExtension, inTypeList[i].ext, kCFCompareCaseInsensitive|kCFCompareNonliteral) == kCFCompareEqualTo)
return true;
}
// check for file type only match
if ( inFileType != 0 && inFileType != '\?\?\?\?' )
for(int i = 0; i < inNumTypes; i++)
{
if( inTypeList[i].type != '\?\?\?\?' && inTypeList[i].ext == NULL && inTypeList[i].type == inFileType )
return true;
}
return false;
}
static Boolean isPlainBinary(OSType ftype, CFStringRef extension)
{
static TypeEntry *allTypes = (TypeEntry *)-1;
static int numTypes;
if(allTypes == (TypeEntry *)-1)
{
fillSemiColonTypes("MAC_BINARY_TYPES_PLAIN", allTypes, numTypes, "\?\?\?\?/gif;\?\?\?\?/tif;\?\?\?\?/tiff;\?\?\?\?/jpg;\?\?\?\?/jpeg;\?\?\?\?/png;\?\?\?\?.icns");
}
return isTypeInList(ftype, extension, allTypes, numTypes, "plain binary mappings");
}
static Boolean testHQXEncoding(OSType ftype, CFStringRef extension)
{
static TypeEntry *allTypes = (TypeEntry *)-1;
static int numTypes;
if(allTypes == (TypeEntry *)-1)
{
fillSemiColonTypes("MAC_BINARY_TYPES_HQX", allTypes, numTypes, "rsrc;RSRC;\?\?\?\?/rsrc;\?\?\?\?.ppob");
}
return isTypeInList(ftype, extension, allTypes, numTypes, "HQX mappings");
}
static Boolean testAppleSingleEncoding(OSType ftype, CFStringRef extension)
{
static TypeEntry *allTypes = (TypeEntry *)-1;
static int numTypes;
if(allTypes == (TypeEntry *)-1)
{
fillSemiColonTypes("MAC_BINARY_TYPES_SINGLE", allTypes, numTypes, NULL);
}
return isTypeInList(ftype, extension, allTypes, numTypes, "AppleSingle mappings");
}
// - Tells which encoder to use. Check the env. variables "MAC_BINARY_TYPES_HQX"
// and "MAC_BINARY_TYPES_SINGLE". If the type is not inside, return the
// default encoder "MAC_DEFAULT_RESOURCE_ENCODING".
// - Note that the plain binary test has to overide this one in every cases.
typedef enum
{
eEncodeDefault = -1,
eEncodeHQX,
eEncodeAppleSingle,
eEncodePlainBinary
} encodingPolicy;
static encodingPolicy determineEncodingPolicy(OSType ftype, CFStringRef extension)
{
if(isPlainBinary(ftype, extension))
{
return eEncodePlainBinary;
}
else if(testHQXEncoding(ftype, extension))
{
return eEncodeHQX;
}
else if(testAppleSingleEncoding(ftype, extension))
{
return eEncodeAppleSingle;
}
else
{
return eEncodeDefault;
}
}
static void getDefaultEncodingPolicy(encodingPolicy *policy)
{
char mac_default_resource_encoding[]="MAC_DEFAULT_RESOURCE_ENCODING";
char cvs_default_resource_encoding[]="CVS_DEFAULT_RESOURCE_ENCODING";
// get the default encoder
static char *envRes = (char *)CProtocolLibrary::GetEnvironment(mac_default_resource_encoding);
if(envRes == 0L)
envRes = (char *)CProtocolLibrary::GetEnvironment(cvs_default_resource_encoding);
if(envRes == 0L)
{
// default to plain binary, to avoid problems when working cross-platform
*policy = eEncodePlainBinary;
return;
}
if(strcmp(envRes, "HQX") == 0)
{
*policy = eEncodeHQX;
return;
}
else if(strcmp(envRes, "AppleSingle") == 0)
{
*policy = eEncodeAppleSingle;
return;
}
else if(strcmp(envRes, "PlainBinary") == 0)
{
*policy = eEncodePlainBinary;
return;
}
error (1, errno, "Unknown resource encoding '%s' !\n", envRes);
}
static FILE *gDestFile;
static FILE *gSrcFile;
static OSErr MyDest(void* buffer, long count, long param) {
fwrite(buffer, count, 1, gDestFile);
return noErr;
}
static OSErr MySource(void* buffer, long *count, long param) {
*count = fread(buffer, 1, *count, gSrcFile);
return noErr;
}
struct AutoCFStringRef
{
CFStringRef ref;
AutoCFStringRef() : ref(NULL) {}
~AutoCFStringRef() { if ( ref ) CFRelease(ref); }
operator CFStringRef() const { return ref; }
};
int
convert_hqx_file (const char *infile, int encode, const char *outfile, int *bin)
{
OSErr err = fnfErr;
encodingPolicy inFileType;
OSType filetype = 0;
OSType filecreator;
FSRef inspec, outspec;
FSCatalogInfo catalogInfo, catalogDestInfo;
HFSUniStr255 fileName;
AutoCFStringRef extension;
if (!encode)
{
// the cvswrapper has to be coherent !!!
if((*bin) == 0)
return 0;
gSrcFile = fopen(infile, "r");
if(gSrcFile == NULL)
error(1, errno, "Cannot open %s (%s %d)", infile, __FILE__, __LINE__);
char buf[100];
static char hqxheader[] = "(This file must be converted with BinHex 4.0)";
UInt32 asheader = AS_MAGIC_NUM;
fread (buf, sizeof(char), 100, gSrcFile);
// Determine whether the file is one of the known encodings
if ( memcmp(hqxheader, buf, strlen(hqxheader) * sizeof(char)) == 0)
{
inFileType = eEncodeHQX;
fseek(gSrcFile, 0, SEEK_SET);
}
else if ( memcmp(&asheader, buf, sizeof(asheader)) == 0 )
{
fclose(gSrcFile);
inFileType = eEncodeAppleSingle;
}
else
{
// it is a "plain" binary
fclose(gSrcFile);
return 0;
}
}
else
{
// check if it is a text file
OSStatus status = PathToFSRef(infile, &inspec);
if(status != noErr)
error(1, status, "Internal error: %s, %d", __FILE__, __LINE__);
status = ::FSGetCatalogInfo(&inspec, kFSCatInfoFinderInfo | kFSCatInfoRsrcSizes,
&catalogInfo, &fileName, 0L, 0L);
if(status != noErr)
error(1, status, "Internal error: %s, %d", __FILE__, __LINE__);
filetype = ((FInfo *)catalogInfo.finderInfo)->fdType;
if(filetype == 'TEXT')
return 0;
if ( *bin == 0 )
{
const char *envRes = CProtocolLibrary::GetEnvironment("MAC_ENCODE_ONLY_BINARY_FILES");
if ( envRes == NULL || strcmp(envRes, "0") != 0 ) {
if ( !really_quiet && catalogInfo.rsrcLogicalSize != 0 )
{
cvs_output ("Resource fork of non-binary file '", 0);
cvs_output (infile, 0);
cvs_output ("' discarded.\n", 0);
}
return 0;
}
}
}
if(encode)
{
encodingPolicy policy;
AutoCFStringRef fname;
CFIndex extensionStart;
// we won't use LSGetExtensionInfo to determine the extension, since this will only detect 'known' extensions,
// but some of the extensions used for resource fork handling might not be detected by LSGetExtensionInfo. Thus,
// we'll just search for the last '.' and use any following characters as the extension.
fname.ref = CFStringCreateWithCharactersNoCopy(NULL, fileName.unicode, fileName.length, kCFAllocatorNull);
if ( fname.ref ) {
CFRange foundRange;
if ( CFStringFindWithOptions(fname, CFSTR("."), CFRangeMake(0, fileName.length), kCFCompareBackwards|kCFCompareNonliteral|kCFCompareCaseInsensitive, &foundRange) && (foundRange.location + 1 < fileName.length) ) {
extension.ref = CFStringCreateWithCharactersNoCopy(NULL, fileName.unicode + foundRange.location + 1, fileName.length - foundRange.location - 1, kCFAllocatorNull);
if ( extension.ref == NULL )
error (0, 0, "Warning: Can't determine extension of file '%s', thus resource fork handling might not be correct.\n", infile);
}
}
else {
error (0, 0, "Warning: Can't determine extension of file '%s', thus resource fork handling might not be correct.\n", infile);
}
policy = determineEncodingPolicy(filetype, extension);
// special case, some files may be forced as plain binary.
// (env. variable "MAC_BINARY_TYPES_PLAIN")
if(policy == eEncodePlainBinary)
{
if ( !really_quiet && catalogInfo.rsrcLogicalSize != 0 )
{
cvs_output ("Resource fork of file '", 0);
cvs_output (infile, 0);
cvs_output ("' discarded because plain binary mapping was specified.\n", 0);
}
*bin = 1;
return 0;
}
else if(policy == eEncodeDefault)
{
// Never encode any files that have no resource fork
// Should we just use the test: if (
if(catalogInfo.rsrcLogicalSize == 0)
{
// it is a "plain" binary
*bin = 1;
return 0;
}
// get default policy
getDefaultEncodingPolicy(&policy);
if(policy == eEncodePlainBinary)
{
if ( !really_quiet && catalogInfo.rsrcLogicalSize != 0 )
{
cvs_output ("Resource fork of file '", 0);
cvs_output (infile, 0);
cvs_output ("' discarded because default mapping 'plain binary' was used.\n", 0);
}
*bin = 1;
return 0;
}
}
if(policy == eEncodeHQX)
{
if ( !really_quiet )
{
cvs_output ("Using BinHex encoding for file '", 0);
cvs_output (infile, 0);
cvs_output ("'.\n", 0);
}
gDestFile = fopen(outfile, "w");
if(gDestFile == NULL)
error(1, errno, "Internal error: %s, %d", __FILE__, __LINE__);
err = HQXEncode(infile, MyDest, 0);
fflush(gDestFile);
fclose(gDestFile);
if(err != noErr)
error(1, err, "Internal error: %s, %d", __FILE__, __LINE__);
}
else if ( policy == eEncodeAppleSingle )
{
if ( !really_quiet )
{
cvs_output ("Using AppleSingle encoding for file '", 0);
cvs_output (infile, 0);
cvs_output ("'.\n", 0);
}
#define APPLESINGLE_WANTED_ENTRIES ((UInt32)AS_DATA_BIT | AS_RESOURCE_BIT | AS_COMMENT_BIT | AS_FINDERINFO_BIT | AS_MACINFO_BIT)
UInt32 wantedEntries = APPLESINGLE_WANTED_ENTRIES;
err = encodeAppleSingle(infile, outfile, wantedEntries);
if (err != noErr)
error(1, err, "Internal error: %s, %d", __FILE__, __LINE__);
}
else
{
error(1, errno, "Internal error: %s, %d", __FILE__, __LINE__);
}
}
else // decoding
{
if ( inFileType == eEncodeHQX )
{
err = HQXDecode(MySource, outfile, true, true, 0);
fclose(gSrcFile);
if(err != noErr)
error(1, err, "Internal error: %s, %d", __FILE__, __LINE__);
}
else if ( inFileType == eEncodeAppleSingle)
{
UInt32 wantedEntries = APPLESINGLE_WANTED_ENTRIES;
err = decodeAppleSingle(infile, outfile, wantedEntries);
if (err != noErr)
error(1, err, "Internal error: %s, %d", __FILE__, __LINE__);
// Sometimes, type/creator information is not encoded inside the AS file
// If so, we want to set type/creator using Internet Config
OSStatus status = PathToFSRef(outfile, &outspec);
if(status != noErr)
error(1, status, "Internal error: %s, %d", __FILE__, __LINE__);
status = ::FSGetCatalogInfo(&outspec, kFSCatInfoFinderInfo,
&catalogDestInfo, 0L, 0L, 0L);
if(status != noErr)
error(1, status, "Internal error: %s, %d", __FILE__, __LINE__);
filetype = ((FInfo *)catalogDestInfo.finderInfo)->fdType;
filecreator = ((FInfo *)catalogDestInfo.finderInfo)->fdCreator;
if(filetype == AS_DEFAULT_TYPE && filecreator == AS_DEFAULT_CREATOR)
{
set_file_type(outfile, true);
}
}
else
{
error(1, errno, "Internal error: %s, %d", __FILE__, __LINE__);
}
}
return 1;
}
static OSStatus CachedICStart (ICInstance* outInstance)
{
static ICInstance inst = 0;
static OSErr theErr = noErr;
if(inst == 0 && theErr == noErr)
theErr = ICStart(&inst, 'CVS '); // Use your creator code if you have one!
if (theErr == noErr)
*outInstance = inst;
return theErr;
}
void set_file_type(const char *outfile, Boolean warnOnFail)
{
OSStatus err;
ICInstance inst;
Str255 filename;
c2pstrcpy(filename, outfile);
err = CachedICStart(&inst); // Use your creator code if you have one!
if (err != noErr)
{
static Boolean firsttime = true;
if(firsttime)
{
error(0, err, "WARNING Internet config's missing !");
firsttime = false;
}
return;
}
ICMapEntry entry;
err = ICMapFilename(inst, filename, &entry);
if(err == icPrefNotFoundErr)
{
#if 0
// TODO: to restore. create a new protocol getenv
entry.fileCreator = FOUR_CHAR_CODE('CWIE');
entry.fileType = FOUR_CHAR_CODE('TEXT');
err = noErr;
#endif
}
if (err != noErr)
{
if (warnOnFail)
error(0, err, "WARNING: Internet Config cannot map file %s", outfile);
return;
}
FInfo *fndrInfo;
FSRef outspec;
OSStatus status;
err = PathToFSRef(outfile, &outspec);
if(err != noErr)
{
error(0, err, "Internal error: %s, %d", __FILE__, __LINE__);
return;
}
FSCatalogInfo catalogInfo;
status = ::FSGetCatalogInfo(&outspec, kFSCatInfoFinderInfo,
&catalogInfo, 0L, 0L, 0L);
if(status != noErr)
{
error(0, status, "Internal error: %s, %d", __FILE__, __LINE__);
return;
}
fndrInfo = (FInfo *)catalogInfo.finderInfo;
if(entry.fileCreator != 0)
fndrInfo->fdCreator = entry.fileCreator;
if(entry.fileType != 0)
fndrInfo->fdType = entry.fileType;
status = ::FSSetCatalogInfo(&outspec, kFSCatInfoFinderInfo,
&catalogInfo);
if(status != noErr)
{
error(0, status, "Internal error: %s, %d", __FILE__, __LINE__);
}
}
unsigned char const mac_to_iso_maccvspro[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, /* 0 - 7 */
8, 9, 10, 11, 12, 13, 14, 15, /* 8 - 15 */
16, 17, 18, 19, 20, 21, 22, 23, /* 16 - 23 */
24, 25, 26, 27, 28, 29, 30, 31, /* 24 - 31 */
32, 33, 34, 35, 36, 37, 38, 39, /* 32 - 39 */
40, 41, 42, 43, 44, 45, 46, 47, /* 40 - 47 */
48, 49, 50, 51, 52, 53, 54, 55, /* 48 - 55 */
56, 57, 58, 59, 60, 61, 62, 63, /* 56 - 63 */
64, 65, 66, 67, 68, 69, 70, 71, /* 64 - 71 */
72, 73, 74, 75, 76, 77, 78, 79, /* 72 - 79 */
80, 81, 82, 83, 84, 85, 86, 87, /* 80 - 87 */
88, 89, 90, 91, 92, 93, 94, 95, /* 88 - 95 */
96, 97, 98, 99, 100, 101, 102, 103, /* 96 - 103 */
104, 105, 106, 107, 108, 109, 110, 111, /* 104 - 111 */
112, 113, 114, 115, 116, 117, 118, 119, /* 112 - 119 */
120, 121, 122, 123, 124, 125, 126, 127, /* 120 - 127 */
196, 197, 199, 201, 209, 214, 220, 225, /* 128 - 135 */
224, 226, 228, 227, 229, 231, 233, 232, /* 136 - 143 */
234, 235, 237, 236, 238, 239, 241, 243, /* 144 - 151 */
242, 244, 246, 245, 250, 249, 251, 252, /* 152 - 159 */
190, 176, 162, 163, 167, 130, 182, 223, /* 160 - 167 */
174, 169, 142, 180, 168, 173, 198, 216, /* 168 - 175 */
141, 177, 178, 179, 165, 181, 166, 135, /* 176 - 183 */
159, 185, 188, 170, 186, 189, 230, 248, /* 184 - 191 */
191, 161, 172, 146, 128, 129, 140, 171, /* 192 - 199 */
187, 131, 160, 192, 195, 144, 145, 147, /* 200 - 207 */
208, 132, 150, 148, 149, 213, 247, 215, /* 208 - 215 */
255, 153, 152, 164, 134, 221, 222, 151, /* 216 - 223 */
136, 183, 137, 139, 138, 194, 202, 193, /* 224 - 231 */
203, 200, 205, 206, 207, 204, 211, 212, /* 232 - 239 */
240, 210, 218, 219, 217, 155, 154, 133, /* 240 - 247 */
175, 157, 156, 158, 184, 253, 254, 143, /* 248 - 255 */
};
/* Conversion table generated mechanically by Free `recode' 3.5
for sequence ISO-8859-1..macintosh (reversible). */
unsigned char const iso_to_mac_maccvspro[256] =
{
0, 1, 2, 3, 4, 5, 6, 7, /* 0 - 7 */
8, 9, 10, 11, 12, 13, 14, 15, /* 8 - 15 */
16, 17, 18, 19, 20, 21, 22, 23, /* 16 - 23 */
24, 25, 26, 27, 28, 29, 30, 31, /* 24 - 31 */
32, 33, 34, 35, 36, 37, 38, 39, /* 32 - 39 */
40, 41, 42, 43, 44, 45, 46, 47, /* 40 - 47 */
48, 49, 50, 51, 52, 53, 54, 55, /* 48 - 55 */
56, 57, 58, 59, 60, 61, 62, 63, /* 56 - 63 */
64, 65, 66, 67, 68, 69, 70, 71, /* 64 - 71 */
72, 73, 74, 75, 76, 77, 78, 79, /* 72 - 79 */
80, 81, 82, 83, 84, 85, 86, 87, /* 80 - 87 */
88, 89, 90, 91, 92, 93, 94, 95, /* 88 - 95 */
96, 97, 98, 99, 100, 101, 102, 103, /* 96 - 103 */
104, 105, 106, 107, 108, 109, 110, 111, /* 104 - 111 */
112, 113, 114, 115, 116, 117, 118, 119, /* 112 - 119 */
120, 121, 122, 123, 124, 125, 126, 127, /* 120 - 127 */
196, 197, 165, 201, 209, 247, 220, 183, /* 128 - 135 */
224, 226, 228, 227, 198, 176, 170, 255, /* 136 - 143 */
205, 206, 195, 207, 211, 212, 210, 223, /* 144 - 151 */
218, 217, 246, 245, 250, 249, 251, 184, /* 152 - 159 */
202, 193, 162, 163, 219, 180, 182, 164, /* 160 - 167 */
172, 169, 187, 199, 194, 173, 168, 248, /* 168 - 175 */
161, 177, 178, 179, 171, 181, 166, 225, /* 176 - 183 */
252, 185, 188, 200, 186, 189, 160, 192, /* 184 - 191 */
203, 231, 229, 204, 128, 129, 174, 130, /* 192 - 199 */
233, 131, 230, 232, 237, 234, 235, 236, /* 200 - 207 */
208, 132, 241, 238, 239, 213, 133, 215, /* 208 - 215 */
175, 244, 242, 243, 134, 221, 222, 167, /* 216 - 223 */
136, 135, 137, 139, 138, 140, 190, 141, /* 224 - 231 */
143, 142, 144, 145, 147, 146, 148, 149, /* 232 - 239 */
240, 150, 152, 151, 153, 155, 154, 214, /* 240 - 247 */
191, 157, 156, 158, 159, 253, 254, 216, /* 248 - 255 */
};
/* From Fetch. */
unsigned char const mac_to_iso[256] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0xC4, 0xC5, 0xC7, 0xC9, 0xD1, 0xD6, 0xDC, 0xE1,
0xE0, 0xE2, 0xE4, 0xE3, 0xE5, 0xE7, 0xE9, 0xE8,
0xEA, 0xEB, 0xED, 0xEC, 0xEE, 0xEF, 0xF1, 0xF3,
0xF2, 0xF4, 0xF6, 0xF5, 0xFA, 0xF9, 0xFB, 0xFC,
0xDD, 0xB0, 0xA2, 0xA3, 0xA7, 0x80, 0xB6, 0xDF,
0xAE, 0xA9, 0x81, 0xB4, 0xA8, 0x82, 0xC6, 0xD8,
0x83, 0xB1, 0xBE, 0x84, 0xA5, 0xB5, 0x8F, 0x85,
0xBD, 0xBC, 0x86, 0xAA, 0xBA, 0x87, 0xE6, 0xF8,
0xBF, 0xA1, 0xAC, 0x88, 0x9F, 0x89, 0x90, 0xAB,
0xBB, 0x8A, 0xA0, 0xC0, 0xC3, 0xD5, 0x91, 0xA6,
0xAD, 0x8B, 0xB3, 0xB2, 0x8C, 0xB9, 0xF7, 0xD7,
0xFF, 0x8D, 0x8E, 0xA4, 0xD0, 0xF0, 0xDE, 0xFE,
0xFD, 0xB7, 0x92, 0x93, 0x94, 0xC2, 0xCA, 0xC1,
0xCB, 0xC8, 0xCD, 0xCE, 0xCF, 0xCC, 0xD3, 0xD4,
0x95, 0xD2, 0xDA, 0xDB, 0xD9, 0x9E, 0x96, 0x97,
0xAF, 0x98, 0x99, 0x9A, 0xB8, 0x9B, 0x9C, 0x9D,
};
unsigned char const iso_to_mac[256] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0xA5, 0xAA, 0xAD, 0xB0, 0xB3, 0xB7, 0xBA, 0xBD,
0xC3, 0xC5, 0xC9, 0xD1, 0xD4, 0xD9, 0xDA, 0xB6,
0xC6, 0xCE, 0xE2, 0xE3, 0xE4, 0xF0, 0xF6, 0xF7,
0xF9, 0xFA, 0xFB, 0xFD, 0xFE, 0xFF, 0xF5, 0xC4,
0xCA, 0xC1, 0xA2, 0xA3, 0xDB, 0xB4, 0xCF, 0xA4,
0xAC, 0xA9, 0xBB, 0xC7, 0xC2, 0xD0, 0xA8, 0xF8,
0xA1, 0xB1, 0xD3, 0xD2, 0xAB, 0xB5, 0xA6, 0xE1,
0xFC, 0xD5, 0xBC, 0xC8, 0xB9, 0xB8, 0xB2, 0xC0,
0xCB, 0xE7, 0xE5, 0xCC, 0x80, 0x81, 0xAE, 0x82,
0xE9, 0x83, 0xE6, 0xE8, 0xED, 0xEA, 0xEB, 0xEC,
0xDC, 0x84, 0xF1, 0xEE, 0xEF, 0xCD, 0x85, 0xD7,
0xAF, 0xF4, 0xF2, 0xF3, 0x86, 0xA0, 0xDE, 0xA7,
0x88, 0x87, 0x89, 0x8B, 0x8A, 0x8C, 0xBE, 0x8D,
0x8F, 0x8E, 0x90, 0x91, 0x93, 0x92, 0x94, 0x95,
0xDD, 0x96, 0x98, 0x97, 0x99, 0x9B, 0x9A, 0xD6,
0xBF, 0x9D, 0x9C, 0x9E, 0x9F, 0xE0, 0xDF, 0xD8
};
static const unsigned char *convert_iso(int convert_from, int iso)
{
if(iso != 1 && iso != 2) // only Latin 1 available right now
return NULL;
if(iso == 1)
{
return convert_from ? iso_to_mac : mac_to_iso;
}
else
return convert_from ? iso_to_mac_maccvspro : mac_to_iso_maccvspro;
}
void
mac_convert_file (const char *infile, int encode, char *outfile, int binary)
{
FILE *infd, *outfd;
char buf[8192];
int len;
int decode; /* 1 : server to client format, 0: client to server format */
# define ISO8559_VALID(iso) ((iso) == 1 || (iso) == 2)
static int set_text_signature = -1;
static int convert_iso8559 = -1;
static int convert_maclf = -1;
decode = encode ? 0 : 1;
if(convert_iso8559 == -1)
{
const char *iso = CProtocolLibrary::GetEnvironment("ISO8859");
if(iso == NULL || sscanf(iso, "%d", &convert_iso8559) != 1 ||
!ISO8559_VALID(convert_iso8559))
convert_iso8559 = 0;
}
if(set_text_signature == -1)
{
set_text_signature = CProtocolLibrary::GetEnvironment("IC_ON_TXT") != NULL ? 1 : 0;
}
// create text files with the Mac CR (0x0D)
// the default is LF on OSX
if(convert_maclf == -1)
{
convert_maclf = CProtocolLibrary::GetEnvironment("CVS_MACLF") != NULL ? 1 : 0;
}
/* "update" doesn't check if we can erase the dest file */
chmod(outfile, S_IRWXU);
if(convert_hqx_file(infile, encode, outfile, &binary))
return;
const unsigned char *isotab = NULL;
if(convert_iso8559)
isotab = convert_iso(decode, convert_iso8559);
if ((infd = fopen (infile, (binary || convert_maclf) ? "rb" : "r")) == NULL)
error (1, errno, "cannot read %s", infile);
if ((outfd = fopen (outfile, (binary || convert_maclf) ? "wb" : "w")) == NULL)
error (1, errno, "cannot write %s", outfile);
while ((len = fread (buf, sizeof (char), sizeof (buf) / sizeof(char), infd)) > 0)
{
// for a text file, we have some post process depending
// if we encode for the server or decode from the server
if(binary == 0)
{
char * conv = buf;
int convlen = len;
while (convlen--)
{
if(isotab != NULL)
{
*conv = (char)isotab[(unsigned char)*conv];
}
// on OSX, we don't have MSL-stdio switching the CR <-> LF,
// we can go straigth to the point
if(convert_maclf)
{
if(decode)
{
// for a text file, this will turn the line feed
// to the mac one
if(*conv == 0x0a)
*conv = 0x0d;
}
else
{
if(*conv == 0x0d)
*conv = 0x0a;
}
}
conv++;
}
}
if (fwrite (buf, sizeof(char), len, outfd) < 0)
error (1, errno, "error writing %s", outfile);
}
if (len < 0)
error (1, errno, "error reading %s", infile);
if (fclose (outfd) != 0)
error (0, errno, "warning: cannot close %s", outfile);
if (fclose (infd) != 0)
error (0, errno, "warning: cannot close %s", infile);
if((binary || set_text_signature) && decode)
set_file_type(outfile, !quiet);
}
#endif /* __MACH__ */
syntax highlighted by Code2HTML, v. 0.9.1