swad-core/swad_forum.c

3528 lines
128 KiB
C
Raw Permalink Normal View History

2014-12-01 23:55:08 +01:00
// swad_forum.c: forums
/*
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-2023 Antonio Ca<EFBFBD>as Vargas
2014-12-01 23:55:08 +01:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public 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 <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
2018-10-22 00:31:44 +02:00
#define _GNU_SOURCE // For asprintf
2014-12-01 23:55:08 +01:00
#include <malloc.h> // For malloc
#include <mysql/mysql.h> // To access MySQL databases
2019-12-29 12:39:00 +01:00
#include <stddef.h> // For NULL
2018-10-22 00:31:44 +02:00
#include <stdio.h> // For asprintf
2014-12-01 23:55:08 +01:00
#include <string.h>
#include <time.h> // For time_t
#include "swad_action.h"
#include "swad_action_list.h"
2017-06-10 21:38:10 +02:00
#include "swad_box.h"
#include "swad_center_database.h"
2014-12-01 23:55:08 +01:00
#include "swad_config.h"
#include "swad_course_database.h"
2014-12-01 23:55:08 +01:00
#include "swad_database.h"
#include "swad_degree_database.h"
#include "swad_error.h"
2020-04-14 17:15:17 +02:00
#include "swad_figure.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2014-12-01 23:55:08 +01:00
#include "swad_forum.h"
#include "swad_forum_database.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
2021-02-11 23:27:48 +01:00
#include "swad_hierarchy.h"
2019-10-23 19:05:05 +02:00
#include "swad_HTML.h"
2014-12-01 23:55:08 +01:00
#include "swad_layout.h"
2015-01-17 20:06:25 +01:00
#include "swad_logo.h"
2020-04-14 17:15:17 +02:00
#include "swad_message.h"
2014-12-01 23:55:08 +01:00
#include "swad_notification.h"
#include "swad_notification_database.h"
2020-04-07 03:01:41 +02:00
#include "swad_pagination.h"
2014-12-01 23:55:08 +01:00
#include "swad_parameter.h"
#include "swad_parameter_code.h"
2015-03-14 17:39:04 +01:00
#include "swad_profile.h"
#include "swad_profile_database.h"
#include "swad_program_database.h"
2016-12-13 13:32:19 +01:00
#include "swad_role.h"
2019-03-12 21:25:55 +01:00
#include "swad_timeline.h"
#include "swad_timeline_database.h"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
2019-11-21 11:39:30 +01:00
/************************ Public constants and types *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
const Act_Action_t For_ActionsSeeFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActSeeForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActSeeForCrsTch,
[For_FORUM_DEGREE_USRS] = ActSeeForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActSeeForDegTch,
[For_FORUM_CENTER_USRS] = ActSeeForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActSeeForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActSeeForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActSeeForInsTch,
[For_FORUM_GLOBAL_USRS] = ActSeeForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActSeeForGenTch,
[For_FORUM__SWAD__USRS] = ActSeeForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActSeeForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsSeePstFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActSeePstForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActSeePstForCrsTch,
[For_FORUM_DEGREE_USRS] = ActSeePstForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActSeePstForDegTch,
[For_FORUM_CENTER_USRS] = ActSeePstForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActSeePstForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActSeePstForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActSeePstForInsTch,
[For_FORUM_GLOBAL_USRS] = ActSeePstForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActSeePstForGenTch,
[For_FORUM__SWAD__USRS] = ActSeePstForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActSeePstForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsRecThrFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActRcvThrForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActRcvThrForCrsTch,
[For_FORUM_DEGREE_USRS] = ActRcvThrForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActRcvThrForDegTch,
[For_FORUM_CENTER_USRS] = ActRcvThrForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActRcvThrForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActRcvThrForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActRcvThrForInsTch,
[For_FORUM_GLOBAL_USRS] = ActRcvThrForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActRcvThrForGenTch,
[For_FORUM__SWAD__USRS] = ActRcvThrForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActRcvThrForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsRecRepFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActRcvRepForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActRcvRepForCrsTch,
[For_FORUM_DEGREE_USRS] = ActRcvRepForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActRcvRepForDegTch,
[For_FORUM_CENTER_USRS] = ActRcvRepForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActRcvRepForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActRcvRepForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActRcvRepForInsTch,
[For_FORUM_GLOBAL_USRS] = ActRcvRepForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActRcvRepForGenTch,
[For_FORUM__SWAD__USRS] = ActRcvRepForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActRcvRepForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsReqDelThr[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActReqDelThrCrsUsr,
[For_FORUM_COURSE_TCHS] = ActReqDelThrCrsTch,
[For_FORUM_DEGREE_USRS] = ActReqDelThrDegUsr,
[For_FORUM_DEGREE_TCHS] = ActReqDelThrDegTch,
[For_FORUM_CENTER_USRS] = ActReqDelThrCtrUsr,
[For_FORUM_CENTER_TCHS] = ActReqDelThrCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActReqDelThrInsUsr,
[For_FORUM_INSTIT_TCHS] = ActReqDelThrInsTch,
[For_FORUM_GLOBAL_USRS] = ActReqDelThrGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActReqDelThrGenTch,
[For_FORUM__SWAD__USRS] = ActReqDelThrSWAUsr,
[For_FORUM__SWAD__TCHS] = ActReqDelThrSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsDelThrFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActDelThrForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActDelThrForCrsTch,
[For_FORUM_DEGREE_USRS] = ActDelThrForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActDelThrForDegTch,
[For_FORUM_CENTER_USRS] = ActDelThrForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActDelThrForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActDelThrForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActDelThrForInsTch,
[For_FORUM_GLOBAL_USRS] = ActDelThrForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActDelThrForGenTch,
[For_FORUM__SWAD__USRS] = ActDelThrForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActDelThrForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsCutThrFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActCutThrForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActCutThrForCrsTch,
[For_FORUM_DEGREE_USRS] = ActCutThrForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActCutThrForDegTch,
[For_FORUM_CENTER_USRS] = ActCutThrForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActCutThrForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActCutThrForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActCutThrForInsTch,
[For_FORUM_GLOBAL_USRS] = ActCutThrForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActCutThrForGenTch,
[For_FORUM__SWAD__USRS] = ActCutThrForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActCutThrForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsPasThrFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActPasThrForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActPasThrForCrsTch,
[For_FORUM_DEGREE_USRS] = ActPasThrForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActPasThrForDegTch,
[For_FORUM_CENTER_USRS] = ActPasThrForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActPasThrForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActPasThrForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActPasThrForInsTch,
[For_FORUM_GLOBAL_USRS] = ActPasThrForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActPasThrForGenTch,
[For_FORUM__SWAD__USRS] = ActPasThrForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActPasThrForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsDelPstFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActDelPstForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActDelPstForCrsTch,
[For_FORUM_DEGREE_USRS] = ActDelPstForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActDelPstForDegTch,
[For_FORUM_CENTER_USRS] = ActDelPstForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActDelPstForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActDelPstForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActDelPstForInsTch,
[For_FORUM_GLOBAL_USRS] = ActDelPstForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActDelPstForGenTch,
[For_FORUM__SWAD__USRS] = ActDelPstForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActDelPstForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsEnbPstFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActEnbPstForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActEnbPstForCrsTch,
[For_FORUM_DEGREE_USRS] = ActEnbPstForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActEnbPstForDegTch,
[For_FORUM_CENTER_USRS] = ActEnbPstForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActEnbPstForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActEnbPstForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActEnbPstForInsTch,
[For_FORUM_GLOBAL_USRS] = ActEnbPstForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActEnbPstForGenTch,
[For_FORUM__SWAD__USRS] = ActEnbPstForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActEnbPstForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
2014-12-01 23:55:08 +01:00
};
2019-11-21 11:39:30 +01:00
2014-12-01 23:55:08 +01:00
const Act_Action_t For_ActionsDisPstFor[For_NUM_TYPES_FORUM] =
{
2019-11-21 11:39:30 +01:00
[For_FORUM_COURSE_USRS] = ActDisPstForCrsUsr,
[For_FORUM_COURSE_TCHS] = ActDisPstForCrsTch,
[For_FORUM_DEGREE_USRS] = ActDisPstForDegUsr,
[For_FORUM_DEGREE_TCHS] = ActDisPstForDegTch,
[For_FORUM_CENTER_USRS] = ActDisPstForCtrUsr,
[For_FORUM_CENTER_TCHS] = ActDisPstForCtrTch,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = ActDisPstForInsUsr,
[For_FORUM_INSTIT_TCHS] = ActDisPstForInsTch,
[For_FORUM_GLOBAL_USRS] = ActDisPstForGenUsr,
[For_FORUM_GLOBAL_TCHS] = ActDisPstForGenTch,
[For_FORUM__SWAD__USRS] = ActDisPstForSWAUsr,
[For_FORUM__SWAD__TCHS] = ActDisPstForSWATch,
[For_FORUM_UNKNOWN ] = ActSeeFor,
};
/*****************************************************************************/
/*********************** Private constants and types *************************/
/*****************************************************************************/
#define For_FORUM_MAX_LEVELS 5
2019-11-21 11:39:30 +01:00
static const unsigned PermissionThreadDeletion[For_NUM_TYPES_FORUM] =
{
[For_FORUM_COURSE_USRS] = 0x3F0,
[For_FORUM_COURSE_TCHS] = 0x3F0,
[For_FORUM_DEGREE_USRS] = 0x3E0,
[For_FORUM_DEGREE_TCHS] = 0x3E0,
[For_FORUM_CENTER_USRS] = 0x3C0,
[For_FORUM_CENTER_TCHS] = 0x3C0,
2019-11-21 11:39:30 +01:00
[For_FORUM_INSTIT_USRS] = 0x380,
[For_FORUM_INSTIT_TCHS] = 0x380,
[For_FORUM_GLOBAL_USRS] = 0x300,
[For_FORUM_GLOBAL_TCHS] = 0x300,
[For_FORUM__SWAD__USRS] = 0x300,
[For_FORUM__SWAD__TCHS] = 0x300,
[For_FORUM_UNKNOWN ] = 0x000,
2014-12-01 23:55:08 +01:00
};
2016-04-10 14:09:50 +02:00
// Forum images will be saved with:
// - maximum width of For_IMAGE_SAVED_MAX_HEIGHT
// - maximum height of For_IMAGE_SAVED_MAX_HEIGHT
// - maintaining the original aspect ratio (aspect ratio recommended: 3:2)
#define For_IMAGE_SAVED_MAX_WIDTH 768
2020-02-13 22:33:31 +01:00
#define For_IMAGE_SAVED_MAX_HEIGHT 768
#define For_IMAGE_SAVED_QUALITY 90 // 1 to 100
2016-04-10 14:09:50 +02:00
struct For_FiguresForum
{
unsigned NumForums;
unsigned NumThreads;
unsigned NumPosts;
unsigned NumUsrsToBeNotifiedByEMail;
};
2020-04-07 03:01:41 +02:00
/*****************************************************************************/
/****************************** Private prototypes ***************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-04-10 19:19:20 +02:00
static long For_InsertForumPst (long ThrCod,long UsrCod,
const char *Subject,const char *Content,
2021-02-11 00:58:53 +01:00
struct Med_Media *Media);
2019-03-18 15:42:22 +01:00
static bool For_RemoveForumPst (long PstCod,long MedCod);
2016-04-10 19:19:20 +02:00
static unsigned For_NumPstsInThrWithPstCod (long PstCod,long *ThrCod);
static void For_RemoveThreadOnly (long ThrCod);
static void For_RemoveThreadAndItsPsts (long ThrCod);
2017-04-18 19:55:56 +02:00
2015-10-24 20:12:03 +02:00
static time_t For_GetThrReadTime (long ThrCod);
static void For_PutIconsOneThread (void *Forums);
2016-11-07 10:53:03 +01:00
static void For_PutParsNewPost (void *Forums);
2020-10-14 00:59:24 +02:00
static void For_ShowAForumPost (struct For_Forums *Forums,
unsigned PstNum,
2017-01-17 03:10:43 +01:00
bool LastPst,char LastSubject[Cns_MAX_BYTES_SUBJECT + 1],
2016-11-07 10:53:03 +01:00
bool NewPst,bool ICanModerateForum);
static void For_GetPstData (long PstCod,long *UsrCod,time_t *CreatTimeUTC,
char Subject[Cns_MAX_BYTES_SUBJECT + 1],
2017-01-17 03:10:43 +01:00
char Content[Cns_MAX_BYTES_LONG_TEXT + 1],
2021-02-11 00:58:53 +01:00
struct Med_Media *Media);
2020-04-07 03:01:41 +02:00
static void For_WriteNumberOfPosts (const struct For_Forums *Forums,long UsrCod);
2016-11-07 10:53:03 +01:00
static void For_PutParsForum (void *Forums);
2020-10-14 00:59:24 +02:00
static void For_PutParForumSet (For_ForumSet_t ForumSet);
2017-04-17 12:19:58 +02:00
2020-04-08 03:41:05 +02:00
static void For_PutIconsForums (__attribute__((unused)) void *Args);
2020-04-07 03:01:41 +02:00
static void For_PutFormWhichForums (const struct For_Forums *Forums);
2017-04-16 13:45:11 +02:00
2020-04-07 03:01:41 +02:00
static void For_WriteLinksToGblForums (const struct For_Forums *Forums,
bool IsLastItemInLevel[1 + For_FORUM_MAX_LEVELS]);
static void For_WriteLinksToPlatformForums (const struct For_Forums *Forums,
bool IsLastForum,
2017-01-28 15:58:46 +01:00
bool IsLastItemInLevel[1 + For_FORUM_MAX_LEVELS]);
2020-04-07 03:01:41 +02:00
static long For_WriteLinksToInsForums (const struct For_Forums *Forums,
long InsCod,bool IsLastIns,
2017-01-28 15:58:46 +01:00
bool IsLastItemInLevel[1 + For_FORUM_MAX_LEVELS]);
2020-04-07 03:01:41 +02:00
static long For_WriteLinksToCtrForums (const struct For_Forums *Forums,
long CtrCod,bool IsLastCtr,
2017-01-28 15:58:46 +01:00
bool IsLastItemInLevel[1 + For_FORUM_MAX_LEVELS]);
2020-04-07 03:01:41 +02:00
static long For_WriteLinksToDegForums (const struct For_Forums *Forums,
long DegCod,bool IsLastDeg,
2017-01-28 15:58:46 +01:00
bool IsLastItemInLevel[1 + For_FORUM_MAX_LEVELS]);
2020-04-07 03:01:41 +02:00
static long For_WriteLinksToCrsForums (const struct For_Forums *Forums,
long CrsCod,bool IsLastCrs,
2017-01-28 15:58:46 +01:00
bool IsLastItemInLevel[1 + For_FORUM_MAX_LEVELS]);
2020-04-07 03:01:41 +02:00
static void For_WriteLinkToForum (const struct For_Forums *Forums,
const struct For_Forum *Forum,
2019-11-18 17:59:02 +01:00
bool Highlight,
2017-04-19 12:34:38 +02:00
unsigned Level,
bool IsLastItemInLevel[1 + For_FORUM_MAX_LEVELS]);
static unsigned For_GetNumThrsWithNewPstsInForum (const struct For_Forum *Forum,
2017-04-16 23:48:05 +02:00
unsigned NumThreads);
2014-12-01 23:55:08 +01:00
static unsigned For_GetNumOfUnreadPostsInThr (long ThrCod,unsigned NumPostsInThr);
2015-04-11 14:00:23 +02:00
2019-11-18 17:59:02 +01:00
static void For_WriteNumberOfThrs (unsigned NumThrs);
static void For_PutIconsThreads (void *Forums);
static void For_PutParsNewThread (void *Forums);
2020-04-10 19:14:08 +02:00
static void For_ListForumThrs (struct For_Forums *Forums,
2020-04-07 03:01:41 +02:00
long ThrCods[Pag_ITEMS_PER_PAGE],
2017-04-14 01:02:33 +02:00
long ThrCodHighlighted,
struct Pag_Pagination *PaginationThrs);
2017-04-12 20:56:45 +02:00
2020-04-07 03:01:41 +02:00
static void For_SetForumType (struct For_Forums *Forums);
static void For_RestrictAccess (const struct For_Forums *Forums);
2014-12-01 23:55:08 +01:00
2020-04-09 21:36:21 +02:00
static void For_WriteFormForumPst (struct For_Forums *Forums,
2020-04-07 03:01:41 +02:00
bool IsReply,const char *Subject);
2017-04-17 12:19:58 +02:00
static void For_PutParsRemThread (void *Forums);
2017-04-28 10:35:41 +02:00
2017-04-18 13:17:40 +02:00
static bool For_CheckIfICanMoveThreads (void);
2017-04-17 12:19:58 +02:00
static void For_InsertThrInClipboard (long ThrCod);
static void For_ShowStatOfAForumType (For_ForumType_t ForumType,
long HieCod[Hie_NUM_LEVELS],
struct For_FiguresForum *FiguresForum);
static void For_WriteForumTitleAndStats (For_ForumType_t ForumType,
long HieCod[Hie_NUM_LEVELS],
const char *Icon,struct For_FiguresForum *FiguresForum,
const char *ForumName1,const char *ForumName2);
static void For_WriteForumTotalStats (struct For_FiguresForum *FiguresForum);
2020-04-07 03:01:41 +02:00
/*****************************************************************************/
/********************************** Reset forum ******************************/
/*****************************************************************************/
void For_ResetForums (struct For_Forums *Forums)
{
2020-04-14 00:11:28 +02:00
Forums->ForumSet = For_DEFAULT_FORUM_SET;
Forums->ThreadsOrder = For_DEFAULT_ORDER;
Forums->CurrentPageThrs = 0;
Forums->CurrentPagePsts = 0;
2020-04-10 21:57:50 +02:00
2020-04-14 00:11:28 +02:00
Forums->Forum.Type = For_FORUM_UNKNOWN;
Forums->Forum.HieCod = -1L;
2020-04-10 19:14:08 +02:00
2020-11-11 01:14:53 +01:00
Forums->Thread.Selected =
Forums->Thread.Current =
Forums->Thread.ToMove = -1L;
2020-04-10 19:14:08 +02:00
2020-04-14 00:11:28 +02:00
Forums->PstCod = -1L;
2020-04-07 03:01:41 +02:00
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/****************************** Enable a forum post **************************/
/*****************************************************************************/
2017-04-18 16:44:44 +02:00
void For_EnablePost (void)
2014-12-01 23:55:08 +01:00
{
2019-03-06 10:13:39 +01:00
extern const char *Txt_FORUM_Post_unbanned;
2020-04-07 03:01:41 +02:00
struct For_Forums Forums;
/***** Reset forum *****/
For_ResetForums (&Forums);
2014-12-01 23:55:08 +01:00
2017-04-16 13:45:11 +02:00
/***** Get parameters related to forum *****/
For_GetParsForums (&Forums);
2014-12-01 23:55:08 +01:00
/***** Delete post from table of disabled posts *****/
For_DB_RemovePstFromDisabled (Forums.PstCod);
2014-12-01 23:55:08 +01:00
2017-04-18 13:17:40 +02:00
/***** Show forum list again *****/
2020-04-07 03:01:41 +02:00
For_ShowForumList (&Forums);
2017-04-18 13:17:40 +02:00
/***** Show threads again *****/
2020-04-07 03:01:41 +02:00
For_ShowForumThreadsHighlightingOneThread (&Forums,Ale_SUCCESS,NULL);
2017-04-18 13:17:40 +02:00
2014-12-01 23:55:08 +01:00
/***** Show the posts again *****/
2020-04-07 03:01:41 +02:00
For_ShowPostsOfAThread (&Forums,Ale_SUCCESS,Txt_FORUM_Post_unbanned);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************************** Disable a forum post **************************/
/*****************************************************************************/
2017-04-18 16:44:44 +02:00
void For_DisablePost (void)
2014-12-01 23:55:08 +01:00
{
2019-03-06 10:13:39 +01:00
extern const char *Txt_FORUM_Post_banned;
2020-04-07 03:01:41 +02:00
struct For_Forums Forums;
2014-12-01 23:55:08 +01:00
2020-04-07 03:01:41 +02:00
/***** Get parameters related to forums *****/
For_GetParsForums (&Forums);
2014-12-01 23:55:08 +01:00
/***** Check if post really exists, if it has not been removed *****/
if (For_DB_CheckIfForumPstExists (Forums.PstCod))
2014-12-01 23:55:08 +01:00
{
/***** Insert post into table of banned posts *****/
For_DB_InsertPstIntoDisabled (Forums.PstCod);
2017-04-18 09:55:25 +02:00
2017-04-18 13:17:40 +02:00
/***** Show forum list again *****/
2020-04-07 03:01:41 +02:00
For_ShowForumList (&Forums);
2017-04-18 13:17:40 +02:00
/***** Show threads again *****/
2020-04-07 03:01:41 +02:00
For_ShowForumThreadsHighlightingOneThread (&Forums,Ale_SUCCESS,NULL);
2017-04-18 13:17:40 +02:00
2017-04-18 09:55:25 +02:00
/***** Show the posts again *****/
2020-04-07 03:01:41 +02:00
For_ShowPostsOfAThread (&Forums,Ale_SUCCESS,Txt_FORUM_Post_banned);
2014-12-01 23:55:08 +01:00
}
else
Err_WrongPostExit ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************** Insert a post new in the table of posts of forums ************/
/*****************************************************************************/
2016-04-10 19:19:20 +02:00
static long For_InsertForumPst (long ThrCod,long UsrCod,
const char *Subject,const char *Content,
2021-02-11 00:58:53 +01:00
struct Med_Media *Media)
2014-12-01 23:55:08 +01:00
{
2019-03-19 11:20:29 +01:00
/***** Store media in filesystem and database *****/
Med_RemoveKeepOrStoreMedia (-1L,Media);
2019-03-18 15:42:22 +01:00
2014-12-01 23:55:08 +01:00
/***** Insert forum post in the database *****/
return For_DB_InsertForumPst (ThrCod,UsrCod,Subject,Content,Media->MedCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Delete a post from the forum post table *******************/
/*****************************************************************************/
// Return true if the post thread is deleted
2019-03-18 15:42:22 +01:00
static bool For_RemoveForumPst (long PstCod,long MedCod)
2014-12-01 23:55:08 +01:00
{
long ThrCod;
bool ThreadDeleted = false;
2019-03-02 21:49:11 +01:00
/***** Remove media file attached to forum post *****/
2019-03-18 15:42:22 +01:00
Med_RemoveMedia (MedCod);
2016-04-10 23:59:45 +02:00
2014-12-01 23:55:08 +01:00
/***** If the post is the only one in its thread, delete that thread *****/
if (For_NumPstsInThrWithPstCod (PstCod,&ThrCod) < 2)
{
For_RemoveThreadOnly (ThrCod);
ThreadDeleted = true;
}
/***** Delete the post from the table of disabled forum posts *****/
For_DB_RemovePstFromDisabled (PstCod);
/***** Delete post from forum post table *****/
For_DB_RemovePst (PstCod);
2014-12-01 23:55:08 +01:00
/***** Update the last post of the thread *****/
if (!ThreadDeleted)
For_DB_UpdateThrLastPst (ThrCod,For_DB_GetThrLastPst (ThrCod));
2014-12-01 23:55:08 +01:00
return ThreadDeleted;
}
/*****************************************************************************/
/*********** Get the number of posts in the thread than holds a post *********/
/*****************************************************************************/
2016-04-10 19:19:20 +02:00
static unsigned For_NumPstsInThrWithPstCod (long PstCod,long *ThrCod)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumPsts;
/***** Initialize default values *****/
*ThrCod = -1L;
NumPsts = 0;
/***** Trivial check: PstCod should be > 0 *****/
if (PstCod <= 0)
return NumPsts;
2014-12-01 23:55:08 +01:00
/***** Get number of posts in the thread that holds a post from database *****/
if (For_DB_GetThreadAndNumPostsGivenPstCod (&mysql_res,PstCod) == 1) // Result should have one row
{
row = mysql_fetch_row (mysql_res);
/*
row[0]: ThrCod
row[1]: COUNT(PstCod)
*/
if (sscanf (row[0],"%ld",ThrCod) != 1)
Err_ShowErrorAndExit ("Error when getting number of posts in a thread.");
if (sscanf (row[1],"%u",&NumPsts) != 1)
Err_ShowErrorAndExit ("Error when getting number of posts in a thread.");
}
2014-12-01 23:55:08 +01:00
DB_FreeMySQLResult (&mysql_res);
return NumPsts;
}
/*****************************************************************************/
/*************** Delete a thread from the forum thread table *****************/
/*****************************************************************************/
2016-04-10 19:19:20 +02:00
static void For_RemoveThreadOnly (long ThrCod)
2014-12-01 23:55:08 +01:00
{
/***** Indicate that this thread has not been read by anyone *****/
For_DB_RemoveThrFromReadThrs (ThrCod);
2014-12-01 23:55:08 +01:00
/***** Remove thread code from thread clipboard *****/
For_DB_RemoveThrFromClipboard (ThrCod);
2014-12-01 23:55:08 +01:00
/***** Delete thread from forum thread table *****/
For_DB_RemoveThread (ThrCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*************** Delete a thread from the forum thread table *****************/
/*****************************************************************************/
2016-04-10 19:19:20 +02:00
static void For_RemoveThreadAndItsPsts (long ThrCod)
2014-12-01 23:55:08 +01:00
{
/***** Delete disabled posts in thread *****/
For_DB_RemoveDisabledPstsInThread (ThrCod);
2014-12-01 23:55:08 +01:00
/***** Delete thread posts *****/
For_DB_RemoveThreadPsts (ThrCod);
2014-12-01 23:55:08 +01:00
/***** Delete thread from forum thread table *****/
For_RemoveThreadOnly (ThrCod);
}
/*****************************************************************************/
/*********** Get thread, forum type and hierarchy code of a post *************/
/*****************************************************************************/
// Return thread to which the post belongs
long For_GetThreadForumTypeAndHieCodOfAPost (long PstCod,struct For_Forum *Forum)
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned UnsignedNum;
long ThrCod;
/***** Set defaults *****/
Forum->Type = For_FORUM_UNKNOWN;
Forum->HieCod = -1L;
ThrCod = -1L;
/***** Check if there is a row with forum type *****/
if (For_DB_GetThreadForumTypeAndHieCodOfAPost (&mysql_res,PstCod))
{
row = mysql_fetch_row (mysql_res);
/* Get forum thread (row[0]) */
if (sscanf (row[0],"%ld",&ThrCod) != 1)
Err_WrongThreadExit ();
/* Get forum type (row[1]) */
if (sscanf (row[1],"%u",&UnsignedNum) == 1)
if (UnsignedNum < For_NUM_TYPES_FORUM)
Forum->Type = (For_ForumType_t) UnsignedNum;
/* Get forum hierarchy code (row[2]) */
if (sscanf (row[2],"%ld",&Forum->HieCod) != 1)
Err_WrongForumExit ();
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return ThrCod;
}
/*****************************************************************************/
/*************** Get forum type and hierarchy code of a post *****************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void For_GetForumTypeAndHieCodOfAThread (long ThrCod,struct For_Forum *Forum)
2014-12-01 23:55:08 +01:00
{
2017-04-18 19:55:56 +02:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned UnsignedNum;
/***** Set defaults *****/
2017-04-19 12:34:38 +02:00
Forum->Type = For_FORUM_UNKNOWN;
Forum->HieCod = -1L;
2014-12-01 23:55:08 +01:00
/***** Check if there is a row with forum type *****/
if (For_DB_GetForumTypeAndHieCodOfAThread (&mysql_res,ThrCod))
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
2017-04-16 23:48:05 +02:00
/* Get forum type (row[0]) */
2017-04-18 19:55:56 +02:00
if (sscanf (row[0],"%u",&UnsignedNum) == 1)
if (UnsignedNum < For_NUM_TYPES_FORUM)
2017-04-19 12:34:38 +02:00
Forum->Type = (For_ForumType_t) UnsignedNum;
2017-04-16 23:48:05 +02:00
/* Get forum hierarchy code (row[1]) */
if (sscanf (row[1],"%ld",&Forum->HieCod) != 1)
Err_WrongForumExit ();
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/****************** Get thread read time for the current user ****************/
/*****************************************************************************/
2015-10-24 20:12:03 +02:00
static time_t For_GetThrReadTime (long ThrCod)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2015-10-24 20:12:03 +02:00
time_t ReadTimeUTC;
2014-12-01 23:55:08 +01:00
/***** Get read time of a thread from database *****/
if (For_DB_GetThrReadTime (&mysql_res,ThrCod))
2014-12-01 23:55:08 +01:00
{
2015-10-24 20:12:03 +02:00
/***** There is a row ==> get read time *****/
2014-12-01 23:55:08 +01:00
row = mysql_fetch_row (mysql_res);
2015-10-24 20:12:03 +02:00
ReadTimeUTC = Dat_GetUNIXTimeFromStr (row[0]);
2014-12-01 23:55:08 +01:00
}
else
ReadTimeUTC = (time_t) 0; // If there is no row for this thread and current user,
// then current user has not read this thread
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
2015-10-24 20:12:03 +02:00
return ReadTimeUTC;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2017-04-13 20:09:22 +02:00
/************************ Show posts in a thread *****************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void For_ShowPostsOfAThread (struct For_Forums *Forums,
Ale_AlertType_t AlertType,const char *Message)
2014-12-01 23:55:08 +01:00
{
2020-09-26 17:20:01 +02:00
extern const char *Hlp_COMMUNICATION_Forums_posts;
2015-04-11 14:00:23 +02:00
extern const char *Txt_Thread;
2020-04-14 00:11:28 +02:00
struct For_Thread Thread;
2017-04-11 19:05:15 +02:00
char LastSubject[Cns_MAX_BYTES_SUBJECT + 1];
char FrameTitle[128 + Cns_MAX_BYTES_SUBJECT];
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRow;
2014-12-01 23:55:08 +01:00
unsigned NumPst = 0; // Initialized to avoid warning
unsigned NumPsts;
2015-10-24 20:12:03 +02:00
time_t ReadTimeUTC; // Read time of thread for the current user
time_t CreatTimeUTC; // Creation time of post
struct Pag_Pagination PaginationPsts;
2014-12-01 23:55:08 +01:00
bool NewPst = false;
bool ICanModerateForum = false;
2017-04-16 13:45:11 +02:00