Blame view

maidag/mailquota.c 7.06 KB
1
/* GNU Mailutils -- a suite of utilities for electronic mail
2
   Copyright (C) 1999-2002, 2004-2005, 2007, 2009-2012, 2014-2016 Free
3
   Software Foundation, Inc.
4 5 6 7 8 9 10 11 12 13 14 15

   GNU Mailutils 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 3, or (at your option)
   any later version.

   GNU Mailutils 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
16
   along with GNU Mailutils.  If not, see <http://www.gnu.org/licenses/>. */
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

#include "maidag.h"

#if defined (USE_MAILBOX_QUOTAS)

#define DEFRETVAL MQUOTA_UNLIMITED

mu_off_t groupquota = 5*1024*1024UL;
static int get_size (char *, mu_off_t *, char **);

int
get_size (char *str, mu_off_t *size, char **endp)
{
  mu_off_t s;

  s = strtol (str, &str, 0);
  switch (*str)
    {
    case 0:
      break;
      
    case 'k':
    case 'K':
      s *= 1024;
      break;
      
    case 'm':
    case 'M':
      s *= 1024*1024;
      break;
      
    default:
      *endp = str;
      return -1;
    }
  *size = s;
  return 0;
}

#define RETR_OK        0
#define RETR_UNLIMITED -1
#define RETR_FAILURE   1

int
fail_retrieve_quota (char *name, mu_off_t *quota)
{
63
  mu_error (_("no quota retrieving mechanism"));
64 65 66
  return RETR_FAILURE;
}

67
#ifdef ENABLE_DBM
68 69 70
int
dbm_retrieve_quota (char *name, mu_off_t *quota)
{
71 72
  mu_dbm_file_t db;
  struct mu_dbm_datum  named, contentd;
73 74 75 76 77 78
  char buffer[64];
  int unlimited = 0;
  int rc;

  if (!quotadbname)
    return RETR_FAILURE;
79

80
  rc = mu_dbm_create (quotadbname, &db, MU_FILE_SAFETY_ALL);
81 82 83 84 85 86 87 88
  if (rc)
    {
      mu_error (_("unable to create quota db"));
      return RETR_FAILURE;
    }

  rc = mu_dbm_safety_check (db);
  if (rc && rc != ENOENT)
89
    {
90 91 92 93 94 95 96 97 98 99 100 101
      mu_error (_("quota db fails safety check: %s"),
		mu_strerror (rc));
      mu_dbm_destroy (&db);
      return RETR_FAILURE;
    }

  rc = mu_dbm_open (db, MU_STREAM_READ, 0600);
  if (rc)
    {
      mu_error (_("cannot open file %s: %s"),
		quotadbname, mu_strerror (rc));
      mu_dbm_destroy (&db);
102 103 104 105 106
      return RETR_FAILURE;
    }
  
  memset (&named, 0, sizeof named);
  memset (&contentd, 0, sizeof contentd);
107 108 109 110
  named.mu_dptr = name;
  named.mu_dsize = strlen (name);
  rc = mu_dbm_fetch (db, &named, &contentd);
  if (rc)
111 112
    {
      /* User not in database, try default quota */
113 114 115 116 117
      mu_dbm_datum_free (&named);
      named.mu_dptr = "DEFAULT";
      named.mu_dsize = strlen ("DEFAULT");
      rc = mu_dbm_fetch (db, &named, &contentd);
      if (rc == MU_ERR_NOENT)
118
	{
119 120 121 122 123 124 125
	  mu_dbm_destroy (&db);
	  return RETR_FAILURE;
	}
      else if (rc)
	{
	  mu_error (_("can't fetch data: %s"), mu_dbm_strerror (db));
	  mu_dbm_destroy (&db);
126 127 128 129
	  return RETR_FAILURE;
	}
    }

130
  if (mu_c_strncasecmp("none", contentd.mu_dptr, contentd.mu_dsize) == 0) 
131
      unlimited = 1;
132
  else if (contentd.mu_dsize > sizeof (buffer) - 1)
133
    {
Sergey Poznyakoff authored
134 135
      mu_error (ngettext ("mailbox quota for `%s' is too big: %lu digit",
			  "mailbox quota for `%s' is too big: %lu digits",
136
			  contentd.mu_dsize),
Sergey Poznyakoff authored
137
		name, (unsigned long) contentd.mu_dsize);
138 139 140 141 142 143
      *quota = groupquota;
    }
  else
    {
      char *p;
		
144 145
      strncpy (buffer, contentd.mu_dptr, contentd.mu_dsize);
      buffer[contentd.mu_dsize] = 0;
146 147 148
      *quota = strtoul (buffer, &p, 0);
      if (get_size (buffer, quota, &p))
	{
149
	  mu_error (_("bogus mailbox quota for `%s' (near `%s')"), name, p);
150 151 152
	  *quota = groupquota;
	}
    }
153 154 155
  
  mu_dbm_datum_free (&contentd);
  mu_dbm_destroy (&db);
156 157 158 159 160 161 162 163 164 165 166 167
  
  return unlimited ? RETR_UNLIMITED : RETR_OK;
}

# define default_retrieve_quota dbm_retrieve_quota
#else
# define default_retrieve_quota fail_retrieve_quota
#endif

#ifdef USE_SQL
#include <mailutils/sql.h>

Wojciech Polak authored
168 169
/* FIXME: defined in libmu_auth/sql.c */
#include <libmu_auth/sql.h>
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

int
sql_retrieve_quota (char *name, mu_off_t *quota)
{
  mu_sql_connection_t conn;
  char *query_str;
  int rc, status;
  char *tmp;
  size_t n;
  
  query_str = mu_sql_expand_query (quota_query, name);
  if (!query_str)
    return RETR_FAILURE;

  status = mu_sql_connection_init (&conn,
185 186 187 188 189 190
				   mu_sql_module_config.interface,
				   mu_sql_module_config.host,
				   mu_sql_module_config.port,
				   mu_sql_module_config.user,
				   mu_sql_module_config.passwd,
				   mu_sql_module_config.db);
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216
  
  if (status)
    {
      mu_error ("%s. SQL error: %s",
		mu_strerror (status), mu_sql_strerror (conn));
      mu_sql_connection_destroy (&conn);
      free (query_str);
      return RETR_FAILURE;
    }

  status = mu_sql_connect (conn);

  if (status)
    {
      mu_error ("%s. SQL error: %s",
		mu_strerror (status), mu_sql_strerror (conn));
      mu_sql_connection_destroy (&conn);
      free (query_str);
      return  RETR_FAILURE;
    }
  
  status = mu_sql_query (conn, query_str);
  free (query_str);
  
  if (status)
    {
Sergey Poznyakoff authored
217
      mu_error (_("SQL query failed: %s"),
218 219 220 221 222 223 224 225 226 227
		(status == MU_ERR_SQL) ?  mu_sql_strerror (conn) :
	 	                          mu_strerror (status));
      mu_sql_connection_destroy (&conn);
      return  RETR_FAILURE;
    }

  status = mu_sql_store_result (conn);

  if (status)
    {
228
      mu_error (_("cannot store SQL result: %s"),
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
		(status == MU_ERR_SQL) ?  mu_sql_strerror (conn) :
	 	                          mu_strerror (status));
      mu_sql_connection_destroy (&conn);
      return RETR_FAILURE;
    }

  mu_sql_num_tuples (conn, &n);
  if (n == 0)
    {
      rc = RETR_FAILURE;
    }
  else
    {
      rc = RETR_OK;
      tmp = NULL;
      status = mu_sql_get_column (conn, 0, 0, &tmp);
      if (status)
	{
247
	  mu_error (_("cannot retrieve mailbox quota from SQL: %s"),
248 249 250 251
		    (status == MU_ERR_SQL) ?  mu_sql_strerror (conn) :
		    mu_strerror (status));
	  rc = RETR_FAILURE;
	}
252
      else if (tmp == NULL || tmp[0] == 0 || mu_c_strcasecmp (tmp, "none") == 0)
253 254 255 256 257 258 259
	rc = RETR_UNLIMITED;
      else
	{
	  char *p;
	  
	  if (get_size (tmp, quota, &p))
	    {
260
	      mu_error (_("bogus mailbox quota for `%s' (near `%s')"),
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
			name, p);
	      *quota = groupquota;
	    }
	}
    }
  
  mu_sql_release_result (conn);
  mu_sql_disconnect (conn);
  mu_sql_connection_destroy (&conn);
  return rc;
}
#endif


static int
retrieve_quota (struct mu_auth_data *auth, mu_off_t *quota)
{
  if (MU_HAS_QUOTA (auth))
    {
      if (auth->quota == 0)
	return RETR_UNLIMITED;
      *quota = auth->quota;
      return RETR_OK;
    }
  
#ifdef USE_SQL
  if (quota_query)
    return sql_retrieve_quota (auth->name, quota);
#endif
  return default_retrieve_quota (auth->name, quota);
}

int
check_quota (struct mu_auth_data *auth, mu_off_t size, mu_off_t *rest)
{
  mu_off_t quota;
297 298 299

  if (!auth)
    return MQUOTA_OK;
300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320
  
  switch (retrieve_quota (auth, &quota))
    {
    case RETR_FAILURE:
      return DEFRETVAL;
      
    case RETR_UNLIMITED:
      return MQUOTA_UNLIMITED;

    case RETR_OK:
      if (quota < size)  /* Mailbox full */
	return MQUOTA_EXCEEDED;
	
      if (rest)
	*rest = quota - size;
    }
  
  return MQUOTA_OK;
}
  
#endif /* USE_MAIL_QUOTA */