/*
* SARG Squid Analysis Report Generator http://sarg.sourceforge.net
- * 1998, 2011
+ * 1998, 2015
*
* SARG donations:
* please look at http://sarg.sourceforge.net/donations.php
#include "include/conf.h"
#include "include/defs.h"
+#include "include/stringbuffer.h"
+#include "include/alias.h"
//! The number of users to group in one unit.
#define USERS_PER_GROUP 50
static struct usergroupstruct *first_user_group=NULL;
//! The counter to generate unique user number when ::AnonymousOutputFiles is set.
static int AnonymousCounter=0;
+//! String buffer to store the user's related constants.
+static StringBufferObject UserStrings=NULL;
+//! User aliases.
+static AliasObject UserAliases=NULL;
-struct userinfostruct *userinfo_create(const char *userid)
+struct userinfostruct *userinfo_create(const char *userid,const char *ip)
{
struct usergroupstruct *group, *last;
struct userinfostruct *user;
int flen;
int count, clen;
char cstr[9];
+ char filename[MAX_USER_FNAME_LEN];
+
+ if (!UserStrings) {
+ UserStrings=StringBuffer_Create();
+ if (!UserStrings) {
+ debuga(_("Not enough memory to store the user's strings\n"));
+ exit(EXIT_FAILURE);
+ }
+ }
last=NULL;
for (group=first_user_group ; group ; group=group->next) {
if (!group) {
group=malloc(sizeof(*group));
if (!group) {
- debuga(_("Not enough memory to store the user\n"));
+ debuga(_("Not enough memory to store user \"%s\"\n"),userid);
exit(EXIT_FAILURE);
}
memset(group,0,sizeof(*group));
}
user=group->list+group->nusers++;
- safe_strcpy(user->id,userid,sizeof(user->id));
+ user->id=StringBuffer_Store(UserStrings,userid);
+ if (!user->id) {
+ debuga(_("Not enough memory to store user ID \"%s\"\n"),userid);
+ exit(EXIT_FAILURE);
+ }
+ user->label=user->id; //assign a label to avoid a NULL pointer in case none is provided
+ if (ip) {
+ /*
+ * IP address is not the same as the user's ID. A separate buffer
+ * must be allocated.
+ */
+ user->id_is_ip=false;
+ user->ip=StringBuffer_Store(UserStrings,ip);
+ } else {
+ /*
+ * User's IP address share the same buffer as the user's ID.
+ */
+ user->id_is_ip=true;
+ user->ip=user->id;
+ }
if (AnonymousOutputFiles) {
- snprintf(user->filename,sizeof(user->filename),"%d",AnonymousCounter++);
+ snprintf(filename,sizeof(filename),"%d",AnonymousCounter++);
} else {
skip=0;
j=0;
for (i=0 ; userid[i] && j<MAX_USER_FNAME_LEN-1 ; i++) {
if (isalnum(userid[i]) || userid[i]=='-' || userid[i]=='_') {
- user->filename[j++]=userid[i];
+ filename[j++]=userid[i];
skip=0;
} else {
if (!skip) {
- user->filename[j++]='_';
+ filename[j++]='_';
skip=1;
}
}
}
- user->filename[j]='\0';
- flen=i-1;
+ if (j==0) filename[j++]='_'; //don't leave a file name empty
+ flen=j;
+ filename[j]='\0';
count=0;
for (group=first_user_group ; group ; group=group->next) {
lastuser=(group->next) ? group->nusers : group->nusers-1;
for (i=0 ; i<lastuser ; i++) {
- if (strcasecmp(user->filename,group->list[i].filename)==0) {
- clen=sprintf(cstr,"-%04X",count++);
+ if (strcasecmp(filename,group->list[i].filename)==0) {
+ clen=sprintf(cstr,"+%X",count++);
if (flen+clen<MAX_USER_FNAME_LEN)
- strcpy(user->filename+flen,cstr);
+ strcpy(filename+flen,cstr);
else
- strcpy(user->filename+MAX_USER_FNAME_LEN-clen,cstr);
+ strcpy(filename+MAX_USER_FNAME_LEN-clen,cstr);
}
}
}
}
+ user->filename=StringBuffer_Store(UserStrings,filename);
+ if (!user->filename)
+ {
+ debuga(_("Not enough memory to store the file name for user \"%s\"\n"),user->id);
+ exit(EXIT_FAILURE);
+ }
return(user);
}
free(group);
}
first_user_group=NULL;
+ StringBuffer_Destroy(&UserStrings);
+}
+
+/*!
+ * Store the user's label.
+ * \param uinfo The user info structure created by userinfo_create().
+ * \param label The string label to store.
+ */
+void userinfo_label(struct userinfostruct *uinfo,const char *label)
+{
+ if (!uinfo) return;
+ if (!UserStrings) return;
+ uinfo->label=StringBuffer_Store(UserStrings,label);
+ if (!uinfo->label) {
+ debuga(_("Not enough memory to store label \"%s\" of user \"%s\"\n"),label,uinfo->id);
+ exit(EXIT_FAILURE);
+ }
}
struct userinfostruct *userinfo_find_from_file(const char *filename)
return(NULL);
}
+struct userinfostruct *userinfo_find_from_ip(const char *ip)
+{
+ struct usergroupstruct *group;
+ int i;
+
+ for (group=first_user_group ; group ; group=group->next) {
+ for (i=0 ; i<group->nusers ; i++)
+ if (strcmp(ip,group->list[i].ip)==0)
+ return(group->list+i);
+ }
+ return(NULL);
+}
+
/*!
Start the scanning of the user list.
}
}
+/*!
+Read the file containing the user names to alias in the report.
+
+\param Filename The name of the file.
+*/
+void read_useralias(const char *Filename)
+{
+ FILE *fi;
+ longline line;
+ char *buf;
+
+ if (debug) debuga(_("Reading user alias file \"%s\"\n"),Filename);
+
+ UserAliases=Alias_Create();
+ if (!UserAliases) {
+ debuga(_("Cannot store user's aliases\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ fi=fopen(Filename,"rt");
+ if (!fi) {
+ debuga(_("Cannot read user name alias file \"%s\": %s\n"),Filename,strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if ((line=longline_create())==NULL) {
+ debuga(_("Not enough memory to read the user name aliases\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ while ((buf=longline_read(fi,line)) != NULL) {
+ if (Alias_Store(UserAliases,buf)<0) {
+ debuga(_("While reading \"%s\"\n"),Filename);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ longline_destroy(&line);
+ if (fclose(fi)==EOF) {
+ debuga(_("Read error in \"%s\": %s\n"),Filename,strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (debug) {
+ debuga(_("List of user names to alias:\n"));
+ Alias_PrintList(UserAliases);
+ }
+}
+
+/*!
+Free the memory allocated by read_useralias().
+*/
+void free_useralias(void)
+{
+ Alias_Destroy(&UserAliases);
+}
+
+/*!
+Replace the user's name or ID by an alias if one is defined.
+
+\param user The user's name or ID as extracted from the report.
+*/
+const char *process_user(const char *user)
+{
+ user=Alias_Replace(UserAliases,user);
+ return(user);
+}