]> git.ipfire.org Git - thirdparty/sarg.git/blame - userinfo.c
Don't force the use of libpcre
[thirdparty/sarg.git] / userinfo.c
CommitLineData
f2ec8c75
FM
1/*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
67302a9e 3 * 1998, 2013
f2ec8c75
FM
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
9 * ---------------------------------------------------------------------
10 *
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.
15 *
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.
20 *
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.
24 *
25 */
26
27#include "include/conf.h"
28#include "include/defs.h"
b6b6cb8c 29#include "include/stringbuffer.h"
c4f0ea8f 30#include "include/alias.h"
f2ec8c75
FM
31
32//! The number of users to group in one unit.
33#define USERS_PER_GROUP 50
34
35/*! \brief Group the users in one allocation unit.
36Structure to store a group of users and reduce the number of memory
37allocations.
38*/
39struct usergroupstruct
40{
9bd92830
FM
41 //! The next group of users.
42 struct usergroupstruct *next;
43 //! A group of users.
44 struct userinfostruct list[USERS_PER_GROUP];
45 //! The number of users stored in the list.
46 int nusers;
f2ec8c75
FM
47};
48
93551487
FM
49/*! \brief Hold pointer to scan through the user list.
50*/
51struct userscanstruct
52{
53 //! The group containing the user.
54 struct usergroupstruct *group;
55 //! The index of the user in the group.
56 int index;
57};
58
f2ec8c75
FM
59//! The first group of users.
60static struct usergroupstruct *first_user_group=NULL;
829a53c2
FM
61//! The counter to generate unique user number when ::AnonymousOutputFiles is set.
62static int AnonymousCounter=0;
b6b6cb8c
FM
63//! String buffer to store the user's related constants.
64static StringBufferObject UserStrings=NULL;
c4f0ea8f
FM
65//! User aliases.
66static AliasObject UserAliases=NULL;
f2ec8c75
FM
67
68struct userinfostruct *userinfo_create(const char *userid)
69{
9bd92830
FM
70 struct usergroupstruct *group, *last;
71 struct userinfostruct *user;
d09d93c6 72 int i, j, lastuser;
9bd92830
FM
73 int skip;
74 int flen;
75 int count, clen;
76 char cstr[9];
b6b6cb8c
FM
77 char filename[MAX_USER_FNAME_LEN];
78
79 if (!UserStrings) {
80 UserStrings=StringBuffer_Create();
81 if (!UserStrings) {
82 debuga(_("Not enough memory to store the user's strings\n"));
83 exit(EXIT_FAILURE);
84 }
85 }
9bd92830
FM
86
87 last=NULL;
88 for (group=first_user_group ; group ; group=group->next) {
89 if (group->nusers<USERS_PER_GROUP) break;
90 last=group;
91 }
92
93 if (!group) {
94 group=malloc(sizeof(*group));
95 if (!group) {
b6b6cb8c 96 debuga(_("Not enough memory to store user \"%s\"\n"),userid);
9bd92830
FM
97 exit(EXIT_FAILURE);
98 }
99 memset(group,0,sizeof(*group));
100 if (last)
101 last->next=group;
102 else
103 first_user_group=group;
104 }
105 user=group->list+group->nusers++;
106
b6b6cb8c
FM
107 user->id=StringBuffer_Store(UserStrings,userid);
108 if (!user->id) {
109 debuga(_("Not enough memory to store user ID \"%s\"\n"),userid);
110 exit(EXIT_FAILURE);
111 }
112 user->label=user->id; //assign a label to avoid a NULL pointer in case none is provided
9bd92830 113
829a53c2 114 if (AnonymousOutputFiles) {
b6b6cb8c 115 snprintf(filename,sizeof(filename),"%d",AnonymousCounter++);
829a53c2
FM
116 } else {
117 skip=0;
118 j=0;
119 for (i=0 ; userid[i] && j<MAX_USER_FNAME_LEN-1 ; i++) {
120 if (isalnum(userid[i]) || userid[i]=='-' || userid[i]=='_') {
b6b6cb8c 121 filename[j++]=userid[i];
829a53c2
FM
122 skip=0;
123 } else {
124 if (!skip) {
b6b6cb8c 125 filename[j++]='_';
829a53c2
FM
126 skip=1;
127 }
9bd92830
FM
128 }
129 }
b6b6cb8c 130 if (j==0) filename[j++]='_'; //don't leave a file name empty
4754959e 131 flen=j;
b6b6cb8c 132 filename[j]='\0';
829a53c2
FM
133
134 count=0;
135 for (group=first_user_group ; group ; group=group->next) {
136 lastuser=(group->next) ? group->nusers : group->nusers-1;
137 for (i=0 ; i<lastuser ; i++) {
b6b6cb8c 138 if (strcasecmp(filename,group->list[i].filename)==0) {
4754959e 139 clen=sprintf(cstr,"+%X",count++);
829a53c2 140 if (flen+clen<MAX_USER_FNAME_LEN)
b6b6cb8c 141 strcpy(filename+flen,cstr);
829a53c2 142 else
b6b6cb8c 143 strcpy(filename+MAX_USER_FNAME_LEN-clen,cstr);
829a53c2 144 }
9bd92830
FM
145 }
146 }
147 }
b6b6cb8c
FM
148 user->filename=StringBuffer_Store(UserStrings,filename);
149 if (!user->filename)
150 {
151 debuga(_("Not enough memory to store the file name for user \"%s\"\n"),user->id);
152 exit(EXIT_FAILURE);
153 }
9bd92830
FM
154
155 return(user);
f2ec8c75
FM
156}
157
158void userinfo_free(void)
159{
9bd92830 160 struct usergroupstruct *group, *next;
f2ec8c75 161
9bd92830
FM
162 for (group=first_user_group ; group ; group=next) {
163 next=group->next;
164 free(group);
165 }
166 first_user_group=NULL;
b6b6cb8c
FM
167 StringBuffer_Destroy(&UserStrings);
168}
169
170/*!
171 * Store the user's label.
172 * \param uinfo The user info structure created by userinfo_create().
173 * \param label The string label to store.
174 */
175void userinfo_label(struct userinfostruct *uinfo,const char *label)
176{
177 if (!uinfo) return;
178 if (!UserStrings) return;
179 uinfo->label=StringBuffer_Store(UserStrings,label);
180 if (!uinfo->label) {
181 debuga(_("Not enough memory to store label \"%s\" of user \"%s\"\n"),label,uinfo->id);
182 exit(EXIT_FAILURE);
183 }
f2ec8c75
FM
184}
185
186struct userinfostruct *userinfo_find_from_file(const char *filename)
187{
9bd92830
FM
188 struct usergroupstruct *group;
189 int i;
190
191 for (group=first_user_group ; group ; group=group->next) {
192 for (i=0 ; i<group->nusers ; i++)
193 if (strcmp(filename,group->list[i].filename)==0)
194 return(group->list+i);
195 }
196 return(NULL);
f2ec8c75
FM
197}
198
199struct userinfostruct *userinfo_find_from_id(const char *id)
200{
9bd92830
FM
201 struct usergroupstruct *group;
202 int i;
203
204 for (group=first_user_group ; group ; group=group->next) {
205 for (i=0 ; i<group->nusers ; i++)
206 if (strcmp(id,group->list[i].id)==0)
207 return(group->list+i);
208 }
209 return(NULL);
f2ec8c75 210}
93551487
FM
211
212/*!
213Start the scanning of the user list.
214
215\return The object to pass to subsequent scanning functions or NULL
216if it failed. The object must be freed with a call to userinfo_stop().
217*/
218userscan userinfo_startscan(void)
219{
220 userscan uscan;
221
222 uscan=malloc(sizeof(*uscan));
223 if (!uscan) return(NULL);
224 uscan->group=first_user_group;
225 uscan->index=0;
226 return(uscan);
227}
228
229/*!
230Free the memory allocated by userinfo_start().
231
232\param uscan The object created by userinfo_start().
233*/
234void userinfo_stopscan(userscan uscan)
235{
236 free(uscan);
237}
238
239/*!
240Get the user pointed to by the object and advance the object
241to the next user.
242
243\param uscan The object created by userinfo_start().
244
245\return The user in the list or NULL if the end of the list
246is reached.
247*/
248struct userinfostruct *userinfo_advancescan(userscan uscan)
249{
250 struct userinfostruct *uinfo;
251
252 if (!uscan) return(NULL);
253 if (!uscan->group) return(NULL);
254 if (uscan->index<0 || uscan->index>=uscan->group->nusers) return(NULL);
255
256 uinfo=uscan->group->list+uscan->index;
257
258 ++uscan->index;
259 if (uscan->index>=uscan->group->nusers) {
260 uscan->group=uscan->group->next;
261 uscan->index=0;
262 }
263 return(uinfo);
264}
a58e6d54
FM
265
266/*!
267Clear the general purpose flag from all the user's info.
268*/
269void userinfo_clearflag(void)
270{
271 struct usergroupstruct *group;
272 int i;
273
274 for (group=first_user_group ; group ; group=group->next) {
275 for (i=0 ; i<group->nusers ; i++)
276 group->list[i].flag=0;
277 }
278}
279
c4f0ea8f
FM
280/*!
281Read the file containing the user names to alias in the report.
282
283\param Filename The name of the file.
284*/
285void read_useralias(const char *Filename)
286{
287 FILE *fi;
288 longline line;
289 char *buf;
290
291 if (debug) debuga(_("Reading user alias file \"%s\"\n"),Filename);
292
293 UserAliases=Alias_Create();
294 if (!UserAliases) {
295 debuga(_("Cannot store user's aliases\n"));
296 exit(EXIT_FAILURE);
297 }
298
299 fi=fopen(Filename,"rt");
300 if (!fi) {
301 debuga(_("Cannot read user name alias file \"%s\" - %s\n"),Filename,strerror(errno));
302 exit(EXIT_FAILURE);
303 }
304
305 if ((line=longline_create())==NULL) {
306 debuga(_("Not enough memory to read the user name aliases\n"));
307 exit(EXIT_FAILURE);
308 }
309
310 while ((buf=longline_read(fi,line)) != NULL) {
311 if (Alias_Store(UserAliases,buf)<0) {
312 debuga(_("While reading \"%s\"\n"),Filename);
313 exit(EXIT_FAILURE);
314 }
315 }
316
317 longline_destroy(&line);
318 fclose(fi);
319
320 if (debug) {
321 debuga(_("List of user names to alias:\n"));
322 Alias_PrintList(UserAliases);
323 }
324}
325
326/*!
327Free the memory allocated by read_useralias().
328*/
329void free_useralias(void)
330{
331 Alias_Destroy(&UserAliases);
332}
333
334/*!
335Replace the user's name or ID by an alias if one is defined.
336
337\param user The user's name or ID as extracted from the report.
338*/
339const char *process_user(const char *user)
340{
341 user=Alias_Replace(UserAliases,user);
342 return(user);
343}