swad-core/swad_nickname.c

542 lines
19 KiB
C
Raw Permalink Normal View History

2014-12-01 23:55:08 +01:00
// swad_nickname.c: Users' nicknames
/*
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-2024 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 ***********************************/
/*****************************************************************************/
#include <string.h> // For string functions
2014-12-12 22:39:55 +01:00
#include "swad_account.h"
#include "swad_action_list.h"
#include "swad_alert.h"
2018-10-15 14:07:12 +02:00
#include "swad_box.h"
2014-12-01 23:55:08 +01:00
#include "swad_database.h"
2018-11-09 20:47:39 +01:00
#include "swad_form.h"
2014-12-01 23:55:08 +01:00
#include "swad_global.h"
2019-10-23 19:05:05 +02:00
#include "swad_HTML.h"
#include "swad_nickname_database.h"
2014-12-01 23:55:08 +01:00
#include "swad_parameter.h"
#include "swad_QR.h"
#include "swad_user.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/***************************** Private variables *****************************/
/*****************************************************************************/
2018-10-16 01:36:13 +02:00
const char *Nck_NICKNAME_SECTION_ID = "nickname_section";
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
static void Nck_ShowFormChangeUsrNickname (Usr_MeOrOther_t MeOrOther,
2018-10-16 01:36:13 +02:00
bool IMustFillNickname);
static void Nck_PutParsRemoveMyNick (void *Nick);
static void Nck_PutParsRemoveOtherNick (void *Nick);
2018-10-15 14:07:12 +02:00
static void Nck_ChangeUsrNick (struct Usr_Data *UsrDat);
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********* Check whether a nickname (with initial arroba) if valid ***********/
/*****************************************************************************/
bool Nck_CheckIfNickWithArrIsValid (const char *NickWithArr)
2014-12-01 23:55:08 +01:00
{
char CopyOfNick[Nck_MAX_BYTES_NICK_WITH_ARROBA + 1];
2014-12-01 23:55:08 +01:00
unsigned Length;
const char *Ptr;
/***** A nickname must start by '@' *****/
if (NickWithArr[0] != '@') // It's not a nickname
2014-12-01 23:55:08 +01:00
return false;
/***** Make a copy of nickname *****/
Str_Copy (CopyOfNick,NickWithArr,sizeof (CopyOfNick) - 1);
Str_RemoveLeadingArrobas (CopyOfNick);
Length = strlen (CopyOfNick); // Leading arrobas already removed
2014-12-01 23:55:08 +01:00
/***** A nick (without arroba) must have a number of characters
Nck_MIN_CHARS_NICK_WITHOUT_ARROBA <= Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA *****/
if (Length < Nck_MIN_CHARS_NICK_WITHOUT_ARROBA ||
Length > Nck_MAX_CHARS_NICK_WITHOUT_ARROBA)
2014-12-01 23:55:08 +01:00
return false;
/***** A nick can have digits, letters and '_' *****/
for (Ptr = CopyOfNick; // Leading arrobas already removed
2014-12-01 23:55:08 +01:00
*Ptr;
Ptr++)
if (!Str_ChIsAlphaNum (*Ptr))
2014-12-01 23:55:08 +01:00
return false;
return true;
}
/*****************************************************************************/
/************** Get user's code of a user from his/her nickname **************/
/*****************************************************************************/
2015-03-05 01:55:46 +01:00
// Nickname may have leading '@'
2014-12-01 23:55:08 +01:00
// Returns true if nickname found in database
long Nck_GetUsrCodFromNickname (const char *NickWithArr)
2014-12-01 23:55:08 +01:00
{
char CopyOfNick[Nck_MAX_BYTES_NICK_WITH_ARROBA + 1];
/***** Trivial check 1: nickname should be not null *****/
if (!NickWithArr)
return -1L;
/***** Trivial check 2: nickname should be not empty *****/
if (!NickWithArr[0])
return -1L;
/***** Remove leading arrobas *****/
Str_Copy (CopyOfNick,NickWithArr,sizeof (CopyOfNick) - 1);
Str_RemoveLeadingArrobas (CopyOfNick);
/***** Get user's code from database *****/
return Nck_DB_GetUsrCodFromNickname (CopyOfNick);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/******************* Put form to request the new nickname ********************/
/*****************************************************************************/
void Nck_PutFormToGetNewNickname (const char *NewNickWithoutArr)
{
extern const char *Txt_Nickname;
extern const char *Txt_HELP_nickname;
char NewNickWithArr[Nck_MAX_BYTES_NICK_WITH_ARROBA + 1];
/***** Nickname *****/
HTM_TR_Begin (NULL);
/* Label */
Frm_LabelColumn ("Frm_C1 RM","NewNick",Txt_Nickname);
/* Data */
HTM_TD_Begin ("class=\"Frm_C2 LM\"");
if (NewNickWithoutArr[0])
snprintf (NewNickWithArr,sizeof (NewNickWithArr),"@%s",
NewNickWithoutArr);
else
NewNickWithArr[0] = '\0';
HTM_INPUT_TEXT ("NewNick",1 + Nck_MAX_CHARS_NICK_WITHOUT_ARROBA,
NewNickWithArr,HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"NewNick\" size=\"16\" placeholder=\"%s\""
" class=\"Frm_C2_INPUT INPUT_%s\""
" required=\"required\"",
Txt_HELP_nickname,
The_GetSuffix ());
HTM_TD_End ();
HTM_TR_End ();
}
/*****************************************************************************/
2014-12-01 23:55:08 +01:00
/*********************** Show form to change my nickname *********************/
/*****************************************************************************/
2018-10-15 14:07:12 +02:00
void Nck_ShowFormChangeMyNickname (bool IMustFillNickname)
2014-12-01 23:55:08 +01:00
{
Nck_ShowFormChangeUsrNickname (Usr_ME,
2018-10-16 01:36:13 +02:00
IMustFillNickname);
2018-10-15 14:07:12 +02:00
}
/*****************************************************************************/
/*********************** Show form to change my nickname *********************/
/*****************************************************************************/
void Nck_ShowFormChangeOtherUsrNickname (void)
{
Nck_ShowFormChangeUsrNickname (Usr_OTHER,
2018-10-16 01:36:13 +02:00
false); // IMustFillNickname
2018-10-15 14:07:12 +02:00
}
/*****************************************************************************/
/*********************** Show form to change my nickname *********************/
/*****************************************************************************/
static void Nck_ShowFormChangeUsrNickname (Usr_MeOrOther_t MeOrOther,
2018-10-16 01:36:13 +02:00
bool IMustFillNickname)
2018-10-15 14:07:12 +02:00
{
extern const char *Hlp_PROFILE_Account;
extern const char *Txt_Nickname;
extern const char *Txt_Before_going_to_any_other_option_you_must_fill_your_nickname;
2014-12-01 23:55:08 +01:00
extern const char *Txt_Current_nickname;
extern const char *Txt_Other_nicknames;
extern const char *Txt_Use_this_nickname;
extern const char *Txt_New_nickname;
extern const char *Txt_Change_nickname;
2019-02-18 18:27:45 +01:00
extern const char *Txt_Save_changes;
static const struct
{
Act_Action_t Remove;
Act_Action_t Change;
} NextAction[Rol_NUM_ROLES] =
{
[Rol_UNK ] = {ActRemNicOth,ActChgNicOth},
[Rol_GST ] = {ActRemNicOth,ActChgNicOth},
[Rol_USR ] = {ActRemNicOth,ActChgNicOth},
[Rol_STD ] = {ActRemNicStd,ActChgNicStd},
[Rol_NET ] = {ActRemNicTch,ActChgNicTch},
[Rol_TCH ] = {ActRemNicTch,ActChgNicTch},
[Rol_DEG_ADM] = {ActRemNicOth,ActChgNicOth},
[Rol_CTR_ADM] = {ActRemNicOth,ActChgNicOth},
[Rol_INS_ADM] = {ActRemNicOth,ActChgNicOth},
[Rol_SYS_ADM] = {ActRemNicOth,ActChgNicOth},
};
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumNicks;
unsigned NumNick;
char NickWithArr[Nck_MAX_BYTES_NICK_WITH_ARROBA + 1];
static struct Usr_Data *UsrDat[Usr_NUM_ME_OR_OTHER] =
{
[Usr_ME ] = &Gbl.Usrs.Me.UsrDat,
[Usr_OTHER] = &Gbl.Usrs.Other.UsrDat
};
static void (*FuncParsRemove[Usr_NUM_ME_OR_OTHER]) (void *ID) =
{
[Usr_ME ] = Nck_PutParsRemoveMyNick,
[Usr_OTHER] = Nck_PutParsRemoveOtherNick
};
struct
{
Act_Action_t Remove;
Act_Action_t Change;
} ActNck[Rol_NUM_ROLES] =
{
[Usr_ME ] = {.Remove = ActRemMyNck,
.Change = ActChgMyNck},
[Usr_OTHER] = {.Remove = NextAction[Gbl.Usrs.Other.UsrDat.Roles.InCurrentCrs].Remove,
.Change = NextAction[Gbl.Usrs.Other.UsrDat.Roles.InCurrentCrs].Change}
};
2014-12-01 23:55:08 +01:00
/***** Begin section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_Begin (Nck_NICKNAME_SECTION_ID);
2018-10-15 14:07:12 +02:00
/***** Get my nicknames *****/
NumNicks = Nck_DB_GetUsrNicknames (&mysql_res,UsrDat[MeOrOther]->UsrCod);
/***** Begin box *****/
Box_BoxBegin (Txt_Nickname,Acc_PutLinkToRemoveMyAccount,NULL,
Hlp_PROFILE_Account,Box_NOT_CLOSABLE);
/***** Show possible alerts *****/
Ale_ShowAlerts (Nck_NICKNAME_SECTION_ID);
/***** Help message *****/
if (IMustFillNickname)
Ale_ShowAlert (Ale_WARNING,Txt_Before_going_to_any_other_option_you_must_fill_your_nickname);
/***** Begin table *****/
HTM_TABLE_BeginPadding (2);
/***** List nicknames *****/
for (NumNick = 1;
NumNick <= NumNicks;
NumNick++)
{
/* Get nickname */
row = mysql_fetch_row (mysql_res);
if (NumNick == 1)
{
/* The first nickname is the current one */
HTM_TR_Begin (NULL);
/* Label */
Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_Current_nickname);
/* Data */
HTM_TD_Begin ("class=\"Frm_C2 LT DAT_STRONG_%s\"",
The_GetSuffix ());
}
else // NumNick >= 2
{
if (NumNick == 2)
{
HTM_TR_Begin (NULL);
/* Label */
Frm_LabelColumn ("Frm_C1 RT",NULL,Txt_Other_nicknames);
/* Data */
HTM_TD_Begin ("class=\"Frm_C2 LT DAT_%s\"",
The_GetSuffix ());
}
/* Form to remove old nickname */
Ico_PutContextualIconToRemove (ActNck[MeOrOther].Remove,Nck_NICKNAME_SECTION_ID,
FuncParsRemove[MeOrOther],row[0]);
}
/* Nickname */
HTM_TxtF ("@%s",row[0]);
/* Link to QR code */
if (NumNick == 1 && UsrDat[MeOrOther]->Nickname[0])
QR_PutLinkToPrintQRCode (ActPrnUsrQR,
Usr_PutParOtherUsrCodEncrypted,UsrDat[MeOrOther]->EnUsrCod);
/* Form to change the nickname */
if (NumNick > 1)
{
HTM_BR ();
Frm_BeginFormAnchor (ActNck[MeOrOther].Change,Nck_NICKNAME_SECTION_ID);
if (MeOrOther == Usr_OTHER)
Usr_PutParUsrCodEncrypted (Gbl.Usrs.Other.UsrDat.EnUsrCod);
snprintf (NickWithArr,sizeof (NickWithArr),"@%s",row[0]);
Par_PutParString (NULL,"NewNick",NickWithArr); // Nickname
Btn_PutConfirmButtonInline (Txt_Use_this_nickname);
Frm_EndForm ();
}
if (NumNick == 1 ||
NumNick == NumNicks)
{
HTM_TD_End ();
HTM_TR_End ();
}
else
HTM_BR ();
}
/***** Form to enter new nickname *****/
HTM_TR_Begin (NULL);
/* Label */
Frm_LabelColumn ("Frm_C1 RT","NewNick",
NumNicks ? Txt_New_nickname : // A new nickname
Txt_Nickname); // The first nickname
/* Data */
HTM_TD_Begin ("class=\"Frm_C2 LT DAT_%s\"",The_GetSuffix ());
Frm_BeginFormAnchor (ActNck[MeOrOther].Change,Nck_NICKNAME_SECTION_ID);
if (MeOrOther == Usr_OTHER)
Usr_PutParUsrCodEncrypted (Gbl.Usrs.Other.UsrDat.EnUsrCod);
snprintf (NickWithArr,sizeof (NickWithArr),"@%s",
UsrDat[MeOrOther]->Nickname);
HTM_INPUT_TEXT ("NewNick",1 + Nck_MAX_CHARS_NICK_WITHOUT_ARROBA,
NickWithArr,HTM_DONT_SUBMIT_ON_CHANGE,
"id=\"NewNick\""
" class=\"Frm_C2_INPUT INPUT_%s\""
" size=\"16\"",
The_GetSuffix ());
HTM_BR ();
Btn_PutCreateButtonInline (NumNicks ? Txt_Change_nickname : // I already have a nickname
Txt_Save_changes); // I have no nickname yet);
Frm_EndForm ();
HTM_TD_End ();
HTM_TR_End ();
/***** End table and box *****/
Box_BoxTableEnd ();
2018-10-15 14:07:12 +02:00
/***** End section *****/
2019-10-26 01:56:36 +02:00
HTM_SECTION_End ();
2014-12-01 23:55:08 +01:00
}
static void Nck_PutParsRemoveMyNick (void *Nick)
2020-10-14 00:59:24 +02:00
{
if (Nick)
Par_PutParString (NULL,"Nick",Nick);
2020-10-14 00:59:24 +02:00
}
static void Nck_PutParsRemoveOtherNick (void *Nick)
2020-10-14 00:59:24 +02:00
{
if (Nick)
{
Usr_PutParUsrCodEncrypted (Gbl.Usrs.Other.UsrDat.EnUsrCod);
Par_PutParString (NULL,"Nick",Nick);
2020-10-14 00:59:24 +02:00
}
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-16 01:36:13 +02:00
/***************************** Remove my nickname ****************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-16 01:36:13 +02:00
void Nck_RemoveMyNick (void)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_Nickname_X_removed;
extern const char *Txt_You_can_not_delete_your_current_nickname;
char NickWithoutArr[Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1];
2014-12-01 23:55:08 +01:00
2018-10-16 01:36:13 +02:00
/***** Get nickname from form *****/
Par_GetParText ("Nick",NickWithoutArr,
Nck_MAX_BYTES_NICK_WITHOUT_ARROBA);
2014-12-01 23:55:08 +01:00
if (strcasecmp (NickWithoutArr,Gbl.Usrs.Me.UsrDat.Nickname)) // Only if not my current nickname
2014-12-01 23:55:08 +01:00
{
/***** Remove one of my old nicknames *****/
Nck_DB_RemoveNickname (Gbl.Usrs.Me.UsrDat.UsrCod,NickWithoutArr);
2014-12-01 23:55:08 +01:00
/***** Show message *****/
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_SUCCESS,Nck_NICKNAME_SECTION_ID,
Txt_Nickname_X_removed,
NickWithoutArr);
2014-12-01 23:55:08 +01:00
}
else
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,Nck_NICKNAME_SECTION_ID,
Txt_You_can_not_delete_your_current_nickname);
2014-12-01 23:55:08 +01:00
/***** Show my account again *****/
2018-10-15 14:07:12 +02:00
Acc_ShowFormChgMyAccount ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
2018-10-16 01:36:13 +02:00
/********************* Remove another user's nickname ************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2018-10-16 01:36:13 +02:00
void Nck_RemoveOtherUsrNick (void)
{
extern const char *Txt_Nickname_X_removed;
char NickWithoutArr[Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1];
2018-10-16 01:36:13 +02:00
/***** Get user whose nick must be removed *****/
if (Usr_GetParOtherUsrCodEncryptedAndGetUsrData ())
switch (Usr_CheckIfICanEditOtherUsr (&Gbl.Usrs.Other.UsrDat))
2018-10-16 01:36:13 +02:00
{
case Usr_CAN:
/***** Get nickname from form *****/
Par_GetParText ("Nick",NickWithoutArr,
Nck_MAX_BYTES_NICK_WITHOUT_ARROBA);
/***** Remove one of the old nicknames *****/
Nck_DB_RemoveNickname (Gbl.Usrs.Other.UsrDat.UsrCod,NickWithoutArr);
/***** Show message *****/
Ale_CreateAlert (Ale_SUCCESS,Nck_NICKNAME_SECTION_ID,
Txt_Nickname_X_removed,
NickWithoutArr);
/***** Show user's account again *****/
Acc_ShowFormChgOtherUsrAccount ();
break;
case Usr_CAN_NOT:
default:
Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission ();
break;
2018-10-16 01:36:13 +02:00
}
else // User not found
2019-03-09 20:12:44 +01:00
Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission ();
2018-10-16 01:36:13 +02:00
}
/*****************************************************************************/
/***************************** Update my nickname ****************************/
/*****************************************************************************/
void Nck_UpdateMyNick (void)
{
/***** Update my nickname *****/
Nck_ChangeUsrNick (&Gbl.Usrs.Me.UsrDat);
2018-10-16 01:36:13 +02:00
/***** Show my account again *****/
Acc_ShowFormChgMyAccount ();
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Change another user's nickname **********************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
void Nck_ChangeOtherUsrNick (void)
2018-10-16 01:36:13 +02:00
{
/***** Get user whose nick must be changed *****/
if (Usr_GetParOtherUsrCodEncryptedAndGetUsrData ())
switch (Usr_CheckIfICanEditOtherUsr (&Gbl.Usrs.Other.UsrDat))
2018-10-16 01:36:13 +02:00
{
case Usr_CAN:
/***** Update user's nickname *****/
Nck_ChangeUsrNick (&Gbl.Usrs.Other.UsrDat);
/***** Show user's account again *****/
Acc_ShowFormChgOtherUsrAccount ();
break;
case Usr_CAN_NOT:
default:
Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission ();
break;
2018-10-16 01:36:13 +02:00
}
else // User not found
2019-03-09 20:12:44 +01:00
Ale_ShowAlertUserNotFoundOrYouDoNotHavePermission ();
2018-10-16 01:36:13 +02:00
}
/*****************************************************************************/
/*************************** Change user's nickname **************************/
2018-10-16 01:36:13 +02:00
/*****************************************************************************/
static void Nck_ChangeUsrNick (struct Usr_Data *UsrDat)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_The_nickname_matches_the_one_you_had_previously_registered;
extern const char *Txt_The_nickname_had_been_registered_by_another_user;
extern const char *Txt_The_nickname_has_been_registered_successfully;
extern const char *Txt_The_nickname_is_not_valid_;
char NewNick[Nck_MAX_BYTES_NICK_WITH_ARROBA + 1];
2014-12-01 23:55:08 +01:00
/***** Get new nickname from form *****/
Par_GetParText ("NewNick",NewNick,sizeof (NewNick) - 1);
if (Nck_CheckIfNickWithArrIsValid (NewNick)) // If new nickname is valid
2014-12-01 23:55:08 +01:00
{
/***** Remove arrobas at the beginning *****/
Str_RemoveLeadingArrobas (NewNick);
2014-12-01 23:55:08 +01:00
/***** Check if new nickname exists in database *****/
if (!strcmp (UsrDat->Nickname,NewNick)) // User's nickname match exactly the new nickname
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,Nck_NICKNAME_SECTION_ID,
Txt_The_nickname_matches_the_one_you_had_previously_registered);
else if (strcasecmp (UsrDat->Nickname,NewNick)) // User's nickname does not match, not even case insensitive, the new nickname
2014-12-01 23:55:08 +01:00
{
/***** Check if the new nickname matches any of my old nicknames *****/
if (!Nck_DB_CheckIfNickMatchesAnyUsrNick (UsrDat->UsrCod,NewNick)) // No matches
2014-12-01 23:55:08 +01:00
/***** Check if the new nickname matches any of the nicknames of other users *****/
if (Nck_DB_CheckIfNickMatchesAnyOtherUsrsNicks (UsrDat->UsrCod,NewNick)) // A nickname of another user is the same that user's nickname
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,Nck_NICKNAME_SECTION_ID,
Txt_The_nickname_had_been_registered_by_another_user);
2014-12-01 23:55:08 +01:00
}
2019-03-09 20:12:44 +01:00
if (Ale_GetNumAlerts () == 0) // No problems
2014-12-01 23:55:08 +01:00
{
2018-10-16 01:36:13 +02:00
// Now we know the new nickname is not already in database
// and is diffent to the current one
Nck_DB_UpdateNick (UsrDat->UsrCod,NewNick); // Leading arrobas already removed
Str_Copy (UsrDat->Nickname,NewNick,sizeof (UsrDat->Nickname) - 1);
2014-12-01 23:55:08 +01:00
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_SUCCESS,Nck_NICKNAME_SECTION_ID,
Txt_The_nickname_has_been_registered_successfully);
2014-12-01 23:55:08 +01:00
}
}
else // New nickname is not valid
2019-03-09 20:12:44 +01:00
Ale_CreateAlert (Ale_WARNING,Nck_NICKNAME_SECTION_ID,
Txt_The_nickname_is_not_valid_,
Nck_MIN_CHARS_NICK_WITHOUT_ARROBA,
Nck_MAX_CHARS_NICK_WITHOUT_ARROBA);
2014-12-01 23:55:08 +01:00
}