]> git.ipfire.org Git - thirdparty/sarg.git/commitdiff
Create multiple per_user_limit files
authorFrederic Marchal <fmarchal@users.sourceforge.net>
Wed, 5 Jun 2013 20:17:02 +0000 (22:17 +0200)
committerFrederic Marchal <fmarchal@users.sourceforge.net>
Wed, 5 Jun 2013 20:17:02 +0000 (22:17 +0200)
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.

getconf.c
html.c
include/conf.h
include/defs.h
sarg.conf
userinfo.c

index 6722a2b25d6e4d30d16ba1116323f1816635fb51..20b7a72b5c868c4bc3bb21d826f0e2bf4742085d 100644 (file)
--- a/getconf.c
+++ b/getconf.c
@@ -32,6 +32,8 @@
 
 extern numlist hours, weekdays;
 extern FileListObject AccessLog;
+extern int PerUserLimitsNumber;
+extern struct PerUserLimitStruct PerUserLimits[MAX_USER_LIMITS];
 
 struct param_list
 {
@@ -435,6 +437,66 @@ static int getparam_sort(const char *param,struct sort_list *options,int noption
        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];
@@ -567,10 +629,7 @@ static void parmtest(char *buf)
 
        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;
 
diff --git a/html.c b/html.c
index 54d953f25970196b9975198254947bec6b574440..d330b773398d7fd871cf1fb9998c65c61a3d0680 100644 (file)
--- a/html.c
+++ b/html.c
 #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)
@@ -51,13 +56,15 @@ 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)) {
@@ -77,6 +84,14 @@ void htmlrel(void)
 
        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"));
@@ -129,6 +144,9 @@ void htmlrel(void)
                        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;
@@ -527,22 +545,35 @@ void htmlrel(void)
                        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) {
index 4611f29c22464f0369369c587ce5b96f9472bb7e..821ce85a924af528f6ae5dac7b0fdfe5f556f218 100755 (executable)
@@ -279,6 +279,9 @@ Sarg will complain that there are too many days in the files if this limit is ov
 //! 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.
@@ -346,8 +349,6 @@ char module[255];
 char ExcludeHosts[255];
 char ExcludeUsers[255];
 char DateFormat;
-char PerUserLimitFile[255];
-int PerUserLimit;
 bool UserIp;
 char MaxElapsed[255];
 unsigned long int datetimeby;
index 676080656e512292233395c00c741ffc0bf49dc1..9431913a69ad0d06312378cfc6f021a67db54ce9 100755 (executable)
@@ -61,8 +61,6 @@ struct userinfostruct
        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
@@ -118,6 +116,19 @@ struct ReadLogDataStruct
        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);
 
index 5a078d4f48a45a5246a2c7f72629b65c6eca538a..f52d1085802e467ac9dce4bf2da70fc931f94c8a 100644 (file)
--- a/sarg.conf
+++ b/sarg.conf
 #
 #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
 
index 37451b07b130f7afe2f4724907a2d39e6c945d9d..24b038f15553cfd41cf30c45df138aabc1375c3c 100644 (file)
@@ -117,7 +117,6 @@ struct userinfostruct *userinfo_create(const char *userid,const char *ip)
                user->id_is_ip=1;
                user->ip=user->id;
        }
-       user->user_limit=0;
 
        if (AnonymousOutputFiles) {
                snprintf(filename,sizeof(filename),"%d",AnonymousCounter++);