]> git.ipfire.org Git - thirdparty/sarg.git/blob - userinfo.c
Check the release date when archiving the project
[thirdparty/sarg.git] / userinfo.c
1 /*
2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
3 * 1998, 2013
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,const char *ip)
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 safe_strcpy(user->id,userid,sizeof(user->id));
93
94 if (AnonymousOutputFiles) {
95 snprintf(user->filename,sizeof(user->filename),"%d",AnonymousCounter++);
96 } else {
97 skip=0;
98 j=0;
99 for (i=0 ; userid[i] && j<MAX_USER_FNAME_LEN-1 ; i++) {
100 if (isalnum(userid[i]) || userid[i]=='-' || userid[i]=='_') {
101 user->filename[j++]=userid[i];
102 skip=0;
103 } else {
104 if (!skip) {
105 user->filename[j++]='_';
106 skip=1;
107 }
108 }
109 }
110 if (j==0) user->filename[j++]='_'; //don't leave a file name empty
111 flen=j;
112 user->filename[j]='\0';
113 strncpy(user->ip,ip,sizeof(user->ip)-1);
114 user->ip[sizeof(user->ip)-1]='\0';
115
116 count=0;
117 for (group=first_user_group ; group ; group=group->next) {
118 lastuser=(group->next) ? group->nusers : group->nusers-1;
119 for (i=0 ; i<lastuser ; i++) {
120 if (strcasecmp(user->filename,group->list[i].filename)==0) {
121 clen=sprintf(cstr,"+%X",count++);
122 if (flen+clen<MAX_USER_FNAME_LEN)
123 strcpy(user->filename+flen,cstr);
124 else
125 strcpy(user->filename+MAX_USER_FNAME_LEN-clen,cstr);
126 }
127 }
128 }
129 }
130
131 return(user);
132 }
133
134 void userinfo_free(void)
135 {
136 struct usergroupstruct *group, *next;
137
138 for (group=first_user_group ; group ; group=next) {
139 next=group->next;
140 free(group);
141 }
142 first_user_group=NULL;
143 }
144
145 struct userinfostruct *userinfo_find_from_file(const char *filename)
146 {
147 struct usergroupstruct *group;
148 int i;
149
150 for (group=first_user_group ; group ; group=group->next) {
151 for (i=0 ; i<group->nusers ; i++)
152 if (strcmp(filename,group->list[i].filename)==0)
153 return(group->list+i);
154 }
155 return(NULL);
156 }
157
158 struct userinfostruct *userinfo_find_from_id(const char *id)
159 {
160 struct usergroupstruct *group;
161 int i;
162
163 for (group=first_user_group ; group ; group=group->next) {
164 for (i=0 ; i<group->nusers ; i++)
165 if (strcmp(id,group->list[i].id)==0)
166 return(group->list+i);
167 }
168 return(NULL);
169 }
170
171 /*!
172 Start the scanning of the user list.
173
174 \return The object to pass to subsequent scanning functions or NULL
175 if it failed. The object must be freed with a call to userinfo_stop().
176 */
177 userscan userinfo_startscan(void)
178 {
179 userscan uscan;
180
181 uscan=malloc(sizeof(*uscan));
182 if (!uscan) return(NULL);
183 uscan->group=first_user_group;
184 uscan->index=0;
185 return(uscan);
186 }
187
188 /*!
189 Free the memory allocated by userinfo_start().
190
191 \param uscan The object created by userinfo_start().
192 */
193 void userinfo_stopscan(userscan uscan)
194 {
195 free(uscan);
196 }
197
198 /*!
199 Get the user pointed to by the object and advance the object
200 to the next user.
201
202 \param uscan The object created by userinfo_start().
203
204 \return The user in the list or NULL if the end of the list
205 is reached.
206 */
207 struct userinfostruct *userinfo_advancescan(userscan uscan)
208 {
209 struct userinfostruct *uinfo;
210
211 if (!uscan) return(NULL);
212 if (!uscan->group) return(NULL);
213 if (uscan->index<0 || uscan->index>=uscan->group->nusers) return(NULL);
214
215 uinfo=uscan->group->list+uscan->index;
216
217 ++uscan->index;
218 if (uscan->index>=uscan->group->nusers) {
219 uscan->group=uscan->group->next;
220 uscan->index=0;
221 }
222 return(uinfo);
223 }
224
225 /*!
226 Clear the general purpose flag from all the user's info.
227 */
228 void userinfo_clearflag(void)
229 {
230 struct usergroupstruct *group;
231 int i;
232
233 for (group=first_user_group ; group ; group=group->next) {
234 for (i=0 ; i<group->nusers ; i++)
235 group->list[i].flag=0;
236 }
237 }
238