/*****************************************************************************\
* Copyright (c) 2002 Pelle Johansson.                                         *
* All rights reserved.                                                        *
*                                                                             *
* This file is part of the moftpd package. Use and distribution of            *
* this software is governed by the terms in the file LICENCE, which           *
* should have come with this package.                                         *
\*****************************************************************************/

/* $moftpd: com_settings.c 1251 2005-03-06 22:24:29Z morth $ */

#include "system.h"

#include "commands.h"

#include "connection.h"
#include "utf8fs/memory.h"

extern const char *localeDir;
extern const char *localeSuffix;

/* Settings commands */

int command_mode(connection_t *conn, const char *arg, int expected)
{
  switch(arg[0])
  {
  case 0:
    reply (conn, "501 Argument missing.");
    return 0;
  case 'S':
  case 's':
    reply (conn, "200 Mode set to Stream.");
    return 0;
  case 'B':
  case 'b':
    reply (conn, "504 Mode Block unsupported.");
    return 0;
  case 'C':
  case 'c':
    reply (conn, "504 Mode Compressed unsupported.");
    return 0;
  }
  
  reply (conn, "501 Unrecognised mode.");
  return 0;
}

int command_type(connection_t *conn, const char *arg, int expected)
{
  switch(arg[0])
  {
  case 0:
    reply (conn, "501 Argument missing.");
    return 0;
  case 'A':
  case 'a':
    if (arg[1] == ' ')
    {
      switch (arg[2])
      {
      case 0:
      case 'N':
	conn->subtype = 0;
	reply (conn, "200 Type set to Non-Print Text.");
	break;
      case 'T':
	conn->subtype = 'T';
	reply (conn, "504 Type Telnet Formatted Text unsupported.");
	return 0;
      case 'C':
	reply (conn, "504 Type Carriage Control Text unsupported.");
	return 0;
      }
    }
    else
    {
      conn->subtype = 0;
      reply(conn, "200 Type set to Non-Print Text.");
    }
    conn->type = ttText;
    return 0;
  case 'E':
  case 'e':
    reply (conn, "504 Type EBCDIC unsupported.");
    return 0;
  case 'I':
  case 'i':
    reply (conn, "200 Type set to Image.");
    conn->type = ttImage;
    conn->subtype = 0;
    return 0;
  case 'L':
  case 'l':
    if (arg[1] == ' ')
    {
      if (atoi (arg + 2) == 8)
      {
	conn->type = ttImage;
	conn->subtype = 8;
	reply (conn, "200 Type set to Local 8.");
      }
      else
	reply (conn, "504 Unsupported local size.");
    }
    else
      reply (conn, "501 Missing argument to L");
    return 0;
  }
  
  reply(conn, "501 Unrecognised type.");
  return 0;
}

int command_stru(connection_t *conn, const char *arg, int expected)
{
  switch(arg[0])
  {
  case 0:
    reply (conn, "501 Argument missing.");
    return 0;
  case 'F':
  case 'f':
    reply (conn, "200 File structure set to File.");
    return 0;
  case 'R':
  case 'r':
    reply (conn, "504 File structure Record unsupported.");
    return 0;
  case 'P':
  case 'p':
    reply (conn, "504 File structure Page unsupported.");
    return 0;
  }
  
  reply(conn, "501 Unrecognised file structure.");
  return 0;
}

int command_opts (connection_t *conn, const char *arg, int expected)
{
  const char *ap;
  
  if (!strlen (arg))
  {
    reply (conn, "501 Argument missing.");
    return 0;
  }
  if (!strncasecmp (arg, "MLST", 4) && (arg[4] == ' ' || !arg[4]))
  {
    conn->mlstTags = 0;
    if (arg[4])
    {
      arg += 5;
      while ((ap = strchr (arg, ';')))
      {
	switch (ap - arg)
	{
	case 4:
	  if (!strncasecmp (arg, "TYPE", 4))
	    conn->mlstTags |= tfType;
	  else if (!strncasecmp (arg, "PERM", 4))
	    conn->mlstTags |= tfPerm;
	  else if (!strncasecmp (arg, "SIZE", 4))
	    conn->mlstTags |= tfSize;
	  break;
	case 6:
	  if (!strncasecmp (arg, "UNIQUE", 6))
	    conn->mlstTags |= tfUnique;
	  else if (!strncasecmp (arg, "MODIFY", 6))
	    conn->mlstTags |= tfModify;
	  break;
	}
	arg = ap + 1;
      }
    }
    reply (conn, "200 MLST OPTS %s%s%s%s%s",
	  conn->mlstTags & tfType? "TYPE;" : "",
	  conn->mlstTags & tfUnique? "UNIQUE;" : "",
	  conn->mlstTags & tfModify? "MODIFY;" : "",
	  conn->mlstTags & tfPerm? "PERM;" : "",
	  conn->mlstTags & tfSize? "SIZE;" : "");
  }
  else if (!strncasecmp (arg, "UTF8", 4) && (!arg[4] || arg[4] == ' '))
  {
    if (arg[4] == ' ' && !strcasecmp (arg + 5, "ON"))
      reply (conn, "200 UTF8 is always on.");
    else
      reply (conn, "500 UTF8 is always on.");
  }
  else
    reply (conn, "501 No such setting.");
  return 0;
}

int command_lang(connection_t *conn, const char *arg, int expected)
{
  char *tmp, *tp, *lp;
  int fd;
  
  if (!strlen (arg))
    arg = "en";
  
  tmp = talloc (strlen (localeDir) + strlen (arg) + strlen (localeSuffix) + 1);
  if (!tmp)
  {
    reply (conn, "500 %s", strerror (errno));
    return 0;
  }
  strcpy (tmp, localeDir);
  lp = tp = tmp + strlen (tmp);
  strcpy (tp, arg);
  while (*tp)
  {
    *tp = tolower (*tp);
    tp++;
  }
  
  while (tp)
  {
    *tp = 0;
    if (!strcmp (lp, "en"))
    {
      if (conn->langFd >= 0)
	close_shared (conn->langFd);
      conn->langFd = -1;
      pfree (conn->currLang, conn);
      conn->currLang = NULL;
      reply (conn, "200 Language set to English.");
      return 0;
    }
    strcpy (tp, localeSuffix);
    fd = open_shared (tmp);
    if (fd >= 0)
    {
      if (conn->langFd >= 0)
	close_shared (conn->langFd);
      conn->langFd = fd;
      pfree (conn->currLang, conn);
      *tp = 0;
      conn->currLang = pstring (lp, conn);
      reply (conn, "200 Language set to English.");
      return 0;
    }
    *tp = 0;
    tp = strrchr (lp, '-');
  }
  reply (conn, "504 Unknown language.");
  return 0;
}



syntax highlighted by Code2HTML, v. 0.9.1