Direcionando log Squid para banco MySQL

Este artigo traz algumas explicações sobre o LOG do Squid e como direcioná-lo para o banco de dados MySQL.

[ Hits: 87.749 ]

Por: Filipe Binat Gallo em 26/11/2007


Editando o access_log.c



Acesse com seu editor de textos o arquivo access_log.c que está dentro da pasta src. Logo no início do arquivo inclua as seguintes linhas:

#include "squid.h"
#include <mysql/mysql.h>
#include <stdlib.h>
#include <stdio.h>

char insertSQL[400];
char intconvstr[5];
int res;
MYSQL conexao;

Aqui estamos incluindo as bibliotecas e declarando as variáveis necessárias para fazermos os inserts no banco. Agora procure no arquivo pelas seguintes linhas...

if (user && !*user)
        safe_free(user);
    if (!Config.onoff.log_mime_hdrs) {

... ao encontrá-las substitua todo o código até o fecha chave correto do if } pelo seguinte:

if (!Config.onoff.log_mime_hdrs) {
            strcpy(insertSQL,"INSERT INTO logSquid( date, clientIP, tags_HIT_MISS, http_code, cache_size, private_method_str,
            strcat(insertSQL,client);
            strcat(insertSQL,"','");
            strcat(insertSQL,log_tags[al->cache.code]);
            strcat(insertSQL,"','");
            snprintf(intconvstr,3,"%d",al->http.code);
            strcat(insertSQL,intconvstr);                
            strcat(insertSQL,"','");
            snprintf(intconvstr,11,"%d",al->cache.size);
            strcat(insertSQL,intconvstr);
            strcat(insertSQL,"','");
            strcat(insertSQL,al->private.method_str);
            strcat(insertSQL,"','");
            strcat(insertSQL,al->url);
            strcat(insertSQL,"','");
            strcat(insertSQL,user ? user : dash_str);
            strcat(insertSQL,"');");

            mysql_init(&conexao);
            if ( mysql_real_connect(&conexao, "localhost", "proxy", "proxy", "proxy", 0, NULL, 0) )
            {
                res = mysql_query(&conexao,insertSQL);
                if (res)
                     logfilePrintf(logfile,"Erro na inserção %d : %s\n%s", mysql_errno(&conexao), mysql_error(&conexao),insertSQL)
                mysql_close(&conexao);

            }
            else
            {
                logfilePrintf(logfile,"Falha de conexao\n");
                logfilePrintf(logfile,"Erro %d : %s\n", mysql_errno(&conexao), mysql_error(&conexao));
            }

Muita atenção para ver onde se abre e fecha as chaves { }.

Vamos então entender o que estamos fazendo, a função logfilePrintf() é a responsável por escrever uma string dentro do arquivo de log, assim repare que estamos utilizando ela para inserir no arquivo de log caso não seja possível fazer a inserção no banco.

res = mysql_query(&conexao,insertSQL);
                if (res)
                     logfilePrintf(logfile,"Erro na inserção %d : %s\n%s", mysql_errno(&conexao), mysql_error(&conexao),nsertSQL)
                mysql_close(&conexao);

A função strcpy(insertSQL,"... irá copiar a instrução SQL com os campos da tabela para a variável insertSQL, a partir dai note que temos diversos strcat(insertSQL ... que tem a função concatenar na variável insertSQL os valores que seriam inseridos no log.

Vale lembrar que alguns valores são recebidos como sendo do tipo inteiro, por isso em alguns casos foi necessário utilizar a função snprintf(intconvstr,11,"%d",al->cache.size), como no exemplo, para converter os valores para string.

Agora acesse o arquivo squid.h, dentro da mesma da pasta src e adicione a seguinte linha.

#include "config.h"
#include <mysql/mysql.h>

Para que possamos compilar com as bibliotecas de acesso ao MYSQL.

Página anterior     Próxima página

Páginas do artigo
   1. Entendendo o log do Squid
   2. Preparando os aplicativos necessários
   3. Editando o access_log.c
   4. Compilando o Squid
   5. Conclusões
Outros artigos deste autor

Postfix - Integração AD e autenticação

Leitura recomendada

Implementação de um proxy/cache para ganho de conexão

DansGuardian versões 2.9.3.0 e superiores em Debian 5.01

Squid - Entendendo um pouco as configurações

Servidor Ubuntu 8.04 com proxy autenticado + SARG + Samba + CUPS

Recebendo relatório do SARG via e-mail (Gmail)

  
Comentários
[1] Comentário enviado por wellcastellani em 26/11/2007 - 14:30h

Muito util esta solução, vlw pela contribuição!

[2] Comentário enviado por agk em 26/11/2007 - 16:18h

Muito bom, parabéns, mas vejo um pequeno problema nisso, como que vai ficar o tamanho do banco depois de uns 3 meses ou daqui 1 ano?

Teria que ter um esquema de rotação ou dump em dvd mensal e limpeza do banco.

São algumas idéias, mas o projeto é bom, realmente parabéns pela iniciativa.

[3] Comentário enviado por balani em 26/11/2007 - 17:46h

Cara, vc acertou na veia, é isso que eu estava procurando, muito bom, isso sera muito util para mim, obrigado pela contribuição!!

[4] Comentário enviado por m@verick em 26/11/2007 - 18:39h

Bem lembrado agk, estarei fazendo uma pesquisa e nas proximas semanas estarei postando um script para isso

[5] Comentário enviado por balani em 11/12/2007 - 08:56h

Bom dia, sua solução é oque eu estou querendo, porem, ao aplica-la apresentou o seguinte erro:
access_log.c: In function 'accessLogSquid':
access_log.c:1033: error: missing terminating " character
access_log.c:1034: error: expected ')' before ';' token
access_log.c:1066: error: expected ';' before '}' token
access_log.c:1070: error: invalid storage class for function 'accessLogCommon'
access_log.c:1271: error: expected declaration or statement at end of input
make[3]: *** [access_log.o] Error 1
make[3]: Leaving directory `/usr/src/Squid+htb/squid-2.6.STABLE17/src'
make[2]: *** [all-recursive] Error 1
make[2]: Leaving directory `/usr/src/Squid+htb/squid-2.6.STABLE17/src'
make[1]: *** [all] Error 2
make[1]: Leaving directory `/usr/src/Squid+htb/squid-2.6.STABLE17/src'
make: *** [all-recursive] Error 1

Se vc poder me ajudar, ficarei muito grato.

[6] Comentário enviado por m@verick em 11/12/2007 - 12:52h

Balani, por favor poste todo o seu arquivo accesslog.c para que eu possa dar uma olhada.
Deve ser algo na ordem em que foi inserido o codigo para gerar a string SQL.
Ok Obrigdo

[7] Comentário enviado por balani em 12/12/2007 - 11:16h

Olá amigo, obrigado pela atenção, abaixo segue o codigo:

/*
* $Id: access_log.c,v 1.95.2.2 2007/06/03 00:40:32 hno Exp $
*
* DEBUG: section 46 Access Log
* AUTHOR: Duane Wessels
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
* Squid is the result of efforts by numerous individuals from
* the Internet community; see the CONTRIBUTORS file for full
* details. Many organizations have provided support for Squid's
* development; see the SPONSORS file for full details. Squid is
* Copyrighted (C) 2001 by the Regents of the University of
* California; see the COPYRIGHT file for full details. Squid
* incorporates software developed and/or copyrighted by other
* sources; see the CREDITS file for full details.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/


#include "squid.h"
#include <mysql/mysql.h>
#include <stdlib.h>
#include <stdio.h>

char insertSQL[400];
char intconvstr[5];
int res;
MYSQL conexao;

#if HEADERS_LOG
static Logfile *headerslog = NULL;
#endif

#if MULTICAST_MISS_STREAM
static int mcast_miss_fd = -1;
static struct sockaddr_in mcast_miss_to;
static void mcast_encode(unsigned int *, size_t, const unsigned int *);
#endif

#if FORW_VIA_DB
typedef struct {
hash_link hash;
int n;
} fvdb_entry;
static hash_table *via_table = NULL;
static hash_table *forw_table = NULL;
static void fvdbInit(void);
static void fvdbDumpTable(StoreEntry * e, hash_table * hash);
static void fvdbCount(hash_table * hash, const char *key);
static OBJH fvdbDumpVia;
static OBJH fvdbDumpForw;
static FREE fvdbFreeEntry;
static void fvdbClear(void);
#endif

static int LogfileStatus = LOG_DISABLE;
#define LOG_BUF_SZ (MAX_URL<<2)

static const char c2x[] =
"000102030405060708090a0b0c0d0e0f"
"101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f"
"303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f"
"505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f"
"707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f"
"909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";

/* log_quote -- URL-style encoding on MIME headers. */

char *
log_quote(const char *header)
{
int c;
int i;
char *buf;
char *buf_cursor;
if (header == NULL) {
buf = xcalloc(1, 1);
*buf = '{COMENTARIO}';
return buf;
}
buf = xcalloc(1, (strlen(header) * 3) + 1);
buf_cursor = buf;
/*
* We escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF
* which is the default escape list for the CPAN Perl5 URI module
* modulo the inclusion of space (x40) to make the raw logs a bit
* more readable.
*/
while ((c = *(const unsigned char *) header++) != '{COMENTARIO}') {
#if !OLD_LOG_MIME
if (c == '\r') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'r';
} else if (c == '\n') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'n';
} else
#endif
if (c <= 0x1F
|| c >= 0x7F
|| c == '%'
#if OLD_LOG_MIME
|| c == '"'
|| c == '#'
|| c == ';'
|| c == '<'
|| c == '>'
|| c == '?'
|| c == '{'
|| c == '}'
|| c == '|'
|| c == '\\'
|| c == '^'
|| c == '~'
|| c == '`'
#endif
|| c == '['
|| c == ']') {
*buf_cursor++ = '%';
i = c * 2;
*buf_cursor++ = c2x[i];
*buf_cursor++ = c2x[i + 1];
#if !OLD_LOG_MIME
} else if (c == '\\') {
*buf_cursor++ = '\\';
*buf_cursor++ = '\\';
#endif
} else {
*buf_cursor++ = (char) c;
}
}
*buf_cursor = '{COMENTARIO}';
return buf;
}

static char *
username_quote(const char *header)
/* copy of log_quote. Bugs there will be found here */
{
int c;
int i;
char *buf;
char *buf_cursor;
if (header == NULL) {
buf = xcalloc(1, 1);
*buf = '{COMENTARIO}';
return buf;
}
buf = xcalloc(1, (strlen(header) * 3) + 1);
buf_cursor = buf;
/*
* We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF
* to prevent garbage in the logs. CR and LF are also there just in case.
*/
while ((c = *(const unsigned char *) header++) != '{COMENTARIO}') {
if (c == '\r') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'r';
} else if (c == '\n') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'n';
} else if (c <= 0x1F
|| c >= 0x7F
|| c == '%'
|| c == ' ') {
*buf_cursor++ = '%';
i = c * 2;
*buf_cursor++ = c2x[i];
*buf_cursor++ = c2x[i + 1];
} else {
*buf_cursor++ = (char) c;
}
}
*buf_cursor = '{COMENTARIO}';
return buf;
}

static char *
accessLogFormatName(const char *name)
{
if (NULL == name)
return NULL;
if (name[0] == '{COMENTARIO}')
return NULL;
return username_quote(name);
}

static char *
log_quoted_string(const char *str)
{
char *out = xmalloc(strlen(str) * 2 + 1);
char *p = out;
while (*str) {
int l = strcspn(str, "\"\\\r\n\t");
memcpy(p, str, l);
str += l;
p += l;
switch (*str) {
case '{COMENTARIO}':
break;
case '\r':
*p++ = '\\';
*p++ = 'r';
str++;
break;
case '\n':
*p++ = '\\';
*p++ = 'n';
str++;
break;
case '\t':
*p++ = '\\';
*p++ = 't';
str++;
break;
default:
*p++ = '\\';
*p++ = *str;
str++;
break;
}
}
*p++ = '{COMENTARIO}';
return out;
}

/*
* Bytecodes for the configureable logformat stuff
*/
typedef enum {
LFT_NONE, /* dummy */
LFT_STRING,

LFT_CLIENT_IP_ADDRESS,
LFT_CLIENT_FQDN,
LFT_CLIENT_PORT,

/*LFT_SERVER_IP_ADDRESS, */
LFT_SERVER_IP_OR_PEER_NAME,
/*LFT_SERVER_PORT, */

LFT_LOCAL_IP,
LFT_LOCAL_PORT,
/*LFT_LOCAL_NAME, */

LFT_TIME_SECONDS_SINCE_EPOCH,
LFT_TIME_SUBSECOND,
LFT_TIME_LOCALTIME,
LFT_TIME_GMT,
LFT_TIME_TO_HANDLE_REQUEST,

LFT_REQUEST_HEADER,
LFT_REQUEST_HEADER_ELEM,
LFT_REQUEST_ALL_HEADERS,

LFT_REPLY_HEADER,
LFT_REPLY_HEADER_ELEM,
LFT_REPLY_ALL_HEADERS,

LFT_USER_NAME,
LFT_USER_LOGIN,
/*LFT_USER_REALM, */
/*LFT_USER_SCHEME, */
LFT_USER_IDENT,
LFT_USER_EXT,
#if USE_SSL
LFT_USER_SSL,
#endif

LFT_HTTP_CODE,
/*LFT_HTTP_STATUS, */

LFT_SQUID_STATUS,
/*LFT_SQUID_ERROR, */
LFT_SQUID_HIERARCHY,

LFT_MIME_TYPE,

LFT_REQUEST_METHOD,
LFT_REQUEST_URI,
/*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */
LFT_REQUEST_VERSION,

LFT_REQUEST_SIZE_TOTAL,
/*LFT_REQUEST_SIZE_LINE, */
/*LFT_REQUEST_SIZE_HEADERS, */
/*LFT_REQUEST_SIZE_BODY, */
/*LFT_REQUEST_SIZE_BODY_NO_TE, */

LFT_REPLY_SIZE_TOTAL,
/*LFT_REPLY_SIZE_LINE, */
/*LFT_REPLY_SIZE_HEADERS, */
/*LFT_REPLY_SIZE_BODY, */
/*LFT_REPLY_SIZE_BODY_NO_TE, */

LFT_IO_SIZE_TOTAL,

LFT_EXT_LOG,

LFT_PERCENT /* special string cases for escaped chars */
} logformat_bcode_t;

enum log_quote {
LOG_QUOTE_NONE = 0,
LOG_QUOTE_QUOTES,
LOG_QUOTE_BRAKETS,
LOG_QUOTE_URL,
LOG_QUOTE_RAW
};
struct _logformat_token {
logformat_bcode_t type;
union {
char *string;
struct {
char *header;
char *element;
char separator;
} header;
char *timespec;
} data;
unsigned char width;
unsigned char precision;
enum log_quote quote:3;
unsigned int left:1;
unsigned int space:1;
unsigned int zero:1;
int divisor;
logformat_token *next; /* todo: move from linked list to array */
};

struct logformat_token_table_entry {
const char *config;
logformat_bcode_t token_type;
int options;
};

struct logformat_token_table_entry logformat_token_table[] =
{

{">a", LFT_CLIENT_IP_ADDRESS},
{">p", LFT_CLIENT_PORT},
{">A", LFT_CLIENT_FQDN},

/*{ "<a", LFT_SERVER_IP_ADDRESS }, */
/*{ "<p", LFT_SERVER_PORT }, */
{"<A", LFT_SERVER_IP_OR_PEER_NAME},

{"la", LFT_LOCAL_IP},
{"lp", LFT_LOCAL_PORT},
/*{ "lA", LFT_LOCAL_NAME }, */

{"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
{"tu", LFT_TIME_SUBSECOND},
{"tl", LFT_TIME_LOCALTIME},
{"tg", LFT_TIME_GMT},
{"tr", LFT_TIME_TO_HANDLE_REQUEST},

{">h", LFT_REQUEST_HEADER},
{">h", LFT_REQUEST_ALL_HEADERS},
{"<h", LFT_REPLY_HEADER},
{"<h", LFT_REPLY_ALL_HEADERS},

{"un", LFT_USER_NAME},
{"ul", LFT_USER_LOGIN},
/*{ "ur", LFT_USER_REALM }, */
/*{ "us", LFT_USER_SCHEME }, */
{"ui", LFT_USER_IDENT},
#if USE_SSL
{"us", LFT_USER_SSL},
#endif
{"ue", LFT_USER_EXT},

{"Hs", LFT_HTTP_CODE},
/*{ "Ht", LFT_HTTP_STATUS }, */

{"Ss", LFT_SQUID_STATUS},
/*{ "Se", LFT_SQUID_ERROR }, */
{"Sh", LFT_SQUID_HIERARCHY},

{"mt", LFT_MIME_TYPE},

{"rm", LFT_REQUEST_METHOD},
{"ru", LFT_REQUEST_URI}, /* doesn't include the query-string */
/* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
{">v", LFT_REQUEST_VERSION},
{"rv", LFT_REQUEST_VERSION},

{">st", LFT_REQUEST_SIZE_TOTAL},
/*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */
/*{ ">sh", LFT_REQUEST_SIZE_HEADERS }, */
/*{ ">sb", LFT_REQUEST_SIZE_BODY }, */
/*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */

{"<st", LFT_REPLY_SIZE_TOTAL},
/*{ "<sl", LFT_REPLY_SIZE_LINE }, * / / * the reply line (protocol, code, text) */
/*{ "<sh", LFT_REPLY_SIZE_HEADERS }, */
/*{ "<sb", LFT_REPLY_SIZE_BODY }, */
/*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */

{"st", LFT_IO_SIZE_TOTAL},

{"ea", LFT_EXT_LOG},

{"%", LFT_PERCENT},

{NULL, LFT_NONE} /* this must be last */
};

static void
accessLogCustom(AccessLogEntry * al, customlog * log)
{
logformat *lf;
Logfile *logfile;
logformat_token *fmt;
static MemBuf mb = MemBufNULL;
char tmp[1024];
String sb = StringNull;

memBufReset(&mb);

lf = log->logFormat;
logfile = log->logfile;
for (fmt = lf->format; fmt != NULL; fmt = fmt->next) { /* for each token */
const char *out = NULL;
int quote = 0;
long int outint = 0;
int doint = 0;
int dofree = 0;
switch (fmt->type) {
case LFT_NONE:
out = "";
break;
case LFT_STRING:
out = fmt->data.string;
break;
case LFT_CLIENT_IP_ADDRESS:
out = inet_ntoa(al->cache.caddr);
break;

case LFT_CLIENT_FQDN:
out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
if (!out)
out = inet_ntoa(al->cache.caddr);
break;

case LFT_CLIENT_PORT:
if (al->request) {
outint = al->request->client_port;
doint = 1;
}
break;

/* case LFT_SERVER_IP_ADDRESS: */

case LFT_SERVER_IP_OR_PEER_NAME:
out = al->hier.host;
break;

/* case LFT_SERVER_PORT: */

case LFT_LOCAL_IP:
if (al->request)
out = inet_ntoa(al->request->my_addr);
break;

case LFT_LOCAL_PORT:
if (al->request) {
outint = al->request->my_port;
doint = 1;
}
break;

case LFT_TIME_SECONDS_SINCE_EPOCH:
outint = current_time.tv_sec;
doint = 1;
break;

case LFT_TIME_SUBSECOND:
outint = current_time.tv_usec / fmt->divisor;
doint = 1;
break;


case LFT_TIME_LOCALTIME:
case LFT_TIME_GMT:
{
const char *spec;
struct tm *t;
spec = fmt->data.timespec;
if (!spec)
spec = "%d/%b/%Y:%H:%M:%S %z";
if (fmt->type == LFT_TIME_LOCALTIME)
t = localtime(&squid_curtime);
else
t = gmtime(&squid_curtime);
strftime(tmp, sizeof(tmp), spec, t);
out = tmp;
}
break;

case LFT_TIME_TO_HANDLE_REQUEST:
outint = al->cache.msec;
doint = 1;
break;

case LFT_REQUEST_HEADER:
if (al->request)
sb = httpHeaderGetByName(&al->request->header, fmt->data.header.header);
out = strBuf(sb);
quote = 1;
break;

case LFT_REPLY_HEADER:
if (al->reply)
sb = httpHeaderGetByName(&al->reply->header, fmt->data.header.header);
out = strBuf(sb);
quote = 1;
break;

case LFT_REQUEST_HEADER_ELEM:
if (al->request)
sb = httpHeaderGetByNameListMember(&al->request->header, fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
out = strBuf(sb);
quote = 1;
break;

case LFT_REPLY_HEADER_ELEM:
if (al->reply)
sb = httpHeaderGetByNameListMember(&al->reply->header, fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
out = strBuf(sb);
quote = 1;
break;

case LFT_REQUEST_ALL_HEADERS:
out = al->headers.request;
quote = 1;
break;

case LFT_REPLY_ALL_HEADERS:
out = al->headers.reply;
quote = 1;
break;

case LFT_USER_NAME:
out = al->cache.authuser;
if (!out || !*out)
out = al->cache.rfc931;
#if USE_SSL
if (!out || !*out)
out = al->cache.ssluser;
#endif
quote = 1;
break;

case LFT_USER_LOGIN:
out = al->cache.authuser;
quote = 1;
break;

case LFT_USER_IDENT:
out = al->cache.rfc931;
quote = 1;
break;

/* case LFT_USER_REALM: */
/* case LFT_USER_SCHEME: */

#if USE_SSL
case LFT_USER_SSL:
out = al->cache.ssluser;
quote = 1;
break;
#endif

case LFT_USER_EXT:
if (al->request)
out = strBuf(al->request->extacl_log);
quote = 1;
break;

case LFT_HTTP_CODE:
outint = al->http.code;
doint = 1;
break;

/* case LFT_HTTP_STATUS:
* out = statusline->text;
* quote = 1;
* break;
*/

case LFT_SQUID_STATUS:
out = log_tags[al->cache.code];
break;

/* case LFT_SQUID_ERROR: */

case LFT_SQUID_HIERARCHY:
if (al->hier.ping.timedout)
memBufAppend(&mb, "TIMEOUT_", 8);
out = hier_strings[al->hier.code];
break;

case LFT_MIME_TYPE:
out = al->http.content_type;
break;

case LFT_REQUEST_METHOD:
out = al->private.method_str;
break;

case LFT_REQUEST_URI:
out = al->url;
break;

case LFT_REQUEST_VERSION:
snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
out = tmp;
break;

case LFT_REQUEST_SIZE_TOTAL:
outint = al->cache.rq_size;
doint = 1;
break;
/*case LFT_REQUEST_SIZE_LINE: */
/*case LFT_REQUEST_SIZE_HEADERS: */
/*case LFT_REQUEST_SIZE_BODY: */
/*case LFT_REQUEST_SIZE_BODY_NO_TE: */

case LFT_REPLY_SIZE_TOTAL:
outint = al->cache.size;
doint = 1;
break;

/*case LFT_REPLY_SIZE_LINE: */
/*case LFT_REPLY_SIZE_HEADERS: */
/*case LFT_REPLY_SIZE_BODY: */
/*case LFT_REPLY_SIZE_BODY_NO_TE: */

case LFT_IO_SIZE_TOTAL:
outint = al->cache.size + al->cache.rq_size;
doint = 1;
break;

case LFT_EXT_LOG:
if (al->request)
out = strBuf(al->request->extacl_log);

quote = 1;
break;

case LFT_PERCENT:
out = "%";
break;
}

if (doint) {
snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
out = tmp;
}
if (out && *out) {
if (quote || fmt->quote != LOG_QUOTE_NONE) {
char *newout = NULL;
int newfree = 0;
switch (fmt->quote) {
case LOG_QUOTE_NONE:
newout = rfc1738_escape_unescaped(out);
break;
case LOG_QUOTE_QUOTES:
newout = log_quoted_string(out);
newfree = 1;
break;
case LOG_QUOTE_BRAKETS:
newout = log_quote(out);
newfree = 1;
break;
case LOG_QUOTE_URL:
newout = rfc1738_escape(out);
break;
case LOG_QUOTE_RAW:
break;
}
if (newout) {
if (dofree)
safe_free(out);
out = newout;
dofree = newfree;
}
}
if (fmt->width) {
if (fmt->left)
memBufPrintf(&mb, "%-*s", (int) fmt->width, out);
else
memBufPrintf(&mb, "%*s", (int) fmt->width, out);
} else
memBufAppend(&mb, out, strlen(out));
} else {
memBufAppend(&mb, "-", 1);
}
if (fmt->space)
memBufAppend(&mb, " ", 1);
stringClean(&sb);
if (dofree)
safe_free(out);
}
logfilePrintf(logfile, "%s\n", mb.buf);
}

/* parses a single token. Returns the token length in characters,
* and fills in the lt item with the token information.
* def is for sure null-terminated
*/
static int
accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote)
{
char *cur = def;
struct logformat_token_table_entry *lte;
int l;

memset(lt, 0, sizeof(*lt));
l = strcspn(cur, "%");
if (l > 0) {
char *cp;
/* it's a string for sure, until {COMENTARIO} or the next % */
cp = xmalloc(l + 1);
xstrncpy(cp, cur, l + 1);
lt->type = LFT_STRING;
lt->data.string = cp;
while (l > 0) {
switch (*cur) {
case '"':
if (*quote == LOG_QUOTE_NONE)
*quote = LOG_QUOTE_QUOTES;
else if (*quote == LOG_QUOTE_QUOTES)
*quote = LOG_QUOTE_NONE;
break;
case '[':
if (*quote == LOG_QUOTE_NONE)
*quote = LOG_QUOTE_BRAKETS;
break;
case ']':
if (*quote == LOG_QUOTE_BRAKETS)
*quote = LOG_QUOTE_NONE;
break;
}
cur++;
l--;
}
goto done;
}
if (!*cur)
goto done;
cur++;
switch (*cur) {
case '"':
lt->quote = LOG_QUOTE_QUOTES;
cur++;
break;
case '\'':
lt->quote = LOG_QUOTE_RAW;
cur++;
break;
case '[':
lt->quote = LOG_QUOTE_BRAKETS;
cur++;
break;
case '#':
lt->quote = LOG_QUOTE_URL;
cur++;
break;
default:
lt->quote = *quote;
break;
}
if (*cur == '-') {
lt->left = 1;
cur++;
}
if (*cur == '0') {
lt->zero = 1;
cur++;
}
if (xisdigit(*cur))
lt->width = strtol(cur, &cur, 10);
if (*cur == '.')
lt->precision = strtol(cur + 1, &cur, 10);
if (*cur == '{') {
char *cp;
cur++;
l = strcspn(cur, "}");
cp = xmalloc(l + 1);
xstrncpy(cp, cur, l + 1);
lt->data.string = cp;
cur += l;
if (*cur == '}')
cur++;
}
lt->type = LFT_NONE;
for (lte = logformat_token_table; lte->config != NULL; lte++) {
if (strncmp(lte->config, cur, strlen(lte->config)) == 0) {
lt->type = lte->token_type;
cur += strlen(lte->config);
break;
}
}
if (lt->type == LFT_NONE) {
fatalf("Can't parse configuration token: '%s'\n",
def);
}
if (*cur == ' ') {
lt->space = 1;
cur++;
}
done:
switch (lt->type) {
case LFT_REQUEST_HEADER:
case LFT_REPLY_HEADER:
if (lt->data.string) {
char *header = lt->data.string;
char *cp = strchr(header, ':');
if (cp) {
*cp++ = '{COMENTARIO}';
if (*cp == ',' || *cp == ';' || *cp == ':')
lt->data.header.separator = *cp++;
else
lt->data.header.separator = ',';
lt->data.header.element = cp;
lt->type = (lt->type == LFT_REQUEST_HEADER) ?
LFT_REQUEST_HEADER_ELEM :
LFT_REPLY_HEADER_ELEM;
}
lt->data.header.header = header;
} else {
lt->type = (lt->type == LFT_REQUEST_HEADER) ?
LFT_REQUEST_ALL_HEADERS :
LFT_REPLY_ALL_HEADERS;
Config.onoff.log_mime_hdrs = 1;
}
break;
case LFT_CLIENT_FQDN:
Config.onoff.log_fqdn = 1;
break;
case LFT_TIME_SUBSECOND:
lt->divisor = 1000;
if (lt->precision) {
int i;
lt->divisor = 1000000;
for (i = lt->precision; i > 1; i--)
lt->divisor /= 10;
if (!lt->divisor)
lt->divisor = 0;
}
break;
default:
break;
}
return (cur - def);
}

int
accessLogParseLogFormat(logformat_token ** fmt, char *def)
{
char *cur, *eos;
logformat_token *new_lt, *last_lt;
enum log_quote quote = LOG_QUOTE_NONE;

debug(46, 1) ("accessLogParseLogFormat: got definition '%s'\n", def);

/* very inefficent parser, but who cares, this needs to be simple */
/* First off, let's tokenize, we'll optimize in a second pass.
* A token can either be a %-prefixed sequence (usually a dynamic
* token but it can be an escaped sequence), or a string. */
cur = def;
eos = def + strlen(def);
*fmt = new_lt = last_lt = xmalloc(sizeof(logformat_token));
cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
while (cur < eos) {
new_lt = xmalloc(sizeof(logformat_token));
last_lt->next = new_lt;
last_lt = new_lt;
cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
}
return 1;
}

void
accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions)
{
logformat_token *t;
logformat *format;
struct logformat_token_table_entry *te;
debug(46, 4) ("accessLogDumpLogFormat called\n");

for (format = definitions; format; format = format->next) {
debug(46, 4) ("Dumping logformat definition for %s\n", format->name);
storeAppendPrintf(entry, "logformat %s ", format->name);
for (t = format->format; t; t = t->next) {
if (t->type == LFT_STRING)
storeAppendPrintf(entry, "%s", t->data.string);
else {
char argbuf[256];
char *arg = NULL;
logformat_bcode_t type = t->type;

switch (type) {
/* special cases */
case LFT_STRING:
break;
case LFT_REQUEST_HEADER_ELEM:
case LFT_REPLY_HEADER_ELEM:
if (t->data.header.separator != ',')
snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
else
snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);

arg = argbuf;
type = (type == LFT_REQUEST_HEADER_ELEM) ?
LFT_REQUEST_HEADER :
LFT_REPLY_HEADER;
break;

case LFT_REQUEST_ALL_HEADERS:
case LFT_REPLY_ALL_HEADERS:
type = (type == LFT_REQUEST_ALL_HEADERS) ?
LFT_REQUEST_HEADER :
LFT_REPLY_HEADER;
break;

default:
if (t->data.string)
arg = t->data.string;
break;
}
storeAppend(entry, "%", 1);
switch (t->quote) {
case LOG_QUOTE_QUOTES:
storeAppend(entry, "\"", 1);
break;
case LOG_QUOTE_BRAKETS:
storeAppend(entry, "[", 1);
break;
case LOG_QUOTE_URL:
storeAppend(entry, "#", 1);
break;
case LOG_QUOTE_RAW:
storeAppend(entry, "'", 1);
break;
case LOG_QUOTE_NONE:
break;
}
if (t->left)
storeAppend(entry, "-", 1);
if (t->zero)
storeAppend(entry, "0", 1);
if (t->width)
storeAppendPrintf(entry, "%d", (int) t->width);
if (t->precision)
storeAppendPrintf(entry, ".%d", (int) t->precision);
if (arg)
storeAppendPrintf(entry, "{%s}", arg);
for (te = logformat_token_table; te->config != NULL; te++) {
if (te->token_type == t->type) {
storeAppendPrintf(entry, "%s", te->config);
break;
}
}
if (t->space)
storeAppend(entry, " ", 1);
assert(te->config != NULL);
}
}
storeAppend(entry, "\n", 1);
}
}

void
accessLogFreeLogFormat(logformat_token ** tokens)
{
while (*tokens) {
logformat_token *token = *tokens;
*tokens = token->next;
safe_free(token->data.string);
xfree(token);
}
}

static void
accessLogSquid(AccessLogEntry * al, Logfile * logfile)
{
const char *client = NULL;
const char *user = NULL;
if (Config.onoff.log_fqdn)
client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
if (client == NULL)
client = inet_ntoa(al->cache.caddr);
user = accessLogFormatName(al->cache.authuser);
if (!user)
user = accessLogFormatName(al->cache.rfc931);
#if USE_SSL
if (!user)
user = accessLogFormatName(al->cache.ssluser);
#endif
if (user && !*user)
safe_free(user);
if (!Config.onoff.log_mime_hdrs) {
strcpy(insertSQL,"INSERT INTO logSquid( date, clientIP, tags_HIT_MISS, http_code, cache_size, private_method_str,
strcat(insertSQL,client);
strcat(insertSQL,"','");
strcat(insertSQL,log_tags[al->cache.code]);
strcat(insertSQL,"','");
snprintf(intconvstr,3,"%d",al->http.code);
strcat(insertSQL,intconvstr);
strcat(insertSQL,"','");
snprintf(intconvstr,11,"%d",al->cache.size);
strcat(insertSQL,intconvstr);
strcat(insertSQL,"','");
strcat(insertSQL,al->private.method_str);
strcat(insertSQL,"','");
strcat(insertSQL,al->url);
strcat(insertSQL,"','");
strcat(insertSQL,user ? user : dash_str);
strcat(insertSQL,"');");

mysql_init(&conexao);
if ( mysql_real_connect(&conexao, "localhost", "proxy", "proxy", "proxy", 0, NULL, 0) )
{
res = mysql_query(&conexao,insertSQL);
if (res)
logfilePrintf(logfile,"Erro na inserção %d : %s\n%s", mysql_errno(&conexao), mysql_error(&conexao),insertSQL)
mysql_close(&conexao);

}
else
{
logfilePrintf(logfile,"Falha de conexao\n");
logfilePrintf(logfile,"Erro %d : %s\n", mysql_errno(&conexao), mysql_error(&conexao));
}
safe_free(user);
}

static void
accessLogCommon(AccessLogEntry * al, Logfile * logfile)
{
const char *client = NULL;
char *user1 = NULL, *user2 = NULL;
if (Config.onoff.log_fqdn)
client = fqdncache_gethostbyaddr(al->cache.caddr, 0);
if (client == NULL)
client = inet_ntoa(al->cache.caddr);
user1 = accessLogFormatName(al->cache.authuser);
user2 = accessLogFormatName(al->cache.rfc931);
logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %" PRINTF_OFF_T " %s:%s",
client,
user2 ? user2 : dash_str,
user1 ? user1 : dash_str,
mkhttpdlogtime(&squid_curtime),
al->private.method_str,
al->url,
al->http.version.major, al->http.version.minor,
al->http.code,
al->cache.size,
log_tags[al->cache.code],
hier_strings[al->hier.code]);
safe_free(user1);
safe_free(user2);
if (Config.onoff.log_mime_hdrs) {
char *ereq = log_quote(al->headers.request);
char *erep = log_quote(al->headers.reply);
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
} else {
logfilePrintf(logfile, "\n");
}
}

void
accessLogLog(AccessLogEntry * al, aclCheck_t * checklist)
{
customlog *log;
if (LogfileStatus != LOG_ENABLE)
return;
if (al->url == NULL)
al->url = dash_str;
if (!al->http.content_type || *al->http.content_type == '{COMENTARIO}')
al->http.content_type = dash_str;
if (al->icp.opcode)
al->private.method_str = icp_opcode_str[al->icp.opcode];
else
al->private.method_str = RequestMethodStr[al->http.method];
if (al->hier.host[0] == '{COMENTARIO}')
xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN);

for (log = Config.Log.accesslogs; log; log = log->next) {
if (checklist && log->aclList && aclMatchAclList(log->aclList, checklist) != 1)
continue;
switch (log->type) {
case CLF_AUTO:
if (Config.onoff.common_log)
accessLogCommon(al, log->logfile);
else
accessLogSquid(al, log->logfile);
break;
case CLF_SQUID:
accessLogSquid(al, log->logfile);
break;
case CLF_COMMON:
accessLogCommon(al, log->logfile);
break;
case CLF_CUSTOM:
accessLogCustom(al, log);
break;
case CLF_NONE:
goto last;
default:
fatalf("Unknown log format %d\n", log->type);
break;
}
logfileFlush(log->logfile);
if (!checklist)
break;
}
last:
(void) 0; /* NULL statement for label */

#if MULTICAST_MISS_STREAM
if (al->cache.code != LOG_TCP_MISS)
(void) 0;
else if (al->http.method != METHOD_GET)
(void) 0;
else if (mcast_miss_fd < 0)
(void) 0;
else {
unsigned int ibuf[365];
size_t isize;
xstrncpy((char *) ibuf, al->url, 364 * sizeof(int));
isize = ((strlen(al->url) + 8) / 8) * 2;
if (isize > 364)
isize = 364;
mcast_encode((unsigned int *) ibuf, isize,
(const unsigned int *) Config.mcast_miss.encode_key);
comm_udp_sendto(mcast_miss_fd,
&mcast_miss_to, sizeof(mcast_miss_to),
ibuf, isize * sizeof(int));
}
#endif
}

void
accessLogRotate(void)
{
customlog *log;
#if FORW_VIA_DB
fvdbClear();
#endif
for (log = Config.Log.accesslogs; log; log = log->next) {
if (log->logfile) {
logfileRotate(log->logfile);
}
}
#if HEADERS_LOG
logfileRotate(headerslog);
#endif
}

void
accessLogClose(void)
{
customlog *log;
for (log = Config.Log.accesslogs; log; log = log->next) {
if (log->logfile) {
logfileClose(log->logfile);
log->logfile = NULL;
}
}
#if HEADERS_LOG
logfileClose(headerslog);
headerslog = NULL;
#endif
}

void
hierarchyNote(HierarchyLogEntry * hl,
hier_code code,
const char *cache_peer)
{
assert(hl != NULL);
hl->code = code;
xstrncpy(hl->host, cache_peer, SQUIDHOSTNAMELEN);
}

void
accessLogInit(void)
{
customlog *log;
for (log = Config.Log.accesslogs; log; log = log->next) {
if (log->type == CLF_NONE)
continue;
log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1);
LogfileStatus = LOG_ENABLE;
}
#if HEADERS_LOG
headerslog = logfileOpen("/var/log/squid/headers.log", MAX_URL << 1, 0);
assert(NULL != headerslog);
#endif
#if FORW_VIA_DB
fvdbInit();
#endif
#if MULTICAST_MISS_STREAM
if (Config.mcast_miss.addr.s_addr != no_addr.s_addr) {
memset(&mcast_miss_to, '{COMENTARIO}', sizeof(mcast_miss_to));
mcast_miss_to.sin_family = AF_INET;
mcast_miss_to.sin_port = htons(Config.mcast_miss.port);
mcast_miss_to.sin_addr.s_addr = Config.mcast_miss.addr.s_addr;
mcast_miss_fd = comm_open(SOCK_DGRAM,
IPPROTO_UDP,
Config.Addrs.udp_incoming,
Config.mcast_miss.port,
COMM_NONBLOCKING,
"Multicast Miss Stream");
if (mcast_miss_fd < 0)
fatal("Cannot open Multicast Miss Stream Socket");
debug(46, 1) ("Multicast Miss Stream Socket opened on FD %d\n",
mcast_miss_fd);
mcastSetTtl(mcast_miss_fd, Config.mcast_miss.ttl);
if (strlen(Config.mcast_miss.encode_key) < 16)
fatal("mcast_encode_key is too short, must be 16 characters");
}
#endif
}

const char *
accessLogTime(time_t t)
{
struct tm *tm;
static char buf[128];
static time_t last_t = 0;
if (t != last_t) {
tm = localtime(&t);
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
last_t = t;
}
return buf;
}


#if FORW_VIA_DB

static void
fvdbInit(void)
{
via_table = hash_create((HASHCMP *) strcmp, 977, hash4);
forw_table = hash_create((HASHCMP *) strcmp, 977, hash4);
cachemgrRegister("via_headers", "Via Request Headers", fvdbDumpVia, 0, 1);
cachemgrRegister("forw_headers", "X-Forwarded-For Request Headers",
fvdbDumpForw, 0, 1);
}

static void
fvdbCount(hash_table * hash, const char *key)
{
fvdb_entry *fv;
if (NULL == hash)
return;
fv = hash_lookup(hash, key);
if (NULL == fv) {
fv = xcalloc(1, sizeof(fvdb_entry));
fv->hash.key = xstrdup(key);
hash_join(hash, &fv->hash);
}
fv->n++;
}

void
fvdbCountVia(const char *key)
{
fvdbCount(via_table, key);
}

void
fvdbCountForw(const char *key)
{
fvdbCount(forw_table, key);
}

static void
fvdbDumpTable(StoreEntry * e, hash_table * hash)
{
hash_link *h;
fvdb_entry *fv;
if (hash == NULL)
return;
hash_first(hash);
while ((h = hash_next(hash))) {
fv = (fvdb_entry *) h;
storeAppendPrintf(e, "%9d %s\n", fv->n, hashKeyStr(&fv->hash));
}
}

static void
fvdbDumpVia(StoreEntry * e)
{
fvdbDumpTable(e, via_table);
}

static void
fvdbDumpForw(StoreEntry * e)
{
fvdbDumpTable(e, forw_table);
}

static
void
fvdbFreeEntry(void *data)
{
fvdb_entry *fv = data;
xfree(fv->hash.key);
xfree(fv);
}

static void
fvdbClear(void)
{
hashFreeItems(via_table, fvdbFreeEntry);
hashFreeMemory(via_table);
via_table = hash_create((HASHCMP *) strcmp, 977, hash4);
hashFreeItems(forw_table, fvdbFreeEntry);
hashFreeMemory(forw_table);
forw_table = hash_create((HASHCMP *) strcmp, 977, hash4);
}

#endif

#if MULTICAST_MISS_STREAM
/*
* From http://www.io.com/~paulhart/game/algorithms/tea.html
*
* size of 'ibuf' must be a multiple of 2.
* size of 'key' must be 4.
* 'ibuf' is modified in place, encrypted data is written in
* network byte order.
*/
static void
mcast_encode(unsigned int *ibuf, size_t isize, const unsigned int *key)
{
unsigned int y;
unsigned int z;
unsigned int sum;
const unsigned int delta = 0x9e3779b9;
unsigned int n = 32;
const unsigned int k0 = htonl(key[0]);
const unsigned int k1 = htonl(key[1]);
const unsigned int k2 = htonl(key[2]);
const unsigned int k3 = htonl(key[3]);
int i;
for (i = 0; i < isize; i += 2) {
y = htonl(ibuf[i]);
z = htonl(ibuf[i + 1]);
sum = 0;
for (n = 32; n; n--) {
sum += delta;
y += (z << 4) + (k0 ^ z) + (sum ^ (z >> 5)) + k1;
z += (y << 4) + (k2 ^ y) + (sum ^ (y >> 5)) + k3;
}
ibuf[i] = htonl(y);
ibuf[i + 1] = htonl(z);
}
}

#endif

#if HEADERS_LOG
void
headersLog(int cs, int pq, method_t m, void *data)
{
HttpReply *rep;
request_t *req;
unsigned short magic = 0;
unsigned char M = (unsigned char) m;
unsigned short S;
char *hmask;
int ccmask = 0;
if (0 == pq) {
/* reply */
rep = data;
req = NULL;
magic = 0x0050;
hmask = rep->header.mask;
if (rep->cache_control)
ccmask = rep->cache_control->mask;
} else {
/* request */
req = data;
rep = NULL;
magic = 0x0051;
hmask = req->header.mask;
if (req->cache_control)
ccmask = req->cache_control->mask;
}
if (0 == cs) {
/* client */
magic |= 0x4300;
} else {
/* server */
magic |= 0x5300;
}
magic = htons(magic);
ccmask = htonl(ccmask);
if (0 == pq)
S = (unsigned short) rep->sline.status;
else
S = (unsigned short) HTTP_STATUS_NONE;
logfileWrite(headerslog, &magic, sizeof(magic));
logfileWrite(headerslog, &M, sizeof(M));
logfileWrite(headerslog, &S, sizeof(S));
logfileWrite(headerslog, hmask, sizeof(HttpHeaderMask));
logfileWrite(headerslog, &ccmask, sizeof(int));
logfileFlush(headerslog);
}

#endif

[8] Comentário enviado por m@verick em 17/12/2007 - 00:23h

Balani, tudo OK, desculpe a demora na resposta é que as coisas andam meio corridas de um olhada nestre trecho do código eu postei faltando um parenteses e uma aspas observe logo depois desta palavra private_method_str

f (!Config.onoff.log_mime_hdrs) {
strcpy(insertSQL,"INSERT INTO logSquid( date, clientIP, tags_HIT_MISS, http_code, cache_size, private_method_str"),

isto ja deve resolver, se não entre em contato novamente.

[9] Comentário enviado por balani em 17/12/2007 - 09:23h

Bom dia amigo, muito obrigado pela atenção, a sua dica resolveu aquele problema, me desculpe, mais não entendo muito de programação C, e está apresentando o seguinte erro agora:

access_log.c: In function 'accessLogSquid':
access_log.c:1067: error: invalid storage class for function 'accessLogCommon'
access_log.c:1268: error: expected declaration or statement at end of input


Se vc puder quebrar mais esse galho, eu agradeço desde já.

[10] Comentário enviado por m@verick em 08/01/2008 - 21:00h

Balani, depois destas férias só pude responder agora, segue abaixo o codigo que compilei e posso dizer que funciona.


/*
* $Id: access_log.c,v 1.95.2.2 2007/06/03 00:40:32 hno Exp $
*
* DEBUG: section 46 Access Log
* AUTHOR: Duane Wessels
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
* Squid is the result of efforts by numerous individuals from
* the Internet community; see the CONTRIBUTORS file for full
* details. Many organizations have provided support for Squid's
* development; see the SPONSORS file for full details. Squid is
* Copyrighted (C) 2001 by the Regents of the University of
* California; see the COPYRIGHT file for full details. Squid
* incorporates software developed and/or copyrighted by other
* sources; see the CREDITS file for full details.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/


#include "squid.h"
#include <mysql/mysql.h>
#include <stdlib.h>
#include <stdio.h>

char insertSQL[400];
char intconvstr[5];
int res;
MYSQL conexao;

#if HEADERS_LOG
static Logfile *headerslog = NULL;
#endif

#if MULTICAST_MISS_STREAM
static int mcast_miss_fd = -1;
static struct sockaddr_in mcast_miss_to;
static void mcast_encode(unsigned int *, size_t, const unsigned int *);
#endif

#if FORW_VIA_DB
typedef struct {
hash_link hash;
int n;
} fvdb_entry;
static hash_table *via_table = NULL;
static hash_table *forw_table = NULL;
static void fvdbInit(void);
static void fvdbDumpTable(StoreEntry * e, hash_table * hash);
static void fvdbCount(hash_table * hash, const char *key);
static OBJH fvdbDumpVia;
static OBJH fvdbDumpForw;
static FREE fvdbFreeEntry;
static void fvdbClear(void);
#endif

static int LogfileStatus = LOG_DISABLE;
#define LOG_BUF_SZ (MAX_URL<<2)

static const char c2x[] =
"000102030405060708090a0b0c0d0e0f"
"101112131415161718191a1b1c1d1e1f"
"202122232425262728292a2b2c2d2e2f"
"303132333435363738393a3b3c3d3e3f"
"404142434445464748494a4b4c4d4e4f"
"505152535455565758595a5b5c5d5e5f"
"606162636465666768696a6b6c6d6e6f"
"707172737475767778797a7b7c7d7e7f"
"808182838485868788898a8b8c8d8e8f"
"909192939495969798999a9b9c9d9e9f"
"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
"d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
"e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
"f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";


/* log_quote -- URL-style encoding on MIME headers. */

char *
log_quote(const char *header)
{
int c;
int i;
char *buf;
char *buf_cursor;
if (header == NULL) {
buf = xcalloc(1, 1);
*buf = '{COMENTARIO}';
return buf;
}
buf = xcalloc(1, (strlen(header) * 3) + 1);
buf_cursor = buf;
/*
* We escape: \x00-\x1F"#%;<>?{}|\\\\^~`\[\]\x7F-\xFF
* which is the default escape list for the CPAN Perl5 URI module
* modulo the inclusion of space (x40) to make the raw logs a bit
* more readable.
*/
while ((c = *(const unsigned char *) header++) != '{COMENTARIO}') {
#if !OLD_LOG_MIME
if (c == '\r') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'r';
} else if (c == '\n') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'n';
} else
#endif
if (c <= 0x1F
|| c >= 0x7F
|| c == '%'
#if OLD_LOG_MIME
|| c == '"'
|| c == '#'
|| c == ';'
|| c == '<'
|| c == '>'
|| c == '?'
|| c == '{'
|| c == '}'
|| c == '|'
|| c == '\\'
|| c == '^'
|| c == '~'
|| c == '`'
#endif
|| c == '['
|| c == ']') {
*buf_cursor++ = '%';
i = c * 2;
*buf_cursor++ = c2x[i];
*buf_cursor++ = c2x[i + 1];
#if !OLD_LOG_MIME
} else if (c == '\\') {
*buf_cursor++ = '\\';
*buf_cursor++ = '\\';
#endif
} else {
*buf_cursor++ = (char) c;
}
}
*buf_cursor = '{COMENTARIO}';
return buf;
}

static char *
username_quote(const char *header)
/* copy of log_quote. Bugs there will be found here */
{
int c;
int i;
char *buf;
char *buf_cursor;
if (header == NULL) {
buf = xcalloc(1, 1);
*buf = '{COMENTARIO}';
return buf;
}
buf = xcalloc(1, (strlen(header) * 3) + 1);
buf_cursor = buf;
/*
* We escape: space \x00-\x1F and space (0x40) and \x7F-\xFF
* to prevent garbage in the logs. CR and LF are also there just in case.
*/
while ((c = *(const unsigned char *) header++) != '{COMENTARIO}') {
if (c == '\r') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'r';
} else if (c == '\n') {
*buf_cursor++ = '\\';
*buf_cursor++ = 'n';
} else if (c <= 0x1F
|| c >= 0x7F
|| c == '%'
|| c == ' ') {
*buf_cursor++ = '%';
i = c * 2;
*buf_cursor++ = c2x[i];
*buf_cursor++ = c2x[i + 1];
} else {
*buf_cursor++ = (char) c;
}
}
*buf_cursor = '{COMENTARIO}';
return buf;
}

static char *
accessLogFormatName(const char *name)
{
if (NULL == name)
return NULL;
if (name[0] == '{COMENTARIO}')
return NULL;
return username_quote(name);
}

static char *
log_quoted_string(const char *str)
{
char *out = xmalloc(strlen(str) * 2 + 1);
char *p = out;
while (*str) {
int l = strcspn(str, "\"\\\r\n\t");
memcpy(p, str, l);
str += l;
p += l;
switch (*str) {
case '{COMENTARIO}':
break;
case '\r':
*p++ = '\\';
*p++ = 'r';
str++;
break;
case '\n':
*p++ = '\\';
*p++ = 'n';
str++;
break;
case '\t':
*p++ = '\\';
*p++ = 't';
str++;
break;
default:
*p++ = '\\';
*p++ = *str;
str++;
break;
}
}
*p++ = '{COMENTARIO}';
return out;
}

/*
* Bytecodes for the configureable logformat stuff
*/
typedef enum {
LFT_NONE, /* dummy */
LFT_STRING,

LFT_CLIENT_IP_ADDRESS,
LFT_CLIENT_FQDN,
LFT_CLIENT_PORT,

/*LFT_SERVER_IP_ADDRESS, */
LFT_SERVER_IP_OR_PEER_NAME,
/*LFT_SERVER_PORT, */

LFT_LOCAL_IP,
LFT_LOCAL_PORT,
/*LFT_LOCAL_NAME, */

LFT_TIME_SECONDS_SINCE_EPOCH,
LFT_TIME_SUBSECOND,
LFT_TIME_LOCALTIME,
LFT_TIME_GMT,
LFT_TIME_TO_HANDLE_REQUEST,

LFT_REQUEST_HEADER,
LFT_REQUEST_HEADER_ELEM,
LFT_REQUEST_ALL_HEADERS,

LFT_REPLY_HEADER,
LFT_REPLY_HEADER_ELEM,
LFT_REPLY_ALL_HEADERS,

LFT_USER_NAME,
LFT_USER_LOGIN,
/*LFT_USER_REALM, */
/*LFT_USER_SCHEME, */
LFT_USER_IDENT,
LFT_USER_EXT,
#if USE_SSL
LFT_USER_SSL,
#endif

LFT_HTTP_CODE,
/*LFT_HTTP_STATUS, */

LFT_SQUID_STATUS,
/*LFT_SQUID_ERROR, */
LFT_SQUID_HIERARCHY,

LFT_MIME_TYPE,

LFT_REQUEST_METHOD,
LFT_REQUEST_URI,
/*LFT_REQUEST_QUERY, * // * this is not needed. see strip_query_terms */
LFT_REQUEST_VERSION,

LFT_REQUEST_SIZE_TOTAL,
/*LFT_REQUEST_SIZE_LINE, */
/*LFT_REQUEST_SIZE_HEADERS, */
/*LFT_REQUEST_SIZE_BODY, */
/*LFT_REQUEST_SIZE_BODY_NO_TE, */

LFT_REPLY_SIZE_TOTAL,
/*LFT_REPLY_SIZE_LINE, */
/*LFT_REPLY_SIZE_HEADERS, */
/*LFT_REPLY_SIZE_BODY, */
/*LFT_REPLY_SIZE_BODY_NO_TE, */

LFT_IO_SIZE_TOTAL,

LFT_EXT_LOG,

LFT_PERCENT /* special string cases for escaped chars */
} logformat_bcode_t;

enum log_quote {
LOG_QUOTE_NONE = 0,
LOG_QUOTE_QUOTES,
LOG_QUOTE_BRAKETS,
LOG_QUOTE_URL,
LOG_QUOTE_RAW
};
struct _logformat_token {
logformat_bcode_t type;
union {
char *string;
struct {
char *header;
char *element;
char separator;
} header;
char *timespec;
} data;
unsigned char width;
unsigned char precision;
enum log_quote quote:3;
unsigned int left:1;
unsigned int space:1;
unsigned int zero:1;
int divisor;
logformat_token *next; /* todo: move from linked list to array */
};

struct logformat_token_table_entry {
const char *config;
logformat_bcode_t token_type;
int options;
};

struct logformat_token_table_entry logformat_token_table[] =
{

{">a", LFT_CLIENT_IP_ADDRESS},
{">p", LFT_CLIENT_PORT},
{">A", LFT_CLIENT_FQDN},

/*{ "<a", LFT_SERVER_IP_ADDRESS }, */
/*{ "<p", LFT_SERVER_PORT }, */
{"<A", LFT_SERVER_IP_OR_PEER_NAME},

{"la", LFT_LOCAL_IP},
{"lp", LFT_LOCAL_PORT},
/*{ "lA", LFT_LOCAL_NAME }, */

{"ts", LFT_TIME_SECONDS_SINCE_EPOCH},
{"tu", LFT_TIME_SUBSECOND},
{"tl", LFT_TIME_LOCALTIME},
{"tg", LFT_TIME_GMT},
{"tr", LFT_TIME_TO_HANDLE_REQUEST},

{">h", LFT_REQUEST_HEADER},
{">h", LFT_REQUEST_ALL_HEADERS},
{"<h", LFT_REPLY_HEADER},
{"<h", LFT_REPLY_ALL_HEADERS},

{"un", LFT_USER_NAME},
{"ul", LFT_USER_LOGIN},
/*{ "ur", LFT_USER_REALM }, */
/*{ "us", LFT_USER_SCHEME }, */
{"ui", LFT_USER_IDENT},
#if USE_SSL
{"us", LFT_USER_SSL},
#endif
{"ue", LFT_USER_EXT},

{"Hs", LFT_HTTP_CODE},
/*{ "Ht", LFT_HTTP_STATUS }, */

{"Ss", LFT_SQUID_STATUS},
/*{ "Se", LFT_SQUID_ERROR }, */
{"Sh", LFT_SQUID_HIERARCHY},

{"mt", LFT_MIME_TYPE},

{"rm", LFT_REQUEST_METHOD},
{"ru", LFT_REQUEST_URI}, /* doesn't include the query-string */
/* { "rq", LFT_REQUEST_QUERY }, * / / * the query-string, INCLUDING the leading ? */
{">v", LFT_REQUEST_VERSION},
{"rv", LFT_REQUEST_VERSION},

{">st", LFT_REQUEST_SIZE_TOTAL},
/*{ ">sl", LFT_REQUEST_SIZE_LINE }, * / / * the request line "GET ... " */
/*{ ">sh", LFT_REQUEST_SIZE_HEADERS }, */
/*{ ">sb", LFT_REQUEST_SIZE_BODY }, */
/*{ ">sB", LFT_REQUEST_SIZE_BODY_NO_TE }, */

{"<st", LFT_REPLY_SIZE_TOTAL},
/*{ "<sl", LFT_REPLY_SIZE_LINE }, * / / * the reply line (protocol, code, text) */
/*{ "<sh", LFT_REPLY_SIZE_HEADERS }, */
/*{ "<sb", LFT_REPLY_SIZE_BODY }, */
/*{ "<sB", LFT_REPLY_SIZE_BODY_NO_TE }, */

{"st", LFT_IO_SIZE_TOTAL},

{"ea", LFT_EXT_LOG},

{"%", LFT_PERCENT},

{NULL, LFT_NONE} /* this must be last */
};

static void
accessLogCustom(AccessLogEntry * al, customlog * log)
{
logformat *lf;
Logfile *logfile;
logformat_token *fmt;
static MemBuf mb = MemBufNULL;
char tmp[1024];
String sb = StringNull;

memBufReset(&mb);

lf = log->logFormat;
logfile = log->logfile;
for (fmt = lf->format; fmt != NULL; fmt = fmt->next) { /* for each token */
const char *out = NULL;
int quote = 0;
long int outint = 0;
int doint = 0;
int dofree = 0;
switch (fmt->type) {
case LFT_NONE:
out = "";
break;
case LFT_STRING:
out = fmt->data.string;
break;
case LFT_CLIENT_IP_ADDRESS:
out = inet_ntoa(al->cache.caddr);
break;

case LFT_CLIENT_FQDN:
out = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
if (!out)
out = inet_ntoa(al->cache.caddr);
break;

case LFT_CLIENT_PORT:
if (al->request) {
outint = al->request->client_port;
doint = 1;
}
break;

/* case LFT_SERVER_IP_ADDRESS: */

case LFT_SERVER_IP_OR_PEER_NAME:
out = al->hier.host;
break;

/* case LFT_SERVER_PORT: */

case LFT_LOCAL_IP:
if (al->request)
out = inet_ntoa(al->request->my_addr);
break;

case LFT_LOCAL_PORT:
if (al->request) {
outint = al->request->my_port;
doint = 1;
}
break;

case LFT_TIME_SECONDS_SINCE_EPOCH:
outint = current_time.tv_sec;
doint = 1;
break;

case LFT_TIME_SUBSECOND:
outint = current_time.tv_usec / fmt->divisor;
doint = 1;
break;


case LFT_TIME_LOCALTIME:
case LFT_TIME_GMT:
{
const char *spec;
struct tm *t;
spec = fmt->data.timespec;
if (!spec)
spec = "%d/%b/%Y:%H:%M:%S %z";
if (fmt->type == LFT_TIME_LOCALTIME)
t = localtime(&squid_curtime);
else
t = gmtime(&squid_curtime);
strftime(tmp, sizeof(tmp), spec, t);
out = tmp;
}
break;

case LFT_TIME_TO_HANDLE_REQUEST:
outint = al->cache.msec;
doint = 1;
break;

case LFT_REQUEST_HEADER:
if (al->request)
sb = httpHeaderGetByName(&al->request->header, fmt->data.header.header);
out = strBuf(sb);
quote = 1;
break;

case LFT_REPLY_HEADER:
if (al->reply)
sb = httpHeaderGetByName(&al->reply->header, fmt->data.header.header);
out = strBuf(sb);
quote = 1;
break;

case LFT_REQUEST_HEADER_ELEM:
if (al->request)
sb = httpHeaderGetByNameListMember(&al->request->header, fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
out = strBuf(sb);
quote = 1;
break;

case LFT_REPLY_HEADER_ELEM:
if (al->reply)
sb = httpHeaderGetByNameListMember(&al->reply->header, fmt->data.header.header, fmt->data.header.element, fmt->data.header.separator);
out = strBuf(sb);
quote = 1;
break;

case LFT_REQUEST_ALL_HEADERS:
out = al->headers.request;
quote = 1;
break;

case LFT_REPLY_ALL_HEADERS:
out = al->headers.reply;
quote = 1;
break;

case LFT_USER_NAME:
out = al->cache.authuser;
if (!out || !*out)
out = al->cache.rfc931;
#if USE_SSL
if (!out || !*out)
out = al->cache.ssluser;
#endif
quote = 1;
break;

case LFT_USER_LOGIN:
out = al->cache.authuser;
quote = 1;
break;

case LFT_USER_IDENT:
out = al->cache.rfc931;
quote = 1;
break;

/* case LFT_USER_REALM: */
/* case LFT_USER_SCHEME: */

#if USE_SSL
case LFT_USER_SSL:
out = al->cache.ssluser;
quote = 1;
break;
#endif

case LFT_USER_EXT:
if (al->request)
out = strBuf(al->request->extacl_log);
quote = 1;
break;

case LFT_HTTP_CODE:
outint = al->http.code;
doint = 1;
break;

/* case LFT_HTTP_STATUS:
* out = statusline->text;
* quote = 1;
* break;
*/

case LFT_SQUID_STATUS:
out = log_tags[al->cache.code];
break;

/* case LFT_SQUID_ERROR: */

case LFT_SQUID_HIERARCHY:
if (al->hier.ping.timedout)
memBufAppend(&mb, "TIMEOUT_", 8);
out = hier_strings[al->hier.code];
break;

case LFT_MIME_TYPE:
out = al->http.content_type;
break;

case LFT_REQUEST_METHOD:
out = al->private.method_str;
break;

case LFT_REQUEST_URI:
out = al->url;
break;

case LFT_REQUEST_VERSION:
snprintf(tmp, sizeof(tmp), "%d.%d", (int) al->http.version.major, (int) al->http.version.minor);
out = tmp;
break;

case LFT_REQUEST_SIZE_TOTAL:
outint = al->cache.rq_size;
doint = 1;
break;
/*case LFT_REQUEST_SIZE_LINE: */
/*case LFT_REQUEST_SIZE_HEADERS: */
/*case LFT_REQUEST_SIZE_BODY: */
/*case LFT_REQUEST_SIZE_BODY_NO_TE: */

case LFT_REPLY_SIZE_TOTAL:
outint = al->cache.size;
doint = 1;
break;

/*case LFT_REPLY_SIZE_LINE: */
/*case LFT_REPLY_SIZE_HEADERS: */
/*case LFT_REPLY_SIZE_BODY: */
/*case LFT_REPLY_SIZE_BODY_NO_TE: */

case LFT_IO_SIZE_TOTAL:
outint = al->cache.size + al->cache.rq_size;
doint = 1;
break;

case LFT_EXT_LOG:
if (al->request)
out = strBuf(al->request->extacl_log);

quote = 1;
break;

case LFT_PERCENT:
out = "%";
break;
}

if (doint) {
snprintf(tmp, sizeof(tmp), "%0*ld", fmt->zero ? (int) fmt->width : 0, outint);
out = tmp;
}
if (out && *out) {
if (quote || fmt->quote != LOG_QUOTE_NONE) {
char *newout = NULL;
int newfree = 0;
switch (fmt->quote) {
case LOG_QUOTE_NONE:
newout = rfc1738_escape_unescaped(out);
break;
case LOG_QUOTE_QUOTES:
newout = log_quoted_string(out);
newfree = 1;
break;
case LOG_QUOTE_BRAKETS:
newout = log_quote(out);
newfree = 1;
break;
case LOG_QUOTE_URL:
newout = rfc1738_escape(out);
break;
case LOG_QUOTE_RAW:
break;
}
if (newout) {
if (dofree)
safe_free(out);
out = newout;
dofree = newfree;
}
}
if (fmt->width) {
if (fmt->left)
memBufPrintf(&mb, "%-*s", (int) fmt->width, out);
else
memBufPrintf(&mb, "%*s", (int) fmt->width, out);
} else
memBufAppend(&mb, out, strlen(out));
} else {
memBufAppend(&mb, "-", 1);
}
if (fmt->space)
memBufAppend(&mb, " ", 1);
stringClean(&sb);
if (dofree)
safe_free(out);
}
logfilePrintf(logfile, "%s\n", mb.buf);
}

/* parses a single token. Returns the token length in characters,
* and fills in the lt item with the token information.
* def is for sure null-terminated
*/
static int
accessLogGetNewLogFormatToken(logformat_token * lt, char *def, enum log_quote *quote)
{
char *cur = def;
struct logformat_token_table_entry *lte;
int l;

memset(lt, 0, sizeof(*lt));
l = strcspn(cur, "%");
if (l > 0) {
char *cp;
/* it's a string for sure, until {COMENTARIO} or the next % */
cp = xmalloc(l + 1);
xstrncpy(cp, cur, l + 1);
lt->type = LFT_STRING;
lt->data.string = cp;
while (l > 0) {
switch (*cur) {
case '"':
if (*quote == LOG_QUOTE_NONE)
*quote = LOG_QUOTE_QUOTES;
else if (*quote == LOG_QUOTE_QUOTES)
*quote = LOG_QUOTE_NONE;
break;
case '[':
if (*quote == LOG_QUOTE_NONE)
*quote = LOG_QUOTE_BRAKETS;
break;
case ']':
if (*quote == LOG_QUOTE_BRAKETS)
*quote = LOG_QUOTE_NONE;
break;
}
cur++;
l--;
}
goto done;
}
if (!*cur)
goto done;
cur++;
switch (*cur) {
case '"':
lt->quote = LOG_QUOTE_QUOTES;
cur++;
break;
case '\'':
lt->quote = LOG_QUOTE_RAW;
cur++;
break;
case '[':
lt->quote = LOG_QUOTE_BRAKETS;
cur++;
break;
case '#':
lt->quote = LOG_QUOTE_URL;
cur++;
break;
default:
lt->quote = *quote;
break;
}
if (*cur == '-') {
lt->left = 1;
cur++;
}
if (*cur == '0') {
lt->zero = 1;
cur++;
}
if (xisdigit(*cur))
lt->width = strtol(cur, &cur, 10);
if (*cur == '.')
lt->precision = strtol(cur + 1, &cur, 10);
if (*cur == '{') {
char *cp;
cur++;
l = strcspn(cur, "}");
cp = xmalloc(l + 1);
xstrncpy(cp, cur, l + 1);
lt->data.string = cp;
cur += l;
if (*cur == '}')
cur++;
}
lt->type = LFT_NONE;
for (lte = logformat_token_table; lte->config != NULL; lte++) {
if (strncmp(lte->config, cur, strlen(lte->config)) == 0) {
lt->type = lte->token_type;
cur += strlen(lte->config);
break;
}
}
if (lt->type == LFT_NONE) {
fatalf("Can't parse configuration token: '%s'\n",
def);
}
if (*cur == ' ') {
lt->space = 1;
cur++;
}
done:
switch (lt->type) {
case LFT_REQUEST_HEADER:
case LFT_REPLY_HEADER:
if (lt->data.string) {
char *header = lt->data.string;
char *cp = strchr(header, ':');
if (cp) {
*cp++ = '{COMENTARIO}';
if (*cp == ',' || *cp == ';' || *cp == ':')
lt->data.header.separator = *cp++;
else
lt->data.header.separator = ',';
lt->data.header.element = cp;
lt->type = (lt->type == LFT_REQUEST_HEADER) ?
LFT_REQUEST_HEADER_ELEM :
LFT_REPLY_HEADER_ELEM;
}
lt->data.header.header = header;
} else {
lt->type = (lt->type == LFT_REQUEST_HEADER) ?
LFT_REQUEST_ALL_HEADERS :
LFT_REPLY_ALL_HEADERS;
Config.onoff.log_mime_hdrs = 1;
}
break;
case LFT_CLIENT_FQDN:
Config.onoff.log_fqdn = 1;
break;
case LFT_TIME_SUBSECOND:
lt->divisor = 1000;
if (lt->precision) {
int i;
lt->divisor = 1000000;
for (i = lt->precision; i > 1; i--)
lt->divisor /= 10;
if (!lt->divisor)
lt->divisor = 0;
}
break;
default:
break;
}
return (cur - def);
}

int
accessLogParseLogFormat(logformat_token ** fmt, char *def)
{
char *cur, *eos;
logformat_token *new_lt, *last_lt;
enum log_quote quote = LOG_QUOTE_NONE;

debug(46, 1) ("accessLogParseLogFormat: got definition '%s'\n", def);

/* very inefficent parser, but who cares, this needs to be simple */
/* First off, let's tokenize, we'll optimize in a second pass.
* A token can either be a %-prefixed sequence (usually a dynamic
* token but it can be an escaped sequence), or a string. */
cur = def;
eos = def + strlen(def);
*fmt = new_lt = last_lt = xmalloc(sizeof(logformat_token));
cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
while (cur < eos) {
new_lt = xmalloc(sizeof(logformat_token));
last_lt->next = new_lt;
last_lt = new_lt;
cur += accessLogGetNewLogFormatToken(new_lt, cur, "e);
}
return 1;
}

void
accessLogDumpLogFormat(StoreEntry * entry, const char *name, logformat * definitions)
{
logformat_token *t;
logformat *format;
struct logformat_token_table_entry *te;
debug(46, 4) ("accessLogDumpLogFormat called\n");

for (format = definitions; format; format = format->next) {
debug(46, 4) ("Dumping logformat definition for %s\n", format->name);
storeAppendPrintf(entry, "logformat %s ", format->name);
for (t = format->format; t; t = t->next) {
if (t->type == LFT_STRING)
storeAppendPrintf(entry, "%s", t->data.string);
else {
char argbuf[256];
char *arg = NULL;
logformat_bcode_t type = t->type;

switch (type) {
/* special cases */
case LFT_STRING:
break;
case LFT_REQUEST_HEADER_ELEM:
case LFT_REPLY_HEADER_ELEM:
if (t->data.header.separator != ',')
snprintf(argbuf, sizeof(argbuf), "%s:%c%s", t->data.header.header, t->data.header.separator, t->data.header.element);
else
snprintf(argbuf, sizeof(argbuf), "%s:%s", t->data.header.header, t->data.header.element);

arg = argbuf;
type = (type == LFT_REQUEST_HEADER_ELEM) ?
LFT_REQUEST_HEADER :
LFT_REPLY_HEADER;
break;

case LFT_REQUEST_ALL_HEADERS:
case LFT_REPLY_ALL_HEADERS:
type = (type == LFT_REQUEST_ALL_HEADERS) ?
LFT_REQUEST_HEADER :
LFT_REPLY_HEADER;
break;

default:
if (t->data.string)
arg = t->data.string;
break;
}
storeAppend(entry, "%", 1);
switch (t->quote) {
case LOG_QUOTE_QUOTES:
storeAppend(entry, "\"", 1);
break;
case LOG_QUOTE_BRAKETS:
storeAppend(entry, "[", 1);
break;
case LOG_QUOTE_URL:
storeAppend(entry, "#", 1);
break;
case LOG_QUOTE_RAW:
storeAppend(entry, "'", 1);
break;
case LOG_QUOTE_NONE:
break;
}
if (t->left)
storeAppend(entry, "-", 1);
if (t->zero)
storeAppend(entry, "0", 1);
if (t->width)
storeAppendPrintf(entry, "%d", (int) t->width);
if (t->precision)
storeAppendPrintf(entry, ".%d", (int) t->precision);
if (arg)
storeAppendPrintf(entry, "{%s}", arg);
for (te = logformat_token_table; te->config != NULL; te++) {
if (te->token_type == t->type) {
storeAppendPrintf(entry, "%s", te->config);
break;
}
}
if (t->space)
storeAppend(entry, " ", 1);
assert(te->config != NULL);
}
}
storeAppend(entry, "\n", 1);
}
}

void
accessLogFreeLogFormat(logformat_token ** tokens)
{
while (*tokens) {
logformat_token *token = *tokens;
*tokens = token->next;
safe_free(token->data.string);
xfree(token);
}
}

static void
accessLogSquid(AccessLogEntry * al, Logfile * logfile)
{
const char *client = NULL;
const char *user = NULL;
if (Config.onoff.log_fqdn)
client = fqdncache_gethostbyaddr(al->cache.caddr, FQDN_LOOKUP_IF_MISS);
if (client == NULL)
client = inet_ntoa(al->cache.caddr);
user = accessLogFormatName(al->cache.authuser);
if (!user)
user = accessLogFormatName(al->cache.rfc931);
#if USE_SSL
if (!user)
user = accessLogFormatName(al->cache.ssluser);
#endif
if (user && !*user)
safe_free(user);
if (!Config.onoff.log_mime_hdrs) {
logfilePrintf(logfile, "%9ld.%03d %6d %s %s/%03d %" PRINTF_OFF_T " %s %s %s %s%s/%s %s\n",
(long int) current_time.tv_sec,
(int) current_time.tv_usec / 1000,
al->cache.msec,
client,
log_tags[al->cache.code],
al->http.code,
al->cache.size,
al->private.method_str,
al->url,
user ? user : dash_str,
al->hier.ping.timedout ? "TIMEOUT_" : "",
hier_strings[al->hier.code],
al->hier.host,
al->http.content_type);

strcpy(insertSQL,"INSERT INTO logSquid( date, clientIP, tags_HIT_MISS, http_code, cache_size, private_method_str, url, user) values ( now(),'");
strcat(insertSQL,client);
strcat(insertSQL,"','");
strcat(insertSQL,log_tags[al->cache.code]);
strcat(insertSQL,"','");


snprintf(intconvstr,3,"%d",al->http.code);
strcat(insertSQL,intconvstr); // Sprintf(Stringdestino,tipodeconverção"%d INTEIRO",valorinteiro)

strcat(insertSQL,"','");
snprintf(intconvstr,11,"%d",al->cache.size);

strcat(insertSQL,intconvstr);
strcat(insertSQL,"','");
strcat(insertSQL,al->private.method_str);
strcat(insertSQL,"','");
strcat(insertSQL,al->url);
strcat(insertSQL,"','");
strcat(insertSQL,user ? user : dash_str);
strcat(insertSQL,"');");

mysql_init(&conexao);
if ( mysql_real_connect(&conexao, "localhost", "Usuario", "Senha", "SeuBANCO", 0, NULL, 0) )
{
res = mysql_query(&conexao,insertSQL);
if (!res) logfilePrintf(logfile,"Registros inseridos %d\n", mysql_affected_rows(&conexao));
else logfilePrintf(logfile,"Erro na inserção %d : %s\n", mysql_errno(&conexao), mysql_error(&conexao));
mysql_close(&conexao);

}
else
{
logfilePrintf(logfile,"Falha de conexao\n");
logfilePrintf(logfile,"Erro %d : %s\n", mysql_errno(&conexao), mysql_error(&conexao));
}
} else {
char *ereq = log_quote(al->headers.request);
char *erep = log_quote(al->headers.reply);
logfilePrintf(logfile, "%9ld.%03d %6d %s %s/%03d %" PRINTF_OFF_T " %s %s %s %s%s/%s %s [%s] [%s]\n",
(long int) current_time.tv_sec,
(int) current_time.tv_usec / 1000,
al->cache.msec,
client,
log_tags[al->cache.code],
al->http.code,
al->cache.size,
al->private.method_str,
al->url,
user ? user : dash_str,
al->hier.ping.timedout ? "TIMEOUT_" : "",
hier_strings[al->hier.code],
al->hier.host,
al->http.content_type,
ereq,
erep);
safe_free(ereq);
safe_free(erep);
}
safe_free(user);
}

static void
accessLogCommon(AccessLogEntry * al, Logfile * logfile)
{
const char *client = NULL;
char *user1 = NULL, *user2 = NULL;
if (Config.onoff.log_fqdn)
client = fqdncache_gethostbyaddr(al->cache.caddr, 0);
if (client == NULL)
client = inet_ntoa(al->cache.caddr);
user1 = accessLogFormatName(al->cache.authuser);
user2 = accessLogFormatName(al->cache.rfc931);
logfilePrintf(logfile, "%s %s %s [%s] \"%s %s HTTP/%d.%d\" %d %" PRINTF_OFF_T " %s:%s",
client,
user2 ? user2 : dash_str,
user1 ? user1 : dash_str,
mkhttpdlogtime(&squid_curtime),
al->private.method_str,
al->url,
al->http.version.major, al->http.version.minor,
al->http.code,
al->cache.size,
log_tags[al->cache.code],
hier_strings[al->hier.code]);
safe_free(user1);
safe_free(user2);
if (Config.onoff.log_mime_hdrs) {
char *ereq = log_quote(al->headers.request);
char *erep = log_quote(al->headers.reply);
logfilePrintf(logfile, " [%s] [%s]\n", ereq, erep);
safe_free(ereq);
safe_free(erep);
} else {
logfilePrintf(logfile, "\n");
}
}

void
accessLogLog(AccessLogEntry * al, aclCheck_t * checklist)
{
customlog *log;
if (LogfileStatus != LOG_ENABLE)
return;
if (al->url == NULL)
al->url = dash_str;
if (!al->http.content_type || *al->http.content_type == '{COMENTARIO}')
al->http.content_type = dash_str;
if (al->icp.opcode)
al->private.method_str = icp_opcode_str[al->icp.opcode];
else
al->private.method_str = RequestMethodStr[al->http.method];
if (al->hier.host[0] == '{COMENTARIO}')
xstrncpy(al->hier.host, dash_str, SQUIDHOSTNAMELEN);

for (log = Config.Log.accesslogs; log; log = log->next) {
if (checklist && log->aclList && aclMatchAclList(log->aclList, checklist) != 1)
continue;
switch (log->type) {
case CLF_AUTO:
if (Config.onoff.common_log)
accessLogCommon(al, log->logfile);
else
accessLogSquid(al, log->logfile);
break;
case CLF_SQUID:
accessLogSquid(al, log->logfile);
break;
case CLF_COMMON:
accessLogCommon(al, log->logfile);
break;
case CLF_CUSTOM:
accessLogCustom(al, log);
break;
case CLF_NONE:
goto last;
default:
fatalf("Unknown log format %d\n", log->type);
break;
}
logfileFlush(log->logfile);
if (!checklist)
break;
}
last:
(void) 0; /* NULL statement for label */

#if MULTICAST_MISS_STREAM
if (al->cache.code != LOG_TCP_MISS)
(void) 0;
else if (al->http.method != METHOD_GET)
(void) 0;
else if (mcast_miss_fd < 0)
(void) 0;
else {
unsigned int ibuf[365];
size_t isize;
xstrncpy((char *) ibuf, al->url, 364 * sizeof(int));
isize = ((strlen(al->url) + 8) / 8) * 2;
if (isize > 364)
isize = 364;
mcast_encode((unsigned int *) ibuf, isize,
(const unsigned int *) Config.mcast_miss.encode_key);
comm_udp_sendto(mcast_miss_fd,
&mcast_miss_to, sizeof(mcast_miss_to),
ibuf, isize * sizeof(int));
}
#endif
}

void
accessLogRotate(void)
{
customlog *log;
#if FORW_VIA_DB
fvdbClear();
#endif
for (log = Config.Log.accesslogs; log; log = log->next) {
if (log->logfile) {
logfileRotate(log->logfile);
}
}
#if HEADERS_LOG
logfileRotate(headerslog);
#endif
}

void
accessLogClose(void)
{
customlog *log;
for (log = Config.Log.accesslogs; log; log = log->next) {
if (log->logfile) {
logfileClose(log->logfile);
log->logfile = NULL;
}
}
#if HEADERS_LOG
logfileClose(headerslog);
headerslog = NULL;
#endif
}

void
hierarchyNote(HierarchyLogEntry * hl,
hier_code code,
const char *cache_peer)
{
assert(hl != NULL);
hl->code = code;
xstrncpy(hl->host, cache_peer, SQUIDHOSTNAMELEN);
}

void
accessLogInit(void)
{
customlog *log;
for (log = Config.Log.accesslogs; log; log = log->next) {
if (log->type == CLF_NONE)
continue;
log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1);
LogfileStatus = LOG_ENABLE;
}
#if HEADERS_LOG
headerslog = logfileOpen("/usr/local/squid/logs/headers.log", MAX_URL << 1, 0);
assert(NULL != headerslog);
#endif
#if FORW_VIA_DB
fvdbInit();
#endif
#if MULTICAST_MISS_STREAM
if (Config.mcast_miss.addr.s_addr != no_addr.s_addr) {
memset(&mcast_miss_to, '{COMENTARIO}', sizeof(mcast_miss_to));
mcast_miss_to.sin_family = AF_INET;
mcast_miss_to.sin_port = htons(Config.mcast_miss.port);
mcast_miss_to.sin_addr.s_addr = Config.mcast_miss.addr.s_addr;
mcast_miss_fd = comm_open(SOCK_DGRAM,
IPPROTO_UDP,
Config.Addrs.udp_incoming,
Config.mcast_miss.port,
COMM_NONBLOCKING,
"Multicast Miss Stream");
if (mcast_miss_fd < 0)
fatal("Cannot open Multicast Miss Stream Socket");
debug(46, 1) ("Multicast Miss Stream Socket opened on FD %d\n",
mcast_miss_fd);
mcastSetTtl(mcast_miss_fd, Config.mcast_miss.ttl);
if (strlen(Config.mcast_miss.encode_key) < 16)
fatal("mcast_encode_key is too short, must be 16 characters");
}
#endif
}

const char *
accessLogTime(time_t t)
{
struct tm *tm;
static char buf[128];
static time_t last_t = 0;
if (t != last_t) {
tm = localtime(&t);
strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
last_t = t;
}
return buf;
}


#if FORW_VIA_DB

static void
fvdbInit(void)
{
via_table = hash_create((HASHCMP *) strcmp, 977, hash4);
forw_table = hash_create((HASHCMP *) strcmp, 977, hash4);
cachemgrRegister("via_headers", "Via Request Headers", fvdbDumpVia, 0, 1);
cachemgrRegister("forw_headers", "X-Forwarded-For Request Headers",
fvdbDumpForw, 0, 1);
}

static void
fvdbCount(hash_table * hash, const char *key)
{
fvdb_entry *fv;
if (NULL == hash)
return;
fv = hash_lookup(hash, key);
if (NULL == fv) {
fv = xcalloc(1, sizeof(fvdb_entry));
fv->hash.key = xstrdup(key);
hash_join(hash, &fv->hash);
}
fv->n++;
}

void
fvdbCountVia(const char *key)
{
fvdbCount(via_table, key);
}

void
fvdbCountForw(const char *key)
{
fvdbCount(forw_table, key);
}

static void
fvdbDumpTable(StoreEntry * e, hash_table * hash)
{
hash_link *h;
fvdb_entry *fv;
if (hash == NULL)
return;
hash_first(hash);
while ((h = hash_next(hash))) {
fv = (fvdb_entry *) h;
storeAppendPrintf(e, "%9d %s\n", fv->n, hashKeyStr(&fv->hash));
}
}

static void
fvdbDumpVia(StoreEntry * e)
{
fvdbDumpTable(e, via_table);
}

static void
fvdbDumpForw(StoreEntry * e)
{
fvdbDumpTable(e, forw_table);
}

static
void
fvdbFreeEntry(void *data)
{
fvdb_entry *fv = data;
xfree(fv->hash.key);
xfree(fv);
}

static void
fvdbClear(void)
{
hashFreeItems(via_table, fvdbFreeEntry);
hashFreeMemory(via_table);
via_table = hash_create((HASHCMP *) strcmp, 977, hash4);
hashFreeItems(forw_table, fvdbFreeEntry);
hashFreeMemory(forw_table);
forw_table = hash_create((HASHCMP *) strcmp, 977, hash4);
}

#endif

#if MULTICAST_MISS_STREAM
/*
* From http://www.io.com/~paulhart/game/algorithms/tea.html
*
* size of 'ibuf' must be a multiple of 2.
* size of 'key' must be 4.
* 'ibuf' is modified in place, encrypted data is written in
* network byte order.
*/
static void
mcast_encode(unsigned int *ibuf, size_t isize, const unsigned int *key)
{
unsigned int y;
unsigned int z;
unsigned int sum;
const unsigned int delta = 0x9e3779b9;
unsigned int n = 32;
const unsigned int k0 = htonl(key[0]);
const unsigned int k1 = htonl(key[1]);
const unsigned int k2 = htonl(key[2]);
const unsigned int k3 = htonl(key[3]);
int i;
for (i = 0; i < isize; i += 2) {
y = htonl(ibuf[i]);
z = htonl(ibuf[i + 1]);
sum = 0;
for (n = 32; n; n--) {
sum += delta;
y += (z << 4) + (k0 ^ z) + (sum ^ (z >> 5)) + k1;
z += (y << 4) + (k2 ^ y) + (sum ^ (y >> 5)) + k3;
}
ibuf[i] = htonl(y);
ibuf[i + 1] = htonl(z);
}
}

#endif

#if HEADERS_LOG
void
headersLog(int cs, int pq, method_t m, void *data)
{
HttpReply *rep;
request_t *req;
unsigned short magic = 0;
unsigned char M = (unsigned char) m;
unsigned short S;
char *hmask;
int ccmask = 0;
if (0 == pq) {
/* reply */
rep = data;
req = NULL;
magic = 0x0050;
hmask = rep->header.mask;
if (rep->cache_control)
ccmask = rep->cache_control->mask;
} else {
/* request */
req = data;
rep = NULL;
magic = 0x0051;
hmask = req->header.mask;
if (req->cache_control)
ccmask = req->cache_control->mask;
}
if (0 == cs) {
/* client */
magic |= 0x4300;
} else {
/* server */
magic |= 0x5300;
}
magic = htons(magic);
ccmask = htonl(ccmask);
if (0 == pq)
S = (unsigned short) rep->sline.status;
else
S = (unsigned short) HTTP_STATUS_NONE;
logfileWrite(headerslog, &magic, sizeof(magic));
logfileWrite(headerslog, &M, sizeof(M));
logfileWrite(headerslog, &S, sizeof(S));
logfileWrite(headerslog, hmask, sizeof(HttpHeaderMask));
logfileWrite(headerslog, &ccmask, sizeof(int));
logfileFlush(headerslog);
}

#endif

[11] Comentário enviado por balani em 09/01/2008 - 19:54h

Valeu Amigo, vou testar

[12] Comentário enviado por balani em 10/01/2008 - 09:56h

Agora deu certo, muito obrigado pela atenção.

[13] Comentário enviado por rosemberg em 02/09/2008 - 23:09h

Filipe Meus parabens adorei o artigo como sou novato em linux, surgiu uma duvida, no meu caso o mysql encontra-se em outro servidor, seria possivel o redirecionamento ?

[14] Comentário enviado por m@verick em 03/09/2008 - 10:10h

Acredito que sim rosemberg, apesar de pessoalmente eu não ter testado, bastaria alterar esta parte do código

if ( mysql_real_connect(&conexao, "localhost", "Usuario", "Senha", "SeuBANCO", 0, NULL, 0) )
{

que está definindo o servidor como "localhost" para o "IP DE SEU SERVIDOR" , mas vale lembrar que isto geraria muito tráfego em sua rede por isso seria interessante ter um switch ou mesmo optar por manter o banco local mesmo.
Espero ter ajudado, T+

[15] Comentário enviado por viniciuspedra em 23/04/2009 - 17:46h

duvida...
para fazer esta inserção no mysql eu posso usar o squid q já eh instalado no debian ou terei que baixar a versão indicada no script?

[16] Comentário enviado por m@verick em 24/04/2009 - 00:30h

Olá Vinícius, na verdade o squid quando instalado pelo apt já foi compilado de modo que não é possível realizar as alterações necessárias, assim é preciso seguir o script baixando o source, realizando as alterações e posteriormente gerando uma nova compilação.
Espero ter ajudado, até mais.

[17] Comentário enviado por robsonsbrasil em 18/08/2009 - 08:32h

Bom dia amigos,

Estou seguindo esse tutorial a risca mas estou com o seguinte problema.

=== Depois de fazer toda conf no access_log.c e executo:

./configure CFLAGS=-lmysqlclient --enable-storeio=diskd,ufs

=== Ele mostra o seguinte:

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for gawk... no
checking for mawk... mawk
checking whether make sets $(MAKE)... yes
checking whether to enable maintainer-specific portions of Makefiles... no
checking for gcc... gcc
checking for C compiler default output file name...
configure: error: C compiler cannot create executables
See `config.log' for more details.


==== Veja um trecho meu config.log o qual ele meciona

$ ./configure CFLAGS=-lmysqlclient --enable-storeio=diskd,ufs

## --------- ##
## Platform. ##
## --------- ##

hostname = burucutu
uname -m = i686
uname -r = 2.6.26-2-686
uname -s = Linux
uname -v = #1 SMP Sun Jun 21 04:57:38 UTC 2009

/usr/bin/uname -p = unknown
/bin/uname -X = unknown

/bin/arch = unknown
/usr/bin/arch -k = unknown
/usr/convex/getsysinfo = unknown
/usr/bin/hostinfo = unknown
/bin/machine = unknown
/usr/bin/oslevel = unknown
/bin/universe = unknown

PATH: /usr/local/sbin
PATH: /usr/local/bin
PATH: /usr/sbin
PATH: /usr/bin
PATH: /sbin
PATH: /bin

## ----------- ##
## Core tests. ##
## ----------- ##

configure:2080: checking for a BSD-compatible install
configure:2136: result: /usr/bin/install -c
configure:2147: checking whether build environment is sane
configure:2190: result: yes
configure:2255: checking for gawk
configure:2285: result: no
configure:2255: checking for mawk
configure:2271: found /usr/bin/mawk
configure:2282: result: mawk
configure:2293: checking whether make sets $(MAKE)
configure:2314: result: yes
configure:2499: checking whether to enable maintainer-specific portions of Makefiles
configure:2508: result: no
configure:2579: checking for gcc
configure:2595: found /usr/bin/gcc
configure:2606: result: gcc
configure:2844: checking for C compiler version
configure:2851: gcc --version >&5
gcc (Debian 4.3.2-1.1) 4.3.2
Copyright (C) 2008 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

=== VEJA O /usr/bin/

g++ gcov getconf gettext gpg gpg-zip grog gtbl
g++-4.3 gcov-4.3 getent gettext.sh gpg-convert-from-106 gpic grops
gcc gencat getkeycodes ginstall-info gpgsplit gprof grotty
gcc-4.3 geqn getopt gpasswd gpgv groff groups

c++ c99-gcc catman chattr chsh cmp column consolechars cpanp-run-perl ctstat
c2ph cal cc chcon chvt codepage comm corelist cpp cut
c89 calendar c++filt chfn cksum col comp_err cpan cpp-4.3
c89-gcc captoinfo chage chkdupexe clear colcrt compose cpan2dist crontab
c99 catchsegv charset chrt clear_console colrm config_data cpanp csplit

=== Minha dist Debian 5 (lenny) - squid-2.6.STABLE16

Já coloquei o squid 3 e deu a mesma coisa

Gostaria da colaboração de vocês agradeço desde já
Abracos

PS: m@verick mandei uma mensagem e você não respondeu se possível responda.

[18] Comentário enviado por m0r473n53 em 05/09/2009 - 00:37h

Ola Robson.
tente instalar o pacote libmysqlclient15-dev e tente novamente.

abraço t+

[19] Comentário enviado por m@verick em 05/09/2009 - 13:15h

Me desculpe Robson, estava meio sem tempo para responder, fui postergando e acabei me esquecendo como m0r473n53 disse tente instalar a lib libmysqlclient15-dev

apt-get install libmysqlclient15-dev

Caso não de certo aguardo contato, T+.

[20] Comentário enviado por junior em 11/09/2009 - 19:47h

E aí irmão, certinho?
Eu copiei todo o access_log do seu comentário, o que você disse que funcionou e no final do make && make install, dá os seguintes erros:
access_log.cc:105:8: error: character constant too long for its type
access_log.cc:116:51: error: character constant too long for its type
access_log.cc:159:15: error: character constant too long for its type
access_log.cc:173:8: error: character constant too long for its type
access_log.cc:182:51: error: character constant too long for its type
access_log.cc:201:15: error: character constant too long for its type
access_log.cc:210:16: error: character constant too long for its type
access_log.cc:226:6: error: character constant too long for its type
access_log.cc:250:8: error: character constant too long for its type
access_log.cc:849:9: error: character constant too long for its type
access_log.cc:1155:57: error: character constant too long for its type
access_log.cc:1161:25: error: character constant too long for its type
access_log.cc: In function âchar* log_quote(const char*)â:
access_log.cc:104: error: invalid conversion from âvoid*â to âchar*â
cc1plus: warnings being treated as errors
access_log.cc:105: error: overflow in implicit constant conversion
access_log.cc:108: error: invalid conversion from âvoid*â to âchar*â
access_log.cc:159: error: overflow in implicit constant conversion
access_log.cc: In function âchar* username_quote(const char*)â:
access_log.cc:172: error: invalid conversion from âvoid*â to âchar*â
access_log.cc:173: error: overflow in implicit constant conversion
access_log.cc:176: error: invalid conversion from âvoid*â to âchar*â
access_log.cc:201: error: overflow in implicit constant conversion
access_log.cc: In function âchar* log_quoted_string(const char*)â:
access_log.cc:218: error: invalid conversion from âvoid*â to âchar*â
access_log.cc:226: error: overflow in implicit constant conversion
access_log.cc:250: error: overflow in implicit constant conversion
access_log.cc: At global scope:
access_log.cc:437: error: variable or field âaccessLogCustomâ declared void
access_log.cc:437: error: âAccessLogEntryâ was not declared in this scope
access_log.cc:437: error: âalâ was not declared in this scope
access_log.cc:437: error: expected primary-expression before â*â token
access_log.cc:72: error: âLogfileStatusâ defined but not used
access_log.cc:206: error: âchar* accessLogFormatName(const char*)â defined but not used
access_log.cc:216: error: âchar* log_quoted_string(const char*)â defined but not used
make[3]: ** [access_log.o] Erro 1
make[3]: Saindo do diretório `/root/Arquivos/squid-3.0.STABLE19/src'
make[2]: ** [all-recursive] Erro 1
make[2]: Saindo do diretório `/root/Arquivos/squid-3.0.STABLE19/src'
make[1]: ** [all] Erro 2
make[1]: Saindo do diretório `/root/Arquivos/squid-3.0.STABLE19/src'
make: ** [all-recursive] Erro 1

[21] Comentário enviado por SheylaCristina em 10/04/2010 - 14:51h

gostaria de uma solução de como gravas os logs de acesso do squid no mysql, testei esse tutorial mas nao obtive resultado. O log do squid deve ser gravado no mysql sem auxilio de mysar.

[22] Comentário enviado por m@verick em 10/04/2010 - 16:50h

Olá Sheyla, vc poderia me informar onde esta ocorrendo o problema para que eu possa tentar ajudar, pois esta não é lá das melhores soluções mas funciona desde que esteja atenta as alterações que são necessarias fazer no fonte e todos os passos configuração como o banco de dados, ja faz algum tempo que aplico esta solução, preciso me atualizar com as novas versões do squid.

[23] Comentário enviado por sheylacristina em 15/04/2010 - 10:18h

intao e que preciso saber como eu gravo todos os meus logs do squid no mysql preciso que os logs sejam gravados de forma automatica e a leitura possa ser feita atraves do php como no apache sabe, qndo nos gravamos os logs do apache no mysql e utilizamos o phpmyadmim para visualizar ?! Poise preciso da msma coisa so que neste caso com o SQUID.

[24] Comentário enviado por viniciuspedra em 05/07/2010 - 17:00h

olá! é necessário compilar este squid? Não pode ser utilizado o nativo do linux?

[25] Comentário enviado por keuzar em 10/11/2010 - 09:24h

M@averick, compilei o source normalmente, instalei, mas quanto tento subir o squid ele retorna um erro -- FATAL: cache_dir /usr/local/squid/var/cache: (2) No such file or directory

criei o diretorio cache, e novamente quando tento subir retorna outro erro -- FATAL: Could not determine fully qualified hostname. Please set 'visible_hostname'

pode me ajudar?

[26] Comentário enviado por m@verick em 10/11/2010 - 10:02h

vc executou o squid -z para criar os diretorios de cache, depois confira se os diretorios realmente estao lá, t+

[27] Comentário enviado por keuzar em 11/11/2010 - 08:24h

quando eu executo squid -z diz q o programa nao esta instalado, mas eu executei o make, make install e ate onde vi nao deu erro... que coisa em!!!
q ki eu faco?

to dependendo disso pra faze um trabalho da facul, da um help ai..vlw

[28] Comentário enviado por m@verick em 11/11/2010 - 11:18h

Seguinte procure na pasta onde vc realizou a compilação pelo arquivos binarios, deve haver a pasta bin e lá deve estar o executavel, por ex. vc compilou na pasta /dados ae vc executará o squid da /dados/bin/squid se nao me engano to tentanto lembrar de kbça... de uma procurada OK, espero ajudar t+.

[29] Comentário enviado por keuzar em 11/11/2010 - 19:35h

cara..desculpa a ignorancia, mas to bastante confuso.. a pasta bin esta no diretorio /usr/local/squid
nele contem os executaveis RunCache e SquidClient.., tento executa o SquidCliente ele retorna mensagem de conexao recusada no localhost porta 3128..
na pasta sbin existe o executavel squid, ele sim retorna os erros que te falei no meu primeiro comentario.

sinceramente nao sei oq fazer ..

[30] Comentário enviado por glaucoperucchi em 14/03/2011 - 23:46h

Boa noite amigo,

Estou com seguinte problema, copiei teu fonte dos comentarios cujo o balani disse que funcionou. Mas no meu esta acontecendo o do mesmo erro do junior.rocha.

access_log.c:105:8: warning: character constant too long for its type
access_log.c: In function ‘log_quote’:
access_log.c:105: warning: overflow in implicit constant conversion
access_log.c:116:51: warning: character constant too long for its type
access_log.c:159:15: warning: character constant too long for its type
access_log.c:159: warning: overflow in implicit constant conversion
access_log.c:173:8: warning: character constant too long for its type
access_log.c: In function ‘username_quote’:
access_log.c:173: warning: overflow in implicit constant conversion
access_log.c:182:51: warning: character constant too long for its type
access_log.c:201:15: warning: character constant too long for its type
access_log.c:201: warning: overflow in implicit constant conversion
access_log.c:210:16: warning: character constant too long for its type
access_log.c:226:6: warning: character constant too long for its type
access_log.c: In function ‘log_quoted_string’:
access_log.c:226: warning: case label value exceeds maximum value for type
access_log.c:250:8: warning: character constant too long for its type
access_log.c:250: warning: overflow in implicit constant conversion
access_log.c:849:9: warning: character constant too long for its type
access_log.c: In function ‘accessLogGetNewLogFormatToken’:
access_log.c:849: warning: overflow in implicit constant conversion
access_log.c:1155:57: warning: character constant too long for its type
access_log.c:1161:25: warning: character constant too long for its type
make[3]: ** [access_log.o] Erro 1
make[3]: Saindo do diretório `/usr/local/etc/squid-2.6.STABLE16/src'
make[2]: ** [all-recursive] Erro 1
make[2]: Saindo do diretório `/usr/local/etc/squid-2.6.STABLE16/src'
make[1]: ** [all] Erro 2
make[1]: Saindo do diretório `/usr/local/etc/squid-2.6.STABLE16/src'
make: ** [all-recursive] Erro 1

Poderia me ajudar?
Obrigado pela atenção

[31] Comentário enviado por m@verick em 30/03/2011 - 08:50h

opa me desculpem pela demora,
Este erro glauco.skt se deve a alguma incompatilbilidade com o GCC, não me recordo a versao que usavao antes , ao inves de opiar o fonte tente alterar apenas a linhas indicadas no codigo fonte original.

[32] Comentário enviado por fabriciobslogan em 27/04/2011 - 16:34h

Puxa sou iniciante no squid e isso me ajudou bastante sempre tive interesse em saber o que significava cada item!!!
Muito Obrigado !!!
vlw.
Fica com Deus!!!

[33] Comentário enviado por ewerton.silveira em 16/11/2011 - 23:08h

Cara adorei seu tópico sobre o log do squid fiz aqui e funciono só gostaria de saber como ficaria o codigo para que todas as informaçoes do log ficasse armazenadas no bd?

OBS: Mandei a dúvida por email mais acredito que possa ser util para outros por isso postei aqui também!!

Att,

Ewerton Silveira

[34] Comentário enviado por m@verick em 25/11/2011 - 10:14h

Ewerton,
desculpa a demora em respoder cara, seguinte para armazenar todos os dados no db basta
incluir os campos que vc deseja e da uma olhada nos atributos disponiveis no obj al->
p ex para pegar a url solicita usamos al->url e concatemos direto na string SQL pq ->url ja é string os demais itens basta verificar o tipo e fazer as conversões, todo o caso me posta os itens que vc ficou em duvida e deseja incluir, T+.

[35] Comentário enviado por vermei em 22/05/2012 - 11:56h

Olá segui todos os passos, mas quando executo o comando make da o seguite erro.


Making all in lib
make[1]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/lib'
make[1]: Nada a ser feito para `all'.
make[1]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/lib'
Making all in scripts
make[1]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/scripts'
make[1]: Nada a ser feito para `all'.
make[1]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/scripts'
Making all in src
make[1]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/src'
sed "\
s%@DEFAULT_HTTP_PORT@%3128%g;\
s%@DEFAULT_ICP_PORT@%3130%g;\
s%@DEFAULT_MIME_TABLE@%/usr/local/squid/etc/mime.conf%g;\
s%@DEFAULT_DNSSERVER@%/usr/local/squid/libexec/`echo dnsserver | sed 's,x,x,;s/$//'`%g;\
s%@DEFAULT_UNLINKD@%/usr/local/squid/libexec/`echo unlinkd | sed 's,x,x,;s/$//'`%g;\
s%@DEFAULT_PINGER@%/usr/local/squid/libexec/`echo pinger | sed 's,x,x,;s/$//'`%g;\
s%@DEFAULT_DISKD@%/usr/local/squid/libexec/`echo diskd-daemon | sed 's,x,x,;s/$//'`%g;\
s%@DEFAULT_LOGFILED@%/usr/local/squid/libexec/`echo logfile-daemon | sed 's,x,x,;s/$//'`%g;\
s%@DEFAULT_CACHE_LOG@%/usr/local/squid/var/logs/cache.log%g;\
s%@DEFAULT_ACCESS_LOG@%/usr/local/squid/var/logs/access.log%g;\
s%@DEFAULT_STORE_LOG@%/usr/local/squid/var/logs/store.log%g;\
s%@DEFAULT_PID_FILE@%/usr/local/squid/var/logs/squid.pid%g;\
s%@DEFAULT_NETDB_FILE@%/usr/local/squid/var/logs/netdb.state%g;\
s%@DEFAULT_SWAP_DIR@%/usr/local/squid/var/cache%g;\
s%@DEFAULT_ICON_DIR@%/usr/local/squid/share/icons%g;\
s%@DEFAULT_MIB_PATH@%/usr/local/squid/share/mib.txt%g;\
s%@DEFAULT_ERROR_DIR@%/usr/local/squid/share/errors/English%g;\
s%@DEFAULT_PREFIX@%/usr/local/squid%g;\
s%@DEFAULT_HOSTS@%/etc/hosts%g;\
s%@[V]ERSION@%2.7.STABLE9%g;"\
< ./cf.data.pre >cf.data
./cf_gen cf.data ./cf.data.depend
/bin/bash ./repl_modules.sh lru > repl_modules.c
/bin/bash ./store_modules.sh diskd ufs >store_modules.c
make all-recursive
make[2]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/src'
Making all in fs
make[3]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/src/fs'
make[3]: Nada a ser feito para `all'.
make[3]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/src/fs'
Making all in repl
make[3]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/src/repl'
make[3]: Nada a ser feito para `all'.
make[3]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/src/repl'
Making all in auth
make[3]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/src/auth'
make[3]: Nada a ser feito para `all'.
make[3]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/src/auth'
make[3]: Entrando no diretório `/home/usuario/squid-2.7.STABLE9/src'
gcc -DHAVE_CONFIG_H -DDEFAULT_CONFIG_FILE=\"/usr/local/squid/etc/squid.conf\" -I. -I../include -I. -I. -I../include -I../include -lmysqlclient -MT access_log.o -MD -MP -MF .deps/access_log.Tpo -c -o access_log.o access_log.c
access_log.c: Na função âlog_quoteâ:
access_log.c:106:8: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:106:1: aviso: overflow in implicit constant conversion [-Woverflow]
access_log.c:117:51: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:160:15: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:160:1: aviso: overflow in implicit constant conversion [-Woverflow]
access_log.c: Na função âusername_quoteâ:
access_log.c:174:8: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:174:1: aviso: overflow in implicit constant conversion [-Woverflow]
access_log.c:183:51: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:202:15: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:202:1: aviso: overflow in implicit constant conversion [-Woverflow]
access_log.c: Na função âaccessLogFormatNameâ:
access_log.c:211:16: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c: Na função âlog_quoted_stringâ:
access_log.c:227:6: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:227:1: aviso: case label value exceeds maximum value for type [habilitado por padrão]
access_log.c:251:8: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:251:1: aviso: overflow in implicit constant conversion [-Woverflow]
access_log.c: Na função âaccessLogGetNewLogFormatTokenâ:
access_log.c:850:9: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:850:1: aviso: overflow in implicit constant conversion [-Woverflow]
access_log.c: Na função âaccessLogSquidâ:
access_log.c:1065:1: aviso: formato â%dâ expects argument of type âintâ, but argument 4 has type âsquid_off_tâ [-Wformat]
access_log.c:1065:1: aviso: formato â%dâ expects argument of type âintâ, but argument 4 has type âsquid_off_tâ [-Wformat]
access_log.c:1080:1: aviso: formato â%dâ expects argument of type âintâ, but argument 3 has type âmy_ulonglongâ [-Wformat]
access_log.c: Na função âaccessLogLogâ:
access_log.c:1168:57: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
access_log.c:1173:26: erro: âRequestMethodStrâ undeclared (first use in this function)
access_log.c:1173:26: nota: each undeclared identifier is reported only once for each function it appears in
access_log.c:1174:25: aviso: constante de caracteres muito longa para seu tipo [habilitado por padrão]
make[3]: ** [access_log.o] Erro 1
make[3]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/src'
make[2]: ** [all-recursive] Erro 1
make[2]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/src'
make[1]: ** [all] Erro 2
make[1]: Saindo do diretório `/home/usuario/squid-2.7.STABLE9/src'
make: ** [all-recursive] Erro 1

[36] Comentário enviado por marcos.ths em 27/03/2014 - 10:30h

Amigo, funciona com squid3 ?

Pois estou tentando aqui e esta dando erros na compilação.

[37] Comentário enviado por m@verick em 25/05/2020 - 20:47h


[36] Comentário enviado por marcos.ths em 27/03/2014 - 10:30h

Amigo, funciona com squid3 ?

Pois estou tentando aqui e esta dando erros na compilação.


Marcos as bibliotecas mudaram muito mas na versão 2
vai que é um fuke...


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts