swad-core/swad_alert.c

494 lines
16 KiB
C
Raw Normal View History

2017-12-09 18:32:23 +01:00
// swad_alert.c: alerts
/*
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.
2019-01-07 21:52:19 +01:00
Copyright (C) 1999-2019 Antonio Ca<EFBFBD>as Vargas
2017-12-09 18:32:23 +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 ***********************************/
/*****************************************************************************/
2019-02-15 23:38:44 +01:00
#define _GNU_SOURCE // For vasprintf
2017-12-09 18:32:23 +01:00
#include <linux/stddef.h> // For NULL
2019-02-15 23:38:44 +01:00
#include <stdarg.h> // For va_start, va_end
#include <stdio.h> // For FILE, fprintf, vasprintf
#include <stdlib.h> // For free
2019-03-25 19:05:10 +01:00
#include <string.h> // For string functions
2017-12-09 18:32:23 +01:00
#include "swad_alert.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2017-12-09 18:32:23 +01:00
#include "swad_global.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/****************************** Public constants *****************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
static const char *Ale_AlertIcons[Ale_NUM_ALERT_TYPES] =
{
NULL, // Ale_NONE
2019-01-08 13:13:04 +01:00
"clipboard.svg", // Ale_CLIPBOARD
2019-01-10 15:26:33 +01:00
"info-circle.svg", // Ale_INFO
2019-01-11 02:55:01 +01:00
"check-circle.svg", // Ale_SUCCESS
2017-12-09 18:32:23 +01:00
"question64x64.gif", // Ale_QUESTION animated gif
"warning64x64.gif", // Ale_WARNING animated gif
"error64x64.gif", // Ale_ERROR animated gif
};
/*****************************************************************************/
/******************************* Private types *******************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
static void Ale_ResetLastAlert (void);
static void Ale_ResetAlert (size_t i);
2019-02-16 14:37:34 +01:00
static void Ale_ShowFixAlert (Ale_AlertType_t AlertType,const char *Txt);
2019-02-17 01:14:55 +01:00
static void Ale_ShowFixAlertAndButton1 (Ale_AlertType_t AlertType,const char *Txt);
2018-10-16 01:36:13 +02:00
2017-12-09 18:32:23 +01:00
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
/**************************** Create a new alert *****************************/
/*****************************************************************************/
void Ale_CreateAlert (Ale_AlertType_t Type,const char *Section,
const char *fmt,...)
{
va_list ap;
int NumBytesPrinted;
2019-03-25 19:05:10 +01:00
size_t i;
2019-03-09 20:12:44 +01:00
if (Gbl.Alerts.Num + 1 > Ale_MAX_ALERTS)
Lay_ShowErrorAndExit ("Too many alerts.");
2019-03-25 19:05:10 +01:00
i = Gbl.Alerts.Num;
2019-03-09 20:12:44 +01:00
Gbl.Alerts.Num++;
2019-03-25 19:05:10 +01:00
Gbl.Alerts.List[i].Type = Type;
2019-03-09 20:12:44 +01:00
2019-03-25 19:05:10 +01:00
Gbl.Alerts.List[i].Section = NULL;
2019-03-09 20:12:44 +01:00
if (Section)
if (Section[0])
2019-03-25 19:05:10 +01:00
if (asprintf (&Gbl.Alerts.List[i].Section,"%s",
Section) < 0)
Lay_NotEnoughMemoryExit ();
2019-03-09 20:12:44 +01:00
va_start (ap,fmt);
2019-03-25 19:05:10 +01:00
NumBytesPrinted = vasprintf (&Gbl.Alerts.List[i].Text,fmt,ap);
2019-03-09 20:12:44 +01:00
va_end (ap);
if (NumBytesPrinted < 0) // If memory allocation wasn't possible,
// or some other error occurs,
// vasprintf will return -1
Lay_NotEnoughMemoryExit ();
}
/*****************************************************************************/
/***************** Get current number of delayed alerts **********************/
/*****************************************************************************/
2019-03-25 19:05:10 +01:00
size_t Ale_GetNumAlerts (void)
2019-03-09 20:12:44 +01:00
{
return Gbl.Alerts.Num;
}
/*****************************************************************************/
/********************** Get type of last delayed alert ***********************/
/*****************************************************************************/
Ale_AlertType_t Ale_GetTypeOfLastAlert (void)
{
return Gbl.Alerts.Num ? Gbl.Alerts.List[Gbl.Alerts.Num - 1].Type :
Ale_NONE;
}
/*****************************************************************************/
/********************** Get text of last delayed alert ***********************/
/*****************************************************************************/
const char *Ale_GetTextOfLastAlert (void)
{
return Gbl.Alerts.Num ? Gbl.Alerts.List[Gbl.Alerts.Num - 1].Text :
NULL;
}
/*****************************************************************************/
2019-03-10 00:34:16 +01:00
/***************************** Reset all alerts ******************************/
2017-12-09 18:32:23 +01:00
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
void Ale_ResetAllAlerts (void)
{
size_t i;
for (i = 0;
i < Gbl.Alerts.Num;
i++)
Ale_ResetAlert (i);
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/************************* Reset more recent alert ***************************/
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
static void Ale_ResetLastAlert (void)
2017-12-09 18:32:23 +01:00
{
2019-03-09 20:12:44 +01:00
if (Gbl.Alerts.Num) // There are pending alerts no shown
Ale_ResetAlert (Gbl.Alerts.Num - 1); // Reset the last one
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/********************* Reset one alert given its index ***********************/
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
static void Ale_ResetAlert (size_t i)
{
bool NoMoreAlertsPending;
size_t j;
if (i < Gbl.Alerts.Num)
if (Gbl.Alerts.List[i].Type != Ale_NONE)
{
/***** Reset i-esim alert *****/
Gbl.Alerts.List[i].Type = Ale_NONE; // Reset alert
/***** Free memory allocated for text *****/
if (Gbl.Alerts.List[i].Text)
{
free ((void *) Gbl.Alerts.List[i].Text);
Gbl.Alerts.List[i].Text = NULL;
}
2019-03-25 19:05:10 +01:00
/***** Free memory allocated for section *****/
if (Gbl.Alerts.List[i].Section)
{
free ((void *) Gbl.Alerts.List[i].Section);
Gbl.Alerts.List[i].Section = NULL;
}
2019-03-09 20:12:44 +01:00
}
/***** Set number of alerts to 0
if there are no more alerts
pending to be shown *****/
NoMoreAlertsPending = true;
for (j = 0;
NoMoreAlertsPending && j < Gbl.Alerts.Num;
j++)
if (Gbl.Alerts.List[j].Type != Ale_NONE)
NoMoreAlertsPending = false;
if (NoMoreAlertsPending)
Gbl.Alerts.Num = 0;
2017-12-09 18:32:23 +01:00
}
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
/************************ Show alert messages and exit ***********************/
2017-12-09 18:32:23 +01:00
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
void Ale_ShowAlertsAndExit ()
2019-02-16 14:37:34 +01:00
{
2019-03-09 20:12:44 +01:00
Ale_ShowAlerts (NULL);
Lay_ShowErrorAndExit (NULL);
}
2019-02-17 01:14:55 +01:00
2019-03-09 20:12:44 +01:00
/*****************************************************************************/
2019-03-10 00:34:16 +01:00
/****** Show several alert messages stored in vector of delayed alerts *******/
2019-03-09 20:12:44 +01:00
/*****************************************************************************/
// If Section == NULL ==> show all alerts
// If Section != NULL ==> shown only the alerts assigned to Section
void Ale_ShowAlerts (const char *Section)
{
size_t i;
bool ShowAlert;
2019-03-25 19:05:10 +01:00
size_t NumAlerts = Ale_GetNumAlerts ();
2019-03-09 20:12:44 +01:00
for (i = 0;
2019-03-25 19:05:10 +01:00
i < NumAlerts;
2019-03-09 20:12:44 +01:00
i++)
if (Gbl.Alerts.List[i].Type != Ale_NONE)
{
2019-03-25 19:05:10 +01:00
if (Section)
ShowAlert = (bool) !strcmp (Gbl.Alerts.List[i].Section,Section);
else
2019-04-08 13:06:17 +02:00
ShowAlert = true;
2019-03-09 20:12:44 +01:00
if (ShowAlert)
{
Ale_ShowFixAlert (Gbl.Alerts.List[i].Type,
Gbl.Alerts.List[i].Text);
Ale_ResetAlert (i);
}
}
2019-02-16 14:37:34 +01:00
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/****************** Show one formatted-text alert message ********************/
/*****************************************************************************/
2019-02-16 14:37:34 +01:00
void Ale_ShowAlert (Ale_AlertType_t AlertType,const char *fmt,...)
2019-02-15 23:38:44 +01:00
{
va_list ap;
int NumBytesPrinted;
char *Txt;
if (AlertType != Ale_NONE)
{
2019-02-17 01:14:55 +01:00
/***** Print format and list of variables into text *****/
2019-02-15 23:38:44 +01:00
va_start (ap,fmt);
NumBytesPrinted = vasprintf (&Txt,fmt,ap);
va_end (ap);
if (NumBytesPrinted < 0) // If memory allocation wasn't possible,
2019-02-16 14:37:34 +01:00
// or some other error occurs,
// vasprintf will return -1
2019-02-15 23:38:44 +01:00
Lay_NotEnoughMemoryExit ();
2019-02-17 01:14:55 +01:00
/***** Show alert *****/
2019-02-16 17:20:05 +01:00
Ale_ShowFixAlert (AlertType,Txt);
2019-02-15 23:38:44 +01:00
2019-02-17 01:14:55 +01:00
/***** Free text *****/
2019-02-15 23:38:44 +01:00
free ((void *) Txt);
}
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/********************** Show one fix-text alert message **********************/
/*****************************************************************************/
2019-02-16 14:37:34 +01:00
static void Ale_ShowFixAlert (Ale_AlertType_t AlertType,const char *Txt)
2019-02-15 23:38:44 +01:00
{
if (AlertType != Ale_NONE)
2019-02-17 01:14:55 +01:00
{
/****** Print fix alert and button ******/
Ale_ShowFixAlertAndButton1 (AlertType,Txt);
Ale_ShowAlertAndButton2 (ActUnk,NULL,NULL,
NULL,Btn_NO_BUTTON,NULL);
}
2019-02-15 23:38:44 +01:00
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/**************** Show the more recent alert with a button *******************/
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
void Ale_ShowLastAlertAndButton (Act_Action_t NextAction,const char *Anchor,
const char *OnSubmit,void (*FuncParams) (),
Btn_Button_t Button,const char *TxtButton)
{
/***** Show last alert and then reset it *****/
Ale_ShowLastAlertAndButton1 ();
/***** Show button *****/
Ale_ShowAlertAndButton2 (NextAction,Anchor,OnSubmit,
FuncParams,Button,TxtButton);
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/********** Show the first part of more recent alert with a button ***********/
/*****************************************************************************/
void Ale_ShowLastAlertAndButton1 (void)
{
/***** Show last alert *****/
Ale_ShowFixAlertAndButton1 (Ale_GetTypeOfLastAlert (),Ale_GetTextOfLastAlert ());
/***** Reset last alert *****/
Ale_ResetLastAlert ();
}
/*****************************************************************************/
/*********************** Show an alert with a button *************************/
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
void Ale_ShowAlertAndButton (Act_Action_t NextAction,const char *Anchor,
const char *OnSubmit,void (*FuncParams) (),
2019-02-17 01:14:55 +01:00
Btn_Button_t Button,const char *TxtButton,
Ale_AlertType_t AlertType,const char *fmt,...)
2017-12-09 18:32:23 +01:00
{
2019-02-17 01:14:55 +01:00
va_list ap;
int NumBytesPrinted;
char *Txt;
/***** Print format and list of variables into text *****/
va_start (ap,fmt);
NumBytesPrinted = vasprintf (&Txt,fmt,ap);
va_end (ap);
if (NumBytesPrinted < 0) // If memory allocation wasn't possible,
// or some other error occurs,
// vasprintf will return -1
Lay_NotEnoughMemoryExit ();
/****** Print fix alert and button ******/
Ale_ShowFixAlertAndButton1 (AlertType,Txt);
2017-12-09 18:32:23 +01:00
Ale_ShowAlertAndButton2 (NextAction,Anchor,OnSubmit,
FuncParams,Button,TxtButton);
2019-02-17 01:14:55 +01:00
/***** Free text *****/
free ((void *) Txt);
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/******** Show the first part of a formatted-text alert with a button ********/
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
2019-02-17 01:14:55 +01:00
void Ale_ShowAlertAndButton1 (Ale_AlertType_t AlertType,const char *fmt,...)
{
va_list ap;
int NumBytesPrinted;
char *Txt;
/***** Print format and list of variables into text *****/
va_start (ap,fmt);
NumBytesPrinted = vasprintf (&Txt,fmt,ap);
va_end (ap);
if (NumBytesPrinted < 0) // If memory allocation wasn't possible,
// or some other error occurs,
// vasprintf will return -1
Lay_NotEnoughMemoryExit ();
/****** Print start of fix alert and button ******/
Ale_ShowFixAlertAndButton1 (AlertType,Txt);
/***** Free text *****/
free ((void *) Txt);
2017-12-09 18:32:23 +01:00
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/*********** Show the first part of a fix-text alert with a button ***********/
/*****************************************************************************/
2019-02-17 01:14:55 +01:00
static void Ale_ShowFixAlertAndButton1 (Ale_AlertType_t AlertType,const char *Txt)
2017-12-09 18:32:23 +01:00
{
extern const char *Txt_Close;
2018-11-09 20:47:39 +01:00
char IdAlert[Frm_MAX_BYTES_ID + 1];
2017-12-09 18:32:23 +01:00
static const bool AlertClosable[Ale_NUM_ALERT_TYPES] =
{
false, // Ale_NONE
2018-11-14 23:40:56 +01:00
true, // Ale_CLIPBOARD
2018-10-10 14:03:06 +02:00
true, // Ale_INFO
2017-12-09 18:32:23 +01:00
true, // Ale_SUCCESS
true, // Ale_QUESTION
true, // Ale_WARNING
true, // Ale_ERROR
};
/****** If start of page is not written yet, do it now ******/
if (!Gbl.Layout.HTMLStartWritten)
Lay_WriteStartOfPage ();
/***** Start box *****/
fprintf (Gbl.F.Out,"<div");
if (AlertClosable[AlertType])
{
/* Create unique id for alert */
2018-11-09 20:47:39 +01:00
Frm_SetUniqueId (IdAlert);
2017-12-09 18:32:23 +01:00
fprintf (Gbl.F.Out," id=\"%s\"",IdAlert);
}
fprintf (Gbl.F.Out," class=\"CENTER_MIDDLE\">"
"<div class=\"ALERT\">");
/***** Icon to close the alert *****/
if (AlertClosable[AlertType])
fprintf (Gbl.F.Out,"<div class=\"ALERT_CLOSE\">"
"<a href=\"\""
" onclick=\"toggleDisplay('%s');return false;\" />"
2019-01-08 13:13:04 +01:00
"<img src=\"%s/close.svg\""
2017-12-09 18:32:23 +01:00
" alt=\"%s\" title=\"%s\""
2019-01-08 13:13:04 +01:00
" class=\"ICO16x16\" />"
2017-12-09 18:32:23 +01:00
"</a>"
"</div>",
IdAlert,
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,
2017-12-09 18:32:23 +01:00
Txt_Close,Txt_Close);
/***** Write message *****/
fprintf (Gbl.F.Out,"<div class=\"ALERT_TXT\"");
if (AlertType != Ale_NONE)
fprintf (Gbl.F.Out," style=\"background-image:url('%s/%s');\"",
2019-03-20 01:36:36 +01:00
Cfg_URL_ICON_PUBLIC,Ale_AlertIcons[AlertType]);
2019-02-17 01:14:55 +01:00
fprintf (Gbl.F.Out,">%s"
"</div>",
Txt);
2017-12-09 18:32:23 +01:00
}
2019-03-10 00:34:16 +01:00
/*****************************************************************************/
/*************** Show the second part of an alert with a button **************/
/*****************************************************************************/
2017-12-09 18:32:23 +01:00
void Ale_ShowAlertAndButton2 (Act_Action_t NextAction,const char *Anchor,const char *OnSubmit,
void (*FuncParams) (),
Btn_Button_t Button,const char *TxtButton)
{
/***** Optional button *****/
if (NextAction != ActUnk &&
Button != Btn_NO_BUTTON &&
TxtButton)
if (TxtButton[0])
{
/* Start form */
2018-11-09 20:47:39 +01:00
Frm_StartFormAnchorOnSubmit (NextAction,Anchor,OnSubmit);
2017-12-09 18:32:23 +01:00
if (FuncParams)
FuncParams ();
/* Put button *****/
Btn_PutButton (Button,TxtButton);
/* End form */
2018-11-09 20:47:39 +01:00
Frm_EndForm ();
2017-12-09 18:32:23 +01:00
}
/***** End box *****/
fprintf (Gbl.F.Out,"</div>"
"</div>");
}
2019-02-16 20:07:52 +01:00
2019-03-09 20:12:44 +01:00
/*****************************************************************************/
/** Create alert when user not found or no permission to perform an action ***/
/*****************************************************************************/
void Ale_CreateAlertUserNotFoundOrYouDoNotHavePermission (void)
{
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
Ale_CreateAlert (Ale_WARNING,NULL,
Txt_User_not_found_or_you_do_not_have_permission_);
}
2019-02-16 20:07:52 +01:00
/*****************************************************************************/
2019-02-16 20:44:31 +01:00
/*** Show alert when user not found or no permission to perform an action ****/
2019-02-16 20:07:52 +01:00
/*****************************************************************************/
2019-03-09 20:12:44 +01:00
void Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission (void)
2019-02-16 20:07:52 +01:00
{
extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
Ale_ShowAlert (Ale_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
}