Each file can have a different limit.
For each file, it is possible to write the user's ID or the user's IP
address.
If the files exists, they are purged.
extern numlist hours, weekdays;
extern FileListObject AccessLog;
+extern int PerUserLimitsNumber;
+extern struct PerUserLimitStruct PerUserLimits[MAX_USER_LIMITS];
struct param_list
{
return(1);
}
+static int getparam_userlimit(const char *param,char *buf)
+{
+ int plen;
+ char *file_begin,*file_end;
+ int limit;
+ int digit;
+ int userid;
+
+ plen=strlen(param);
+ if (strncmp(buf,param,plen) != 0) return(0);
+ buf+=plen;
+ if ((unsigned char)*buf>' ') return(0);
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+
+ /*
+ options are made of a file name, an integer limit and an optional
+ integer flag. The file name may contain spaces. We keep searching
+ until a valid number is found after a space.
+ */
+ file_begin=buf;
+ do {
+ while (*buf && (unsigned char)*buf>' ') buf++;
+ if (*buf!=' ') {
+ debuga(_("Missing limit in per_user_limit\n"));
+ exit(EXIT_FAILURE);
+ }
+ file_end=buf;
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+ limit=0;
+ while (*buf && isdigit(*buf)) {
+ digit=*buf-'0';
+ if (limit>=(INT_MAX-digit)/10) break;
+ limit=limit*10+digit;
+ buf++;
+ }
+ } while (*buf && *buf!=' ');
+
+ userid=0;
+ if (*buf==' ') {
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+ if (!isdigit(*buf)) {
+ debuga(_("Invalid user ID/IP output type flag in per_user_limit\n"));
+ exit(EXIT_FAILURE);
+ }
+ userid=*buf-'0';
+ }
+
+ if (PerUserLimitsNumber>=MAX_USER_LIMITS) {
+ debuga(_("Too many per_user_limit\n"));
+ exit(EXIT_FAILURE);
+ }
+ *file_end='\0';
+ safe_strcpy(PerUserLimits[PerUserLimitsNumber].File,file_begin,sizeof(PerUserLimits[PerUserLimitsNumber].File));
+ PerUserLimits[PerUserLimitsNumber].Limit=limit;
+ PerUserLimits[PerUserLimitsNumber].UserId=userid;
+ PerUserLimitsNumber++;
+
+ return(1);
+}
+
static void parmtest(char *buf)
{
char wbuf[2048];
if (getparam_string("output_email",buf,OutputEmail,sizeof(OutputEmail))>0) return;
- if (getparam_2words("per_user_limit",buf,PerUserLimitFile,sizeof(PerUserLimitFile),wbuf,sizeof(wbuf))>0) {
- PerUserLimit=atoi(wbuf);
- return;
- }
+ if (getparam_userlimit("per_user_limit",buf)>0) return;
if (getparam_int("lastlog",buf,&LastLog)>0) return;
#include "include/conf.h"
#include "include/defs.h"
+//! Number of limits.
+int PerUserLimitsNumber=0;
+//! Log user's who downloaded more than the limit.
+struct PerUserLimitStruct PerUserLimits[MAX_USER_LIMITS];
+
extern struct globalstatstruct globstat;
void htmlrel(void)
double perc=0, perc2=0, ouperc=0, inperc=0;
int count;
int cstatus;
+ int i;
+ unsigned int user_limit[(MAX_USER_LIMITS+sizeof(unsigned int)-1)/sizeof(unsigned int)];
bool have_denied_report;
const char *sort_field;
const char *sort_order;
char siteind[MAX_TRUNCATED_URL];
struct getwordstruct gwarea;
longline line,line1;
- struct userinfostruct *uinfo;
+ const struct userinfostruct *uinfo;
userscan uscan;
if (snprintf(tmp2,sizeof(tmp2),"%s/sargtmp.int_unsort",tmp)>=sizeof(tmp2)) {
sort_labels(&sort_field,&sort_order);
+ for (i=0 ; i<PerUserLimitsNumber ; i++) {
+ if (access(PerUserLimits[i].File,R_OK)==0 && unlink(PerUserLimits[i].File)==-1) {
+ debuga(_("Cannot delete per_user_limit file \"%s\": %s"),PerUserLimits[i].File,
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ }
+
uscan=userinfo_startscan();
if (uscan == NULL) {
debuga(_("Cannot enumerate the user list\n"));
exit(EXIT_FAILURE);
}
+ for (i=0 ; i<sizeof(user_limit)/sizeof(user_limit[0]) ; i++)
+ user_limit[i]=0;
+
tnacc=0;
tnbytes=0;
tnelap=0;
fputs("</tr>\n",fp_ou);
}
- if (PerUserLimit > 0 && (int)(tnbytes/1000000LLU) > PerUserLimit && !uinfo->user_limit) {
- FILE *fp_usr;
+ if (PerUserLimitsNumber>0) {
+ int limit=(int)(tnbytes/1000000LLU);
+ int maskid;
+ int mask;
+ for (i=0 ; i<PerUserLimitsNumber ; i++) {
+ maskid=i/sizeof(unsigned int);
+ mask=0x1U << (i % sizeof(unsigned int));
+ if (limit>PerUserLimits[i].Limit && (user_limit[maskid] & mask)==0) {
+ FILE *fp_usr;
+
+ if((fp_usr = fopen(PerUserLimits[i].File, "a")) == 0) {
+ debuga(_("(html10) Cannot open per user limit file %s: %s\n"),PerUserLimits[i].File,strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ if (PerUserLimits[i].UserId)
+ fprintf(fp_usr,"%s\n",uinfo->label);
+ else
+ fprintf(fp_usr,"%s\n",uinfo->ip);
+ if (fclose(fp_usr)==EOF) {
+ debuga(_("Write error in per user limit file %s: %s\n"),PerUserLimits[i].File,strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ user_limit[maskid]|=mask;
- if((fp_usr = fopen(PerUserLimitFile, "a")) == 0) {
- debuga(_("(html10) Cannot open file %s: %s\n"),PerUserLimitFile,strerror(errno));
- exit(EXIT_FAILURE);
- }
- fprintf(fp_usr,"%s\n",uinfo->ip);
- if (fclose(fp_usr)==EOF) {
- debuga(_("Write error in %s: %s\n"),PerUserLimitFile,strerror(errno));
- exit(EXIT_FAILURE);
+ if(debug)
+ debuga(_("User %s limit exceeded (%d MB). Added to file %s\n"),uinfo->label,
+ PerUserLimits[i].Limit,PerUserLimits[i].File);
+ }
}
- uinfo->user_limit=1;
-
- if(debug)
- debuga(_("User %s limit exceeded (%d MB). Added to file %s\n"),uinfo->label,PerUserLimit,PerUserLimitFile);
}
if ((ReportType & REPORT_TYPE_TOPUSERS) != 0 && (UserReportFields & USERREPORTFIELDS_AVERAGE) != 0) {
//! The character prefixed in front of the host names that are aliased.
#define ALIAS_PREFIX '*'
+//! Maximum number of limit files that can be stored.
+#define MAX_USER_LIMITS 16
+
struct periodstruct
{
//! The first date of the period.
char ExcludeHosts[255];
char ExcludeUsers[255];
char DateFormat;
-char PerUserLimitFile[255];
-int PerUserLimit;
bool UserIp;
char MaxElapsed[255];
unsigned long int datetimeby;
const char *filename;
//! \c True if this user is in the topuser list.
int topuser;
- //! \c True if the user's limit has been reached.
- int user_limit;
//! A general purpose flag that can be set when scanning the user's list.
int flag;
#ifdef ENABLE_DOUBLE_CHECK_DATA
int EndTime;
};
+/*!
+\brief How to log every user crossing the download limit.
+*/
+struct PerUserLimitStruct
+{
+ //! File to save the user's IP or ID to.
+ char File[255];
+ //! Limit above which the user is reported.
+ int Limit;
+ //! \c True to report the user's ID or \c false to report the user's IP.
+ bool UserId;
+};
+
// auth.c
void htaccess(const struct userinfostruct *uinfo);
#
#date_format u
-# TAG: per_user_limit file MB
-# Saves userid on file if download exceed n MB.
+# TAG: per_user_limit file MB flag
+# Saves userid (if flag is 1) or userip (if flag is 0) in file if download exceed n MB.
# This option allow you to disable user access if user exceed a download limit.
+# The option may be repeated up to 16 times to generate several files with
+# different content type or limit.
#
#per_user_limit none
user->id_is_ip=1;
user->ip=user->id;
}
- user->user_limit=0;
if (AnonymousOutputFiles) {
snprintf(filename,sizeof(filename),"%d",AnonymousCounter++);