// swad_log.c: access log stored in database
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2021 Antonio Caņas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General 3 License as
published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
/*****************************************************************************/
/*********************************** Headers *********************************/
/*****************************************************************************/
#include // For free
#include // For strlen
#include "swad_action.h"
#include "swad_banner.h"
#include "swad_center_database.h"
#include "swad_config.h"
#include "swad_database.h"
#include "swad_degree_database.h"
#include "swad_exam_log.h"
#include "swad_global.h"
#include "swad_hierarchy.h"
#include "swad_HTML.h"
#include "swad_log.h"
#include "swad_profile.h"
#include "swad_role.h"
#include "swad_statistic.h"
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
#define Log_SECONDS_IN_RECENT_LOG ((time_t) (Cfg_DAYS_IN_RECENT_LOG * 24UL * 60UL * 60UL)) // Remove entries in recent log oldest than this time
/*****************************************************************************/
/****************************** Private types ********************************/
/*****************************************************************************/
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/************************* Private global variables **************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
/*****************************************************************************/
/**************************** Log access in database *************************/
/*****************************************************************************/
void Log_LogAccess (const char *Comments)
{
long LogCod;
long ActCod = Act_GetActCod (Gbl.Action.Act);
size_t MaxLength;
char *CommentsDB;
long BanCodClicked;
Rol_Role_t RoleToStore = (Gbl.Action.Act == ActLogOut) ? Gbl.Usrs.Me.Role.LoggedBeforeCloseSession :
Gbl.Usrs.Me.Role.Logged;
/***** Insert access into database *****/
/* Log access in historical log */
LogCod =
DB_QueryINSERTandReturnCode ("can not log access",
"INSERT INTO log"
" (ActCod,CtyCod,InsCod,CtrCod,DegCod,CrsCod,"
"UsrCod,Role,ClickTime,"
"TimeToGenerate,TimeToSend,IP)"
" VALUES"
" (%ld,%ld,%ld,%ld,%ld,%ld,"
"%ld,%u,NOW(),"
"%ld,%ld,'%s')",
ActCod,
Gbl.Hierarchy.Cty.CtyCod,
Gbl.Hierarchy.Ins.InsCod,
Gbl.Hierarchy.Ctr.CtrCod,
Gbl.Hierarchy.Deg.DegCod,
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
(unsigned) RoleToStore,
Gbl.TimeGenerationInMicroseconds,
Gbl.TimeSendInMicroseconds,
Gbl.IP);
/* Log access in recent log (log_recent) */
DB_QueryINSERT ("can not log access (recent)",
"INSERT INTO log_recent"
" (LogCod,ActCod,CtyCod,InsCod,CtrCod,DegCod,CrsCod,"
"UsrCod,Role,ClickTime,"
"TimeToGenerate,TimeToSend,IP)"
" VALUES"
" (%ld,%ld,%ld,%ld,%ld,%ld,%ld,"
"%ld,%u,NOW(),"
"%ld,%ld,'%s')",
LogCod,
ActCod,
Gbl.Hierarchy.Cty.CtyCod,
Gbl.Hierarchy.Ins.InsCod,
Gbl.Hierarchy.Ctr.CtrCod,
Gbl.Hierarchy.Deg.DegCod,
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
(unsigned) RoleToStore,
Gbl.TimeGenerationInMicroseconds,
Gbl.TimeSendInMicroseconds,
Gbl.IP);
/* Log access while answering exam prints */
ExaLog_LogAccess (LogCod);
/* Log comments */
if (Comments)
{
MaxLength = strlen (Comments) * Str_MAX_BYTES_PER_CHAR;
if ((CommentsDB = malloc (MaxLength + 1)) != NULL)
{
Str_Copy (CommentsDB,Comments,MaxLength);
Str_ChangeFormat (Str_FROM_TEXT,Str_TO_TEXT,
CommentsDB,MaxLength,true); // Avoid SQL injection
DB_QueryINSERT ("can not log access (comments)",
"INSERT INTO log_comments"
" (LogCod,Comments)"
" VALUES"
" (%ld,'%s')",
LogCod,
CommentsDB);
free (CommentsDB);
}
}
/* Log search string */
if (Gbl.Search.LogSearch && Gbl.Search.Str[0])
DB_QueryINSERT ("can not log access (search)",
"INSERT INTO log_search"
" (LogCod,SearchStr)"
" VALUES"
" (%ld,'%s')",
LogCod,
Gbl.Search.Str);
if (Gbl.WebService.IsWebService)
/* Log web service plugin and function */
DB_QueryINSERT ("can not log access (comments)",
"INSERT INTO log_api"
" (LogCod,PlgCod,FunCod)"
" VALUES"
" (%ld,%ld,%u)",
LogCod,
Gbl.WebService.PlgCod,
(unsigned) Gbl.WebService.Function);
else
{
BanCodClicked = Ban_GetBanCodClicked ();
if (BanCodClicked > 0)
/* Log banner clicked */
DB_QueryINSERT ("can not log banner clicked",
"INSERT INTO log_banners"
" (LogCod,BanCod)"
" VALUES"
" (%ld,%ld)",
LogCod,
BanCodClicked);
}
/***** Increment my number of clicks *****/
if (Gbl.Usrs.Me.Logged)
Prf_IncrementNumClicksUsr (Gbl.Usrs.Me.UsrDat.UsrCod);
}
/*****************************************************************************/
/************ Sometimes, we delete old entries in recent log table ***********/
/*****************************************************************************/
void Log_RemoveOldEntriesRecentLog (void)
{
/***** Remove all expired clipboards *****/
DB_QueryDELETE ("can not remove old entries from recent log",
"DELETE LOW_PRIORITY FROM log_recent"
" WHERE ClickTime