00001
00002
00003 #include <string>
00004 #include <ctype.h>
00005 #include "logrecord.h"
00006 #include "date.h"
00007
00008
00009 bool
00010 LogRecord::parse_line(const string& line) {
00011
00012
00013
00014 path_.clear();
00015 domain_.clear();
00016
00017
00018
00019
00020 return parse_date(line) && parse_path(line) && parse_domain(line);
00021 }
00022
00023
00024 bool
00025 LogRecord::parse_date(const string& line) {
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 string::size_type date_start(line.find_first_of('['));
00036 string::size_type date_end(line.find_first_of(' ',date_start));
00037 string date_string(line,date_start+1,date_end - date_start-1);
00038
00039
00040
00041
00042
00043
00044
00045 for (string::size_type i=0; i<date_string.size(); ++i)
00046 if (date_string[i]=='/')
00047 date_string[i] = '-';
00048
00049
00050
00051
00052
00053 date_string.replace(date_string.find_first_of(':'),1," ");
00054
00055
00056
00057
00058
00059 try {
00060 Date date(date_string);
00061 date_ = date;
00062
00063 date_.minutes(0);
00064 date_.seconds(0);
00065 }
00066 catch (exception& e) {
00067 cerr << "parse_date: " << e.what() << endl;
00068 return false;
00069 }
00070 return true;
00071 }
00072
00074
00075
00076 static inline int
00077 hexdigit(char c) {
00078 if (isdigit(c))
00079 return c - '0';
00080 else if (isupper(c))
00081 return c - 'A' + 10;
00082 else
00083 return c - 'a' +10;
00084 }
00085
00086
00087 void
00088 www_decode(string& s) {
00089 unsigned int i(0);
00090 unsigned int j(0);
00091 unsigned int len(s.size());
00092 for (i=0; (i<len); ++i,++j)
00093 switch (s[i]) {
00094
00095 case '%':
00096 if ((i+2<len) && isxdigit(s[i+1]) && isxdigit(s[i+2])) {
00097 s[j] = hexdigit(s[i+1])* 16 + hexdigit(s[i+2]);
00098 i += 2;
00099 }
00100 else
00101 s[j] = s[i];
00102 break;
00103 default: s[j] = s[i]; break;
00104 }
00105 s.resize(j);
00106 }
00108
00109
00110 bool
00111 LogRecord::parse_path(const string& line) {
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121 string::size_type path_start(line.find_first_of('\"'));
00122 if (path_start==string::npos)
00123 return false;
00124
00125
00126
00127
00128
00129 path_start = line.find_first_of(' ',path_start);
00130 if (path_start==string::npos)
00131 return false;
00132 ++path_start;
00133
00134
00135
00136
00137
00138
00139 string::size_type path_end = line.find_first_of("#? ",path_start);
00140 if (path_end==string::npos)
00141 return false;
00142
00143 if (path_end==path_start)
00144 return false;
00145
00146 string path_string(line,path_start,path_end - path_start);
00147
00148
00149 www_decode(path_string);
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 string::size_type n0(path_string.find_first_not_of('/'));
00160
00161 if (n0!=0)
00162 path_.push_back("");
00163
00164 if (n0==string::npos)
00165 return true;
00166
00167 string::size_type n1(string::npos);
00168
00169
00170
00171
00172
00173 while ((n1=path_string.find_first_of('/',n0))!=string::npos) {
00174 if (n1>n0)
00175 path_.push_back(path_string.substr(n0,n1-n0));
00176 n0 = n1+1;
00177 }
00178
00179 if (n0<path_string.size())
00180 path_.push_back(path_string.substr(n0));
00181 return true;
00182 }
00183
00184
00185 bool
00186 LogRecord::parse_domain(const string& line) {
00187
00188
00189
00190
00191
00192
00193 string::size_type domain_start(0);
00194 string::size_type domain_end(line.find_first_of(' '));
00195 if (domain_end==string::npos)
00196 return false;
00197 string domain_string(line,domain_start,domain_end);
00198
00199 string::size_type n0(domain_string.find_first_not_of('.'));
00200 if (n0!=0)
00201 return false;
00202 string::size_type n1(string::npos);
00203
00204 while ((n1 = domain_string.find_first_of('.',n0)) != string::npos) {
00205 if (n1>n0)
00206 domain_.push_back(domain_string.substr(n0,n1-n0));
00207 n0 = n1+1;
00208 }
00209
00210 if (n0<domain_string.size())
00211 domain_.push_back(domain_string.substr(n0));
00212
00213 return true;
00214 }