]> git.ipfire.org Git - thirdparty/sarg.git/blob - userinfo.c
Merge commit '6d4c97986f54adcfd0c7ec'
[thirdparty/sarg.git] / userinfo.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2011
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"
29
30 //! The number of users to group in one unit.
31 #define USERS_PER_GROUP 50
32
33 /*! \brief Group the users in one allocation unit.
34 Structure to store a group of users and reduce the number of memory
35 allocations.
36 */
37 struct usergroupstruct
38 {
39 //! The next group of users.
40 struct usergroupstruct *next;
41 //! A group of users.
42 struct userinfostruct list[USERS_PER_GROUP];
43 //! The number of users stored in the list.
44 int nusers;
45 };
46
47 /*! \brief Hold pointer to scan through the user list.
48 */
49 struct userscanstruct
50 {
51 //! The group containing the user.
52 struct usergroupstruct *group;
53 //! The index of the user in the group.
54 int index;
55 };
56
57 //! The first group of users.
58 static struct usergroupstruct *first_user_group=NULL;
59 //! The counter to generate unique user number when ::AnonymousOutputFiles is set.
60 static int AnonymousCounter=0;
61
62 struct userinfostruct *userinfo_create(const char *userid)
63 {
64 struct usergroupstruct *group, *last;
65 struct userinfostruct *user;
66 int i, j, lastuser;
67 int skip;
68 int flen;
69 int count, clen;
70 char cstr[9];
71
72 last=NULL;
73 for (group=first_user_group ; group ; group=group->next) {
74 if (group->nusers<USERS_PER_GROUP) break;
75 last=group;
76 }
77
78 if (!group) {
79 group=malloc(sizeof(*group));
80 if (!group) {
81 debuga(_("Not enough memory to store the user\n"));
82 exit(EXIT_FAILURE);
83 }
84 memset(group,0,sizeof(*group));
85 if (last)
86 last->next=group;
87 else
88 first_user_group=group;
89 }
90 user=group->list+group->nusers++;
91
92 strncpy(user->id,userid,MAX_USER_LEN-1);
93 user->id[MAX_USER_LEN-1]='\0';
94
95 if (AnonymousOutputFiles) {
96 snprintf(user->filename,sizeof(user->filename),"%d",AnonymousCounter++);
97 } else {
98 skip=0;
99 j=0;
100 for (i=0 ; userid[i] && j<MAX_USER_FNAME_LEN-1 ; i++) {
101 if (isalnum(userid[i]) || userid[i]=='-' || userid[i]=='_') {
102 user->filename[j++]=userid[i];
103 skip=0;
104 } else {
105 if (!skip) {
106 user->filename[j++]='_';
107 skip=1;
108 }
109 }
110 }
111 user->filename[j]='\0';
112 flen=i;
113
114 count=0;
115 for (group=first_user_group ; group ; group=group->next) {
116 lastuser=(group->next) ? group->nusers : group->nusers-1;
117 for (i=0 ; i<lastuser ; i++) {
118 if (strcasecmp(user->filename,group->list[i].filename)==0) {
119 clen=sprintf(cstr,"-%04X",count++);
120 if (flen+clen<MAX_USER_FNAME_LEN)
121 strcpy(user->filename+flen,cstr);
122 else
123 strcpy(user->filename+MAX_USER_FNAME_LEN-clen,cstr);
124 }
125 }
126 }
127 }
128
129 return(user);
130 }
131
132 void userinfo_free(void)
133 {
134 struct usergroupstruct *group, *next;
135
136 for (group=first_user_group ; group ; group=next) {
137 next=group->next;
138 free(group);
139 }
140 first_user_group=NULL;
141 }
142
143 struct userinfostruct *userinfo_find_from_file(const char *filename)
144 {
145 struct usergroupstruct *group;
146 int i;
147
148 for (group=first_user_group ; group ; group=group->next) {
149 for (i=0 ; i<group->nusers ; i++)
150 if (strcmp(filename,group->list[i].filename)==0)
151 return(group->list+i);
152 }
153 return(NULL);
154 }
155
156 struct userinfostruct *userinfo_find_from_id(const char *id)
157 {
158 struct usergroupstruct *group;
159 int i;
160
161 for (group=first_user_group ; group ; group=group->next) {
162 for (i=0 ; i<group->nusers ; i++)
163 if (strcmp(id,group->list[i].id)==0)
164 return(group->list+i);
165 }
166 return(NULL);
167 }
168
169 /*!
170 Start the scanning of the user list.
171
172 \return The object to pass to subsequent scanning functions or NULL
173 if it failed. The object must be freed with a call to userinfo_stop().
174 */
175 userscan userinfo_startscan(void)
176 {
177 userscan uscan;
178
179 uscan=malloc(sizeof(*uscan));
180 if (!uscan) return(NULL);
181 uscan->group=first_user_group;
182 uscan->index=0;
183 return(uscan);
184 }
185
186 /*!
187 Free the memory allocated by userinfo_start().
188
189 \param uscan The object created by userinfo_start().
190 */
191 void userinfo_stopscan(userscan uscan)
192 {
193 free(uscan);
194 }
195
196 /*!
197 Get the user pointed to by the object and advance the object
198 to the next user.
199
200 \param uscan The object created by userinfo_start().
201
202 \return The user in the list or NULL if the end of the list
203 is reached.
204 */
205 struct userinfostruct *userinfo_advancescan(userscan uscan)
206 {
207 struct userinfostruct *uinfo;
208
209 if (!uscan) return(NULL);
210 if (!uscan->group) return(NULL);
211 if (uscan->index<0 || uscan->index>=uscan->group->nusers) return(NULL);
212
213 uinfo=uscan->group->list+uscan->index;
214
215 ++uscan->index;
216 if (uscan->index>=uscan->group->nusers) {
217 uscan->group=uscan->group->next;
218 uscan->index=0;
219 }
220 return(uinfo);
221 }