]>
Commit | Line | Data |
---|---|---|
1c91da07 FM |
1 | /* |
2 | * SARG Squid Analysis Report Generator http://sarg.sourceforge.net | |
110ce984 | 3 | * 1998, 2015 |
1c91da07 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" | |
f83d7b44 | 29 | #include "include/readlog.h" |
1c91da07 FM |
30 | |
31 | /*! | |
32 | A new file is being read. The name of the file is \a FileName. | |
33 | */ | |
34 | static void Common_NewFile(const char *FileName) | |
35 | { | |
36 | } | |
37 | ||
9cf96071 FM |
38 | /*! |
39 | Extract a column containing a long long int from \a Line. | |
40 | ||
41 | The extracted value is stored in \a Value. | |
42 | ||
43 | The pointer to the next byte just after the number is returned | |
44 | by the function. | |
45 | */ | |
46 | static char *Common_GetLongLongInt(char *Line,long long int *Value) | |
47 | { | |
48 | *Value=0LL; | |
49 | if (*Line=='-') { | |
50 | ++Line; | |
51 | } else { | |
52 | while (isdigit(*Line)) *Value=*Value*10+(*Line++-'0'); | |
53 | } | |
54 | return(Line); | |
55 | } | |
56 | ||
1c91da07 FM |
57 | /*! |
58 | Read one entry from a standard squid log format. | |
59 | ||
60 | \param Line One line from the input log file. | |
61 | \param Entry Where to store the information parsed from the line. | |
62 | ||
63 | \retval RLRC_NoError One valid entry is parsed. | |
64 | \retval RLRC_Unknown The line is invalid. | |
65 | \retval RLRC_InternalError An internal error was encountered. | |
66 | */ | |
67 | static enum ReadLogReturnCodeEnum Common_ReadEntry(char *Line,struct ReadLogStruct *Entry) | |
68 | { | |
69 | const char *Begin; | |
70 | int IpLen; | |
71 | int HttpCodeLen; | |
72 | int UrlLen; | |
73 | int UserLen; | |
74 | int Day; | |
75 | char MonthName[4]; | |
76 | int MonthNameLen; | |
77 | int Month; | |
78 | int Year; | |
79 | int Hour; | |
80 | int Minute; | |
81 | int Second; | |
f83d7b44 | 82 | char *Ip; |
7799ec8d | 83 | char *User; |
1c91da07 FM |
84 | |
85 | // get IP address | |
f83d7b44 | 86 | Entry->Ip=Ip=Line; |
1c91da07 FM |
87 | for (IpLen=0 ; *Line && *Line!=' ' ; IpLen++) Line++; |
88 | if (*Line!=' ' || IpLen==0) return(RLRC_Unknown); | |
89 | ||
90 | if (!squid24) { | |
91 | // squid version <= 2.4 store the user ID in the second column: skip the first column here | |
92 | Begin=++Line; | |
93 | while (*Line && *Line!=' ') Line++; | |
94 | if (*Line!=' '|| Line==Begin) return(RLRC_Unknown); | |
95 | } | |
96 | ||
97 | // the ID of the user or - if the user is unidentified | |
7799ec8d | 98 | Entry->User=User=++Line; |
1c91da07 FM |
99 | for (UserLen=0 ; *Line && *Line!=' ' ; UserLen++) Line++; |
100 | if (*Line!=' ' || UserLen==0) return(RLRC_Unknown); | |
b902df7e | 101 | |
1c91da07 FM |
102 | if (squid24) { |
103 | // squid version > 2.4 store the user ID in the first column: skip the second column here | |
104 | Begin=++Line; | |
105 | while (*Line && *Line!=' ') Line++; | |
106 | if (*Line!=' '|| Line==Begin) return(RLRC_Unknown); | |
107 | } | |
108 | ||
109 | // get the date enclosed within square brackets | |
110 | ++Line; | |
111 | if (*Line!='[') return(RLRC_Unknown); | |
112 | ++Line; | |
113 | Day=0; | |
114 | while (isdigit(*Line)) Day=Day*10+(*Line++-'0'); | |
115 | if (*Line!='/' || Day<1 || Day>31) return(RLRC_Unknown); | |
116 | ||
117 | ++Line; | |
118 | for (MonthNameLen=0 ; MonthNameLen<sizeof(MonthName)-1 && isalpha(*Line) ; MonthNameLen++) MonthName[MonthNameLen]=*Line++; | |
119 | if (*Line!='/') return(RLRC_Unknown); | |
120 | MonthName[MonthNameLen]='\0'; | |
121 | Month=month2num(MonthName); | |
122 | if (Month>=12) return(RLRC_Unknown); | |
123 | ||
124 | ++Line; | |
125 | Year=0; | |
126 | while (isdigit(*Line)) Year=Year*10+(*Line++-'0'); | |
127 | if (*Line!=':' || Year<1900 || Year>2200) return(RLRC_Unknown); | |
b902df7e | 128 | |
1c91da07 FM |
129 | // get the time |
130 | ++Line; | |
131 | Hour=0; | |
132 | while (isdigit(*Line)) Hour=Hour*10+(*Line++-'0'); | |
133 | if (*Line!=':' || Hour>=24) return(RLRC_Unknown); | |
134 | ++Line; | |
135 | Minute=0; | |
136 | while (isdigit(*Line)) Minute=Minute*10+(*Line++-'0'); | |
137 | if (*Line!=':' || Minute>=60) return(RLRC_Unknown); | |
138 | ++Line; | |
139 | Second=0; | |
140 | while (isdigit(*Line)) Second=Second*10+(*Line++-'0'); | |
141 | if (*Line!=' ' || Second>60) return(RLRC_Unknown); //second can be 60 due to a leap second | |
142 | ||
143 | // skip the timezone up to the closing ] | |
144 | while (*Line && *Line!=']') Line++; | |
145 | if (*Line!=']') return(RLRC_Unknown); | |
b902df7e | 146 | |
cb53374b | 147 | Entry->EntryTime.tm_year=Year-1900; |
5f43130c | 148 | Entry->EntryTime.tm_mon=Month; |
cb53374b FM |
149 | Entry->EntryTime.tm_mday=Day; |
150 | Entry->EntryTime.tm_hour=Hour; | |
151 | Entry->EntryTime.tm_min=Minute; | |
152 | Entry->EntryTime.tm_sec=Second; | |
7dbbca70 | 153 | Entry->EntryTime.tm_isdst=-1; |
1c91da07 FM |
154 | |
155 | // the URL is enclosed between double qhotes | |
156 | ++Line; | |
157 | if (*Line!=' ') return(RLRC_Unknown); | |
158 | ++Line; | |
159 | if (*Line!='\"') return(RLRC_Unknown); | |
b902df7e | 160 | |
1c91da07 FM |
161 | // skip the HTTP function |
162 | Begin=++Line; | |
163 | while (isalpha(*Line)) Line++; | |
164 | if (*Line!=' ' || Line==Begin) return(RLRC_Unknown); | |
b902df7e | 165 | |
1c91da07 FM |
166 | // get the URL |
167 | Entry->Url=++Line; | |
168 | for (UrlLen=0 ; *Line && *Line!=' ' ; UrlLen++) Line++; | |
169 | if (*Line!=' ' || UrlLen==0) return(RLRC_Unknown); | |
b902df7e | 170 | |
1c91da07 FM |
171 | // skip the HTTP/... |
172 | ++Line; | |
173 | while (*Line && *Line!='\"') Line++; | |
174 | if (*Line!='\"') return(RLRC_Unknown); | |
175 | ++Line; | |
176 | if (*Line!=' ') return(RLRC_Unknown); | |
177 | ||
178 | // get the HTTP code. | |
179 | Entry->HttpCode=++Line; | |
180 | for (HttpCodeLen=0 ; *Line && *Line!=' ' ; HttpCodeLen++) Line++; | |
181 | if (*Line!=' ' || HttpCodeLen==0) return(RLRC_Unknown); | |
b902df7e | 182 | |
1c91da07 FM |
183 | // get the number of transfered bytes. |
184 | Begin=++Line; | |
9cf96071 | 185 | Line=Common_GetLongLongInt(Line,&Entry->DataSize); |
2c46b12f FM |
186 | // some log contains more columns |
187 | if ((*Line && *Line!=' ') || Begin==Line) return(RLRC_Unknown); | |
188 | ||
7dbbca70 FM |
189 | // check the entry time |
190 | if (mktime(&Entry->EntryTime)==-1) { | |
af961877 | 191 | debuga(__FILE__,__LINE__,_("Invalid date or time found in the common log file\n")); |
7dbbca70 FM |
192 | return(RLRC_InternalError); |
193 | } | |
194 | ||
1c91da07 | 195 | // it is safe to alter the line buffer now that we are returning a valid entry |
f83d7b44 | 196 | Ip[IpLen]='\0'; |
1c91da07 FM |
197 | Entry->HttpCode[HttpCodeLen]='\0'; |
198 | Entry->Url[UrlLen]='\0'; | |
7799ec8d | 199 | User[UserLen]='\0'; |
b902df7e | 200 | |
1c91da07 FM |
201 | return(RLRC_NoError); |
202 | } | |
203 | ||
204 | //! \brief Object to read a standard common log format. | |
205 | const struct ReadLogProcessStruct ReadCommonLog= | |
206 | { | |
207 | /* TRANSLATORS: This is the name of the log format displayed when this format is detected in an input log file. */ | |
208 | N_("common log format"), | |
209 | Common_NewFile, | |
210 | Common_ReadEntry | |
211 | }; |