/*
 * by Dirk Meyer (dinoex)
 * Copyright (C) 2004-2007 Dirk Meyer
 * 
 * By using this file, you agree to the terms and conditions set
 * forth in the GNU General Public License.  More information is    
 * available in the README file.
 * 
 * If you received this file without documentation, it can be
 * downloaded from http://iroffer.dinoex.net/
 * 
 * $Id: dinoex_admin.c,v 1.2 2007/07/08 09:11:18 dinoex Exp $
 * 
 */

/* include the headers */
#include "iroffer_config.h"
#include "iroffer_defines.h"
#include "iroffer_headers.h"
#include "iroffer_globals.h"
#include "dinoex_utilities.h"
#include "dinoex_admin.h"
#include "dinoex_misc.h"

#include <ctype.h>

void
#ifdef __GNUC__
__attribute__ ((format(printf, 2, 3)))
#endif
a_respond(const userinput * const u, const char *format, ...);

void a_respond(const userinput * const u, const char *format, ...)
{
  va_list args;

  updatecontext();
 
  va_start(args, format);
 
  switch (u->method)
    {
    case method_console:
      vioutput(CALLTYPE_NORMAL, OUT_S, COLOR_NO_COLOR, format, args);
      break;
    case method_dcc:
      vwritedccchat(u->chat, 1, format, args);
      break;
    case method_out_all:
      vioutput(CALLTYPE_NORMAL, OUT_S|OUT_L|OUT_D, COLOR_NO_COLOR, format, args);
      break;
    case method_fd:
      {
        ssize_t retval;
        char tempstr[maxtextlength];
        int llen;

        llen = vsnprintf(tempstr,maxtextlength-3,format,args);
        if ((llen < 0) || (llen >= maxtextlength-3))
          {
            outerror(OUTERROR_TYPE_WARN,"string too long!");
            tempstr[0] = '\0';
            llen = 0;
          }

        if (!gdata.xdcclistfileraw)
          {
            removenonprintablectrl(tempstr);
          }

#if defined(_OS_CYGWIN)
        tempstr[llen++] = '\r';
#endif
        tempstr[llen++] = '\n';
        tempstr[llen] = '\0';

        retval = write(u->fd, tempstr, strlen(tempstr));
        if (retval < 0)
          {
            outerror(OUTERROR_TYPE_WARN_LOUD,"Write failed: %s", strerror(errno));
          }
      }
      break;
    case method_msg:
      vprivmsg(u->snick, format, args);
      break;
    default:
      break;
    }

  va_end(args);
}

int hide_locked(const userinput * const u, const xdcc *xd)
{
  if (gdata.hidelockedpacks == 0)
    return 0;
   
  if (xd->lock == NULL)
    return 0;
   
  switch (u->method)
    {
    case method_fd:
    case method_xdl_channel:
    case method_xdl_user_privmsg:
    case method_xdl_user_notice:
      return 1;
    default:
      break;
    }
  return 0; 
}

int a_xdl_space(void)
{
   int i,s;
   xdcc *xd;

   i = 0;
   xd = irlist_get_head(&gdata.xdccs);
   while(xd)
     {
       i = max2(i,xd->gets);
       xd = irlist_get_next(xd);
     }
   s = 5;
   if (i < 10000) s = 4;
   if (i < 1000) s = 3;
   if (i < 100) s = 2;
   if (i < 10) s = 1;
   return s;
}
   
int a_xdl_left(void)
{
   int n;
   int l;

   n = irlist_size(&gdata.xdccs);
   l = 5;
   if (n < 10000) l = 4;
   if (n < 1000) l = 3;
   if (n < 100) l = 2;
   if (n < 10) l = 1;
   return l;
}

int reorder_new_groupdesc(const char *group, const char *desc)
{
  xdcc *xd;
  int k;

  updatecontext();

  k = 0;
  xd = irlist_get_head(&gdata.xdccs);
  while(xd)
    {
      if (xd->group != NULL)
        {
          if (strcasecmp(xd->group,group) == 0)
            {
              k++;
              /* delete all matching entires */
              if (xd->group_desc != NULL)
                mydelete(xd->group_desc);
              /* write only the first entry */
              if (k == 1)
                {
                  if (desc && strlen(desc))
                    {
                      xd->group_desc = mystrdup(desc);
                    }
                }
            }
        }
      xd = irlist_get_next(xd);
    }

  return k;
}

int reorder_groupdesc(const char *group)
{
  xdcc *xd; 
  xdcc *firstxd;
  xdcc *descxd;
  int k;

  updatecontext();

  k = 0;
  firstxd = NULL;
  descxd = NULL;
  xd = irlist_get_head(&gdata.xdccs);
  while(xd)
    {
      if (xd->group != NULL)
        {
          if (strcasecmp(xd->group,group) == 0)
            {
              k++;
              if (xd->group_desc != NULL)
                {
                   if (descxd == NULL)
                     {
                       descxd = xd;
                     }
                   else
                     {
                       /* more than one desc */
                       mydelete(xd->group_desc);
                     }
                }
              /* check only the first entry */
              if (k == 1)
                {
                  firstxd = xd;
                }
            }
        }
      xd = irlist_get_next(xd);
    }

  if (k == 0)
    return k;

  if (descxd == NULL)
    return k;

  if (descxd == firstxd)
    return k;

  firstxd->group_desc = descxd->group_desc;
  descxd->group_desc = NULL;
  return k;
}

int add_default_groupdesc(const char *group)
{
  xdcc *xd; 
  xdcc *firstxd;
  int k;

  updatecontext();

  k = 0;
  firstxd = NULL;
  xd = irlist_get_head(&gdata.xdccs); 
  while(xd) 
    {
      if (xd->group != NULL)
        {
          if (strcasecmp(xd->group,group) == 0)
            {
              k++;
              if (xd->group_desc != NULL) 
                return 0;
              
              /* check only the first entry */
              if (k == 1)
                {
                  firstxd = xd;
                }
            }
        }
      xd = irlist_get_next(xd);
    }

  if (k != 1)
    return k;

  firstxd->group_desc = mystrdup(group);
  return k; 
}

void strtextcpy(char *d, const char *s)
{
   const char *x;
   char *w;
   char ch;
   size_t l;
   
   if (d == NULL)
      return;
   if (s == NULL)
      return;
   
   /* ignore path */
   x = strrchr(s, '/');
   if (x != NULL)
      x ++;
   else
      x = s;
   
   strcpy(d,x);
   /* ignore extension */
   w = strrchr(d, '.');
   if (w != NULL)
      *w = 0;
   
   l = strlen(d);
   if ( l < 8 )
      return;

   w = d + l - 1;
   ch = *w;
   switch (ch) {
   case '}':
      w = strrchr(d, '{');
      if (w != NULL)
         *w = 0;
      break;
   case ')':
      w = strrchr(d, '(');
      if (w != NULL)
         *w = 0;
      break;
   case ']':
      w = strrchr(d, '[');
      if (w != NULL)
         *w = 0;
      break;
   }

   /* strip numbers */
   x = d;
   w = d;
   for (;;) {
      ch = *(x++);
      *w = ch;
      if (ch == 0)
         break;
      if (isalpha(ch))
         w++;
   }
}

int invalid_group(const userinput * const u, const char *arg)
{
   if (!arg || !strlen(arg))
     {
       a_respond(u, "Try Specifying a Group");
       return 1;
     }
   return 0;
}

int invalid_pwd(const userinput * const u, const char *arg)
{
  if (!arg || !strlen(arg))
    {
      a_respond(u, "Try Specifying a Password");
      return 1;
    }
   return 0;
}

int invalid_announce(const userinput * const u, const char *arg)
{  
  if (!arg || !strlen(arg))
    {
      a_respond(u, "Try Specifying a Message (e.g. NEW)");
      return 1;
    }
   return 0;
}

int invalid_pack(const userinput * const u, int num)
{
  if (num < 1 || num > irlist_size(&gdata.xdccs))
    {
      a_respond(u, "Try Specifying a Valid Pack Number");
      return 1;
    }
   return 0;
}

static int a_set_group(const userinput * const u, xdcc *xd, int num, const char *group)
{
   const char *new;
   char *tmpdesc;
   char *tmpgroup;
   int rc;

   updatecontext();

   if (num == 0) num = number_of_pack(xd);
   new = "MAIN";
   if (group && strlen(group))
     new = group;

   if (xd->group != NULL)
     {
       a_respond(u, "GROUP: [Pack %i] Old: %s New: %s",
                 num, xd->group, new); 
       /* keep group info for later work */
       tmpgroup = xd->group;
       xd->group = NULL;
       tmpdesc = xd->group_desc;
       xd->group_desc = NULL;
        if (tmpdesc != NULL)
         {
           if (tmpgroup != NULL)
             reorder_new_groupdesc(tmpgroup,tmpdesc);
           mydelete(tmpdesc);
         }
       if (tmpgroup != NULL)
         mydelete(tmpgroup);
     }
   else
     {
       a_respond(u, "GROUP: [Pack %i] New: %s",
                 num, new);
     }

  if (group != new)
    return 0;
    
  xd->group = mystrdup(group);
  reorder_groupdesc(group);
  rc = add_default_groupdesc(group);
  if (rc == 1)
    a_respond(u, "New GROUPDESC: %s",group);
  return rc;
}

void a_xdlock(const userinput * const u)
{
   char *tempstr;
   int i;
   int l;
   int s;
   xdcc *xd;

   updatecontext();

   tempstr  = mycalloc(maxtextlength);

   l = a_xdl_left();
   s = a_xdl_space();
   i = 1;
   xd = irlist_get_head(&gdata.xdccs);
   while(xd)
     {
       if (xd->lock != NULL)
         {
           u_xdl_pack(u,tempstr,i,l,s,xd);
           a_respond(u," \2^-\2%*sPassword: %s", s, "", xd->lock);
         }
       i++;
       xd = irlist_get_next(xd);
     }

   mydelete(tempstr);
}

void a_chlimit(const userinput * const u)
{
   int num = 0;
   int val = 0;
   xdcc *xd;
  
   updatecontext();
  
   if (u->arg1) num = atoi(u->arg1);
   if (invalid_pack(u, num) != 0)
      return;
  
   if (!u->arg2 || !strlen(u->arg2)) {
      a_respond(u,"Try Specifying a daily Downloadlimit");
      return;
      }

   xd = irlist_get_nth(&gdata.xdccs, num-1);
   val = atoi(u->arg2);

   a_respond(u, "CHLIMIT: [Pack %i] Old: %d New: %d",
             num,xd->dlimit_max,val);
  
   xd->dlimit_max = val;
   if (val == 0)
     xd->dlimit_used = 0;
   else
     xd->dlimit_used = xd->gets + xd->dlimit_max;
  
   write_statefile();
   xdccsavetext();
}

void a_chlimitinfo(const userinput * const u)
{
  int num = 0;
  xdcc *xd;

  updatecontext();

  if (u->arg1) num = atoi(u->arg1);
  if (invalid_pack(u, num) != 0)
    return;

  xd = irlist_get_nth(&gdata.xdccs, num-1);

  if (!u->arg2 || !strlen(u->arg2))
    {
       a_respond(u, "DLIMIT: [Pack %i] descr removed", num);
       mydelete(xd->dlimit_desc);
       xd->dlimit_desc = NULL;
    }
  else
    {
       a_respond(u, "DLIMIT: [Pack %i] descr: %s", num, u->arg2e);
       xd->dlimit_desc = mystrdup(u->arg2e);
    }

  write_statefile();
  xdccsavetext();
}

void a_lock(const userinput * const u)
{
  int num = 0;
  xdcc *xd;
  
  updatecontext();
  
  if (u->arg1) num = atoi(u->arg1);
  if (invalid_pack(u, num) != 0)
    return;

  if (invalid_pwd(u, u->arg2) != 0)
    return;

  xd = irlist_get_nth(&gdata.xdccs, num-1);
  
  a_respond(u, "LOCK: [Pack %i] Password: %s", num, u->arg2);
  xd->lock = mystrdup(u->arg2);

  write_statefile();
  xdccsavetext();
}

void a_unlock(const userinput * const u)
{
  int num = 0;
  xdcc *xd;
  
  updatecontext();
  
  if (u->arg1) num = atoi(u->arg1);
  if (invalid_pack(u, num) != 0)
    return;

  xd = irlist_get_nth(&gdata.xdccs, num-1);
  a_respond(u, "UNLOCK: [Pack %i]", num);
  
  mydelete(xd->lock);
  xd->lock = NULL;
  
  write_statefile();
  xdccsavetext();
}

void a_lockgroup(const userinput * const u)
{
   xdcc *xd;
   int n;
   
   updatecontext();
   
   if (invalid_group(u, u->arg1) != 0)
      return;
 
   if (invalid_pwd(u, u->arg2) != 0)
      return;

   n = 0;
   xd = irlist_get_head(&gdata.xdccs);
   while(xd)
     {
       n++;
       if (xd->group != NULL)
         {
           if (strcasecmp(xd->group,u->arg1) == 0)
             {
                a_respond(u, "LOCK: [Pack %i] Password: %s", n, u->arg2);
                xd->lock = mystrdup(u->arg2);
             }
         }
       xd = irlist_get_next(xd);
     }
  write_statefile();
  xdccsavetext();
}

void a_unlockgroup(const userinput * const u)
{
   xdcc *xd;
   int n;
   
   updatecontext();

   if (invalid_group(u, u->arg1) != 0)
     return;

   n = 0;
   xd = irlist_get_head(&gdata.xdccs);
   while(xd)
     {
       n++;
       if (xd->group != NULL)
         {
           if (strcasecmp(xd->group,u->arg1) == 0)
             {
                a_respond(u, "UNLOCK: [Pack %i]", n);
                mydelete(xd->lock);
                xd->lock = NULL;
             }
         }
       xd = irlist_get_next(xd);
     }
  write_statefile();
  xdccsavetext();
}

void a_groupdesc(const userinput * const u)
{
  int k;

  updatecontext();

  if (invalid_group(u, u->arg1) != 0)
    return;

  if (u->arg2e && strlen(u->arg2e))
    {
      a_respond(u, "New GROUPDESC: %s",u->arg2e);
    }
  else
    {
      a_respond(u, "Removed GROUPDESC");
    }

  k = reorder_new_groupdesc(u->arg1,u->arg2e);
  if (k == 0)
    return;

  write_statefile();
  xdccsavetext();
}

void a_group(const userinput * const u)
{
  xdcc *xd;
  const char *new;
  int num = 0;
  
  updatecontext();
  
  if (u->arg1) num = atoi(u->arg1);
  if (invalid_pack(u, num) != 0)
    return;

  xd = irlist_get_nth(&gdata.xdccs, num-1);

  new = u->arg2;
  if (!u->arg2 || !strlen(u->arg2))
    {
      if (xd->group == NULL)
      {
        a_respond(u,"Try Specifying a Group");
        return;
      }
      new = NULL;
    }
  else
    {
       if (gdata.groupsincaps)
         caps(u->arg2);
    }

  a_set_group(u, xd, num, new);
  write_statefile();
  xdccsavetext();
}

void a_regroup(const userinput * const u)
{
  xdcc *xd;
  const char *g;
  int k;

  updatecontext();

  if (invalid_group(u, u->arg1) != 0)
     return;

  if (invalid_group(u, u->arg2) != 0)
     return;

  if (gdata.groupsincaps)
    caps(u->arg1);
   
  k = 0;
  xd = irlist_get_head(&gdata.xdccs);
  while(xd)
    {
      if (xd->group != NULL)
        g = xd->group;
      else
        g = "main";
      if (strcasecmp(g,u->arg1) == 0)
        {
          k++;
          if (xd->group != NULL)
            mydelete(xd->group);
          xd->group = mystrdup(u->arg2);
        }
      xd = irlist_get_next(xd);
    }

  if (k == 0)
    return;

  a_respond(u, "GROUP: Old: %s New: %s", u->arg1, u->arg2);
  if (strcasecmp(u->arg1,"main") == 0)
    add_default_groupdesc(u->arg2);
  write_statefile();
  xdccsavetext();
}

void a_amsg(const userinput * const u)
{
  channel_t *ch;
  
  updatecontext ();

  if (invalid_announce(u, u->arg1e) != 0)
    return;

  ch = irlist_get_head(&gdata.channels);
  while(ch) {
    if (ch->flags & CHAN_ONCHAN)
      privmsg_slow(ch->name, "%s", u->arg1e);
    ch = irlist_get_next(ch);
    }
  a_respond(u,"Announced [%s]",u->arg1e);
}

void a_hop(const userinput * const u)
{
   channel_t *ch;

   updatecontext();

   /* part & join channels */
   ch = irlist_get_head(&gdata.channels);
   while(ch)
     {
       if ((!u->arg1) || (!strcasecmp(u->arg1,ch->name)))
         {
           writeserver(WRITESERVER_NORMAL, "PART %s", ch->name);
           clearmemberlist(ch);
           ch->flags &= ~CHAN_ONCHAN;
           joinchannel(ch);
         }
       ch = irlist_get_next(ch);
     }
}

void a_identify(const userinput * const u)
{
  updatecontext();

  if (!gdata.nickserv_pass)
    {
       a_respond(u,"No nickserv_pass set!");
       return;
    }

  identify_needed(1);
  a_respond(u,"nickserv identify send.");
}

void a_holdqueue(const userinput * const u)
{
   int val;
   int i;
   
   updatecontext();
    
   if (gdata.holdqueue)
     {
       val = 0;
     }
   else
     {
       val = 1;
     }
   
   if (u->arg1) val = atoi(u->arg1);
   
   gdata.holdqueue = val;
   a_respond(u,"HOLDQUEUE now %d", val);

   if (val != 0)
     return;

   for (i=0; i<100; i++)
     {
       if (!gdata.exiting &&
           irlist_size(&gdata.mainqueue) &&
           (irlist_size(&gdata.trans) < min2(MAXTRANS,gdata.slotsmax)))
         {
           sendaqueue(0);
         }
     }
}

/* End of File */


syntax highlighted by Code2HTML, v. 0.9.1