/*
** 
** Copyright (C) 1993 Swedish University Network (SUNET)
** 
** 
** This program is developed by UDAC, Uppsala University by commission
** of the Swedish University Network (SUNET). 
** 
** 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 2 of the License, 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 FITTNESS 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.
** 
** 
**                                           Martin.Wendel@its.uu.se
** 				             Torbjorn.Wictorin@its.uu.se
** 
**                                           ITS	
**                                           P.O. Box 887
**                                           S-751 08 Uppsala
**                                           Sweden
** 
*/
#include "emil.h"
#include <assert.h>

int
get_applesingle_binary(struct message *m)
{
  struct data *d;
  struct data *r = NULL;
  unsigned long magic;
  unsigned long version;
  unsigned long filler;
  unsigned short entries;
  unsigned long doffset;
  unsigned long dlength;
  int i;
  doffset = dlength = 0;

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "get_applesingle_binary().\n");
#endif
  if ((d = m->td) != NULL)
    d->offset = d->bodystart;
  else
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "get_applesingle_binary: empty input.\n");
#endif
      return(NOK);
    }

  /* Check magic number */
  if (getlong(&magic, d) != OK)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_applesingle_binary: magic number: short file.\n");
#endif
      return(NOK);
    }
  if (magic != 0x00051600)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_applesingle_binary: Wrong magic number %lX.\n",
		magic);
#endif
      return(NOK);
    }
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "- get_applesingle_binary: got magic number\n");
#endif
  /* Check version number */
  if (getlong(&version, d) != OK)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_applesingle_binary: version number: short file.\n");
#endif
      return(NOK);
    }
  if (version != 0x00020000)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_applesingle_binary: Wrong magic number.\n");
#endif
      return(NOK);
    }
  
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "- get_applesingle_binary: got version number\n");
#endif
  /* Check filler */
  for (i = 0; i < 4; i++)
    {
      if (getlong(&filler, d) != OK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*  get_applesingle_binary: filler: short file.\n");
#endif
	  return(NOK);
	}
      if (filler != 0x00000000)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*  get_applesingle_binary: Wrong filler.\n");
#endif
	  return(NOK);
	}
    }
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "- get_applesingle_binary: got filler\n");
#endif
  
  /* Get entries */
  if (getshort(&entries, d) != OK)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_applesingle_binary: entries: short file.\n");
#endif
      return(NOK);
    }
  if (entries < 1)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "* get_applesingle_binary: emtpy entries, (failed)\n");
#endif
      return(NOK);
    }
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "- get_applesingle_binary: got %u entries\n", entries);
#endif
  /* Get entries */
  for (i = 0; i < entries; i++)
    {
      unsigned long entry_id;
      unsigned long offset;
      unsigned long length;

      /* Get entry ID */
      if (getlong(&entry_id, d) != OK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*  get_applesingle_binary: entry ID: short file %lu.\n", d->offset);
#endif
	  return(NOK);
	}
      
      /* Get offset */
      if (getlong(&offset, d) != OK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*  get_applesingle_binary: offset: short file %lu.\n", d->offset);
#endif
	  return(NOK);
	}
      
      /* Get length */
      if (getlong(&length, d) != OK)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*  get_applesingle_binary: length: short file %lu.\n", d->offset);
#endif
	  return(NOK);
	}
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "- get_applesingle_binary: got entry: id=%lu, offset=%lu, length=%lu\n", entry_id, offset, length);
#endif
      
      switch(entry_id) 
	{
	case 1:
	  /* Data fork */
	  doffset = d->bodystart + offset;
	  dlength = length;
	  if (check_length(d, doffset + dlength) != OK)
	    {
#ifdef DEBUG
	      if (edebug)
		{
		  fprintf(stderr, "*  get_applesingle_binary: data fork: short file %lu.\n", d->offset);
		  fprintf(stderr, "*  get_applesingle_binary: suggested offset: %lu suggested length: %lu\n", offset, length);
		  fprintf(stderr, "*  get_applesingle_binary: bodystart %lu end %lu\n", d->bodystart, d->bodyend);
		}
#endif
	      return(NOK);
	    }
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*   Marked up Applesingle data fork at offset %lu and size %lu. End is %lu.\n", offset, length, d->bodyend);
#endif
	  break;

	case 2:
	  /* Resource fork */
	  if (length)
	    {
	      if (check_length(d, + offset + length) != OK)
		{
#ifdef DEBUG
	      if (edebug)
		{
		  fprintf(stderr, "*  get_applesingle_binary: resource fork: short file %lu.\n", d->offset);
		  fprintf(stderr, "*  get_applesingle_binary: suggested offset: %lu suggested length: %lu\n", offset, length);
		  fprintf(stderr, "*  get_applesingle_binary: bodystart %lu end %lu\n", d->bodystart, d->bodyend);
		}
#endif
	      return(NOK);
	    }
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*   Marked up Applesingle resource fork at offset %lu and size %lu. End is %lu.\n", offset, length, d->bodyend);
#endif

	      r = (struct data *)Yalloc(sizeof(struct data));
	      /* Copied for now */
	      append_data(r, d->contents + d->bodystart + offset, length, pz);
	      r->applefile = ARESOURCE;
	      r->encoding = EBINARY;
	      d->applefile = AFILE;
	    }
	  break;

	case 3:
	  /* Name */
	  if (check_length(d, offset + length) != OK)
	    {
#ifdef DEBUG
	      if (edebug)
		fprintf(stderr, "*  get_applesingle_binary: name: short file %lu.\n", d->offset);
#endif
	      return(NOK);
	    }
	  m->sd->name = (char *)Yalloc(length + 1);
	  bcopy(d->contents + d->bodystart + offset, m->sd->name, length);
	  break;

	case 4:
	  /* Comment */
	  /* Ignore */
	  break;

	case 5:
	  /* BW icon */
	  /* Ignore */
	  break;

	case 6:
	  /* Color icon */
	  /* Ignore */	  
	  break;

	case 8:
	  /* dates */
	  /* Ignore */	  
	  break;

	case 9:
	  /* Finder info */
	  if (check_length(d, offset + length) != OK)
	    {
#ifdef DEBUG
	      if (edebug)
		fprintf(stderr, "*  get_applesingle_binary: finder info: short file %lu.\n", d->offset);
#endif
	      return(NOK);
	    }
	  if (m->sd->appletype == NULL)
	    m->sd->appletype = (char *)Yalloc(9);
	  bcopy(d->contents + d->bodystart + offset, m->sd->appletype, 8);
	  break;

	case 10:
	  /* Mac file info */
	  /* Ignore */	  
	  break;

	case 11:
	  /* ProDOS file info */
	  /* Ignore */	  
	  break;

	case 12:
	  /* MS-DOS file info */
	  /* Ignore */	  
	  break;

	case 13:
	  /* AFP short name */
	  /* Ignore */	  
	  break;

	case 14:
	  /* AFP file info */
	  /* Ignore */	  
	  break;

	case 15:
	  /* AFP directory id */
	  /* Ignore */	  
	  break;

	default:
	  /* Unknown entry ID */
	  return(NOK);
	  break;
	}
    }
  if (dlength != 0)
    {
      d->bodystart = doffset;
      d->bodyend = doffset + dlength;
      if ((d->type = (char *)confextr("APPLEFILE", d->appletype, NULL)) == NULL)
	if ((d->type = (char *)confextr("APPLEFILE", "DEFAULT", NULL)) == NULL)
	  d->type = NEWSTR("APPLICATION");
    }
  else
    {
      free_data(d);
      d = NULL;
    }
  m->td = d;
  d->next = r;
  return(OK);
}

int
put_applesingle(struct message *m)
{
  struct data *target;
  struct data *data;
  struct data *resource;
  int i;
  unsigned long offset, dlength, nlength, rlength, flength;
  
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "*  put_applesingle()...");
#endif
  target = (struct data *)Yalloc(sizeof(struct data));
  target->encoding = EBINARY;
  macify_filename(m);
  if ((data = m->td) != NULL)
    data->offset = data->bodystart;
  else
    return(NOK);
  target->type = data->type;
  if ((resource = m->td->next) != NULL)
    resource->offset = resource->bodystart;
  /* Add magic number */
  append_data(target, makelong(0x00051600, 4), 4, pz);
  
  /* Add version */
  append_data(target, makelong(0x00020000, 4), 4, pz);
  
  /* Add filler */
  for (i = 0; i < 4; i++)
    append_data(target, makelong(0x00000000, 4), 4, pz);
    
  /* Add entries */
  append_data(target, makelong(0x0004, 2), 2, pz);

  /* Add entries, Offset = 26 */
  /* Name */
  offset = 74;
  append_data(target, makelong(0x00000003, 4), 4, pz);
  append_data(target, makelong(offset, 4), 4, pz);
  nlength = strlen(m->sd->name);
  append_data(target, makelong(nlength, 4), 4, pz);
  offset += nlength;

  /* Finder info */
  append_data(target, makelong(0x00000009, 4), 4, pz);
  append_data(target, makelong(offset, 4), 4, pz);
  flength = 32;
  append_data(target, makelong(flength, 4), 4, pz);
  offset += flength;

  /* Data fork */
  append_data(target, makelong(0x00000001, 4), 4, pz);
  append_data(target, makelong(offset, 4), 4, pz);
  dlength = data->bodyend - data->bodystart;
  append_data(target, makelong(dlength, 4), 4, pz);
  offset += dlength;

  /* Resource fork */
  append_data(target, makelong(0x00000002, 4), 4, pz);
  append_data(target, makelong(offset, 4), 4, pz);
  rlength = resource->bodyend - resource->bodystart;
  append_data(target, makelong(rlength, 4), 4, pz);

  /* Add name */
  append_data(target, m->sd->name, nlength, pz);

  /* Add finder info */
  append_data(target, m->sd->appletype, 8, pz);
  for (i = 0; i < 6; i++)
    append_data(target, makelong(0x00000000, 4), 4, pz);

  /* Add data fork */
  append_data(target, data->contents + data->bodystart, dlength, pz);

  /* Add resource fork */
  append_data(target, resource->contents + resource->bodystart, rlength, pz);

  m->td = target;
  m->sd->applefile = ASINGLE;
  m->sd->type = NEWSTR("APPLESINGLE");
  m->td->encoding = EBINARY;
#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "OK.\n");
#endif
  return(OK);
}


/*
 * Check for AppleSingle/AppleDouble
 */

void
check_as_ad(struct message *m)
{
  struct data *d;
  char typer[5];
  long ltyper;

  d = m->td;
  if (d->offset + 4 >= d->end)
      return;

  bzero(typer, 5);
  bcopy(d->contents + d->offset, typer, 4);
  ltyper = strtol(typer, NULL, 16);
  if (0x0051607 ==  ltyper)
    m->sd->applefile = ADOUBLE;
  if (0x0051600 ==  ltyper)
    m->sd->applefile = ASINGLE;
}



syntax highlighted by Code2HTML, v. 0.9.1