// 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_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