/*
**
** Copyright (C) 1994 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@udac.uu.se
**                                        Torbjorn.Wictorin@udac.uu.se
**
**                                        UDAC	
**                                        P.O. Box 174
**                                        S-751 04 Uppsala
**                                        Sweden
**
*/

#include "emil.h"
#include <assert.h>
int
get_appledouble_binary(struct message *m)
{
  struct data *d;
  unsigned long magic;
  unsigned long version;
  unsigned long filler;
  unsigned short entries;
  unsigned long doffset;
  unsigned long dlength;
  int i;

  doffset = dlength = 0;

  d = m->td;
  d->offset = d->bodystart;

  /* Check magic number */
  if (getlong(&magic, d) == NOK)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: magic number: short file.\n");
#endif
      return(NOK);
    }
  if (magic != 0x00051607)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: Wrong magic number %lX.\n",
		magic);
#endif
      return(NOK);
    }

  /* Check version number */
  if (getlong(&version, d) == NOK)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: version number: short file.\n");
#endif
      return(NOK);
    }
  if (version != 0x00020000)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: Wrong magic number.\n");
#endif
      return(NOK);
    }
  
  /* Check filler */
  for (i = 0; i < 4; i++)
    {
      if (getlong(&filler, d) == NOK)
	{
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: filler: short file.\n");
#endif
	  return(NOK);
	}
      if (filler != 0x00000000)
	{
#ifdef DEBUG
	  if (edebug)
	    fprintf(stderr, "*  get_appledouble_binary: Wrong filler.\n");
#endif
	  return(NOK);
	}
    }
  
  /* Get entries */
  if (getshort(&entries, d) == NOK)
    {
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: entries: short file.\n");
#endif
      return(NOK);
    }

  /* 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) == NOK)
	{
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: entry ID: short file %lu.\n", d->offset);
#endif
	  return(NOK);
	}
      
      /* Get offset */
      if (getlong(&offset, d) == NOK)
	{
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: offset: short file %lu.\n", d->offset);
#endif
	  return(NOK);
	}
      
      /* Get length */
      if (getlong(&length, d) == NOK)
	{
#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "*  get_appledouble_binary: length: short file %lu.\n", d->offset);
#endif
	  return(NOK);
	}
      
      switch(entry_id) 
	{
	case 1:
	  /* Data fork */
	  break;

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

	case 3:
	  /* Name */
	  if (check_length(d, offset + length) != OK)
	    {
#ifdef DEBUG
	      if (edebug)
		fprintf(stderr, "*  get_appledouble_binary: name: short file %lu.\n", d->offset);
#endif
	      return(NOK);
	    }
	  m->sd->name = (char *)get_string(d, offset, 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_appledouble_binary: finder info: short file %lu.\n", d->offset);
#endif
	      return(NOK);
	    }
	  m->sd->appletype = get_string(d, offset, 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;
	}
    }
  d->bodystart = doffset;
  d->bodyend = doffset + dlength;

  return(OK);
}

int
put_appledouble(struct message *m)
{
  struct data *target;
  struct data *resource;
  int i;
  unsigned long offset, nlength, rlength, flength;

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, "*  put_appledouble().\n");
#endif

  if ((resource = m->td->next) != NULL)
    resource->offset = resource->bodystart;
  else
    {
      m->sd->applefile = 0;

#ifdef DEBUG
      if (edebug)
	fprintf(stderr, "FAILED.\n");
#endif
      return(NOK);
    }

	    
  target = (struct data *)Yalloc(sizeof(struct data));
  target->encoding = EBINARY;
  macify_filename(m);
  /* Add magic number */

  append_data(target, makelong((unsigned long)0x00051607, 4), 4, pz);
  
  /* Add version */
  append_data(target, makelong((unsigned long)0x00020000, 4), 4, pz);

  
  /* Add filler */
  for (i = 0; i < 4; i++)
    append_data(target, makelong((unsigned long)0x00000000, 4), 4, pz);
    
  /* Add entries */
  append_data(target, makelong((unsigned long)0x0003, 2), 2, pz);

  
  /* Add entries, Offset = 26 */
  /* Name */
  offset = 62;
  append_data(target, makelong((unsigned long)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((unsigned long)0x00000009, 4), 4, pz);
  append_data(target, makelong(offset, 4), 4, pz);
  flength = 32;
  append_data(target, makelong(flength, 4), 4, pz);
  offset += flength;


  /* Resource fork */
  append_data(target, makelong((unsigned long)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);

#ifdef DEBUG
  if (edebug)
    fprintf(stderr, " Creating AppleDouble, name = %s, Type&Creator = %s, Resource fork = %lu\n", m->sd->name, m->sd->appletype, rlength);
#endif


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


  /* Add resource fork */
  append_data(target, resource->contents + resource->bodystart, rlength, pz);
  target->encoding = EBINARY;
  target->next = m->td;

  
  target->next->next = NULL;
  m->td = target;
  m->sd->next = (struct data *)Yalloc(sizeof(struct data ));
  m->sd->type = NEWSTR("APPLEDOUBLE");
  m->sd->applefile = AMDOUBLE;
  return(OK);
}


