/* Time-stamp: <97/01/15 20:41:40 john> */

/* 
# Purpose: write attribute data back to files
 */

#include <stdio.h>
#include "attr.h"
#include "save.h"

/* #define debug_write 1 */

/* a check_entry callback for the attribute file reader */
static int password_check_entry(struct entry *new_entry,
				int entry_count)
{
  return ENTRY_OK;
}

int write_entries_to_file(struct entry *entries,
			  int just_this_one,
			  char *filename,
			  char *mode,
			  char *other_filename,
			  char *other_mode)
{
  FILE *stream = fopen(filename, mode);
  FILE *other_stream = NULL;
  struct entry *entry;

  if (stream == NULL)
    {
      printf("<p>Could not open \"%s\" for writing.</p>\n", filename);
      return 0;
    }

#if 0
  printf("<p>Writing to main file \"%s\" in mode \"%s\"</p>\n", filename, mode);
#endif

  if ((other_filename != NULL) && (other_mode != NULL))
    {
      other_stream = fopen(other_filename, other_mode);
      if (other_stream == NULL)
	{
	  printf("<p>Could not open \"%s\" in mode \"%s\", but never mind, it's only a spare!</p>\n",
		 other_filename, other_mode);
	} else {
	  printf("<p>Writing to spare file \"%s\" in mode \"%s\"</p>\n", other_filename, other_mode);
	}
    }

  for (entry = entries;
       entry != NULL;
       entry = entry->next)
    {
      struct attribute *attr;

#ifdef debug_write
      printf("Writing %s:\n", entry->name);
#endif

      for (attr = entry->attributes;
	   attr != NULL;
	   attr = attr->next)
	{
	  char *v;
	  char c;
	  char pc = ' ';
	  int needs_quotes = 0;

	  if (attr->key[0] == '\0')
	    {
	      continue;
	    }

	  if (attr->value[0] == '\0')
#if 0
	    continue;
#else
	  needs_quotes = 1;
#endif

	  for (v = attr->value;
	       (c = *v) != '\0';
	       v++)
	    {
	      switch (c)
		{
		case '\n':
		case '\r':
		  needs_quotes = 1;
		  break;
		default:
		  break;
		}
	    }
#ifdef debug_write
	  printf("  attr: %#X\n", attr);
	  printf("  attr(%#X,%#X)\n", attr->key, attr->value);
	  printf("  key is %s\n", attr->key);
	  printf("  value is %s\n", attr->value);
	  printf("  %s=\"%s\"\n", attr->key, attr->value);
#endif
	  if (other_stream == NULL)
	    {
#ifdef debug_write
	      printf("About to put key %#X to only stream %#X\n",
		     attr->key, stream);
#endif
	      fputs(attr->key , stream);
	      putc('=', stream);
	      if (needs_quotes) putc('\"', stream);
#ifdef debug_write
	      printf("Put key to only stream\n");
#endif
	      for (v = attr->value;
		   (c = *v) != '\0';
		   v++)
		{
		  switch (c)
		    {
		    case'\"':
		      fputs("\\\"", stream);
		      break;
		      case '\r':
		      case '\n':
			if ((pc != '\r') && (pc != '\n'))
			  {
			    putc(c, stream);
			  }
			break;
		    default:
		      putc(c, stream);
		      break;
		    }
		  pc = c;
		}
	      if (needs_quotes) putc('\"', stream);
	      putc('\n', stream);
#ifdef debug_write
	      printf("Put value to only stream\n");
#endif
	    } else {
#ifdef debug_write
	      printf("About to put key %#X to both streams %#X, %#X\n",
		     attr->key, stream, other_stream);
#endif
	      fputs(attr->key, stream);
	      fputs(attr->key, other_stream);
	      putc('=', stream);
	      putc('=', other_stream);
	      if (needs_quotes) putc('\"', stream);
	      if (needs_quotes) putc('\"', other_stream);

#ifdef debug_write
	      printf("Put key to both streams\n");
#endif
	      for (v = attr->value;
		   (c = *v) != '\0';
		   v++)
		{
		  if (c == '\"')
		    switch (c)
		      {
		      case '\"':
			fputs("\\\"", stream);
			fputs("\\\"", other_stream);
			break;
		      case '\r':
		      case '\n':
			if ((pc != '\r') && (pc != '\n'))
			  {
			    putc(c, stream);
			    putc(c, other_stream);
			  }
			break;
		      default:
			putc(c, stream);
			putc(c, other_stream);
			break;
		      }
		  pc = c;
		}
	      if (needs_quotes) putc('\"', stream);
	      if (needs_quotes) putc('\"', other_stream);
	      putc("\"\n", stream);
	      putc("\"\n", other_stream);
#ifdef debug_write
	      printf("Put value to both streams\n");
#endif
	    }
	}
#ifdef debug_write
      printf("Written\n");
#endif

      putc('\n', stream);
      if (other_stream != NULL)
	{
	  putc('\n', other_stream);
	}

      if (just_this_one)
	{
	  break;
	}
    }

  if (other_stream != NULL)
    {
      fclose(other_stream);
    }

  fclose(stream);

  return 1;
}

void save_edits(struct entry *entries,
		struct entry *this_entry,
		char *pagefile_type,
		char *pagefile_name,
		char *editor,
		char *password,
		char *cumulative_file_type,
		char *cumulative_file_name)
{
  int verified = 0;
#if 0
  if ((editor != NULL) && (editor[0] != '\0'))
    {
      if ((password != NULL) && (password[0] != '\0'))
	{
	  struct entry *passwords = NULL;
	  if (!read_attribute_file("../passwords/editors",
				   &passwords, NULL,
				   password_check_entry, 0))
	    {
	      printf("<p>Could not read password file!</p>\n");
	    } else {
	      char *pw = get_attr(passwords, editor);
	      if ((pw != NULL) &&
		  (strcmp(pw, password) == 0))
		{
		  verified = 1;
		}
	    }
	  free_entries(passwords);
	} else {
	  char mailbuf[1024];
	  if (strlen(editor)<256)
	    {
	      sprintf(mailbuf, "echo \"%s is editing with empty password\" | mail john@harlequin.co.uk", editor);
	      system(mailbuf);
	    }
	}
    }
#endif

#if 0
  verified = 0;
#endif
      
  if (verified)
    {
      char name_buf[1024];
      if ((strlen(pagefile_type) + strlen(pagefile_name)) > 1000)
	{
	  printf("<p>Name too long to save to!</p>\n");
	  return;
	}

      sprintf(name_buf, "../%ss/%s.attr", pagefile_type, pagefile_name);

      printf("<p>Editor and password verified, writing edit to original file... \n");

      if (write_entries_to_file(entries, 0,
				name_buf, "w",
				NULL, NULL))
	{
	  printf("\"%ss/%s\" written</p>\n", pagefile_type, pagefile_name);
	} else {
	  printf("Could not write to \"%ss/%s\"</p>\n", pagefile_type, pagefile_name);
	}
    } else {
#ifdef debugging
      printf("<p>Editor \"%s\" and password not verified, logging edit for streetmaster to merge... \n",
	     editor);
#endif
      {
	struct entry *mark_this;

	for (mark_this = entries;
	     mark_this != NULL;
	     mark_this = mark_this->next)
	  {
	    set_attr(mark_this, "pagetype", pagefile_type);
	    set_attr(mark_this, "pagename", pagefile_name);
	  }
      }

      if ((editor == NULL) || (editor[0] == '\0'))
	{
	  editor="Anon";
	}

      {
	char *prev_editors = get_attr(this_entry, "editors");

	if (prev_editors == NULL)
	  {
	    set_attr(this_entry, "editors", editor);
	  } else {
	    int new_len = strlen(prev_editors) + 3 + strlen(editor);
	    char *new_editors = (char*)malloc(new_editors);
	    if (new_editors != NULL)
	      {
		sprintf(new_editors, "%s, %s", prev_editors, editor);
		set_attr(this_entry, "editors", new_editors);
		Free(new_editors);
	      }
	  }
      }

      {
	char cumulative_file[1024];
	sprintf(cumulative_file, "../%s/%s.attr",
		cumulative_file_type, cumulative_file_name);

	if (write_entries_to_file(this_entry, 1,
				  cumulative_file, "a",
				  NULL, NULL))
	  {
#ifdef debugging
	    printf("\"%s\" written instead of \"%s\".</p>\n",
		   cumulative_file, pagefile);
#endif
	    printf("<p>Your modified entry is as follows:\n");
#if 1
	    show_entry(this_entry);
#else
	    show_entrie(this_entry);
#endif
	    printf("<p>Your edit has been recorded... thank you for your contribution.</p>\n");
	  } else {
#ifdef debugging
	    printf("Could not write to \"%s\".</p>\n", cumulative_file);
#endif
	    printf("<p>Sorry, we could not record your edit. Please <a href=\"mailto:streetmaster@cb1.com\">ask the streetmaster</a> for help.</p>\n");
	  }
      }
    }

}

/* end of save.c */
