daemon/autoresponse.cc
author "Tomas Zeman <tzeman@volny.cz>"
Sun, 20 Jan 2008 00:22:25 +0100
changeset 3 3d1d327cfa68
parent 2 b3afb9f1e801
permissions -rw-r--r--
vmailmgr-0.97

// Copyright (C) 2000 Mike Bell <mike@mikebell.org>,
// Bruce Guenter <bruceg@em.ca>
//
// 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#include <config.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <stdio.h>
#include "daemon.h"
#include "config/configrc.h"
#include "misc/response.h"
#include "misc/lookup.h"
#include "misc/maildir.h"
#include "misc/pwentry_table.h"
#include "misc/stat_fns.h"

response autoresponse_write(const mystring& directory,
			    const mystring& location,
			    const mystring& disabled,
			    const mystring& msg)
{
  mystring tmpfile = location + ".lock";

  if(!is_dir(directory.c_str())) {
    if(mkdir(directory.c_str(), 0755))
      RETURN(err, "Could not create autoresponse directory");
  }
  
  if(is_exist(tmpfile.c_str()))
    RETURN(err, "Temporary autoresponse file already exists");

  if(is_exist(disabled.c_str()))
    RETURN(err, "Autoresponse is disabled, reenable it before writing a new message");
  
  fdobuf out(tmpfile.c_str(), fdobuf::create | fdobuf::excl, 0644);
  if(!out)
    RETURN(err, "Unable to open temporary autoresponse file for writing");

  out << msg;
  if(!out.flush() || !out.close()) {
    unlink(tmpfile.c_str());
    RETURN(err, "Unable to write message to file");
  }
  if(rename(tmpfile.c_str(), location.c_str())) {
    unlink(tmpfile.c_str());
    RETURN(err, "Unable to rename temporary autoresponse file");
  }

  RETURN(ok, "Message successfully written to autoresponse file");
}

response autoresponse_disable(const mystring& location,
			      const mystring& disabled)
{
  if(!is_exist(location.c_str()))
    RETURN(ok, "Autoresponse file did not exist");
  if(is_exist(disabled.c_str()))
    RETURN(err, "Disabled autoresponse file already exists");
  if(rename(location.c_str(), disabled.c_str()))
    RETURN(err, "Unable to rename autoresponse file");
  RETURN(ok, "Autoresponse file sucessfully disabled");
}  

response autoresponse_enable(const mystring& location,
			     const mystring& disabled)
{
  if(is_exist(location.c_str()))
    RETURN(ok, "Autoresponse is already enabled");
  if(!is_exist(disabled.c_str()))
    RETURN(err, "Disabled autoresponse file did not exist");
  if(rename(disabled.c_str(), location.c_str()))
    RETURN(err, "Unable to rename previously disabled autoresponse file");
  RETURN(ok, "Autoresponse file sucessfully restored");
}  

static bool read_file(const mystring& filename, mystring& out)
{
  fdibuf in(filename.c_str());
  if(!in)
    return false;
  char contents[65536];
  unsigned contentlen;
  in.read(contents, 65536);
  contentlen = in.last_count();
  out = mystring(contents, contentlen);
  return true;
}

response autoresponse_read(const mystring& location,
			   const mystring& disabled, int fd)
{
  mystring line;
  if(!is_exist(location.c_str()) &&
     !is_exist(disabled.c_str()))
    RETURN(err, "Autoresponder file does not exist");

  mystring contents;
  if(!read_file(location, contents) &&
     !read_file(disabled, contents))
    RETURN(err, "Unable to read data from autoresponse file");
  response resp(response::ok, contents);
  resp.write(fd);
  RETURN(ok, "Retrieved autoresponse file");
}

response autoresponse_delete(const mystring& directory)
{
  if(!is_dir(directory.c_str()))
    RETURN(err, "Autoresponse directory does not exist.");
  if(!delete_directory(directory))
    RETURN(err, "Could not delete autoresponse directory.");
  RETURN(ok, "Autoresponse directory deleted.");
}

response autoresponse_status(const mystring& directory,
			     const mystring& location,
			     const mystring& disabled)
{
  const char* msg;
  if(is_exist(location.c_str()))
    msg = "enabled";
  else if(is_exist(disabled.c_str()))
    msg = "disabled";
  else if(is_dir(directory.c_str()))
    msg = "missing message file";
  else
    msg = "nonexistant";
  RETURN(ok, msg);
}

CMD_FD(autoresponse)
  // Usage: autoresponse baseuser-virtuser pass action [autorespmessage]
{

  mystring user = args[0];
  mystring pass = args[1];
  args[1] = LOG_PASSWORD;
  mystring action = args[2];
  mystring message;
  if(args.count() == 4) {
    message = args[3];
    args[3] = LOG_MESSAGE;
  }
  logcommand(args);

  pwentry* pw;
  vpwentry* vpw;
  OK_RESPONSE(lookup_and_validate(user, pw, vpw, pass, true, true));

  const mystring directory = vpw->directory + "/" + config->autoresponse_dir();
  const mystring filename = directory + "/" + config->autoresponse_file();
  const mystring disabled = filename + ".disabled";
  
  if(action == "disable")
    return autoresponse_disable(filename, disabled);
  else if(action == "enable")
    return autoresponse_enable(filename, disabled);
  else if(action == "read")
    return autoresponse_read(filename, disabled, fd);
  else if(action == "write")
    if(!message)
      RETURN(bad, "Missing autoresponse message argument");
    else
      return autoresponse_write(directory, filename, disabled, message);
  else if(action == "delete")
    return autoresponse_delete(directory);
  else if(action == "status")
    return autoresponse_status(directory, filename, disabled);
  
  RETURN(err, "Unrecognized command");
}