]> git.ipfire.org Git - thirdparty/sarg.git/blame - readlog_common.c
Add support to decompress xz files
[thirdparty/sarg.git] / readlog_common.c
CommitLineData
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/*!
32A new file is being read. The name of the file is \a FileName.
33*/
34static void Common_NewFile(const char *FileName)
35{
36}
37
9cf96071
FM
38/*!
39Extract a column containing a long long int from \a Line.
40
41The extracted value is stored in \a Value.
42
43The pointer to the next byte just after the number is returned
44by the function.
45*/
46static 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/*!
58Read 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*/
67static 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.
205const 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};