/* HTSQL.c ** SQL LOGGING MODULE ** ** (c) COPYRIGHT MIT 1995. ** Please first read the full copyright statement in the file COPYRIGH. ** @(#) $Id: HTSQLLog.c,v 2.2 1998/05/19 16:49:39 frystyk Exp $ ** ** This module contains a simple SQL based logging mechanism for requests ** and anything else you want to log ** ** History: ** 23 Apr 98 Henrik Frystyk, frystyk@w3.org */ /* Library include files */ #include "WWWLib.h" #include "HTSQL.h" #include "HTSQLLog.h" /* Implemented here */ #include struct _HTSQLLog { HTSQL * sql; char * relative; /* Make URIs relative to */ int accesses; HTSQLLogFlags flags; }; #define DEFAULT_SQL_URIS_TABLE "uris" #define DEFAULT_SQL_REQUESTS_TABLE "requests" #define DEFAULT_SQL_RESOURCES_TABLE "resources" #define DEFAULT_SQL_LINKS_TABLE "links" #define DEFAULT_SQL_KEY_TYPE "int unsigned not null" #define MAX_URI_LENGTH 255 /* ------------------------------------------------------------------------- */ PRIVATE int find_uri(HTSQLLog * me, const char * uri) { int index = -1; if (me && me->sql && uri) { char buf[1024]; char * query = NULL; MYSQL_RES * result = NULL; query = HTSQL_printf(buf, 1024, "select * from %s where uri=%S", DEFAULT_SQL_URIS_TABLE, uri); if (HTSQL_query(me->sql, query) && (result = HTSQL_storeResult(me->sql)) != NULL) { MYSQL_ROW row; if ((row = mysql_fetch_row(result)) && row[0]) index = atoi(row[0]); HTSQL_freeResult(result); } } return index; } PRIVATE int add_uri (HTSQLLog * me, const char * uri) { if (me && me->sql && uri) { int index = -1; char * rel = me->relative ? HTRelative(uri, me->relative) : NULL; /* If we can't find the URI then add it */ if ((index = find_uri(me, rel ? rel : uri)) < 0) { char buf[1024]; char * query = HTSQL_printf(buf, 1024, "insert into %s (uri) values (%S)", DEFAULT_SQL_URIS_TABLE, rel ? rel : uri); if (HTSQL_query(me->sql, query) != YES) { HT_FREE(rel); return -1; } index = HTSQL_getLastInsertId(me->sql); } HT_FREE(rel); return index; } return -1; } PRIVATE BOOL add_linktype (HTSQLLog * me, int srcidx, int dstidx, const char * type, const char * comment) { if (me && me->sql && srcidx>=0 && dstidx>=0 && type) { char buf[1024]; char * query = HTSQL_printf(buf, 1024, "insert into %s values (%u,%u,%S,%S)", DEFAULT_SQL_LINKS_TABLE, srcidx, dstidx, type, comment); return HTSQL_query(me->sql, query); } return NO; } PRIVATE BOOL clear_table (HTSQLLog * me, const char * table) { if (me && me->sql && table) { char buf[1024]; char * query = HTSQL_printf(buf, 1024, "delete from %s", table); return HTSQL_query(me->sql, query); } return NO; } PRIVATE BOOL drop_table (HTSQLLog * me, const char * table) { if (me && me->sql && table) { char buf[1024]; char * query = HTSQL_printf(buf, 1024, "drop table %s", table); return HTSQL_query(me->sql, query); } return NO; } PRIVATE BOOL createTables (HTSQLLog * me, HTSQLLogFlags flags) { if (me && me->sql) { char buf[1024]; char * query = NULL; /* If we have to delete it first */ if (flags & HTSQLLOG_DROP_URIS_TABLE) drop_table(me, DEFAULT_SQL_URIS_TABLE); /* Create URI table (which is the index) */ query = HTSQL_printf(buf, 1024, "create table %s (id %s auto_increment, uri varchar(%u) binary not null, primary key(id), unique (uri), index uri_idx (uri(32)))", DEFAULT_SQL_URIS_TABLE, DEFAULT_SQL_KEY_TYPE, MAX_URI_LENGTH); HTSQL_query(me->sql, query); /* If we have to clear it out */ if (flags & HTSQLLOG_CLEAR_URIS_TABLE) clear_table(me, DEFAULT_SQL_URIS_TABLE); /* If we have to delete it first */ if (flags & HTSQLLOG_DROP_REQUESTS_TABLE) drop_table(me, DEFAULT_SQL_REQUESTS_TABLE); /* Create Request table */ query = HTSQL_printf(buf, 1024, "create table %s (uri %s primary key, method char(16) not null, status int unsigned not null, request_time datetime, response_time datetime)", DEFAULT_SQL_REQUESTS_TABLE, DEFAULT_SQL_KEY_TYPE); HTSQL_query(me->sql, query); /* If we have to clear it out */ if (flags & HTSQLLOG_CLEAR_REQUESTS_TABLE) clear_table(me, DEFAULT_SQL_REQUESTS_TABLE); /* If we have to delete it first */ if (flags & HTSQLLOG_DROP_RESOURCES_TABLE) drop_table(me, DEFAULT_SQL_RESOURCES_TABLE); /* Create Resource table */ query = HTSQL_printf(buf, 1024, "create table %s (uri %s primary key, length bigint unsigned not null, last_modified datetime, expires datetime, content_type char(32), charset char(32), content_encoding char(32), content_language char(32), title char(128))", DEFAULT_SQL_RESOURCES_TABLE, DEFAULT_SQL_KEY_TYPE); HTSQL_query(me->sql, query); /* If we have to clear it out */ if (flags & HTSQLLOG_CLEAR_RESOURCES_TABLE) clear_table(me, DEFAULT_SQL_RESOURCES_TABLE); /* If we have to delete it first */ if (flags & HTSQLLOG_DROP_LINKS_TABLE) drop_table(me, DEFAULT_SQL_LINKS_TABLE); /* Create Link Relations table */ query = HTSQL_printf(buf, 1024, "create table %s (source %s, destination %s, link_type char(32) not null, comment char(128), unique(source,destination,link_type))", DEFAULT_SQL_LINKS_TABLE, DEFAULT_SQL_KEY_TYPE, DEFAULT_SQL_KEY_TYPE); HTSQL_query(me->sql, query); /* If we have to clear it out */ if (flags & HTSQLLOG_CLEAR_LINKS_TABLE) clear_table(me, DEFAULT_SQL_LINKS_TABLE); /* All done */ return YES; } return NO; } /* Open a connection ** ----------------- ** Returns YES if OK, NO on error */ PUBLIC HTSQLLog * HTSQLLog_open (const char * host, const char * user, const char * pw, const char * db, HTSQLLogFlags flags) { HTSQLLog * me = NULL; if (!host || !user || !pw || !db) { if (SQL_TRACE) HTTrace("SQLLog...... Missing SQLLog host, user, password, or db\n"); return NULL; } if ((me = (HTSQLLog *) HT_CALLOC(1, sizeof(HTSQLLog))) == NULL) HT_OUTOFMEM("HTSQLLog_open"); if ((me->sql = HTSQL_new(host, user, pw, 0)) != NULL && HTSQL_connect(me->sql) == YES && HTSQL_selectDB(me->sql, db) == YES) { /* Make sure we have the right set of tables */ createTables(me, flags); me->flags = flags; } else { HTSQL_delete(me->sql); HT_FREE(me); } return me; } /* Close connection ** ---------------- ** Returns YES if OK, NO on error */ PUBLIC BOOL HTSQLLog_close (HTSQLLog * me) { if (me) { if (me->sql) HTSQL_close(me->sql); HT_FREE(me->relative); HT_FREE(me); return YES; } return NO; } PUBLIC BOOL HTSQLLog_clearTables (HTSQLLog * me) { if (me && me->sql) { /* ... */ return YES; } return NO; } PUBLIC BOOL HTSQLLog_makeRelativeTo (HTSQLLog * me, const char * relative) { if (me) { StrAllocCopy(me->relative, relative); return YES; } return NO; } PUBLIC int HTSQLLog_accessCount (HTSQLLog * me) { return me ? me->accesses : -1; } PUBLIC BOOL HTSQLLog_addURI (HTSQLLog * me, const char * uri) { return (me && me->sql && (add_uri(me, uri)>=0)); } PUBLIC BOOL HTSQLLog_addLinkRelationship (HTSQLLog * me, const char * src_uri, const char * dst_uri, const char * link_type, const char * comment) { if (src_uri && dst_uri) { int srcidx = add_uri(me, src_uri); int dstidx = add_uri(me, dst_uri); return add_linktype(me, srcidx, dstidx, link_type, comment); } return NO; } PUBLIC BOOL HTSQLLog_addEntry (HTSQLLog * me, HTRequest * request, int status) { if (me && me->sql) { HTParentAnchor * anchor = HTRequest_anchor(request); HTParentAnchor * parent_anchor = HTRequest_parent(request); char * uri = HTAnchor_address((HTAnchor *) anchor); int index = 0; char buf[512]; char * query = NULL; /* Insert into the URI table */ if ((index = add_uri(me, uri)) < 0) { HT_FREE(uri); return NO; } /* Insert into the request table */ query = HTSQL_printf(buf, 512, "replace into %s values (%u,%S,%u,%T,%T)", DEFAULT_SQL_REQUESTS_TABLE, index, HTMethod_name(HTRequest_method(request)), abs(status), HTRequest_date(request), HTAnchor_date(anchor)); if (HTSQL_query(me->sql, query) != YES) { HT_FREE(uri); return NO; } /* Insert into the resource table */ { HTList * encodings = HTAnchor_encoding(anchor); HTList * languages = HTAnchor_language(anchor); HTFormat format = HTAnchor_format(anchor); HTCharset charset = HTAnchor_charset(anchor); HTEncoding encoding = encodings ? HTList_firstObject(encodings) : NULL; HTLanguage language = languages ? HTList_firstObject(languages) : NULL; query = HTSQL_printf(buf, 512, "replace into %s values (%u,%l,%T,%T,%S,%S,%S,%S,%S)", DEFAULT_SQL_RESOURCES_TABLE, index, HTAnchor_length(anchor), HTAnchor_lastModified(anchor), HTAnchor_expires(anchor), format != WWW_UNKNOWN ? HTAtom_name(format) : NULL, charset ? HTAtom_name(charset) : NULL, encoding ? HTAtom_name(encoding) : NULL, language ? HTAtom_name(language) : NULL, HTAnchor_title(anchor)); if (HTSQL_query(me->sql, query) != YES) { HT_FREE(uri); return NO; } } /* Insert into the relationship table */ if (parent_anchor) { char * parent = HTAnchor_address((HTAnchor *) parent_anchor); if (uri && parent && *parent) { int srcidx = add_uri(me, parent); add_linktype(me, srcidx, index, "referer", NULL); } HT_FREE(parent); } /* Count one more access */ me->accesses++; HT_FREE(uri); return YES; } return NO; }