2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
6 * please look at http://sarg.sourceforge.net/donations.php
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
27 #include "include/conf.h"
28 #include "include/defs.h"
29 #include "include/stringbuffer.h"
30 #include "include/alias.h"
32 //! The number of users to group in one unit.
33 #define USERS_PER_GROUP 50
35 /*! \brief Group the users in one allocation unit.
36 Structure to store a group of users and reduce the number of memory
39 struct usergroupstruct
41 //! The next group of users.
42 struct usergroupstruct
*next
;
44 struct userinfostruct list
[USERS_PER_GROUP
];
45 //! The number of users stored in the list.
49 /*! \brief Hold pointer to scan through the user list.
53 //! The group containing the user.
54 struct usergroupstruct
*group
;
55 //! The index of the user in the group.
59 //! The first group of users.
60 static struct usergroupstruct
*first_user_group
=NULL
;
61 //! The counter to generate unique user number when ::AnonymousOutputFiles is set.
62 static int AnonymousCounter
=0;
63 //! String buffer to store the user's related constants.
64 static StringBufferObject UserStrings
=NULL
;
66 static AliasObject UserAliases
=NULL
;
68 struct userinfostruct
*userinfo_create(const char *userid
,const char *ip
)
70 struct usergroupstruct
*group
, *last
;
71 struct userinfostruct
*user
;
77 char filename
[MAX_USER_FNAME_LEN
];
80 UserStrings
=StringBuffer_Create();
82 debuga(__FILE__
,__LINE__
,_("Not enough memory to store the user's strings\n"));
88 for (group
=first_user_group
; group
; group
=group
->next
) {
89 if (group
->nusers
<USERS_PER_GROUP
) break;
94 group
=malloc(sizeof(*group
));
96 debuga(__FILE__
,__LINE__
,_("Not enough memory to store user \"%s\"\n"),userid
);
99 memset(group
,0,sizeof(*group
));
103 first_user_group
=group
;
105 user
=group
->list
+group
->nusers
++;
107 user
->id
=StringBuffer_Store(UserStrings
,userid
);
109 debuga(__FILE__
,__LINE__
,_("Not enough memory to store user ID \"%s\"\n"),userid
);
112 user
->label
=user
->id
; //assign a label to avoid a NULL pointer in case none is provided
115 * IP address is not the same as the user's ID. A separate buffer
118 user
->id_is_ip
=false;
119 user
->ip
=StringBuffer_Store(UserStrings
,ip
);
122 * User's IP address share the same buffer as the user's ID.
128 if (AnonymousOutputFiles
) {
129 snprintf(filename
,sizeof(filename
),"%d",AnonymousCounter
++);
133 for (i
=0 ; userid
[i
] && j
<MAX_USER_FNAME_LEN
-1 ; i
++) {
134 if (isalnum(userid
[i
]) || userid
[i
]=='-' || userid
[i
]=='_') {
135 filename
[j
++]=userid
[i
];
144 if (j
==0) filename
[j
++]='_'; //don't leave a file name empty
149 for (group
=first_user_group
; group
; group
=group
->next
) {
150 lastuser
=(group
->next
) ? group
->nusers
: group
->nusers
-1;
151 for (i
=0 ; i
<lastuser
; i
++) {
152 if (strcasecmp(filename
,group
->list
[i
].filename
)==0) {
153 clen
=sprintf(cstr
,"+%X",count
++);
154 if (flen
+clen
<MAX_USER_FNAME_LEN
)
155 strcpy(filename
+flen
,cstr
);
157 strcpy(filename
+MAX_USER_FNAME_LEN
-clen
,cstr
);
162 user
->filename
=StringBuffer_Store(UserStrings
,filename
);
165 debuga(__FILE__
,__LINE__
,_("Not enough memory to store the file name for user \"%s\"\n"),user
->id
);
172 void userinfo_free(void)
174 struct usergroupstruct
*group
, *next
;
176 for (group
=first_user_group
; group
; group
=next
) {
180 first_user_group
=NULL
;
181 StringBuffer_Destroy(&UserStrings
);
185 * Store the user's label.
186 * \param uinfo The user info structure created by userinfo_create().
187 * \param label The string label to store.
189 void userinfo_label(struct userinfostruct
*uinfo
,const char *label
)
192 if (!UserStrings
) return;
193 uinfo
->label
=StringBuffer_Store(UserStrings
,label
);
195 debuga(__FILE__
,__LINE__
,_("Not enough memory to store label \"%s\" of user \"%s\"\n"),label
,uinfo
->id
);
200 struct userinfostruct
*userinfo_find_from_file(const char *filename
)
202 struct usergroupstruct
*group
;
205 for (group
=first_user_group
; group
; group
=group
->next
) {
206 for (i
=0 ; i
<group
->nusers
; i
++)
207 if (strcmp(filename
,group
->list
[i
].filename
)==0)
208 return(group
->list
+i
);
213 struct userinfostruct
*userinfo_find_from_id(const char *id
)
215 struct usergroupstruct
*group
;
218 for (group
=first_user_group
; group
; group
=group
->next
) {
219 for (i
=0 ; i
<group
->nusers
; i
++)
220 if (strcmp(id
,group
->list
[i
].id
)==0)
221 return(group
->list
+i
);
226 struct userinfostruct
*userinfo_find_from_ip(const char *ip
)
228 struct usergroupstruct
*group
;
231 for (group
=first_user_group
; group
; group
=group
->next
) {
232 for (i
=0 ; i
<group
->nusers
; i
++)
233 if (strcmp(ip
,group
->list
[i
].ip
)==0)
234 return(group
->list
+i
);
240 Start the scanning of the user list.
242 \return The object to pass to subsequent scanning functions or NULL
243 if it failed. The object must be freed with a call to userinfo_stop().
245 userscan
userinfo_startscan(void)
249 uscan
=malloc(sizeof(*uscan
));
250 if (!uscan
) return(NULL
);
251 uscan
->group
=first_user_group
;
257 Free the memory allocated by userinfo_start().
259 \param uscan The object created by userinfo_start().
261 void userinfo_stopscan(userscan uscan
)
267 Get the user pointed to by the object and advance the object
270 \param uscan The object created by userinfo_start().
272 \return The user in the list or NULL if the end of the list
275 struct userinfostruct
*userinfo_advancescan(userscan uscan
)
277 struct userinfostruct
*uinfo
;
279 if (!uscan
) return(NULL
);
280 if (!uscan
->group
) return(NULL
);
281 if (uscan
->index
<0 || uscan
->index
>=uscan
->group
->nusers
) return(NULL
);
283 uinfo
=uscan
->group
->list
+uscan
->index
;
286 if (uscan
->index
>=uscan
->group
->nusers
) {
287 uscan
->group
=uscan
->group
->next
;
294 Clear the general purpose flag from all the user's info.
296 void userinfo_clearflag(void)
298 struct usergroupstruct
*group
;
301 for (group
=first_user_group
; group
; group
=group
->next
) {
302 for (i
=0 ; i
<group
->nusers
; i
++)
303 group
->list
[i
].flag
=0;
308 Read the file containing the user names to alias in the report.
310 \param Filename The name of the file.
312 void read_useralias(const char *Filename
)
318 if (debug
) debuga(__FILE__
,__LINE__
,_("Reading user alias file \"%s\"\n"),Filename
);
320 UserAliases
=Alias_Create();
322 debuga(__FILE__
,__LINE__
,_("Cannot store user's aliases\n"));
326 fi
=FileObject_Open(Filename
);
328 debuga(__FILE__
,__LINE__
,_("Cannot read user name alias file \"%s\": %s\n"),Filename
,FileObject_GetLastOpenError());
332 if ((line
=longline_create())==NULL
) {
333 debuga(__FILE__
,__LINE__
,_("Not enough memory to read file \"%s\"\n"),Filename
);
337 while ((buf
=longline_read(fi
,line
)) != NULL
) {
338 if (Alias_Store(UserAliases
,buf
)<0) {
339 debuga(__FILE__
,__LINE__
,_("While reading \"%s\"\n"),Filename
);
344 longline_destroy(&line
);
345 if (FileObject_Close(fi
)) {
346 debuga(__FILE__
,__LINE__
,_("Read error in \"%s\": %s\n"),Filename
,FileObject_GetLastCloseError());
351 debuga(__FILE__
,__LINE__
,_("List of user names to alias:\n"));
352 Alias_PrintList(UserAliases
);
357 Free the memory allocated by read_useralias().
359 void free_useralias(void)
361 Alias_Destroy(&UserAliases
);
365 Replace the user's name or ID by an alias if one is defined.
367 \param user The user's name or ID as extracted from the report.
369 const char *process_user(const char *user
)
371 user
=Alias_Replace(UserAliases
,user
);