"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/parser.c" between
goaccess-1.7.tar.gz and goaccess-1.7.1.tar.gz

About: GoAccess is a real-time web log analyzer and interactive viewer ("text-based").

parser.c  (goaccess-1.7):parser.c  (goaccess-1.7.1)
/** /**
* parser.c -- web log parsing * parser.c -- web log parsing
* ______ ___ * ______ ___
* / ____/___ / | _____________ __________ * / ____/___ / | _____________ __________
* / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/ * / / __/ __ \/ /| |/ ___/ ___/ _ \/ ___/ ___/
* / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ ) * / /_/ / /_/ / ___ / /__/ /__/ __(__ |__ )
* \____/\____/_/ |_\___/\___/\___/____/____/ * \____/\____/_/ |_\___/\___/\___/____/____/
* *
* The MIT License (MIT) * The MIT License (MIT)
* Copyright (c) 2009-2022 Gerardo Orellana <hello @ goaccess.io> * Copyright (c) 2009-2023 Gerardo Orellana <hello @ goaccess.io>
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights * in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in al l * The above copyright notice and this permission notice shall be included in al l
* copies or substantial portions of the Software. * copies or substantial portions of the Software.
skipping to change at line 112 skipping to change at line 112
/* Reset an instance of GLog structure. */ /* Reset an instance of GLog structure. */
void void
reset_struct (Logs * logs) { reset_struct (Logs * logs) {
int i = 0; int i = 0;
for (i = 0; i < logs->size; ++i) for (i = 0; i < logs->size; ++i)
logs->glog[i].invalid = logs->glog[i].processed = 0; logs->glog[i].invalid = logs->glog[i].processed = 0;
} }
/* Allocate memory for a new Logs and GLog instance.
*
* On success, the newly allocated Logs is returned . */
Logs *
new_logs (int size) {
Logs *logs = xmalloc (sizeof (*logs));
memset (logs, 0, sizeof *logs);
logs->glog = xcalloc (size, sizeof (GLog));
logs->size = size;
logs->idx = 0;
return logs;
}
/* Allocate, initialize and add the given filename to our logs structure.
*
* On error, 1 is returned.
* On success, the given filename is added to the Logs structure and 0 is
* returned. */
int
set_glog (Logs * logs, const char *filename) {
GLog *tmp = NULL, *glog = NULL;
int newlen = 0;
char const *err;
char *fvh = NULL, *fn = (char *) filename;
if (logs->size - 1 < logs->idx) {
newlen = logs->size + 1;
if (!(tmp = xrealloc (logs->glog, newlen * sizeof (GLog))))
return ERR_LOG_REALLOC_FAILURE;
logs->glog = tmp;
memset (logs->glog + logs->idx, 0, (logs->idx + 1 - logs->size) * sizeof *lo
gs->glog);
logs->size = newlen;
}
glog = logs->glog;
glog[logs->idx].errors = xcalloc (MAX_LOG_ERRORS, sizeof (char *));
glog[logs->idx].filename = xstrdup (fn);
glog[logs->idx].fname = xstrdup (basename (fn));
if (!glog->pipe && conf.fname_as_vhost) {
if (!(fvh = regex_extract_string (glog[logs->idx].fname, conf.fname_as_vhost
, 1, &err)))
FATAL ("%s %s[%s]", err, glog[logs->idx].fname, conf.fname_as_vhost);
glog[logs->idx].fname_as_vhost = fvh;
}
logs->processed = &(glog[logs->idx].processed);
logs->filename = glog[logs->idx].filename;
logs->idx++;
return 0;
}
/* Ensure the given filename is part of our original list of files.
*
* On error, 1 is returned.
* On success, the given filename is added to the Logs structure and 0 is
* returned. */
int
set_log (Logs * logs, const char *value) {
if (str_inarray (value, conf.filenames, conf.filenames_idx) < 0)
return ERR_LOG_NOT_FOUND;
return set_glog (logs, value);
}
/* Allocate memory for a new set of Logs including a GLog instance. /* Allocate memory for a new set of Logs including a GLog instance.
* *
* On success, the newly allocated Logs is returned . */ * On success, the newly allocated Logs is returned . */
Logs * Logs *
init_logs (int size) { init_logs (int size) {
Logs *logs = NULL; Logs *logs = NULL;
GLog *glog = NULL; GLog *glog = NULL;
char *fvh = NULL; int i = 0, ret = 0;
char const *err;
int i = 0;
/* if no logs no a pipe nor restoring, nothing to do then */ /* if no logs no a pipe nor restoring, nothing to do then */
if (!size && !conf.restore) if (!size && !conf.restore)
return NULL; return NULL;
/* If no logs nor a pipe but restoring, we still need an minimal instance of /* If no logs nor a pipe but restoring, we still need an minimal instance of
* logs and a glog */ * logs and a glog */
logs = xcalloc (1, sizeof (*logs));
if (!size) { if (!size) {
logs = xcalloc (1, sizeof (*logs));
logs->glog = xcalloc (1, sizeof (*glog)); logs->glog = xcalloc (1, sizeof (*glog));
logs->processed = &(logs->glog[0].processed); logs->processed = &(logs->glog[0].processed);
return logs; return logs;
} }
glog = xcalloc (size, sizeof (*glog)); logs = new_logs (size);
for (i = 0; i < size; ++i) { logs->size = size;
glog[i].errors = xcalloc (MAX_LOG_ERRORS, sizeof (char *));
glog[i].filename = xstrdup (conf.filenames[i]);
glog[i].fname = xstrdup (basename (glog[i].filename));
if (!glog->pipe && conf.fname_as_vhost) {
if (!(fvh = regex_extract_string (glog[i].fname, conf.fname_as_vhost, 1, &
err)))
FATAL ("%s %s[%s]", err, glog[i].fname, conf.fname_as_vhost);
glog[i].fname_as_vhost = fvh;
}
logs->processed = &(glog[i].processed); for (i = 0; i < size; ++i) {
logs->filename = glog[i].filename; if ((ret = set_log (logs, conf.filenames[i])))
FATAL ("%s\n", ERR_LOG_NOT_FOUND_MSG);
} }
logs->glog = glog;
logs->size = size;
return logs; return logs;
} }
/* Free all log errors stored during parsing. */ /* Free all log errors stored during parsing. */
void void
free_logerrors (GLog * glog) { free_logerrors (GLog * glog) {
int i; int i;
if (!glog->log_erridx) if (!glog->log_erridx)
return; return;
skipping to change at line 787 skipping to change at line 843
* of it. * of it.
* *
* On success, a malloc'd error message is assigned to the log * On success, a malloc'd error message is assigned to the log
* structure and 1 is returned. */ * structure and 1 is returned. */
static int static int
spec_err (GLogItem * logitem, int code, const char spec, const char *tkn) { spec_err (GLogItem * logitem, int code, const char spec, const char *tkn) {
char *err = NULL; char *err = NULL;
const char *fmt = NULL; const char *fmt = NULL;
switch (code) { switch (code) {
case SPEC_TOKN_NUL: case ERR_SPEC_TOKN_NUL:
fmt = "Token for '%%%c' specifier is NULL."; fmt = "Token for '%%%c' specifier is NULL.";
err = xmalloc (snprintf (NULL, 0, fmt, spec) + 1); err = xmalloc (snprintf (NULL, 0, fmt, spec) + 1);
sprintf (err, fmt, spec); sprintf (err, fmt, spec);
break; break;
case SPEC_TOKN_INV: case ERR_SPEC_TOKN_INV:
fmt = "Token '%s' doesn't match specifier '%%%c'"; fmt = "Token '%s' doesn't match specifier '%%%c'";
err = xmalloc (snprintf (NULL, 0, fmt, (tkn ? tkn : "-"), spec) + 1); err = xmalloc (snprintf (NULL, 0, fmt, (tkn ? tkn : "-"), spec) + 1);
sprintf (err, fmt, (tkn ? tkn : "-"), spec); sprintf (err, fmt, (tkn ? tkn : "-"), spec);
break; break;
case SPEC_SFMT_MIS: case ERR_SPEC_SFMT_MIS:
fmt = "Missing braces '%s' and ignore chars for specifier '%%%c'"; fmt = "Missing braces '%s' and ignore chars for specifier '%%%c'";
err = xmalloc (snprintf (NULL, 0, fmt, (tkn ? tkn : "-"), spec) + 1); err = xmalloc (snprintf (NULL, 0, fmt, (tkn ? tkn : "-"), spec) + 1);
sprintf (err, fmt, (tkn ? tkn : "-"), spec); sprintf (err, fmt, (tkn ? tkn : "-"), spec);
break; break;
case SPEC_LINE_INV: case ERR_SPEC_LINE_INV:
fmt = "Incompatible format due to early parsed line ending '\\0'."; fmt = "Incompatible format due to early parsed line ending '\\0'.";
err = xmalloc (snprintf (NULL, 0, fmt, (tkn ? tkn : "-")) + 1); err = xmalloc (snprintf (NULL, 0, fmt, (tkn ? tkn : "-")) + 1);
sprintf (err, fmt, (tkn ? tkn : "-")); sprintf (err, fmt, (tkn ? tkn : "-"));
break; break;
} }
logitem->errstr = err; logitem->errstr = err;
return code; return code;
} }
skipping to change at line 880 skipping to change at line 936
/* Attempt to parse date format containing spaces, /* Attempt to parse date format containing spaces,
* i.e., syslog date format (Jul\s15, Nov\s\s2). * i.e., syslog date format (Jul\s15, Nov\s\s2).
* Note that it's possible a date could contain some padding, e.g., * Note that it's possible a date could contain some padding, e.g.,
* Dec\s\s2 vs Nov\s22, so we attempt to take that into consideration by loo king * Dec\s\s2 vs Nov\s22, so we attempt to take that into consideration by loo king
* ahead the log string and counting the # of spaces until we find an alphan um char. */ * ahead the log string and counting the # of spaces until we find an alphan um char. */
if ((fmtspcs = count_matches (dfmt, ' ')) && (pch = strchr (*str, ' '))) if ((fmtspcs = count_matches (dfmt, ' ')) && (pch = strchr (*str, ' ')))
dspc = find_alpha_count (pch); dspc = find_alpha_count (pch);
if (!(tkn = parse_string (&(*str), end, MAX (dspc, fmtspcs) + 1))) if (!(tkn = parse_string (&(*str), end, MAX (dspc, fmtspcs) + 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
if (str_to_time (tkn, dfmt, &tm, 1) != 0 || set_date (&logitem->date, tm) != 0) { if (str_to_time (tkn, dfmt, &tm, 1) != 0 || set_date (&logitem->date, tm) != 0) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
set_numeric_date (&logitem->numdate, logitem->date); set_numeric_date (&logitem->numdate, logitem->date);
set_tm_dt_logitem (logitem, tm); set_tm_dt_logitem (logitem, tm);
free (tkn); free (tkn);
break; break;
/* time */ /* time */
case 't': case 't':
if (logitem->time) if (logitem->time)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
if (str_to_time (tkn, tfmt, &tm, 1) != 0 || set_time (&logitem->time, tm) != 0) { if (str_to_time (tkn, tfmt, &tm, 1) != 0 || set_time (&logitem->time, tm) != 0) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
set_tm_tm_logitem (logitem, tm); set_tm_tm_logitem (logitem, tm);
free (tkn); free (tkn);
break; break;
/* date/time as decimal, i.e., timestamps, ms/us */ /* date/time as decimal, i.e., timestamps, ms/us */
case 'x': case 'x':
if (logitem->time && logitem->date) if (logitem->time && logitem->date)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
if (str_to_time (tkn, tfmt, &tm, 1) != 0 || set_date (&logitem->date, tm) != 0 || if (str_to_time (tkn, tfmt, &tm, 1) != 0 || set_date (&logitem->date, tm) != 0 ||
set_time (&logitem->time, tm) != 0) { set_time (&logitem->time, tm) != 0) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
set_numeric_date (&logitem->numdate, logitem->date); set_numeric_date (&logitem->numdate, logitem->date);
set_tm_dt_logitem (logitem, tm); set_tm_dt_logitem (logitem, tm);
set_tm_tm_logitem (logitem, tm); set_tm_tm_logitem (logitem, tm);
free (tkn); free (tkn);
break; break;
/* Virtual Host */ /* Virtual Host */
case 'v': case 'v':
if (logitem->vhost) if (logitem->vhost)
return 0; return 0;
tkn = parse_string (&(*str), end, 1); tkn = parse_string (&(*str), end, 1);
if (tkn == NULL) if (tkn == NULL)
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
logitem->vhost = tkn; logitem->vhost = tkn;
break; break;
/* remote user */ /* remote user */
case 'e': case 'e':
if (logitem->userid) if (logitem->userid)
return 0; return 0;
tkn = parse_string (&(*str), end, 1); tkn = parse_string (&(*str), end, 1);
if (tkn == NULL) if (tkn == NULL)
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
logitem->userid = tkn; logitem->userid = tkn;
break; break;
/* cache status */ /* cache status */
case 'C': case 'C':
if (logitem->cache_status) if (logitem->cache_status)
return 0; return 0;
tkn = parse_string (&(*str), end, 1); tkn = parse_string (&(*str), end, 1);
if (tkn == NULL) if (tkn == NULL)
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
if (is_cache_hit (tkn)) if (is_cache_hit (tkn))
logitem->cache_status = tkn; logitem->cache_status = tkn;
else else
free (tkn); free (tkn);
break; break;
/* remote hostname (IP only) */ /* remote hostname (IP only) */
case 'h': case 'h':
if (logitem->host) if (logitem->host)
return 0; return 0;
/* per https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2 */ /* per https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2 */
/* square brackets are possible */ /* square brackets are possible */
if (*str[0] == '[' && (*str += 1) && **str) if (*str[0] == '[' && (*str += 1) && **str)
end = "]"; end = "]";
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
if (!conf.no_ip_validation && invalid_ipaddr (tkn, &logitem->type_ip)) { if (!conf.no_ip_validation && invalid_ipaddr (tkn, &logitem->type_ip)) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
/* require a valid host token (e.g., ord38s18-in-f14.1e100.net) even when we 're /* require a valid host token (e.g., ord38s18-in-f14.1e100.net) even when we 're
* not validating the IP */ * not validating the IP */
if (conf.no_ip_validation && *tkn == '\0') { if (conf.no_ip_validation && *tkn == '\0') {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
logitem->host = tkn; logitem->host = tkn;
break; break;
/* request method */ /* request method */
case 'm': case 'm':
if (logitem->method) if (logitem->method)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
{ {
const char *meth = NULL; const char *meth = NULL;
if (!(meth = extract_method (tkn))) { if (!(meth = extract_method (tkn))) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
logitem->method = xstrdup (meth); logitem->method = xstrdup (meth);
free (tkn); free (tkn);
} }
break; break;
/* request not including method or protocol */ /* request not including method or protocol */
case 'U': case 'U':
if (logitem->req) if (logitem->req)
return 0; return 0;
tkn = parse_string (&(*str), end, 1); tkn = parse_string (&(*str), end, 1);
if (tkn == NULL || *tkn == '\0') { if (tkn == NULL || *tkn == '\0') {
free (tkn); free (tkn);
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
} }
if ((logitem->req = decode_url (tkn)) == NULL) { if ((logitem->req = decode_url (tkn)) == NULL) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
free (tkn); free (tkn);
break; break;
/* query string alone, e.g., ?param=goaccess&tbm=shop */ /* query string alone, e.g., ?param=goaccess&tbm=shop */
case 'q': case 'q':
if (logitem->qstr) if (logitem->qstr)
return 0; return 0;
tkn = parse_string (&(*str), end, 1); tkn = parse_string (&(*str), end, 1);
if (tkn == NULL || *tkn == '\0') { if (tkn == NULL || *tkn == '\0') {
free (tkn); free (tkn);
return 0; return 0;
} }
if ((logitem->qstr = decode_url (tkn)) == NULL) { if ((logitem->qstr = decode_url (tkn)) == NULL) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
free (tkn); free (tkn);
break; break;
/* request protocol */ /* request protocol */
case 'H': case 'H':
if (logitem->protocol) if (logitem->protocol)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
{ {
const char *proto = NULL; const char *proto = NULL;
if (!(proto = extract_protocol (tkn))) { if (!(proto = extract_protocol (tkn))) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
logitem->protocol = xstrdup (proto); logitem->protocol = xstrdup (proto);
free (tkn); free (tkn);
} }
break; break;
/* request, including method + protocol */ /* request, including method + protocol */
case 'r': case 'r':
if (logitem->req) if (logitem->req)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
logitem->req = parse_req (tkn, &logitem->method, &logitem->protocol); logitem->req = parse_req (tkn, &logitem->method, &logitem->protocol);
free (tkn); free (tkn);
break; break;
/* Status Code */ /* Status Code */
case 's': case 's':
if (logitem->status) if (logitem->status)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
/* do not validate HTTP status code */ /* do not validate HTTP status code */
if (conf.no_strict_status) { if (conf.no_strict_status) {
logitem->status = tkn; logitem->status = tkn;
break; break;
} }
status = strtol (tkn, &sEnd, 10); status = strtol (tkn, &sEnd, 10);
if (tkn == sEnd || *sEnd != '\0' || errno == ERANGE || status < 100 || statu s > 599) { if (tkn == sEnd || *sEnd != '\0' || errno == ERANGE || status < 100 || statu s > 599) {
spec_err (logitem, SPEC_TOKN_INV, *p, tkn); spec_err (logitem, ERR_SPEC_TOKN_INV, *p, tkn);
free (tkn); free (tkn);
return 1; return 1;
} }
logitem->status = tkn; logitem->status = tkn;
break; break;
/* size of response in bytes - excluding HTTP headers */ /* size of response in bytes - excluding HTTP headers */
case 'b': case 'b':
if (logitem->resp_size) if (logitem->resp_size)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
bandw = strtoull (tkn, &bEnd, 10); bandw = strtoull (tkn, &bEnd, 10);
if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE) if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE)
bandw = 0; bandw = 0;
logitem->resp_size = bandw; logitem->resp_size = bandw;
conf.bandwidth = 1; conf.bandwidth = 1;
free (tkn); free (tkn);
break; break;
/* referrer */ /* referrer */
case 'R': case 'R':
skipping to change at line 1151 skipping to change at line 1207
} }
logitem->agent = tkn; logitem->agent = tkn;
set_agent_hash (logitem); set_agent_hash (logitem);
break; break;
/* time taken to serve the request, in milliseconds as a decimal number */ /* time taken to serve the request, in milliseconds as a decimal number */
case 'L': case 'L':
/* ignore it if we already have served time */ /* ignore it if we already have served time */
if (logitem->serve_time) if (logitem->serve_time)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
serve_secs = strtoull (tkn, &bEnd, 10); serve_secs = strtoull (tkn, &bEnd, 10);
if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE) if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE)
serve_secs = 0; serve_secs = 0;
/* convert it to microseconds */ /* convert it to microseconds */
logitem->serve_time = (serve_secs > 0) ? serve_secs * MILS : 0; logitem->serve_time = (serve_secs > 0) ? serve_secs * MILS : 0;
contains_usecs (); /* set flag */ contains_usecs (); /* set flag */
free (tkn); free (tkn);
break; break;
/* time taken to serve the request, in seconds with a milliseconds /* time taken to serve the request, in seconds with a milliseconds
* resolution */ * resolution */
case 'T': case 'T':
/* ignore it if we already have served time */ /* ignore it if we already have served time */
if (logitem->serve_time) if (logitem->serve_time)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
if (strchr (tkn, '.') != NULL) if (strchr (tkn, '.') != NULL)
serve_secs = strtod (tkn, &bEnd); serve_secs = strtod (tkn, &bEnd);
else else
serve_secs = strtoull (tkn, &bEnd, 10); serve_secs = strtoull (tkn, &bEnd, 10);
if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE) if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE)
serve_secs = 0; serve_secs = 0;
/* convert it to microseconds */ /* convert it to microseconds */
logitem->serve_time = (serve_secs > 0) ? serve_secs * SECS : 0; logitem->serve_time = (serve_secs > 0) ? serve_secs * SECS : 0;
contains_usecs (); /* set flag */ contains_usecs (); /* set flag */
free (tkn); free (tkn);
break; break;
/* time taken to serve the request, in microseconds */ /* time taken to serve the request, in microseconds */
case 'D': case 'D':
/* ignore it if we already have served time */ /* ignore it if we already have served time */
if (logitem->serve_time) if (logitem->serve_time)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
serve_time = strtoull (tkn, &bEnd, 10); serve_time = strtoull (tkn, &bEnd, 10);
if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE) if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE)
serve_time = 0; serve_time = 0;
logitem->serve_time = serve_time; logitem->serve_time = serve_time;
contains_usecs (); /* set flag */ contains_usecs (); /* set flag */
free (tkn); free (tkn);
break; break;
/* time taken to serve the request, in nanoseconds */
case 'n':
/* ignore it if we already have served time */
if (logitem->serve_time)
return 0;
if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
serve_time = strtoull (tkn, &bEnd, 10);
if (tkn == bEnd || *bEnd != '\0' || errno == ERANGE)
serve_time = 0;
/* convert it to microseconds */
logitem->serve_time = (serve_time > 0) ? serve_time / MILS : 0;
contains_usecs (); /* set flag */
free (tkn);
break;
/* UMS: Krypto (TLS) "ECDHE-RSA-AES128-GCM-SHA256" */ /* UMS: Krypto (TLS) "ECDHE-RSA-AES128-GCM-SHA256" */
case 'k': case 'k':
/* error to set this twice */ /* error to set this twice */
if (logitem->tls_cypher) if (logitem->tls_cypher)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
#if defined(HAVE_LIBSSL) && defined(HAVE_CIPHER_STD_NAME) #if defined(HAVE_LIBSSL) && defined(HAVE_CIPHER_STD_NAME)
{ {
char *tmp = NULL; char *tmp = NULL;
for (tmp = tkn; isdigit (*tmp); tmp++); for (tmp = tkn; isdigit (*tmp); tmp++);
if (!strlen (tmp)) if (!strlen (tmp))
extract_tls_version_cipher (tkn, &logitem->tls_cypher, &logitem->tls_typ e); extract_tls_version_cipher (tkn, &logitem->tls_cypher, &logitem->tls_typ e);
else else
logitem->tls_cypher = tkn; logitem->tls_cypher = tkn;
} }
skipping to change at line 1230 skipping to change at line 1303
#endif #endif
break; break;
/* UMS: Krypto (TLS) parameters like "TLSv1.2" */ /* UMS: Krypto (TLS) parameters like "TLSv1.2" */
case 'K': case 'K':
/* error to set this twice */ /* error to set this twice */
if (logitem->tls_type) if (logitem->tls_type)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
logitem->tls_type = tkn; logitem->tls_type = tkn;
break; break;
/* UMS: Mime-Type like "text/html" */ /* UMS: Mime-Type like "text/html" */
case 'M': case 'M':
/* error to set this twice */ /* error to set this twice */
if (logitem->mime_type) if (logitem->mime_type)
return 0; return 0;
if (!(tkn = parse_string (&(*str), end, 1))) if (!(tkn = parse_string (&(*str), end, 1)))
return spec_err (logitem, SPEC_TOKN_NUL, *p, NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, *p, NULL);
logitem->mime_type = tkn; logitem->mime_type = tkn;
break; break;
/* move forward through str until not a space */ /* move forward through str until not a space */
case '~': case '~':
find_alpha (&(*str)); find_alpha (&(*str));
break; break;
/* everything else skip it */ /* everything else skip it */
default: default:
skipping to change at line 1361 skipping to change at line 1434
* *
* If no IP is found, 1 is returned. * If no IP is found, 1 is returned.
* On success, the malloc'd token is assigned to a GLogItem->host and 0 is retur ned. */ * On success, the malloc'd token is assigned to a GLogItem->host and 0 is retur ned. */
static int static int
find_xff_host (GLogItem * logitem, char **str, char **p) { find_xff_host (GLogItem * logitem, char **str, char **p) {
char *skips = NULL, *extract = NULL; char *skips = NULL, *extract = NULL;
char pch[2] = { 0 }; char pch[2] = { 0 };
int res = 0; int res = 0;
if (!(skips = extract_braces (p))) if (!(skips = extract_braces (p)))
return spec_err (logitem, SPEC_SFMT_MIS, **p, "{}"); return spec_err (logitem, ERR_SPEC_SFMT_MIS, **p, "{}");
/* if the log format current char is not within the braces special chars, then /* if the log format current char is not within the braces special chars, then
* we assume the range of IPs are within hard delimiters */ * we assume the range of IPs are within hard delimiters */
if (!strchr (skips, **p) && strchr (*str, **p)) { if (!strchr (skips, **p) && strchr (*str, **p)) {
strcpy (pch, (char[2]) { (char) **p, '\0' }); strcpy (pch, (char[2]) { (char) **p, '\0' });
if (!(extract = parse_string (&(*str), pch, 1))) if (!(extract = parse_string (&(*str), pch, 1)))
goto clean; goto clean;
if (!(res = set_xff_host (logitem, &extract, skips, 1))) if (!(res = set_xff_host (logitem, &extract, skips, 1)))
free (extract); free (extract);
skipping to change at line 1394 skipping to change at line 1467
* *
* On error, or unable to parse it, 1 is returned. * On error, or unable to parse it, 1 is returned.
* On success, the malloc'd token is assigned to a GLogItem member and * On success, the malloc'd token is assigned to a GLogItem member and
* 0 is returned. */ * 0 is returned. */
static int static int
special_specifier (GLogItem * logitem, char **str, char **p) { special_specifier (GLogItem * logitem, char **str, char **p) {
switch (**p) { switch (**p) {
/* XFF remote hostname (IP only) */ /* XFF remote hostname (IP only) */
case 'h': case 'h':
if (find_xff_host (logitem, str, p)) if (find_xff_host (logitem, str, p))
return spec_err (logitem, SPEC_TOKN_NUL, 'h', NULL); return spec_err (logitem, ERR_SPEC_TOKN_NUL, 'h', NULL);
break; break;
} }
return 0; return 0;
} }
/* Iterate over the given log format. /* Iterate over the given log format.
* *
* On error, or unable to parse it, 1 is returned. * On error, or unable to parse it, 1 is returned.
* On success, the malloc'd token is assigned to a GLogItem member and * On success, the malloc'd token is assigned to a GLogItem member and
skipping to change at line 1426 skipping to change at line 1499
for (p = lfmt; *p; p++) { for (p = lfmt; *p; p++) {
if (*p == '%') { if (*p == '%') {
perc++; perc++;
continue; continue;
} }
if (*p == '~' && perc == 0) { if (*p == '~' && perc == 0) {
tilde++; tilde++;
continue; continue;
} }
if (*str == '\0') if (*str == '\0')
return spec_err (logitem, SPEC_LINE_INV, '-', NULL); return spec_err (logitem, ERR_SPEC_LINE_INV, '-', NULL);
if (*str == '\n') if (*str == '\n')
return 0; return 0;
if (tilde && *p != '\0') { if (tilde && *p != '\0') {
if (*str == '\0') if (*str == '\0')
return 0; return 0;
if (special_specifier (logitem, &str, &p) == 1) if (special_specifier (logitem, &str, &p) == 1)
return 1; return 1;
tilde = 0; tilde = 0;
} }
 End of changes. 46 change blocks. 
58 lines changed or deleted 132 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)