");
+ }
+
+/*****************************************************************************/
+/************* Get parameters for the creation of a new account **************/
+/*****************************************************************************/
+// Return false on error
+
+static bool Enr_GetParamsNewAccount (char *NewNicknameWithoutArroba,
+ char *NewEmail,
+ char *NewEncryptedPassword)
+ {
+ extern const char *Txt_The_nickname_X_had_been_registered_by_another_user;
+ extern const char *Txt_The_nickname_entered_X_is_not_valid_;
+ extern const char *Txt_The_email_address_X_had_been_registered_by_another_user;
+ extern const char *Txt_The_email_address_entered_X_is_not_valid;
+ extern const char *Txt_You_have_not_written_twice_the_same_new_password;
+ char Query[1024];
+ char NewNicknameWithArroba[Nck_MAX_BYTES_NICKNAME_WITH_ARROBA+1];
+ char NewPlainPassword[2][Pwd_MAX_LENGTH_PLAIN_PASSWORD+1];
+ bool Error = false;
+
+ /***** Step 1/3: Get new nickname from form *****/
+ Par_GetParToText ("NewNick",NewNicknameWithArroba,Nck_MAX_BYTES_NICKNAME_WITH_ARROBA);
+
+ if (Nck_CheckIfNickWithArrobaIsValid (NewNicknameWithArroba)) // If new nickname is valid
+ {
+ /***** Remove arrobas at the beginning *****/
+ strncpy (NewNicknameWithoutArroba,NewNicknameWithArroba,Nck_MAX_BYTES_NICKNAME_WITH_ARROBA);
+ NewNicknameWithoutArroba[Nck_MAX_BYTES_NICKNAME_WITH_ARROBA] = '\0';
+ Str_RemoveLeadingArrobas (NewNicknameWithoutArroba);
+
+ /***** Check if the new nickname matches any of the nicknames of other users *****/
+ sprintf (Query,"SELECT COUNT(*) FROM usr_nicknames"
+ " WHERE Nickname='%s' AND UsrCod<>'%ld'",
+ NewNicknameWithoutArroba,Gbl.Usrs.Me.UsrDat.UsrCod);
+ if (DB_QueryCOUNT (Query,"can not check if nickname already existed")) // A nickname of another user is the same that this nickname
+ {
+ Error = true;
+ sprintf (Gbl.Message,Txt_The_nickname_X_had_been_registered_by_another_user,
+ NewNicknameWithoutArroba);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+ }
+ else // New nickname is not valid
+ {
+ Error = true;
+ sprintf (Gbl.Message,Txt_The_nickname_entered_X_is_not_valid_,
+ NewNicknameWithArroba,
+ Nck_MIN_LENGTH_NICKNAME_WITHOUT_ARROBA,
+ Nck_MAX_LENGTH_NICKNAME_WITHOUT_ARROBA);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+
+ /***** Step 2/3: Get new e-mail from form *****/
+ Par_GetParToText ("NewEmail",NewEmail,Cns_MAX_BYTES_STRING);
+
+ if (Mai_CheckIfEmailIsValid (NewEmail)) // New e-mail is valid
+ {
+ /***** Check if the new e-mail matches any of the confirmed e-mails of other users *****/
+ sprintf (Query,"SELECT COUNT(*) FROM usr_emails"
+ " WHERE E_mail='%s' AND Confirmed='Y'",
+ NewEmail);
+ if (DB_QueryCOUNT (Query,"can not check if e-mail already existed")) // An e-mail of another user is the same that my e-mail
+ {
+ Error = true;
+ sprintf (Gbl.Message,Txt_The_email_address_X_had_been_registered_by_another_user,
+ NewEmail);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+ }
+ else // New e-mail is not valid
+ {
+ Error = true;
+ sprintf (Gbl.Message,Txt_The_email_address_entered_X_is_not_valid,
+ NewEmail);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+
+ /***** Step 3/3: Get new user's ID from form *****/
+ Par_GetParToText ("Paswd1",NewPlainPassword[0],Pwd_MAX_LENGTH_PLAIN_PASSWORD);
+ Par_GetParToText ("Paswd2",NewPlainPassword[1],Pwd_MAX_LENGTH_PLAIN_PASSWORD);
+ if (strcmp (NewPlainPassword[0],NewPlainPassword[1]))
+ {
+ // Passwords don't match
+ Error = true;
+ Lay_ShowAlert (Lay_WARNING,Txt_You_have_not_written_twice_the_same_new_password);
+ }
+ else
+ {
+ Str_ChangeFormat (Str_FROM_FORM,Str_TO_TEXT,
+ NewPlainPassword[0],Pwd_MAX_LENGTH_PLAIN_PASSWORD,true);
+ Cry_EncryptSHA512Base64 (NewPlainPassword[0],NewEncryptedPassword);
+ if (!Pwd_SlowCheckIfPasswordIsGood (NewPlainPassword[0],NewEncryptedPassword,-1L)) // New password is good?
+ {
+ Error = true;
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message); // Error message is set in Usr_SlowCheckIfPasswordIsGood
+ }
+ }
+
+ return !Error;
+ }
+
+/*****************************************************************************/
+/***************** Message after creation of a new account *******************/
+/*****************************************************************************/
+
+void Enr_AfterCreationNewAccount (void)
+ {
+ extern const char *Txt_New_account_created;
+
+ if (Gbl.Usrs.Me.Logged) // If account has been created without problem, I am logged
+ {
+ /***** Show message of success *****/
+ Lay_ShowAlert (Lay_SUCCESS,Txt_New_account_created);
+
+ /***** Show form with account data *****/
+ Enr_ShowFormChangeMyAccount ();
+ }
+ }
+
+/*****************************************************************************/
+/******** Show form to change my account or to create a new account **********/
+/*****************************************************************************/
+
+void Enr_ShowFormAccount (void)
+ {
+ if (Gbl.Usrs.Me.Logged)
+ Enr_ShowFormChangeMyAccount ();
+ else
+ Enr_ShowFormRequestNewAccountWithParams ("","");
+ }
+
+/*****************************************************************************/
+/*********************** Show form to change my account **********************/
+/*****************************************************************************/
+
+void Enr_ShowFormChangeMyAccount (void)
+ {
+ extern const char *Txt_Before_going_to_any_other_option_you_must_fill_your_nickname;
+ extern const char *Txt_Before_going_to_any_other_option_you_must_fill_your_email_address;
+ extern const char *Txt_Before_going_to_any_other_option_you_must_fill_your_ID;
+ extern const char *Txt_User_account;
+
+ /***** Get current user's nickname and e-mail address
+ It's necessary because current nickname or e-mail could be just updated *****/
+ Nck_GetNicknameFromUsrCod (Gbl.Usrs.Me.UsrDat.UsrCod,Gbl.Usrs.Me.UsrDat.Nickname);
+ Mai_GetEmailFromUsrCod (Gbl.Usrs.Me.UsrDat.UsrCod,Gbl.Usrs.Me.UsrDat.Email,&(Gbl.Usrs.Me.UsrDat.EmailConfirmed));
+
+ /***** Check nickname and e-mail *****/
+ if (!Gbl.Usrs.Me.UsrDat.Nickname[0])
+ Lay_ShowAlert (Lay_WARNING,Txt_Before_going_to_any_other_option_you_must_fill_your_nickname);
+ else if (!Gbl.Usrs.Me.UsrDat.Email[0])
+ Lay_ShowAlert (Lay_WARNING,Txt_Before_going_to_any_other_option_you_must_fill_your_email_address);
+ else if (!Gbl.Usrs.Me.UsrDat.IDs.Num)
+ Lay_ShowAlert (Lay_WARNING,Txt_Before_going_to_any_other_option_you_must_fill_your_ID);
+
+ /***** Put links to change my password and to remove my account*****/
+ fprintf (Gbl.F.Out,"
",
+ The_ClassSeparator[Gbl.Prefs.Theme]);
+ }
+
+
+/*****************************************************************************/
+/************* Remove completely a user from the whole platform **************/
+/*****************************************************************************/
+
+static void Enr_DeleteUsrFromPlatform (struct UsrData *UsrDat,
+ Cns_QuietOrVerbose_t QuietOrVerbose)
+ {
+ extern const char *Txt_THE_USER_X_has_been_removed_from_all_his_her_courses;
+ extern const char *Txt_THE_USER_X_has_been_removed_as_administrator;
+ extern const char *Txt_Messages_of_THE_USER_X_have_been_deleted;
+ extern const char *Txt_Virtual_pendrive_of_THE_USER_X_has_been_removed;
+ extern const char *Txt_Photo_of_THE_USER_X_has_been_removed;
+ extern const char *Txt_Record_card_of_THE_USER_X_has_been_removed;
+ char Query[1024];
+ bool PhotoRemoved = false;
+
+ /***** Remove the works zones of the user in all courses *****/
+ Brw_RemoveUsrWorksInAllCrss (UsrDat,QuietOrVerbose); // Make this before of removing the user from the courses
+
+ /***** Remove the fields of course record in all courses *****/
+ Rec_RemoveFieldsCrsRecordAll (UsrDat->UsrCod,QuietOrVerbose);
+
+ /***** Remove user from all the attendance events *****/
+ Att_RemoveUsrFromAllAttEvents (UsrDat->UsrCod);
+
+ /***** Remove user from all the groups of all courses *****/
+ Grp_RemUsrFromAllGrps (UsrDat,QuietOrVerbose);
+
+ /***** Remove user's requests for inscription *****/
+ sprintf (Query,"DELETE FROM crs_usr_requests"
+ " WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove user's requests for inscription");
+
+ /***** Remove user from the table of courses and users *****/
+ sprintf (Query,"DELETE FROM crs_usr"
+ " WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove a user from all courses");
+
+ if (QuietOrVerbose == Cns_VERBOSE)
+ {
+ sprintf (Gbl.Message,Txt_THE_USER_X_has_been_removed_from_all_his_her_courses,
+ UsrDat->FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+
+ /***** Remove user as administrator of any degree *****/
+ sprintf (Query,"DELETE FROM deg_admin"
+ " WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove a user as administrator");
+
+ if (QuietOrVerbose == Cns_VERBOSE)
+ {
+ sprintf (Gbl.Message,Txt_THE_USER_X_has_been_removed_as_administrator,
+ UsrDat->FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+
+ /***** Remove user's clipboards *****/
+ Brw_RemoveUsrClipboard (UsrDat->UsrCod);
+ For_RemoveUsrFromThrClipboard (UsrDat->UsrCod);
+
+ /***** Remove user's expanded folders *****/
+ Brw_RemoveUsrExpandedFolders (UsrDat->UsrCod);
+
+ /***** Remove exams made by user in all courses *****/
+ Tst_RemoveExamsMadeByUsrInAllCrss (UsrDat->UsrCod);
+
+ /***** Remove user's notifications *****/
+ Ntf_RemoveUsrNtfs (UsrDat->UsrCod);
+
+ /***** Delete user's messages sent and received *****/
+ Gbl.Msg.FilterContent[0] = '\0';
+ Msg_DelAllRecAndSntMsgsUsr (UsrDat->UsrCod);
+ if (QuietOrVerbose == Cns_VERBOSE)
+ {
+ sprintf (Gbl.Message,Txt_Messages_of_THE_USER_X_have_been_deleted,
+ UsrDat->FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+
+ /***** Remove user from table of banned users *****/
+ Msg_RemoveUsrFromBanned (UsrDat->UsrCod);
+
+ /***** Delete thread read status for this user *****/
+ For_RemoveUsrFromReadThrs (UsrDat->UsrCod);
+
+ /***** Remove user from table of seen announcements *****/
+ Ann_RemoveUsrFromSeenAnnouncements (UsrDat->UsrCod);
+
+ /***** Remove user from table of connected users *****/
+ sprintf (Query,"DELETE FROM connected WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove a user from table of connected users");
+
+ /***** Remove all sessions of this user *****/
+ sprintf (Query,"DELETE FROM sessions WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove sessions of a user");
+
+ /***** Remove the user from the list of users without photo *****/
+ Enr_RemoveUsrFromTableClicksWithoutPhoto (UsrDat->UsrCod);
+
+ /***** Remove the file tree of a user *****/
+ Enr_RemoveUsrBriefcase (UsrDat);
+ if (QuietOrVerbose == Cns_VERBOSE)
+ {
+ sprintf (Gbl.Message,Txt_Virtual_pendrive_of_THE_USER_X_has_been_removed,
+ UsrDat->FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+
+ /***** Remove user's photo *****/
+ PhotoRemoved = Pho_RemovePhoto (UsrDat);
+ if (PhotoRemoved && QuietOrVerbose == Cns_VERBOSE)
+ {
+ sprintf (Gbl.Message,Txt_Photo_of_THE_USER_X_has_been_removed,
+ UsrDat->FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+
+ /***** Remove user *****/
+ Enr_RemoveUsr (UsrDat);
+ if (QuietOrVerbose == Cns_VERBOSE)
+ {
+ sprintf (Gbl.Message,Txt_Record_card_of_THE_USER_X_has_been_removed,
+ UsrDat->FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+ }
+
+/*****************************************************************************/
+/********************** Remove the briefcase of a user ***********************/
+/*****************************************************************************/
+
+void Enr_RemoveUsrBriefcase (struct UsrData *UsrDat)
+ {
+ char PathRelUsr[PATH_MAX+1];
+
+ /***** Remove the briefcase of the user *****/
+ Usr_ConstructPathUsr (UsrDat->UsrCod,PathRelUsr);
+ Brw_RemoveTree (PathRelUsr);
+
+ /***** Remove files in the course from database *****/
+ Brw_RemoveFilesFromDB (-1L,-1L,UsrDat->UsrCod);
+
+ /***** Remove size of the briefcase of the user from database *****/
+ Brw_RemoveSizeOfFileTreeFromDB (-1L,-1L,UsrDat->UsrCod);
+ }
+
+/*****************************************************************************/
+/************************ Remove a user from database ************************/
+/*****************************************************************************/
+
+static void Enr_RemoveUsr (struct UsrData *UsrDat)
+ {
+ char Query[128];
+
+ /***** Remove user's webs / social networks *****/
+ sprintf (Query,"DELETE FROM usr_webs WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove user's webs / social networks");
+
+ /***** Remove user's nicknames *****/
+ sprintf (Query,"DELETE FROM usr_nicknames WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove user's nicknames");
+
+ /***** Remove user's e-mails *****/
+ sprintf (Query,"DELETE FROM pending_emails WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove pending user's e-mails");
+
+ sprintf (Query,"DELETE FROM usr_emails WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove user's e-mails");
+
+ /***** Remove user's IDs *****/
+ sprintf (Query,"DELETE FROM usr_IDs WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove user's IDs");
+
+ /***** Remove user's last data *****/
+ sprintf (Query,"DELETE FROM usr_last WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove user's last data");
+
+ /***** Remove user's data *****/
+ sprintf (Query,"DELETE FROM usr_data WHERE UsrCod='%ld'",
+ UsrDat->UsrCod);
+ DB_QueryDELETE (Query,"can not remove user's data");
+ }
+
+/*****************************************************************************/
+/****** Request acceptation / refusion of register in current course *********/
+/*****************************************************************************/
+
+void Enr_ReqAcceptRegisterInCrs (void)
+ {
+ extern const char *The_ClassFormul[The_NUM_THEMES];
+ extern const char *Txt_A_teacher_or_administrator_has_enrolled_you_into_the_course_;
+ extern const char *Txt_Confirm_my_enrollment;
+ extern const char *Txt_Remove_me_from_this_course;
+
+ /***** Show message *****/
+ sprintf (Gbl.Message,Txt_A_teacher_or_administrator_has_enrolled_you_into_the_course_,
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+
+ /***** Send button to accept register in the current course *****/
+ fprintf (Gbl.F.Out,"
");
+ Act_FormStart (ActAccEnrCrs);
+ Act_LinkFormSubmit (Txt_Confirm_my_enrollment,The_ClassFormul[Gbl.Prefs.Theme]);
+ Lay_PutSendIcon ("ok_green",Txt_Confirm_my_enrollment,Txt_Confirm_my_enrollment);
+ fprintf (Gbl.F.Out,"");
+
+ /***** Send button to refuse register in the current course *****/
+ Act_FormStart (ActRemMeCrs);
+ Act_LinkFormSubmit (Txt_Remove_me_from_this_course,The_ClassFormul[Gbl.Prefs.Theme]);
+ Lay_PutSendIcon ("delon",Txt_Remove_me_from_this_course,Txt_Remove_me_from_this_course);
+ fprintf (Gbl.F.Out,""
+ "
");
+
+ /***** Mark possible notification as seen *****/
+ Ntf_SetNotifAsSeen (Ntf_EVENT_ENROLLMENT,
+ -1L,
+ Gbl.Usrs.Me.UsrDat.UsrCod);
+ }
+
+/*****************************************************************************/
+/****************** Put an enrollment into a notification ********************/
+/*****************************************************************************/
+// This function may be called inside a web service, so don't report error
+
+void Enr_GetNotifEnrollment (char *SummaryStr,
+ long CrsCod,long UsrCod,
+ unsigned MaxChars)
+ {
+ extern const char *Txt_ROLES_SINGULAR_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+ char Query[256];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ struct UsrData UsrDat;
+ Rol_Role_t Role;
+
+ SummaryStr[0] = '\0'; // Return nothing on error
+
+ /***** Get user's role in course from database *****/
+ sprintf (Query,"SELECT Role"
+ " FROM crs_usr"
+ " WHERE CrsCod='%ld' AND UsrCod='%ld'",
+ CrsCod,UsrCod);
+
+ if (!mysql_query (&Gbl.mysql,Query))
+ if ((mysql_res = mysql_store_result (&Gbl.mysql)) != NULL)
+ {
+ /***** Result should have a unique row *****/
+ if (mysql_num_rows (mysql_res) == 1)
+ {
+ /***** Get user's role in course *****/
+ row = mysql_fetch_row (mysql_res);
+
+ /* Initialize structure with user's data */
+ Usr_UsrDataConstructor (&UsrDat);
+
+ /* Get user's data */
+ UsrDat.UsrCod = UsrCod;
+ Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat);
+
+ /* Role (row[0]) */
+ Role = Usr_ConvertUnsignedStrToRole (row[0]);
+ strcpy (SummaryStr,Txt_ROLES_SINGULAR_Abc[Role][UsrDat.Sex]);
+ if (MaxChars)
+ Str_LimitLengthHTMLStr (SummaryStr,MaxChars);
+
+ /* Free memory used for user's data */
+ Usr_UsrDataDestructor (&UsrDat);
+ }
+
+ mysql_free_result (mysql_res);
+ }
+ }
+
+/*****************************************************************************/
+/****************************** Create new user ******************************/
+/*****************************************************************************/
+// UsrDat->UsrCod must be <= 0
+// UsrDat->UsrDat.IDs must contain a list of IDs for the new user
+
+void Enr_CreateNewUsr (struct UsrData *UsrDat)
+ {
+ extern const char *Ico_IconSetId[Ico_NUM_ICON_SETS];
+ extern const char *The_ThemeId[The_NUM_THEMES];
+ extern const char *Txt_STR_LANG_ID[Txt_NUM_LANGUAGES];
+ extern const char *Usr_StringsSexDB[Usr_NUM_SEXS];
+ char Query[2048];
+ char PathRelUsr[PATH_MAX+1];
+ unsigned NumID;
+
+ /***** Check if user's code is initialized *****/
+ if (UsrDat->UsrCod > 0)
+ Lay_ShowErrorAndExit ("Can not create new user.");
+
+ /***** Create encrypted user's code *****/
+ Enr_CreateNewEncryptedUsrCod (UsrDat);
+
+ /***** Filter some user's data before inserting */
+ Enr_FilterUsrDat (UsrDat);
+
+ /***** Insert new user in database *****/
+ /* Insert user's data */
+ sprintf (Query,"INSERT INTO usr_data (EncryptedUsrCod,Password,Surname1,Surname2,FirstName,Sex,"
+ "Layout,Theme,IconSet,Language,PublicPhoto,"
+ "CtyCod,"
+ "LocalAddress,LocalPhone,FamilyAddress,FamilyPhone,OriginPlace,Birthday,Comments,"
+ "SideCols,NotifNtfEvents,EmailNtfEvents)"
+ " VALUES ('%s','%s','%s','%s','%s','%s',"
+ "'%u','%s','%s','%s','%c',"
+ "'%ld',"
+ "'%s','%s','%s','%s','%s','%04u-%02u-%02u','%s',"
+ "'3','-1','0')",
+ UsrDat->EncryptedUsrCod,
+ UsrDat->Password,
+ UsrDat->Surname1,UsrDat->Surname2,UsrDat->FirstName,
+ Usr_StringsSexDB[UsrDat->Sex],
+ (unsigned) UsrDat->Prefs.Layout,
+ The_ThemeId[UsrDat->Prefs.Theme],
+ Ico_IconSetId[UsrDat->Prefs.IconSet],
+ Txt_STR_LANG_ID[UsrDat->Prefs.Language],
+ UsrDat->PublicPhoto ? 'Y' :
+ 'N',
+ UsrDat->CtyCod,
+ UsrDat->LocalAddress ,UsrDat->LocalPhone,
+ UsrDat->FamilyAddress,UsrDat->FamilyPhone,
+ UsrDat->OriginPlace,
+ UsrDat->Birthday.Year,UsrDat->Birthday.Month,UsrDat->Birthday.Day,
+ UsrDat->Comments ? UsrDat->Comments :
+ "");
+ UsrDat->UsrCod = DB_QueryINSERTandReturnCode (Query,"can not create user");
+
+ /* Insert user's IDs as confirmed */
+ for (NumID = 0;
+ NumID < UsrDat->IDs.Num;
+ NumID++)
+ {
+ Str_ConvertToUpperText (UsrDat->IDs.List[NumID].ID);
+ sprintf (Query,"INSERT INTO usr_IDs (UsrCod,UsrID,CreatTime,Confirmed)"
+ " VALUES ('%ld','%s',NOW(),'%c')",
+ UsrDat->UsrCod,
+ UsrDat->IDs.List[NumID].ID,
+ UsrDat->IDs.List[NumID].Confirmed ? 'Y' :
+ 'N');
+ DB_QueryINSERT (Query,"can not store user's ID when creating user");
+ }
+
+ /***** Create directory for the user, if not exists *****/
+ Usr_ConstructPathUsr (UsrDat->UsrCod,PathRelUsr);
+ Fil_CreateDirIfNotExists (PathRelUsr);
+ }
+
+/*****************************************************************************/
+/******************** Create a new encrypted user's code *********************/
+/*****************************************************************************/
+
+#define LENGTH_RANDOM_STR 32
+#define MAX_TRY 10
+
+static void Enr_CreateNewEncryptedUsrCod (struct UsrData *UsrDat)
+ {
+ char RandomStr[LENGTH_RANDOM_STR+1];
+ unsigned NumTry;
+
+ for (NumTry = 0;
+ NumTry < MAX_TRY;
+ NumTry++)
+ {
+ Str_CreateRandomAlphanumStr (RandomStr,LENGTH_RANDOM_STR);
+ Cry_EncryptSHA256Base64 (RandomStr,UsrDat->EncryptedUsrCod);
+ if (!Usr_ChkIfEncryptedUsrCodExists (UsrDat->EncryptedUsrCod))
+ break;
+ }
+ if (NumTry == MAX_TRY)
+ Lay_ShowErrorAndExit ("Can not create a new encrypted user's code.");
+ }
+
+/*****************************************************************************/
+/***************************** Update user's data ****************************/
+/*****************************************************************************/
+// UsrDat->UsrCod must be > 0
+
+void Enr_UpdateUsrData (struct UsrData *UsrDat)
+ {
+ extern const char *Ico_IconSetId[Ico_NUM_ICON_SETS];
+ extern const char *The_ThemeId[The_NUM_THEMES];
+ extern const char *Txt_STR_LANG_ID[Txt_NUM_LANGUAGES];
+ extern const char *Usr_StringsSexDB[Usr_NUM_SEXS];
+ char Query[2048];
+
+ /***** Check if user's code is initialized *****/
+ if (UsrDat->UsrCod <= 0)
+ Lay_ShowErrorAndExit ("Can not update user's data. Wrong user's code.");
+
+ /***** Filter some user's data before updating */
+ Enr_FilterUsrDat (UsrDat);
+
+ /***** Update user's common data *****/
+ sprintf (Query,"UPDATE usr_data"
+ " SET Password='%s',"
+ "Surname1='%s',Surname2='%s',FirstName='%s',Sex='%s',"
+ "Layout='%u',Theme='%s',IconSet='%s',Language='%s',PublicPhoto='%c',"
+ "CtyCod='%ld',"
+ "LocalAddress='%s',LocalPhone='%s',FamilyAddress='%s',FamilyPhone='%s',OriginPlace='%s',Birthday='%04u-%02u-%02u',Comments='%s'"
+ " WHERE UsrCod='%ld'",
+ UsrDat->Password,
+ UsrDat->Surname1,UsrDat->Surname2,UsrDat->FirstName,
+ Usr_StringsSexDB[UsrDat->Sex],
+ (unsigned) UsrDat->Prefs.Layout,
+ The_ThemeId[UsrDat->Prefs.Theme],
+ Ico_IconSetId[UsrDat->Prefs.IconSet],
+ Txt_STR_LANG_ID[UsrDat->Prefs.Language],
+ UsrDat->PublicPhoto ? 'Y' :
+ 'N',
+ UsrDat->CtyCod,
+ UsrDat->LocalAddress,UsrDat->LocalPhone,
+ UsrDat->FamilyAddress,UsrDat->FamilyPhone,UsrDat->OriginPlace,
+ UsrDat->Birthday.Year,UsrDat->Birthday.Month,UsrDat->Birthday.Day,
+ UsrDat->Comments ? UsrDat->Comments :
+ "",
+ UsrDat->UsrCod);
+ DB_QueryUPDATE (Query,"can not update user's data");
+ }
+
+/*****************************************************************************/
+/************************* Filter some user's data ***************************/
+/*****************************************************************************/
+
+static void Enr_FilterUsrDat (struct UsrData *UsrDat)
+ {
+ /***** Fix birthday *****/
+ if (UsrDat->Birthday.Year < Gbl.Now.Date.Year-99 ||
+ UsrDat->Birthday.Year > Gbl.Now.Date.Year-16)
+ UsrDat->Birthday.Year =
+ UsrDat->Birthday.Month =
+ UsrDat->Birthday.Day = 0;
+ }
+
+/*****************************************************************************/
+/**************** Update institution, centre and department ******************/
+/*****************************************************************************/
+
+void Enr_UpdateInstitutionCentreDepartment (void)
+ {
+ char Query[256];
+
+ sprintf (Query,"UPDATE usr_data"
+ " SET InsCtyCod='%ld',InsCod='%ld',CtrCod='%ld',DptCod='%ld'"
+ " WHERE UsrCod='%ld'",
+ Gbl.Usrs.Me.UsrDat.InsCtyCod,
+ Gbl.Usrs.Me.UsrDat.InsCod,
+ Gbl.Usrs.Me.UsrDat.Tch.CtrCod,
+ Gbl.Usrs.Me.UsrDat.Tch.DptCod,
+ Gbl.Usrs.Me.UsrDat.UsrCod);
+ DB_QueryUPDATE (Query,"can not update institution, centre and department");
+ }
+
+/*****************************************************************************/
+/***** Register/remove users (taken from a list) in/from current course ******/
+/*****************************************************************************/
+
+void Enr_ShowFormRegRemSeveralUsrs (void)
+ {
+ extern const char *The_ClassTitle[The_NUM_THEMES];
+ extern const char *Txt_Step_1_Provide_a_list_of_users;
+ extern const char *Txt_Option_a_Import_students_from_the_official_lists;
+ extern const char *Txt_There_is_no_external_service_for_authentication_and_official_lists;
+ extern const char *Txt_Select_the_groups_of_students_you_want_to_register_in_remove_from_this_course;
+ extern const char *Txt_Option_b_Type_or_paste_a_list_of_users;
+ extern const char *Txt_Type_or_paste_a_list_of_IDs_nicks_or_emails_;
+ extern const char *Txt_Step_2_Select_the_type_of_user_to_register_remove;
+ extern const char *Txt_Step_3_Select_the_desired_action;
+ extern const char *Txt_Step_4_Optionally_select_groups;
+ extern const char *Txt_Select_the_groups_in_from_which_you_want_to_register_remove_users_;
+ extern const char *Txt_No_groups_have_been_created_in_the_course_X_Therefore_;
+ extern const char *Txt_Step_5_Confirm_the_enrollment_removing;
+ extern const char *Txt_Confirm;
+
+ fprintf (Gbl.F.Out,"
");
+
+ /***** Put link to remove all the students in the current course *****/
+ if (Gbl.CurrentCrs.Crs.CrsCod > 0) // Course selected
+ Enr_PutFormToRemAllStdsThisCrs ();
+
+ /***** Put link to remove old users *****/
+ if (Gbl.Usrs.Me.LoggedRole == Rol_ROLE_SUPERUSER)
+ Enr_PutFormToRemOldUsrs ();
+
+ /***** Form to send students to be enrolled / removed *****/
+ Act_FormStart (ActRcvFrmMdfUsrCrs);
+
+ /***** Step 1: List of students to be enrolled / removed *****/
+ fprintf (Gbl.F.Out,"
"
+ " %s
",
+ The_ClassTitle[Gbl.Prefs.Theme],
+ Txt_Step_1_Provide_a_list_of_users);
+
+ /* Option a: get students from official lists */
+ fprintf (Gbl.F.Out,"
"
+ " %s
",
+ The_ClassTitle[Gbl.Prefs.Theme],
+ Txt_Option_a_Import_students_from_the_official_lists);
+ if (Cfg_EXTERNAL_LOGIN_CLIENT_COMMAND[0] == '\0')
+ Lay_ShowAlert (Lay_INFO,Txt_There_is_no_external_service_for_authentication_and_official_lists);
+ else
+ {
+ Lay_ShowAlert (Lay_INFO,Txt_Select_the_groups_of_students_you_want_to_register_in_remove_from_this_course);
+ Imp_ListMyImpGrpsAndStdsForm ();
+ }
+
+ /* Option b: get students' IDs from pasted text */
+ fprintf (Gbl.F.Out,"
"
+ " %s
",
+ The_ClassTitle[Gbl.Prefs.Theme],
+ Txt_Option_b_Type_or_paste_a_list_of_users);
+ Lay_ShowAlert (Lay_INFO,Txt_Type_or_paste_a_list_of_IDs_nicks_or_emails_);
+ Enr_PutAreaToEnterUsrsIDs ();
+
+ /***** Step 2: Select type of user to register/remove to/from current course *****/
+ fprintf (Gbl.F.Out,"
"
+ " %s
",
+ The_ClassTitle[Gbl.Prefs.Theme],
+ Txt_Step_2_Select_the_type_of_user_to_register_remove);
+ if (Gbl.CurrentCrs.Crs.CrsCod > 0) // Course selected
+ Enr_PutAllRolesRegRemUsrsCrs ();
+
+ /***** Step 3: Put different actions to register/remove students to/from current course *****/
+ fprintf (Gbl.F.Out,"
"
+ " %s
",
+ The_ClassTitle[Gbl.Prefs.Theme],
+ Txt_Step_3_Select_the_desired_action);
+ Enr_PutActionsRegRemSeveralUsrs ();
+
+ /***** Step 4: Select groups in which register / remove students *****/
+ fprintf (Gbl.F.Out,"
"
+ " %s
",
+ The_ClassTitle[Gbl.Prefs.Theme],
+ Txt_Step_4_Optionally_select_groups);
+ if (Gbl.CurrentCrs.Crs.CrsCod > 0) // Course selected
+ {
+ if (Gbl.CurrentCrs.Grps.NumGrps) // This course has groups?
+ {
+ Lay_ShowAlert (Lay_INFO,Txt_Select_the_groups_in_from_which_you_want_to_register_remove_users_);
+ Grp_ShowLstGrpsToChgOtherUsrsGrps (-1L);
+ }
+ else
+ {
+ /* Write help message */
+ sprintf (Gbl.Message,Txt_No_groups_have_been_created_in_the_course_X_Therefore_,
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+ }
+ }
+
+ /***** Step 5: Button to register / remove students *****/
+ fprintf (Gbl.F.Out,"
"
+ " %s
",
+ The_ClassTitle[Gbl.Prefs.Theme],
+ Txt_Step_5_Confirm_the_enrollment_removing);
+ Pwd_AskForConfirmationOnDangerousAction ();
+ Lay_PutSendButton (Txt_Confirm);
+
+ /***** End of form *****/
+ fprintf (Gbl.F.Out,""
+ "
");
+ }
+
+/*****************************************************************************/
+/******************** Put a link (form) to remove old users ******************/
+/*****************************************************************************/
+
+static void Enr_PutFormToRemOldUsrs (void)
+ {
+ extern const char *The_ClassFormul[The_NUM_THEMES];
+ extern const char *Txt_Remove_old_users;
+
+ /***** Put form to remove old users *****/
+ Act_FormStart (ActReqRemOldUsr);
+ Act_LinkFormSubmit (Txt_Remove_old_users,The_ClassFormul[Gbl.Prefs.Theme]);
+ Lay_PutSendIcon ("delon",Txt_Remove_old_users,Txt_Remove_old_users);
+ fprintf (Gbl.F.Out,"");
+ }
+
+/*****************************************************************************/
+/*********************** Write form to remove old users **********************/
+/*****************************************************************************/
+
+void Enr_AskRemoveOldUsrs (void)
+ {
+ extern const char *The_ClassFormul[The_NUM_THEMES];
+ extern const char *Txt_Eliminate_all_users_who_are_not_enrolled_on_any_courses_PART_1_OF_2;
+ extern const char *Txt_Eliminate_all_users_who_are_not_enrolled_on_any_courses_PART_2_OF_2;
+ extern const char *Txt_Eliminate;
+ unsigned MonthsWithoutAccess = Usr_DEF_MONTHS_WITHOUT_ACCESS_TO_REMOVE_OLD_USRS;
+ unsigned i;
+
+ /***** Form to request number of months without clicks *****/
+ fprintf (Gbl.F.Out,"
");
+ }
+
+/*****************************************************************************/
+/*** Select types of user to register/remove users to/from current course ****/
+/*****************************************************************************/
+
+static void Enr_PutOneRoleRegRemUsrsCrs (Rol_Role_t Role,bool Checked)
+ {
+ extern const char *Txt_ROLES_SINGULAR_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+
+ fprintf (Gbl.F.Out,"
"
+ "%s
",
+ Txt_ROLES_SINGULAR_Abc[Role][Usr_SEX_UNKNOWN]);
+ }
+
+/*****************************************************************************/
+/******* Receive the list of users of the course to register/remove **********/
+/*****************************************************************************/
+
+void Enr_ReceiveFormUsrsCrs (void)
+ {
+ extern const char *Txt_You_must_specify_in_step_3_the_action_to_perform;
+ extern const char *Txt_In_a_type_of_group_with_single_enrollment_students_can_not_be_registered_in_more_than_one_group;
+ extern const char *Txt_No_user_has_been_eliminated;
+ extern const char *Txt_One_user_has_been_eliminated;
+ extern const char *Txt_No_user_has_been_removed;
+ extern const char *Txt_One_user_has_been_removed;
+ extern const char *Txt_X_users_have_been_eliminated;
+ extern const char *Txt_X_users_have_been_removed;
+ extern const char *Txt_No_user_has_been_enrolled;
+ extern const char *Txt_One_user_has_been_enrolled;
+ extern const char *Txt_X_users_have_been_enrolled_including_possible_repetitions;
+ char ListExternalGrpCods[Imp_MAX_BYTES_LIST_EXTERNAL_GRP_CODS+1];
+ char ExternalStr[1+10+1+Crs_LENGTH_INSTITUTIONAL_CRS_COD+1];
+ char ExternalCrsCod[Crs_LENGTH_INSTITUTIONAL_CRS_COD+1];
+ char UnsignedStr[10+1];
+ unsigned UnsignedNum;
+ long LongNum;
+ Rol_Role_t RegRemRole = Rol_ROLE_STUDENT;
+ struct
+ {
+ bool RemoveUsrs;
+ bool RemoveSpecifiedUsrs;
+ bool EliminateUsrs;
+ bool RegisterUsrs;
+ } WhatToDo;
+ char *ListUsrsIDs;
+ struct ListUsrCods ListUsrCods; // List with users' codes for a given user's ID
+ unsigned NumUsrFound;
+ const char *Ptr;
+ unsigned NumCurrentUsr;
+ long GrpCod;
+ unsigned NumUsrsRegistered = 0;
+ unsigned NumUsrsRemoved = 0;
+ unsigned NumUsrsEliminated = 0;
+ struct ListUsers *LstCurrentUsrs;
+ struct ListCodGrps LstGrps;
+ struct UsrData UsrDat;
+ bool ItLooksLikeAUsrID;
+ Enr_RegRemUsrsAction_t RegRemUsrsAction;
+ bool ErrorInForm = false;
+
+ /***** Get confirmation *****/
+ if (!Pwd_GetConfirmationOnDangerousAction ())
+ return;
+
+ /***** Get the type of user to register / remove *****/
+ Par_GetParToText ("RegRemRole",UnsignedStr,1);
+ if (UnsignedStr[0])
+ switch ((RegRemRole = Usr_ConvertUnsignedStrToRole (UnsignedStr)))
+ {
+ case Rol_ROLE_STUDENT:
+ break;
+ case Rol_ROLE_TEACHER:
+ switch (Gbl.Usrs.Me.LoggedRole) // Can I register/remove teachers?
+ {
+ case Rol_ROLE_DEG_ADMIN:
+ case Rol_ROLE_SUPERUSER: // Yes, I can
+ break;
+ default: // No, I can not (TODO: teachers should be able to register/remove existing teachers)
+ Lay_ShowErrorAndExit ("You are not allowed to perform this action."); // If user manipulated the form
+ break;
+ }
+ break;
+ default:
+ Lay_ShowErrorAndExit ("Wrong role."); // If user manipulated the form
+ break;
+ }
+
+ /***** Get the action to do *****/
+ WhatToDo.RemoveUsrs = false;
+ WhatToDo.RemoveSpecifiedUsrs = false;
+ WhatToDo.EliminateUsrs = false;
+ WhatToDo.RegisterUsrs = false;
+
+ Par_GetParToText ("RegRemAction",UnsignedStr,1);
+ if (sscanf (UnsignedStr,"%u",&UnsignedNum) == 1)
+ if (UnsignedNum < Enr_NUM_ACTIONS_REG_REM_USRS)
+ switch (RegRemUsrsAction = (Enr_RegRemUsrsAction_t) UnsignedNum)
+ {
+ case Enr_REGISTER_SPECIFIED_USRS_IN_CRS:
+ WhatToDo.RemoveUsrs = false;
+ WhatToDo.RemoveSpecifiedUsrs = false; // Ignored
+ WhatToDo.EliminateUsrs = false; // Ignored
+ WhatToDo.RegisterUsrs = true;
+ break;
+ case Enr_REMOVE_SPECIFIED_USRS_FROM_CRS:
+ WhatToDo.RemoveUsrs = true;
+ WhatToDo.RemoveSpecifiedUsrs = true;
+ WhatToDo.EliminateUsrs = false;
+ WhatToDo.RegisterUsrs = false;
+ break;
+ case Enr_REMOVE_NOT_SPECIFIED_USRS_FROM_CRS:
+ WhatToDo.RemoveUsrs = true;
+ WhatToDo.RemoveSpecifiedUsrs = false;
+ WhatToDo.EliminateUsrs = false;
+ WhatToDo.RegisterUsrs = false;
+ break;
+ case Enr_UPDATE_USRS_IN_CRS:
+ WhatToDo.RemoveUsrs = true;
+ WhatToDo.RemoveSpecifiedUsrs = false;
+ WhatToDo.EliminateUsrs = false;
+ WhatToDo.RegisterUsrs = true;
+ break;
+ case Enr_ELIMINATE_USRS_FROM_PLATFORM:
+ if (Gbl.Usrs.Me.LoggedRole == Rol_ROLE_SUPERUSER)
+ {
+ WhatToDo.RemoveUsrs = true;
+ WhatToDo.RemoveSpecifiedUsrs = true;
+ WhatToDo.EliminateUsrs = true;
+ WhatToDo.RegisterUsrs = false;
+ }
+ else
+ Lay_ShowErrorAndExit ("You are not allowed to perform this action.");
+ break;
+ default:
+ Lay_ShowErrorAndExit ("Wrong registering / removing specification.");
+ break;
+ }
+ else
+ Lay_ShowErrorAndExit ("Wrong registering / removing specification.");
+ else
+ {
+ Lay_ShowAlert (Lay_WARNING,Txt_You_must_specify_in_step_3_the_action_to_perform);
+
+ /* Show form again */
+ Enr_ShowFormRegRemSeveralUsrs ();
+ ErrorInForm = true;
+ }
+
+ if (!ErrorInForm)
+ {
+ /***** Get external groups of students *****/
+ Par_GetParMultiToText ("ImpGrpCod",ListExternalGrpCods,Imp_MAX_BYTES_LIST_EXTERNAL_GRP_CODS);
+
+ /***** Get groups to which register/remove users *****/
+ LstGrps.NumGrps = 0;
+ if (Gbl.CurrentCrs.Grps.NumGrps) // This course has groups?
+ {
+ /***** Get list of groups types and groups in current course *****/
+ Grp_GetListGrpTypesAndGrpsInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
+
+ /***** Get the list of groups to which register/remove students *****/
+ Grp_GetLstCodsGrpWanted (&LstGrps);
+
+ /***** A student can't belong to more than one group when the type of group only allows to register in one group *****/
+ if (WhatToDo.RegisterUsrs &&
+ RegRemRole == Rol_ROLE_STUDENT &&
+ LstGrps.NumGrps >= 2)
+ /* Check if I have selected more than one group of single enrollment */
+ if (!Grp_CheckIfSelectionGrpsIsValid (&LstGrps))
+ {
+ /* Show warning message and exit */
+ Lay_ShowAlert (Lay_WARNING,Txt_In_a_type_of_group_with_single_enrollment_students_can_not_be_registered_in_more_than_one_group);
+
+ /* Free memory used by lists of groups and abort */
+ Grp_FreeListCodGrp (&LstGrps);
+ Grp_FreeListGrpTypesAndGrps ();
+ return;
+ }
+ }
+
+ /***** Get list of users' IDs *****/
+ if ((ListUsrsIDs = (char *) malloc (ID_MAX_BYTES_LIST_USRS_IDS+1)) == NULL)
+ Lay_ShowErrorAndExit ("Not enough memory to store users' IDs.");
+ Par_GetParToText ("UsrsIDs",ListUsrsIDs,ID_MAX_BYTES_LIST_USRS_IDS);
+
+ /***** Initialize structure with user's data *****/
+ Usr_UsrDataConstructor (&UsrDat);
+
+ /***** Remove users *****/
+ if (WhatToDo.RemoveUsrs)
+ {
+ /***** Get list of users in current course *****/
+ switch (RegRemRole)
+ {
+ case Rol_ROLE_STUDENT:
+ Usr_GetUsrsLst (Rol_ROLE_STUDENT,Sco_SCOPE_COURSE,NULL,false);
+ LstCurrentUsrs = &Gbl.Usrs.LstStds;
+ break;
+ case Rol_ROLE_TEACHER:
+ Usr_GetUsrsLst (Rol_ROLE_TEACHER,Sco_SCOPE_COURSE,NULL,false);
+ LstCurrentUsrs = &Gbl.Usrs.LstTchs;
+ break;
+ default:
+ LstCurrentUsrs = NULL; // To avoid warning
+ Lay_ShowErrorAndExit ("Wrong role."); // If user manipulated the form
+ break;
+ }
+
+ if (LstCurrentUsrs->NumUsrs)
+ {
+ /***** Initialize list of users to remove *****/
+ for (NumCurrentUsr = 0;
+ NumCurrentUsr < LstCurrentUsrs->NumUsrs;
+ NumCurrentUsr++)
+ LstCurrentUsrs->Lst[NumCurrentUsr].Remove = !WhatToDo.RemoveSpecifiedUsrs;
+
+ /***** Loop 1: go through form list setting if a student must be removed *****/
+ /* Step a: Get students from a list of official groups */
+ if (RegRemRole == Rol_ROLE_STUDENT)
+ {
+ Ptr = ListExternalGrpCods;
+ while (*Ptr)
+ {
+ /* Find next external group code and course code in list */
+ Str_GetNextStringUntilSeparator (&Ptr,ExternalStr,1+10+1+Crs_LENGTH_INSTITUTIONAL_CRS_COD);
+ if (sscanf (ExternalStr,"%ld_%s",&LongNum,ExternalCrsCod) == 2)
+ {
+ GrpCod = LongNum;
+
+ /* Mark users belonging to this official group as removable */
+ Enr_MarkOfficialStdsAsRemovable (GrpCod,WhatToDo.RemoveSpecifiedUsrs);
+ }
+ }
+ }
+
+ /* Step b: Get users from a list of users' IDs */
+ Ptr = ListUsrsIDs;
+ while (*Ptr)
+ {
+ /* Reset user */
+ UsrDat.UsrCod = -1L;
+
+ /* Find next string in text */
+ Str_GetNextStringUntilSeparator (&Ptr,UsrDat.UsrIDNickOrEmail,Usr_MAX_BYTES_USR_LOGIN);
+
+ /* Reset default list of users' codes */
+ ListUsrCods.NumUsrs = 0;
+ ListUsrCods.Lst = NULL;
+
+ /* Check if string is a user's ID, user's nickname or user's e-mail address */
+ if (Nck_CheckIfNickWithArrobaIsValid (UsrDat.UsrIDNickOrEmail)) // 1: It's a nickname
+ {
+ if ((UsrDat.UsrCod = Nck_GetUsrCodFromNickname (UsrDat.UsrIDNickOrEmail)) > 0)
+ {
+ ListUsrCods.NumUsrs = 1;
+ Usr_AllocateListUsrCods (&ListUsrCods);
+ ListUsrCods.Lst[0] = UsrDat.UsrCod;
+ }
+ }
+ else if (Mai_CheckIfEmailIsValid (UsrDat.UsrIDNickOrEmail)) // 2: It's an e-mail
+ {
+ if ((UsrDat.UsrCod = Mai_GetUsrCodFromEmail (UsrDat.UsrIDNickOrEmail)) > 0)
+ {
+ ListUsrCods.NumUsrs = 1;
+ Usr_AllocateListUsrCods (&ListUsrCods);
+ ListUsrCods.Lst[0] = UsrDat.UsrCod;
+ }
+ }
+ else // 3: It looks like a user's ID
+ {
+ // Users' IDs are always stored internally in capitals and without leading zeros
+ Str_RemoveLeadingZeros (UsrDat.UsrIDNickOrEmail);
+ Str_ConvertToUpperText (UsrDat.UsrIDNickOrEmail);
+ if (ID_CheckIfUsrIDSeemsAValidID (UsrDat.UsrIDNickOrEmail))
+ {
+ /***** Find users for this user's ID *****/
+ ID_ReallocateListIDs (&UsrDat,1); // Only one user's ID
+ strcpy (UsrDat.IDs.List[0].ID,UsrDat.UsrIDNickOrEmail);
+ ID_GetListUsrCodsFromUsrID (&UsrDat,NULL,&ListUsrCods,false);
+ }
+ }
+
+ if (WhatToDo.RemoveSpecifiedUsrs) // Remove the specified users (of the role)
+ {
+ if (ListUsrCods.NumUsrs == 1) // If more than one user found ==> do not remove
+ for (NumCurrentUsr = 0;
+ NumCurrentUsr < LstCurrentUsrs->NumUsrs;
+ NumCurrentUsr++)
+ if (LstCurrentUsrs->Lst[NumCurrentUsr].UsrCod == ListUsrCods.Lst[0]) // User found
+ LstCurrentUsrs->Lst[NumCurrentUsr].Remove = true; // Mark as removable
+ }
+ else // Remove all the users (of the role) except these specified
+ {
+ for (NumCurrentUsr = 0;
+ NumCurrentUsr < LstCurrentUsrs->NumUsrs;
+ NumCurrentUsr++)
+ for (NumUsrFound = 0;
+ NumUsrFound < ListUsrCods.NumUsrs;
+ NumUsrFound++)
+ if (LstCurrentUsrs->Lst[NumCurrentUsr].UsrCod == ListUsrCods.Lst[NumUsrFound]) // User found
+ LstCurrentUsrs->Lst[NumCurrentUsr].Remove = false; // Mark as not removable
+ }
+
+ /* Free memory used for list of users' codes found for this ID */
+ Usr_FreeListUsrCods (&ListUsrCods);
+ }
+
+ /***** Loop 2: go through users list removing users *****/
+ for (NumCurrentUsr = 0;
+ NumCurrentUsr < LstCurrentUsrs->NumUsrs;
+ NumCurrentUsr++)
+ if (LstCurrentUsrs->Lst[NumCurrentUsr].Remove) // If this student must be removed
+ {
+ UsrDat.UsrCod = LstCurrentUsrs->Lst[NumCurrentUsr].UsrCod;
+ if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat)) // If user's data exist...
+ {
+ if (WhatToDo.EliminateUsrs) // Eliminate user completely from the platform
+ {
+ Enr_DeleteUsrFromPlatform (&UsrDat,Cns_QUIET); // Remove definitely the user from the platform
+ NumUsrsEliminated++;
+ }
+ else
+ {
+ if (Gbl.CurrentCrs.Grps.NumGrps) // If there are groups in the course
+ {
+ if (LstGrps.NumGrps) // If the teacher has selected groups
+ {
+ if (Grp_RemoveUsrFromGroups (&UsrDat,&LstGrps)) // Remove user from the selected groups, not from the whole course
+ NumUsrsRemoved++;
+ }
+ else // The teacher has not selected groups
+ {
+ Enr_EffectivelyRemUsrFromCrs (&UsrDat,&Gbl.CurrentCrs.Crs,
+ Enr_DO_NOT_REMOVE_WORKS,Cns_QUIET); // Remove user from the course
+ NumUsrsRemoved++;
+ }
+ }
+ else // No groups
+ {
+ Enr_EffectivelyRemUsrFromCrs (&UsrDat,&Gbl.CurrentCrs.Crs,
+ Enr_DO_NOT_REMOVE_WORKS,Cns_QUIET); // Remove user from the course
+ NumUsrsRemoved++;
+ }
+ }
+ }
+ }
+ }
+
+ /***** Free memory for users list *****/
+ Usr_FreeUsrsList (LstCurrentUsrs);
+ }
+
+ /***** Register users *****/
+ if (WhatToDo.RegisterUsrs) // TODO: !!!!! NO CAMBIAR EL ROL DE LOS USUARIOS QUE YA ESTÉN EN LA ASIGNATURA SI HAY MÁS DE UN USUARIO ENCONTRADO PARA EL MISMO DNI !!!!!!
+ {
+ /***** Step a: Get users from a list of official groups *****/
+ if (RegRemRole == Rol_ROLE_STUDENT)
+ {
+ Ptr = ListExternalGrpCods;
+ while (*Ptr)
+ {
+ /* Find next official group code in list */
+ Str_GetNextStringUntilSeparator (&Ptr,ExternalStr,1+10+1+Crs_LENGTH_INSTITUTIONAL_CRS_COD);
+ if (sscanf (ExternalStr,"%ld_%s",&LongNum,ExternalCrsCod) == 2)
+ {
+ GrpCod = LongNum;
+
+ /* Import official group of users */
+ Imp_ImportStdsFromAnImpGrp (GrpCod,&LstGrps,&NumUsrsRegistered);
+
+ /* Update the institutional course code to the external course code */
+ Crs_UpdateCurrentInstitutionalCrsCod (&Gbl.CurrentCrs.Crs,ExternalCrsCod);
+ }
+ }
+ }
+
+ /***** Step b: Get users from a list of users' IDs ******/
+ Ptr = ListUsrsIDs;
+ while (*Ptr)
+ {
+ /* Reset user */
+ UsrDat.UsrCod = -1L;
+ ItLooksLikeAUsrID = false;
+
+ /* Find next string in text */
+ Str_GetNextStringUntilSeparator (&Ptr,UsrDat.UsrIDNickOrEmail,Usr_MAX_BYTES_USR_LOGIN);
+
+ /* Reset default list of users' codes */
+ ListUsrCods.NumUsrs = 0;
+ ListUsrCods.Lst = NULL;
+
+ /* Check if the string is a user's ID, a user's nickname or a user's e-mail address */
+ if (Nck_CheckIfNickWithArrobaIsValid (UsrDat.UsrIDNickOrEmail)) // 1: It's a nickname
+ {
+ if ((UsrDat.UsrCod = Nck_GetUsrCodFromNickname (UsrDat.UsrIDNickOrEmail)) > 0)
+ {
+ ListUsrCods.NumUsrs = 1;
+ Usr_AllocateListUsrCods (&ListUsrCods);
+ ListUsrCods.Lst[0] = UsrDat.UsrCod;
+ }
+ }
+ else if (Mai_CheckIfEmailIsValid (UsrDat.UsrIDNickOrEmail)) // 2: It's an e-mail
+ {
+ if ((UsrDat.UsrCod = Mai_GetUsrCodFromEmail (UsrDat.UsrIDNickOrEmail)) > 0)
+ {
+ ListUsrCods.NumUsrs = 1;
+ Usr_AllocateListUsrCods (&ListUsrCods);
+ ListUsrCods.Lst[0] = UsrDat.UsrCod;
+ }
+ }
+ else // 3: It looks like a user's ID
+ {
+ // Users' IDs are always stored internally in capitals and without leading zeros
+ Str_RemoveLeadingZeros (UsrDat.UsrIDNickOrEmail);
+ Str_ConvertToUpperText (UsrDat.UsrIDNickOrEmail);
+ if (ID_CheckIfUsrIDSeemsAValidID (UsrDat.UsrIDNickOrEmail))
+ {
+ ItLooksLikeAUsrID = true;
+
+ /* Find users for this user's ID */
+ ID_ReallocateListIDs (&UsrDat,1); // Only one user's ID
+ strcpy (UsrDat.IDs.List[0].ID,UsrDat.UsrIDNickOrEmail);
+ ID_GetListUsrCodsFromUsrID (&UsrDat,NULL,&ListUsrCods,false);
+ }
+ }
+
+ /* Register user(s) */
+ if (ListUsrCods.NumUsrs) // User(s) found
+ for (NumUsrFound = 0;
+ NumUsrFound < ListUsrCods.NumUsrs;
+ NumUsrFound++)
+ {
+ UsrDat.UsrCod = ListUsrCods.Lst[NumUsrFound];
+ Enr_RegisterUsr (&UsrDat,RegRemRole,&LstGrps,&NumUsrsRegistered);
+ }
+ else if (ItLooksLikeAUsrID) // User not found. He/she is a new user. Register him/her using ID
+ Enr_RegisterUsr (&UsrDat,RegRemRole,&LstGrps,&NumUsrsRegistered);
+
+ /* Free memory used for list of users' codes found for this ID */
+ Usr_FreeListUsrCods (&ListUsrCods);
+ }
+ }
+
+ /***** Free memory used for user's data *****/
+ Usr_UsrDataDestructor (&UsrDat);
+
+ if (NumUsrsEliminated)
+ /***** Move unused contents of messages to table of deleted contents of messages *****/
+ Msg_MoveUnusedMsgsContentToDeleted ();
+
+ /***** Write messages with the number of users enrolled/removed *****/
+ if (WhatToDo.RemoveUsrs)
+ {
+ if (WhatToDo.EliminateUsrs) // Eliminate completely from the platform
+ switch (NumUsrsEliminated)
+ {
+ case 0:
+ Lay_ShowAlert (Lay_INFO,Txt_No_user_has_been_eliminated);
+ break;
+ case 1:
+ Lay_ShowAlert (Lay_SUCCESS,Txt_One_user_has_been_eliminated);
+ break;
+ default:
+ sprintf (Gbl.Message,Txt_X_users_have_been_eliminated,
+ NumUsrsEliminated);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ break;
+ }
+ else // Only remove from course / groups
+ switch (NumUsrsRemoved)
+ {
+ case 0:
+ Lay_ShowAlert (Lay_INFO,Txt_No_user_has_been_removed);
+ break;
+ case 1:
+ Lay_ShowAlert (Lay_SUCCESS,Txt_One_user_has_been_removed);
+ break;
+ default:
+ sprintf (Gbl.Message,Txt_X_users_have_been_removed,
+ NumUsrsRemoved);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ break;
+ }
+ }
+ if (WhatToDo.RegisterUsrs)
+ switch (NumUsrsRegistered)
+ {
+ case 0:
+ Lay_ShowAlert (Lay_INFO,Txt_No_user_has_been_enrolled);
+ break;
+ case 1:
+ Lay_ShowAlert (Lay_SUCCESS,Txt_One_user_has_been_enrolled);
+ break;
+ default:
+ sprintf (Gbl.Message,Txt_X_users_have_been_enrolled_including_possible_repetitions,
+ NumUsrsRegistered);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ break;
+ }
+
+ /***** Free memory used by the list of user's IDs *****/
+ free (ListUsrsIDs);
+
+ /***** Free memory with the list of groups to/from which register/remove users *****/
+ Grp_FreeListCodGrp (&LstGrps);
+
+ /***** Free list of groups types and groups in current course *****/
+ Grp_FreeListGrpTypesAndGrps ();
+ }
+ }
+
+/*****************************************************************************/
+/********************** Register a user using his/her ID *********************/
+/*****************************************************************************/
+// If user does not exists, UsrDat->IDs must hold the user's ID
+
+static void Enr_RegisterUsr (struct UsrData *UsrDat,Rol_Role_t RegRemRole,
+ struct ListCodGrps *LstGrps,unsigned *NumUsrsRegistered)
+ {
+ /***** Check if I can register this user *****/
+ if (Gbl.Usrs.Me.LoggedRole == Rol_ROLE_TEACHER &&
+ RegRemRole != Rol_ROLE_STUDENT)
+ Lay_ShowErrorAndExit ("A teacher only can register new users if they are students.");
+
+ /***** Check if the record of the user exists and get the type of user *****/
+ if (UsrDat->UsrCod > 0) // User exists in database
+ Usr_GetAllUsrDataFromUsrCod (UsrDat); // Get user's data
+ else // User does not exist in database, create it using his/her ID!
+ {
+ // Reset user's data
+ Usr_ResetUsrDataExceptUsrCodAndIDs (UsrDat); // It's necessary, because the same struct UsrDat was used for former user
+
+ // User does not exist in database;list of IDs is initialized
+ UsrDat->IDs.List[0].Confirmed = true; // If he/she is a new user ==> his/her ID will be stored as confirmed in database
+ Enr_CreateNewUsr (UsrDat);
+ }
+
+ /***** Register user in current course in database *****/
+ if (Gbl.CurrentCrs.Crs.CrsCod > 0) // Course selected
+ {
+ if (Usr_CheckIfUsrBelongsToCrs (UsrDat->UsrCod,Gbl.CurrentCrs.Crs.CrsCod)) // User does belong to current course, modify his/her role
+ Enr_ModifyRoleInCurrentCrs (UsrDat,RegRemRole,
+ Cns_QUIET,Enr_SET_ACCEPTED_TO_FALSE);
+ else
+ Enr_RegisterUsrInCurrentCrs (UsrDat,RegRemRole,
+ Cns_QUIET,Enr_SET_ACCEPTED_TO_FALSE);
+
+ /***** Register user in the selected groups *****/
+ if (Gbl.CurrentCrs.Grps.NumGrps) // If there are groups in the course
+ Grp_RegisterUsrIntoGroups (UsrDat,LstGrps);
+ }
+
+ (*NumUsrsRegistered)++;
+ }
+
+/*****************************************************************************/
+/****** Mark the students belonging to an official group as removable ********/
+/*****************************************************************************/
+
+static void Enr_MarkOfficialStdsAsRemovable (long ImpGrpCod,bool RemoveSpecifiedUsrs)
+ {
+ char Query[1024];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ unsigned NumStds;
+ unsigned NumStd;
+ unsigned NumUsr;
+ struct ListUsrCods ListUsrCods; // List with users' codes for a given user's ID
+ unsigned NumUsrFound;
+
+ /***** Get imported students belonging to this group from database *****/
+ sprintf (Query,"SELECT UsrID FROM imported_students WHERE GrpCod='%ld'",
+ ImpGrpCod);
+ NumStds = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get imported students");
+
+ /***** Mark the students from this official group as removable *****/
+ for (NumStd = 0;
+ NumStd < NumStds;
+ NumStd++) // For each student inside the official group...
+ {
+ /* Get user's ID of the student from official list */
+ row = mysql_fetch_row (mysql_res);
+
+ /***** Allocate space for the list *****/
+ ID_ReallocateListIDs (&Gbl.Usrs.Other.UsrDat,1);
+
+ strncpy (Gbl.Usrs.Other.UsrDat.IDs.List[0].ID,row[0],ID_MAX_LENGTH_USR_ID);
+ Gbl.Usrs.Other.UsrDat.IDs.List[0].ID[ID_MAX_LENGTH_USR_ID] = '\0';
+ // Users' IDs are always stored internally in capitals and without leading zeros
+ Str_RemoveLeadingZeros (Gbl.Usrs.Other.UsrDat.IDs.List[0].ID);
+ Str_ConvertToUpperText (Gbl.Usrs.Other.UsrDat.IDs.List[0].ID);
+
+ /* Check if this official user's ID is in the list of students */
+ if (ID_CheckIfUsrIDIsValid (Gbl.Usrs.Other.UsrDat.IDs.List[0].ID))
+ if (ID_GetListUsrCodsFromUsrID (&Gbl.Usrs.Other.UsrDat,NULL,&ListUsrCods,false)) // User(s) found
+ {
+ for (NumUsr = 0;
+ NumUsr < Gbl.Usrs.LstStds.NumUsrs;
+ NumUsr++)
+ for (NumUsrFound = 0;
+ NumUsrFound < ListUsrCods.NumUsrs;
+ NumUsrFound++)
+ if (Gbl.Usrs.LstStds.Lst[NumUsr].UsrCod == ListUsrCods.Lst[NumUsrFound]) // User found
+ Gbl.Usrs.LstStds.Lst[NumUsr].Remove = RemoveSpecifiedUsrs;
+
+ /* Free memory used for list of users' codes found for this ID */
+ Usr_FreeListUsrCods (&ListUsrCods);
+ }
+ }
+
+ /***** Free structure that stores the query result *****/
+ DB_FreeMySQLResult (&mysql_res);
+ }
+
+/*****************************************************************************/
+/**** Put a link (form) to remove all the students in the current course *****/
+/*****************************************************************************/
+
+static void Enr_PutFormToRemAllStdsThisCrs (void)
+ {
+ extern const char *The_ClassFormul[The_NUM_THEMES];
+ extern const char *Txt_Remove_all_students;
+
+ /***** Put form to remove all the students in the current course *****/
+ Act_FormStart (ActReqRemAllStdCrs);
+ Act_LinkFormSubmit (Txt_Remove_all_students,The_ClassFormul[Gbl.Prefs.Theme]);
+ Lay_PutSendIcon ("delon",Txt_Remove_all_students,Txt_Remove_all_students);
+ fprintf (Gbl.F.Out,"");
+ }
+
+/*****************************************************************************/
+/********** Ask for removing all the students from current course ************/
+/*****************************************************************************/
+
+void Enr_AskRemAllStdsThisCrs (void)
+ {
+ extern const char *Txt_Do_you_really_want_to_remove_the_X_students_from_the_course_Y_;
+ extern const char *Txt_Remove_students;
+ extern const char *Txt_No_users_found[Rol_NUM_ROLES];
+ unsigned NumStds;
+
+ if ((NumStds = Usr_GetNumUsrsInCrs (Rol_ROLE_STUDENT,Gbl.CurrentCrs.Crs.CrsCod)))
+ {
+ /***** Write message to confirm the removing *****/
+ sprintf (Gbl.Message,Txt_Do_you_really_want_to_remove_the_X_students_from_the_course_Y_,
+ NumStds,Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+
+ /***** Form to remove all the students in current course *****/
+ Act_FormStart (ActRemAllStdCrs);
+ Grp_PutParamAllGroups ();
+ Pwd_AskForConfirmationOnDangerousAction ();
+ Lay_PutSendButton (Txt_Remove_students);
+ fprintf (Gbl.F.Out,"");
+ }
+ else
+ {
+ sprintf (Gbl.Message,Txt_No_users_found[Rol_ROLE_STUDENT],
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+ }
+
+/*****************************************************************************/
+/***************** Remove all the students from current course ***************/
+/*****************************************************************************/
+
+void Enr_RemAllStdsThisCrs (void)
+ {
+ extern const char *Txt_The_X_students_who_belonged_to_the_course_Y_have_been_removed_from_it;
+ extern const char *Txt_No_users_found[Rol_NUM_ROLES];
+ unsigned NumStdsInCrs;
+
+ if (Pwd_GetConfirmationOnDangerousAction ())
+ {
+ if ((NumStdsInCrs = Enr_RemAllStdsInCrs (&Gbl.CurrentCrs.Crs)))
+ {
+ sprintf (Gbl.Message,Txt_The_X_students_who_belonged_to_the_course_Y_have_been_removed_from_it,
+ NumStdsInCrs,Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+ else
+ {
+ sprintf (Gbl.Message,Txt_No_users_found[Rol_ROLE_STUDENT],
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+ }
+ }
+
+/*****************************************************************************/
+/***************** Remove all the students from a given course ***************/
+/*****************************************************************************/
+// Returns the numbers of students in the course before deletion
+
+unsigned Enr_RemAllStdsInCrs (struct Course *Crs)
+ {
+ unsigned NumStdsInCrs;
+ unsigned NumUsr;
+
+ /***** Get list of students in current course *****/
+ Gbl.Usrs.ClassPhoto.AllGroups = true; // Get all the students of the current course
+ Usr_GetUsrsLst (Rol_ROLE_STUDENT,Sco_SCOPE_COURSE,NULL,false);
+ NumStdsInCrs = Gbl.Usrs.LstStds.NumUsrs;
+
+ /***** Remove all the students *****/
+ for (NumUsr = 0;
+ NumUsr < NumStdsInCrs;
+ NumUsr++)
+ {
+ Gbl.Usrs.Other.UsrDat.UsrCod = Gbl.Usrs.LstStds.Lst[NumUsr].UsrCod;
+ Enr_EffectivelyRemUsrFromCrs (&Gbl.Usrs.Other.UsrDat,Crs,
+ Enr_REMOVE_WORKS,Cns_QUIET);
+ }
+
+ /***** Free memory for students list *****/
+ Usr_FreeUsrsList (&Gbl.Usrs.LstStds);
+
+ return NumStdsInCrs;
+ }
+
+/*****************************************************************************/
+/************* Form to request sign up in the current course *****************/
+/*****************************************************************************/
+
+void Enr_ReqSignUpInCrs (void)
+ {
+ extern const char *Txt_You_were_already_enrolled_as_X_in_the_course_Y;
+ extern const char *Txt_ROLES_SINGULAR_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+
+ /***** Check if I already belong to course *****/
+ if (Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB >= Rol_ROLE_STUDENT)
+ {
+ sprintf (Gbl.Message,Txt_You_were_already_enrolled_as_X_in_the_course_Y,
+ Txt_ROLES_SINGULAR_abc[Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB][Gbl.Usrs.Me.UsrDat.Sex],
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+ else if (Gbl.Usrs.Me.LoggedRole == Rol_ROLE_GUEST ||
+ Gbl.Usrs.Me.LoggedRole == Rol_ROLE_VISITOR)
+ /***** Show form to modify only the user's role or the user's data *****/
+ Rec_ShowFormSignUpWithMyCommonRecord ();
+ else
+ Lay_ShowErrorAndExit ("You must be logged to sign up in a course."); // This never should happen
+ }
+
+/*****************************************************************************/
+/*********************** Sign up in the current course ***********************/
+/*****************************************************************************/
+
+void Enr_SignUpInCrs (void)
+ {
+ extern const char *Txt_You_were_already_enrolled_as_X_in_the_course_Y;
+ extern const char *Txt_ROLES_SINGULAR_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+ extern const char *Txt_Your_request_for_enrollment_as_X_in_the_course_Y_has_been_accepted_for_processing;
+ char Query[512];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ char UnsignedStr[10+1];
+ Rol_Role_t RoleFromForm;
+ long ReqCod = -1L;
+ unsigned NumUsrsToBeNotifiedByEMail;
+
+ /***** Check if I already belong to course *****/
+ if (Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB >= Rol_ROLE_STUDENT)
+ {
+ sprintf (Gbl.Message,Txt_You_were_already_enrolled_as_X_in_the_course_Y,
+ Txt_ROLES_SINGULAR_abc[Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB][Gbl.Usrs.Me.UsrDat.Sex],
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+ else
+ {
+ /***** Get new role from record form *****/
+ Par_GetParToText ("Role",UnsignedStr,10);
+ RoleFromForm = Usr_ConvertUnsignedStrToRole (UnsignedStr);
+
+ /* Check if role is correct */
+ if (!(RoleFromForm == Rol_ROLE_STUDENT ||
+ RoleFromForm == Rol_ROLE_TEACHER))
+ Lay_ShowErrorAndExit ("Wrong role.");
+
+ /***** Try to get and old request of the same user in the same course from database *****/
+ sprintf (Query,"SELECT ReqCod FROM crs_usr_requests"
+ " WHERE CrsCod='%ld' AND UsrCod='%ld'",
+ Gbl.CurrentCrs.Crs.CrsCod,
+ Gbl.Usrs.Me.UsrDat.UsrCod);
+ if (DB_QuerySELECT (Query,&mysql_res,"can not get enrollment request"))
+ {
+ row = mysql_fetch_row (mysql_res);
+ /* Get request code (row[0]) */
+ ReqCod = Str_ConvertStrCodToLongCod (row[0]);
+ }
+ /* Free structure that stores the query result */
+ DB_FreeMySQLResult (&mysql_res);
+
+ /***** Request user in current course in database *****/
+ if (ReqCod > 0) // Old request exists in database
+ {
+ sprintf (Query,"UPDATE crs_usr_requests SET Role='%u',RequestTime=NOW()"
+ " WHERE ReqCod='%ld' AND CrsCod='%ld' AND UsrCod='%ld'",
+ (unsigned) RoleFromForm,
+ ReqCod,
+ Gbl.CurrentCrs.Crs.CrsCod,
+ Gbl.Usrs.Me.UsrDat.UsrCod);
+ DB_QueryUPDATE (Query,"can not update enrollment request");
+ }
+ else // No request in database for this user in this course
+ {
+ sprintf (Query,"INSERT INTO crs_usr_requests (CrsCod,UsrCod,Role,RequestTime)"
+ " VALUES ('%ld','%ld','%u',NOW())",
+ Gbl.CurrentCrs.Crs.CrsCod,
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ (unsigned) RoleFromForm);
+ ReqCod = DB_QueryINSERTandReturnCode (Query,"can not save enrollment request");
+ }
+
+ /***** Show confirmation message *****/
+ sprintf (Gbl.Message,Txt_Your_request_for_enrollment_as_X_in_the_course_Y_has_been_accepted_for_processing,
+ Txt_ROLES_SINGULAR_abc[RoleFromForm][Gbl.Usrs.Me.UsrDat.Sex],
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+
+ /***** Notify teachers or admins by e-mail about the new enrollment request *****/
+ // If this course has teachers ==> send notification to teachers
+ // If this course has no teachers and I want to be a teacher ==> send notification to administrators or superusers
+ if (Gbl.CurrentCrs.Crs.NumTchs || RoleFromForm == Rol_ROLE_TEACHER)
+ {
+ NumUsrsToBeNotifiedByEMail = Ntf_StoreNotifyEventsToAllUsrs (Ntf_EVENT_ENROLLMENT_REQUEST,ReqCod);
+ Ntf_ShowAlertNumUsrsToBeNotifiedByEMail (NumUsrsToBeNotifiedByEMail);
+ }
+ }
+ }
+
+/*****************************************************************************/
+/************** Put an enrollment request into a notification *****************/
+/*****************************************************************************/
+// This function may be called inside a web service, so don't report error
+
+void Enr_GetNotifEnrollmentRequest (char *SummaryStr,char **ContentStr,
+ long ReqCod,unsigned MaxChars,bool GetContent)
+ {
+ extern const char *Txt_ROLES_SINGULAR_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+ char Query[256];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ struct UsrData UsrDat;
+ Rol_Role_t DesiredRole;
+
+ SummaryStr[0] = '\0'; // Return nothing on error
+
+ /***** Get user and requested role from database *****/
+ sprintf (Query,"SELECT UsrCod,Role,"
+ "DATE_FORMAT(RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM crs_usr_requests"
+ " WHERE ReqCod='%ld'",
+ ReqCod);
+
+ if (!mysql_query (&Gbl.mysql,Query))
+ if ((mysql_res = mysql_store_result (&Gbl.mysql)) != NULL)
+ {
+ /***** Result should have a unique row *****/
+ if (mysql_num_rows (mysql_res) == 1)
+ {
+ /***** Get user and requested role *****/
+ row = mysql_fetch_row (mysql_res);
+
+ /* Initialize structure with user's data */
+ Usr_UsrDataConstructor (&UsrDat);
+
+ /* User's code (row[0]) */
+ UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
+ Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat);
+
+ /* Role (row[1]) */
+ DesiredRole = Usr_ConvertUnsignedStrToRole (row[1]);
+ strcpy (SummaryStr,Txt_ROLES_SINGULAR_Abc[DesiredRole][UsrDat.Sex]);
+ if (MaxChars)
+ Str_LimitLengthHTMLStr (SummaryStr,MaxChars);
+
+ if (GetContent)
+ if ((*ContentStr = (char *) malloc (16+1)))
+ /* Write date (row[2]) into content */
+ sprintf (*ContentStr,"%c%c/%c%c/%c%c%c%c %c%c:%c%c",
+ row[2][ 6],row[2][ 7],
+ row[2][ 4],row[2][ 5],
+ row[2][ 0],row[2][ 1],row[2][ 2],row[2][ 3],
+ row[2][ 8],row[2][ 9],
+ row[2][10],row[2][11]);
+
+ /* Free memory used for user's data */
+ Usr_UsrDataDestructor (&UsrDat);
+ }
+
+ mysql_free_result (mysql_res);
+ }
+ }
+
+/*****************************************************************************/
+/****** Ask if reject the request for enrollment of a user in a course *******/
+/*****************************************************************************/
+
+void Enr_AskIfRejectSignUp (void)
+ {
+ extern const char *Txt_THE_USER_X_is_already_enrolled_in_the_course_Y;
+ extern const char *Txt_Do_you_really_want_to_reject_the_enrollment_request_;
+ extern const char *Txt_ROLES_SINGULAR_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+ extern const char *Txt_Reject;
+ extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
+
+ Rol_Role_t Role;
+
+ /***** Get user's code *****/
+ Usr_GetParamOtherUsrCodEncrypted ();
+
+ if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat)) // If user's data exist...
+ {
+ if (Usr_CheckIfUsrBelongsToCrs (Gbl.Usrs.Other.UsrDat.UsrCod,Gbl.CurrentCrs.Crs.CrsCod))
+ {
+ /* User already belongs to this course */
+ sprintf (Gbl.Message,Txt_THE_USER_X_is_already_enrolled_in_the_course_Y,
+ Gbl.Usrs.Other.UsrDat.FullName,Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ Rec_ShowCommonRecordUnmodifiable (&Gbl.Usrs.Other.UsrDat);
+
+ /* Remove inscription request because it has not sense */
+ Enr_RemoveEnrollmentRequest (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Usrs.Other.UsrDat.UsrCod);
+ }
+ else // User does not belong to this course
+ {
+ Role = Enr_GetRequestedRole (Gbl.Usrs.Other.UsrDat.UsrCod);
+ if (Role == Rol_ROLE_STUDENT ||
+ Role == Rol_ROLE_TEACHER)
+ {
+ /* Ask if reject */
+ sprintf (Gbl.Message,Txt_Do_you_really_want_to_reject_the_enrollment_request_,
+ Gbl.Usrs.Other.UsrDat.FullName,
+ Txt_ROLES_SINGULAR_abc[Role][Gbl.Usrs.Other.UsrDat.Sex],
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+ Rec_ShowCommonRecordUnmodifiable (&Gbl.Usrs.Other.UsrDat);
+
+ /* Button to confirm rejection */
+ Act_FormStart (ActRejSignUp);
+ Usr_PutParamOtherUsrCodEncrypted (Gbl.Usrs.Other.UsrDat.EncryptedUsrCod);
+
+ Lay_PutSendButton (Txt_Reject);
+ fprintf (Gbl.F.Out,"");
+ }
+ else
+ Lay_ShowErrorAndExit ("Wrong role.");
+ }
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+
+/*****************************************************************************/
+/********* Reject the request for enrollment of a user in a course ***********/
+/*****************************************************************************/
+
+void Enr_RejectSignUp (void)
+ {
+ extern const char *Txt_THE_USER_X_is_already_enrolled_in_the_course_Y;
+ extern const char *Txt_Enrollment_of_X_rejected;
+ extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
+
+ /***** Get user's code *****/
+ Usr_GetParamOtherUsrCodEncrypted ();
+
+ if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat)) // If user's data exist...
+ {
+ if (Usr_CheckIfUsrBelongsToCrs (Gbl.Usrs.Other.UsrDat.UsrCod,Gbl.CurrentCrs.Crs.CrsCod))
+ {
+ /* User already belongs to this course */
+ sprintf (Gbl.Message,Txt_THE_USER_X_is_already_enrolled_in_the_course_Y,
+ Gbl.Usrs.Other.UsrDat.FullName,Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ Rec_ShowCommonRecordUnmodifiable (&Gbl.Usrs.Other.UsrDat);
+ }
+
+ /* Remove inscription request */
+ Enr_RemoveEnrollmentRequest (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Usrs.Other.UsrDat.UsrCod);
+
+ /* Confirmation message */
+ sprintf (Gbl.Message,Txt_Enrollment_of_X_rejected,
+ Gbl.Usrs.Other.UsrDat.FullName);
+ Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+
+ /* Show again the rest of registrarion requests */
+ Enr_ShowEnrollmentRequests ();
+ }
+
+/*****************************************************************************/
+/******** Show pending requests for enrollment in the current course *********/
+/*****************************************************************************/
+
+void Enr_ShowEnrollmentRequests (void)
+ {
+ extern const char *The_ClassFormul[The_NUM_THEMES];
+ extern const char *Txt_Scope;
+ extern const char *Txt_Users;
+ extern const char *Txt_Update;
+ extern const char *Txt_Course;
+ extern const char *Txt_Teachers_ABBREVIATION;
+ extern const char *Txt_Requester;
+ extern const char *Txt_Role;
+ extern const char *Txt_Date;
+ extern const char *Txt_Go_to_X;
+ extern const char *Txt_ROLES_SINGULAR_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
+ extern const char *Txt_Register;
+ extern const char *Txt_Reject;
+ extern const char *Txt_No_enrollment_requests;
+ unsigned Roles;
+ char Query[1024];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ unsigned NumReq;
+ unsigned NumRequests;
+ long ReqCod;
+ struct Degree Deg;
+ struct Course Crs;
+ struct UsrData UsrDat;
+ bool UsrExists;
+ bool UsrBelongsToCrs;
+ bool ShowPhoto = false;
+ char PhotoURL[PATH_MAX+1];
+ Rol_Role_t DesiredRole;
+
+ /***** Selection of scope and roles *****/
+ /* Start form */
+ Act_FormStart (ActSeeSignUpReq);
+ fprintf (Gbl.F.Out,"
"
+ "
");
+
+ /* Scope (whole platform, current centre, current degree or current course) */
+ fprintf (Gbl.F.Out,"
",
+ The_ClassFormul[Gbl.Prefs.Theme],Txt_Users);
+ Usr_GetSelectedRoles (&Roles);
+ if (!Roles)
+ /* Set default roles */
+ switch (Gbl.Usrs.Me.LoggedRole)
+ {
+ case Rol_ROLE_TEACHER:
+ Roles = (1 << Rol_ROLE_STUDENT) | (1 << Rol_ROLE_TEACHER);
+ break;
+ case Rol_ROLE_DEG_ADMIN:
+ case Rol_ROLE_SUPERUSER:
+ Roles = (1 << Rol_ROLE_TEACHER);
+ break;
+ default:
+ Lay_ShowErrorAndExit ("You don't have permission to list requesters.");
+ break;
+ }
+ Usr_WriteSelectorRoles (Roles);
+ fprintf (Gbl.F.Out,"
"
+ "
");
+ /* Form end */
+ fprintf (Gbl.F.Out,"
"
+ "
");
+ Lay_PutSendButton (Txt_Update);
+ fprintf (Gbl.F.Out,"");
+
+ /***** Build query *****/
+ switch (Gbl.Scope.Current)
+ {
+ case Sco_SCOPE_PLATFORM: // Show requesters for the whole platform
+ switch (Gbl.Usrs.Me.LoggedRole)
+ {
+ case Rol_ROLE_TEACHER:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM crs_usr,crs_usr_requests"
+ " WHERE crs_usr.UsrCod='%ld'"
+ " AND crs_usr.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ Roles);
+ break;
+ case Rol_ROLE_DEG_ADMIN:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM deg_admin,courses,crs_usr_requests"
+ " WHERE deg_admin.UsrCod='%ld'"
+ " AND deg_admin.DegCod=courses.DegCod"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ Roles);
+ break;
+ case Rol_ROLE_SUPERUSER:
+ sprintf (Query,"SELECT ReqCod,CrsCod,UsrCod,Role,DATE_FORMAT(RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM crs_usr_requests WHERE ((1<0"
+ " ORDER BY RequestTime DESC",
+ Roles);
+ break;
+ default:
+ Lay_ShowErrorAndExit ("You don't have permission to list requesters.");
+ break;
+ }
+ break;
+ case Sco_SCOPE_INSTITUTION: // Show requesters for the current institution
+ switch (Gbl.Usrs.Me.LoggedRole)
+ {
+ case Rol_ROLE_TEACHER:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM crs_usr,centres,degrees,courses,crs_usr_requests"
+ " WHERE crs_usr.UsrCod='%ld'"
+ " AND centres.InsCod='%ld'"
+ " AND crs_usr.CrsCod=courses.CrsCod"
+ " AND degrees.DegCod=courses.DegCod"
+ " AND degrees.CtrCod=centres.CtrCod"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ Gbl.CurrentIns.Ins.InsCod,
+ Roles);
+ break;
+ case Rol_ROLE_DEG_ADMIN:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM deg_admin,centres,degrees,courses,crs_usr_requests"
+ " WHERE deg_admin.UsrCod='%ld'"
+ " AND centres.InsCod='%ld'"
+ " AND deg_admin.DegCod=degrees.DegCod"
+ " AND deg_admin.DegCod=courses.DegCod"
+ " AND degrees.CtrCod=centres.CtrCod"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ Gbl.CurrentIns.Ins.InsCod,
+ Roles);
+ break;
+ case Rol_ROLE_SUPERUSER:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM centres,degrees,courses,crs_usr_requests"
+ " WHERE centres.InsCod='%ld'"
+ " AND centres.CtrCod=degrees.CtrCod"
+ " AND degrees.DegCod=courses.DegCod"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.CurrentIns.Ins.InsCod,
+ Roles);
+ break;
+ default:
+ Lay_ShowErrorAndExit ("You don't have permission to list requesters.");
+ break;
+ }
+ break;
+ case Sco_SCOPE_CENTRE: // Show requesters for the current centre
+ switch (Gbl.Usrs.Me.LoggedRole)
+ {
+ case Rol_ROLE_TEACHER:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM crs_usr,degrees,courses,crs_usr_requests"
+ " WHERE crs_usr.UsrCod='%ld'"
+ " AND degrees.CtrCod='%ld'"
+ " AND crs_usr.CrsCod=courses.CrsCod"
+ " AND degrees.DegCod=courses.DegCod"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ Gbl.CurrentCtr.Ctr.CtrCod,
+ Roles);
+ break;
+ case Rol_ROLE_DEG_ADMIN:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM deg_admin,degrees,courses,crs_usr_requests"
+ " WHERE deg_admin.UsrCod='%ld'"
+ " AND degrees.CtrCod='%ld'"
+ " AND deg_admin.DegCod=degrees.DegCod"
+ " AND deg_admin.DegCod=courses.DegCod"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ Gbl.CurrentCtr.Ctr.CtrCod,
+ Roles);
+ break;
+ case Rol_ROLE_SUPERUSER:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM degrees,courses,crs_usr_requests"
+ " WHERE degrees.CtrCod='%ld'"
+ " AND degrees.DegCod=courses.DegCod"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.CurrentCtr.Ctr.CtrCod,
+ Roles);
+ break;
+ default:
+ Lay_ShowErrorAndExit ("You don't have permission to list requesters.");
+ break;
+ }
+ break;
+ case Sco_SCOPE_DEGREE: // Show requesters for the current degree
+ switch (Gbl.Usrs.Me.LoggedRole)
+ {
+ case Rol_ROLE_TEACHER:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM crs_usr,courses,crs_usr_requests"
+ " WHERE crs_usr.UsrCod='%ld'"
+ " AND crs_usr.CrsCod=courses.CrsCod"
+ " AND courses.DegCod='%ld'"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.Usrs.Me.UsrDat.UsrCod,
+ Gbl.CurrentDeg.Deg.DegCod,
+ Roles);
+ break;
+ case Rol_ROLE_DEG_ADMIN:
+ case Rol_ROLE_SUPERUSER:
+ sprintf (Query,"SELECT crs_usr_requests.ReqCod,crs_usr_requests.CrsCod,crs_usr_requests.UsrCod,crs_usr_requests.Role,DATE_FORMAT(crs_usr_requests.RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM courses,crs_usr_requests"
+ " WHERE courses.DegCod='%ld'"
+ " AND courses.CrsCod=crs_usr_requests.CrsCod"
+ " AND ((1<0"
+ " ORDER BY crs_usr_requests.RequestTime DESC",
+ Gbl.CurrentDeg.Deg.DegCod,
+ Roles);
+ break;
+ default:
+ Lay_ShowErrorAndExit ("You don't have permission to list requesters.");
+ break;
+ }
+ break;
+ case Sco_SCOPE_COURSE: // Show requesters for the current course
+ switch (Gbl.Usrs.Me.LoggedRole)
+ {
+ case Rol_ROLE_TEACHER:
+ case Rol_ROLE_DEG_ADMIN:
+ case Rol_ROLE_SUPERUSER:
+ sprintf (Query,"SELECT ReqCod,CrsCod,UsrCod,Role,DATE_FORMAT(RequestTime,'%%Y%%m%%d%%H%%i%%S')"
+ " FROM crs_usr_requests"
+ " WHERE CrsCod='%ld'"
+ " AND ((1<0"
+ " ORDER BY RequestTime DESC",
+ Gbl.CurrentCrs.Crs.CrsCod,Roles);
+ break;
+ default:
+ Lay_ShowErrorAndExit ("You don't have permission to list requesters.");
+ break;
+ }
+ break;
+ default:
+ Lay_ShowErrorAndExit ("Wrong scope.");
+ break;
+ }
+
+ NumRequests = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get requests for enrollment");
+
+ /***** List requests *****/
+ if (NumRequests)
+ {
+ /* Initialize structure with user's data */
+ Usr_UsrDataConstructor (&UsrDat);
+
+ /* Start table */
+ Lay_StartRoundFrameTable10 (NULL,2,NULL);
+ fprintf (Gbl.F.Out,"
");
+
+ /***** Mark possible notification as seen *****/
+ Ntf_SetNotifAsSeen (Ntf_EVENT_ENROLLMENT_REQUEST,
+ ReqCod,
+ Gbl.Usrs.Me.UsrDat.UsrCod);
+ }
+ else // User does not exists or user already belongs to course ==> remove pair from crs_usr_requests table
+ Enr_RemoveEnrollmentRequest (Crs.CrsCod,UsrDat.UsrCod);
+ }
+
+ /* End of table */
+ Lay_EndRoundFrameTable10 ();
+
+ /* Free memory used for user's data */
+ Usr_UsrDataDestructor (&UsrDat);
+ }
+ else // There are no requests
+ Lay_ShowAlert (Lay_INFO,Txt_No_enrollment_requests);
+ }
+
+/*****************************************************************************/
+/******************** Remove a request for inscription ***********************/
+/*****************************************************************************/
+
+static void Enr_RemoveEnrollmentRequest (long CrsCod,long UsrCod)
+ {
+ char Query[256];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ long ReqCod;
+
+ /***** Mark possible notifications as removed
+ Important: do this before removing the request *****/
+ /* Request request code (returns 0 or 1 rows) */
+ sprintf (Query,"SELECT ReqCod FROM crs_usr_requests"
+ " WHERE CrsCod='%ld' AND UsrCod='%ld'",
+ CrsCod,UsrCod);
+ if (DB_QuerySELECT (Query,&mysql_res,"can not get request code")) // Request exists
+ {
+ /* Get request code */
+ row = mysql_fetch_row (mysql_res);
+ ReqCod = Str_ConvertStrCodToLongCod (row[0]);
+
+ /* Mark possible notifications as removed */
+ Ntf_SetNotifAsRemoved (Ntf_EVENT_ENROLLMENT_REQUEST,ReqCod);
+ }
+ /* Free structure that stores the query result */
+ DB_FreeMySQLResult (&mysql_res);
+
+ /***** Remove enrollment request *****/
+ sprintf (Query,"DELETE FROM crs_usr_requests"
+ " WHERE CrsCod='%ld' AND UsrCod='%ld'",
+ CrsCod,UsrCod);
+ DB_QueryDELETE (Query,"can not remove a request for enrollment");
+ }
+
+/*****************************************************************************/
+/************ Get requested role of a user in current course *****************/
+/*****************************************************************************/
+
+Rol_Role_t Enr_GetRequestedRole (long UsrCod)
+ {
+ char Query[256];
+ MYSQL_RES *mysql_res;
+ MYSQL_ROW row;
+ Rol_Role_t Role = Rol_ROLE_UNKNOWN;
+
+ /***** Get requested role from database *****/
+ sprintf (Query,"SELECT Role FROM crs_usr_requests"
+ " WHERE CrsCod='%ld' AND UsrCod='%ld'",
+ Gbl.CurrentCrs.Crs.CrsCod,UsrCod);
+ if (DB_QuerySELECT (Query,&mysql_res,"can not get requested role"))
+ {
+ /***** Get role *****/
+ row = mysql_fetch_row (mysql_res);
+ Role = Usr_ConvertUnsignedStrToRole (row[0]);
+ }
+
+ /***** Free structure that stores the query result *****/
+ DB_FreeMySQLResult (&mysql_res);
+
+ return Role;
+ }
+
+/*****************************************************************************/
+/************** Form to request the user's ID of another user ****************/
+/*****************************************************************************/
+
+void Enr_ReqRegRemUsr (void)
+ {
+ extern const char *Txt_You_dont_have_permission_to_perform_this_action;
+
+ switch (Gbl.Usrs.Me.LoggedRole)
+ {
+ case Rol_ROLE_GUEST:
+ case Rol_ROLE_VISITOR:
+ case Rol_ROLE_STUDENT:
+ Enr_AskIfRegRemMe ();
+ break;
+ case Rol_ROLE_TEACHER:
+ if (Gbl.CurrentCrs.Crs.CrsCod > 0)
+ Enr_ReqAnotherUsrIDToRegisterRemove ();
+ else
+ Enr_AskIfRegRemMe ();
+ break;
+ case Rol_ROLE_DEG_ADMIN:
+ if (Gbl.CurrentDeg.Deg.DegCod > 0)
+ Enr_ReqAnotherUsrIDToRegisterRemove ();
+ else
+ Enr_AskIfRegRemMe ();
+ break;
+ case Rol_ROLE_CTR_ADMIN:
+ if (Gbl.CurrentCtr.Ctr.CtrCod > 0)
+ Enr_ReqAnotherUsrIDToRegisterRemove ();
+ else
+ Enr_AskIfRegRemMe ();
+ break;
+ case Rol_ROLE_INS_ADMIN:
+ if (Gbl.CurrentIns.Ins.InsCod > 0)
+ Enr_ReqAnotherUsrIDToRegisterRemove ();
+ else
+ Enr_AskIfRegRemMe ();
+ break;
+ case Rol_ROLE_SUPERUSER:
+ Enr_ReqAnotherUsrIDToRegisterRemove ();
+ break;
+ default:
+ Lay_ShowAlert (Lay_ERROR,Txt_You_dont_have_permission_to_perform_this_action);
+ break;
+ }
+ }
+
+/*****************************************************************************/
+/****** Write a form to request another user's ID, @nickname or e-mail *******/
+/*****************************************************************************/
+
+static void Enr_ReqAnotherUsrIDToRegisterRemove (void)
+ {
+ extern const char *Txt_Enter_the_ID_of_the_user_you_want_to_register_remove_;
+
+ Lay_ShowAlert (Lay_INFO,Txt_Enter_the_ID_of_the_user_you_want_to_register_remove_);
+
+ Enr_WriteFormToReqAnotherUsrID (ActReqMdfUsr);
+ }
+
+/*****************************************************************************/
+/********************** Ask me for register/remove me ************************/
+/*****************************************************************************/
+
+static void Enr_AskIfRegRemMe (void)
+ {
+ struct ListUsrCods ListUsrCods;
+
+ /***** I only can admin me *****/
+ Gbl.Usrs.Other.UsrDat.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
+ ListUsrCods.NumUsrs = 1;
+ Usr_AllocateListUsrCods (&ListUsrCods);
+ ListUsrCods.Lst[0] = Gbl.Usrs.Other.UsrDat.UsrCod;
+
+ Enr_AskIfRegRemUsr (&ListUsrCods);
+ }
+
+/*****************************************************************************/
+/****************** Ask me for register/remove another user ******************/
+/*****************************************************************************/
+
+void Enr_AskIfRegRemAnotherUsr (void)
+ {
+ struct ListUsrCods ListUsrCods;
+
+ /***** Check if UsrCod is present in parameters *****/
+ Usr_GetParamOtherUsrCodEncrypted ();
+ if (Gbl.Usrs.Other.UsrDat.UsrCod > 0)
+ {
+ /***** If UsrCod is present in parameters,
+ use this parameter to identify the user to be enrolled / removed *****/
+ ListUsrCods.NumUsrs = 1;
+ Usr_AllocateListUsrCods (&ListUsrCods);
+ ListUsrCods.Lst[0] = Gbl.Usrs.Other.UsrDat.UsrCod;
+ }
+ else // Parameter with user code not present
+ /***** If UsrCod is not present in parameters from form,
+ use user's ID to identify the user to be enrolled /removed *****/
+ Usr_GetParamOtherUsrIDNickOrEMailAndGetUsrCods (&ListUsrCods);
+
+ Enr_AskIfRegRemUsr (&ListUsrCods);
+ }
+
+/*****************************************************************************/
+/********************** Ask me for register/remove user **********************/
+/*****************************************************************************/
+
+static void Enr_AskIfRegRemUsr (struct ListUsrCods *ListUsrCods)
+ {
+ extern const char *Txt_There_are_X_users_with_the_ID_Y;
+ extern const char *Txt_THE_USER_X_is_already_enrolled_in_the_course_Y;
+ extern const char *Txt_THE_USER_X_is_already_in_the_course_Y_but_has_not_yet_accepted_the_enrollment;
+ extern const char *Txt_THE_USER_X_already_exists_in_Y_but_is_not_yet_enrolled_in_the_course_Z;
+ extern const char *Txt_THE_USER_X_already_exists_in_Y;
+ extern const char *Txt_The_user_is_new_does_not_exists_yet_in_X;
+ extern const char *Txt_If_this_is_a_new_user_in_X_you_should_indicate_her_his_ID;
+ unsigned NumUsr;
+ bool NewUsrIDValid;
+
+ if (ListUsrCods->NumUsrs) // User(s) found with the ID
+ {
+ /***** Warning if more than one user found *****/
+ if (ListUsrCods->NumUsrs > 1)
+ {
+ sprintf (Gbl.Message,Txt_There_are_X_users_with_the_ID_Y,
+ ListUsrCods->NumUsrs,Gbl.Usrs.Other.UsrDat.UsrIDNickOrEmail);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+ }
+
+ /***** For each user found... *****/
+ for (NumUsr = 0;
+ NumUsr < ListUsrCods->NumUsrs;
+ NumUsr++)
+ {
+ /* Get user's data */
+ Gbl.Usrs.Other.UsrDat.UsrCod = ListUsrCods->Lst[NumUsr];
+ Usr_GetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat);
+
+ if (Gbl.CurrentCrs.Crs.CrsCod > 0) // Course selected
+ {
+ /* Check if this user belongs to the current course */
+ if (Usr_CheckIfUsrBelongsToCrs (Gbl.Usrs.Other.UsrDat.UsrCod,Gbl.CurrentCrs.Crs.CrsCod))
+ {
+ Gbl.Usrs.Other.UsrDat.Accepted = Usr_GetIfUserHasAcceptedEnrollmentInCurrentCrs (Gbl.Usrs.Other.UsrDat.UsrCod);
+ if (Gbl.Usrs.Other.UsrDat.Accepted)
+ sprintf (Gbl.Message,Txt_THE_USER_X_is_already_enrolled_in_the_course_Y,
+ Gbl.Usrs.Other.UsrDat.FullName,Gbl.CurrentCrs.Crs.FullName);
+ else // Enrollment not yet accepted
+ sprintf (Gbl.Message,Txt_THE_USER_X_is_already_in_the_course_Y_but_has_not_yet_accepted_the_enrollment,
+ Gbl.Usrs.Other.UsrDat.FullName,Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+
+ Enr_ShowFormToEditOtherUsr ();
+ }
+ else // User does not belong to the current course
+ {
+ sprintf (Gbl.Message,Txt_THE_USER_X_already_exists_in_Y_but_is_not_yet_enrolled_in_the_course_Z,
+ Gbl.Usrs.Other.UsrDat.FullName,Cfg_PLATFORM_SHORT_NAME,Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+
+ Enr_ShowFormToEditOtherUsr ();
+ }
+ }
+ else // No course selected
+ {
+ sprintf (Gbl.Message,Txt_THE_USER_X_already_exists_in_Y,
+ Gbl.Usrs.Other.UsrDat.FullName,Cfg_PLATFORM_SHORT_NAME);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+
+ Enr_ShowFormToEditOtherUsr ();
+ }
+ }
+
+ /***** Free list of users' codes *****/
+ Usr_FreeListUsrCods (ListUsrCods);
+ }
+ else // No users found, he/she is a new user
+ {
+ /***** If UsrCod is not present in parameters from form,
+ use user's ID to identify the user to be enrolled *****/
+ if (Gbl.Usrs.Other.UsrDat.IDs.List)
+ NewUsrIDValid = ID_CheckIfUsrIDIsValid (Gbl.Usrs.Other.UsrDat.IDs.List[0].ID); // Check the first element of the list
+ else
+ NewUsrIDValid = false;
+
+ if (NewUsrIDValid)
+ {
+ /* Initialize some data of this new user */
+ Gbl.Usrs.Other.UsrDat.RoleInCurrentCrsDB = Rol_ROLE_STUDENT;
+ Gbl.Usrs.Other.UsrDat.Roles = (1 << Gbl.Usrs.Other.UsrDat.RoleInCurrentCrsDB);
+
+ /***** Show form to enter the data of a new user *****/
+ sprintf (Gbl.Message,Txt_The_user_is_new_does_not_exists_yet_in_X,
+ Cfg_PLATFORM_SHORT_NAME);
+ Lay_ShowAlert (Lay_INFO,Gbl.Message);
+ Rec_ShowFormOtherNewCommonRecord (&Gbl.Usrs.Other.UsrDat);
+ }
+ else // User's ID is not valid
+ {
+ /* Write message and request a new user's ID */
+ sprintf (Gbl.Message,Txt_If_this_is_a_new_user_in_X_you_should_indicate_her_his_ID,
+ Cfg_PLATFORM_SHORT_NAME);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ Enr_ReqRegRemUsr ();
+ }
+ }
+ }
+
+/*****************************************************************************/
+/************ Show form to edit the record of an existing user ***************/
+/*****************************************************************************/
+
+static void Enr_ShowFormToEditOtherUsr (void)
+ {
+ extern const char *Txt_Confirm;
+ bool ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
+
+ fprintf (Gbl.F.Out,"
");
+
+ /***** Buttons for edition *****/
+ if (Pwd_CheckIfICanChangeOtherUsrPassword (Gbl.Usrs.Other.UsrDat.UsrCod))
+ {
+ ID_PutLinkToChangeUsrIDs (&Gbl.Usrs.Other.UsrDat); // Put link (form) to change user's IDs
+ Pwd_PutLinkToChangeUsrPassword (&Gbl.Usrs.Other.UsrDat); // Put link (form) to change user's password
+ }
+ if (Pho_CheckIfICanChangeOtherUsrPhoto (Gbl.Usrs.Other.UsrDat.UsrCod))
+ Pho_PutLinkToChangeUsrPhoto (&Gbl.Usrs.Other.UsrDat); // Put link (form) to change user's photo
+
+ /***** User's record *****/
+ Rec_ShowCommonRecord (Rec_FORM_MODIFY_RECORD_OTHER_EXISTING_USR,&Gbl.Usrs.Other.UsrDat);
+
+ /***** Show list of groups to register/remove me/user *****/
+ if (Gbl.CurrentCrs.Grps.NumGrps) // This course has groups?
+ {
+ if (ItsMe)
+ Grp_ShowLstGrpsToChgMyGrps ((Gbl.Usrs.Me.LoggedRole == Rol_ROLE_STUDENT));
+ else
+ Grp_ShowLstGrpsToChgOtherUsrsGrps (Gbl.Usrs.Other.UsrDat.UsrCod);
+ }
+
+ /***** Which action, register or removing? *****/
+ if (Enr_PutActionsRegRemOneUsr (ItsMe))
+ Lay_PutSendButton (Txt_Confirm);
+
+ fprintf (Gbl.F.Out,""
+ "
");
+ }
+
+/*****************************************************************************/
+/******************* Add an administrator to current degree ******************/
+/*****************************************************************************/
+
+void Enr_AddAdmToDeg (void)
+ {
+ extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
+
+ if (Gbl.CurrentDeg.Deg.DegCod > 0)
+ {
+ /***** Get plain user's ID of the user to add/modify *****/
+ if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
+ {
+ /* Check if it's allowed to register this administrator in degree */
+ if (Gbl.Usrs.Me.LoggedRole == Rol_ROLE_SUPERUSER)
+ {
+ /***** Register administrator in current degree in database *****/
+ Enr_RegisterAdminInCurrentDeg (&Gbl.Usrs.Other.UsrDat);
+
+ /***** Show user's record *****/
+ Rec_ShowCommonRecordUnmodifiable (&Gbl.Usrs.Other.UsrDat);
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+ }
+
+/*****************************************************************************/
+/****************** Ask for remove me from current course ********************/
+/*****************************************************************************/
+
+void Enr_ReqRemMeFromCrs (void)
+ {
+ Enr_AskIfRemoveUsrFromCrs (&Gbl.Usrs.Me.UsrDat,true);
+ }
+
+/*****************************************************************************/
+/************** Ask for remove of a user from current course *****************/
+/*****************************************************************************/
+
+void Enr_ReqRemUsrFromCrs (void)
+ {
+ Enr_ReqRemOrRemUsrFromCrs (Enr_REQUEST_REMOVE_USR);
+ }
+
+/*****************************************************************************/
+/********************* Remove a user from current course *********************/
+/*****************************************************************************/
+
+void Enr_RemUsrFromCrs (void)
+ {
+ if (Pwd_GetConfirmationOnDangerousAction ())
+ Enr_ReqRemOrRemUsrFromCrs (Enr_REMOVE_USR);
+ }
+
+/*****************************************************************************/
+/******************** Remove of a user from current course *******************/
+/*****************************************************************************/
+
+void Enr_ReqRemOrRemUsrFromCrs (Enr_ReqDelOrDelUsr_t ReqDelOrDelUsr)
+ {
+ extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
+ bool ItsMe;
+ bool ICanRemove;
+
+ /***** Get user to be removed *****/
+ if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
+ {
+ /* Check if it's forbidden remove that user */
+ // A teacher can remove a student or himself
+ // An administrator can remove anyone
+ ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
+ ICanRemove = (Gbl.Usrs.Me.LoggedRole == Rol_ROLE_STUDENT ? ItsMe :
+ (Gbl.Usrs.Me.LoggedRole >= Gbl.Usrs.Other.UsrDat.RoleInCurrentCrsDB));
+ if (ICanRemove)
+ switch (ReqDelOrDelUsr)
+ {
+ case Enr_REQUEST_REMOVE_USR: // Ask if remove user from current course
+ Enr_AskIfRemoveUsrFromCrs (&Gbl.Usrs.Other.UsrDat,ItsMe);
+ break;
+ case Enr_REMOVE_USR: // Remove user from current course
+ Enr_EffectivelyRemUsrFromCrs (&Gbl.Usrs.Other.UsrDat,&Gbl.CurrentCrs.Crs,
+ Enr_REMOVE_WORKS,Cns_VERBOSE);
+ break;
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+
+/*****************************************************************************/
+/********* Ask for remove of an administrator from current degree ************/
+/*****************************************************************************/
+
+static void Enr_ReqRemAdmOfDeg (void)
+ {
+ Enr_ReqRemOrRemAdm (Enr_REQUEST_REMOVE_USR);
+ }
+
+/*****************************************************************************/
+/********************* Remove a user from current course *********************/
+/*****************************************************************************/
+
+void Enr_RemAdm (void)
+ {
+ Enr_ReqRemOrRemAdm (Enr_REMOVE_USR);
+ }
+
+/*****************************************************************************/
+/******************** Remove of a user from current course *******************/
+/*****************************************************************************/
+
+static void Enr_ReqRemOrRemAdm (Enr_ReqDelOrDelUsr_t ReqDelOrDelUsr)
+ {
+ extern const char *Txt_THE_USER_X_is_not_an_administrator_of_the_degree_Y;
+ extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
+ bool ItsMe;
+ bool ICanRemove;
+
+ if (Gbl.CurrentDeg.Deg.DegCod > 0)
+ {
+ /***** Get user to be removed *****/
+ if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
+ {
+ /* Check if it's forbidden remove that administrator */
+ // A superuser can remove any administrator
+ // An administrator only can remove itself
+ ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
+ ICanRemove = (ItsMe || Gbl.Usrs.Me.LoggedRole == Rol_ROLE_SUPERUSER);
+ if (ICanRemove)
+ {
+ /* Check if the other user belong to current course */
+ if (Usr_CheckIfUsrIsAdmOfDeg (Gbl.Usrs.Other.UsrDat.UsrCod,Gbl.CurrentDeg.Deg.DegCod))
+ { // The other user is an administrator of current degree ==> ask for removing or remove him
+ switch (ReqDelOrDelUsr)
+ {
+ case Enr_REQUEST_REMOVE_USR: // Ask if remove administrator from current degree
+ Enr_AskIfRemAdmFromDeg (ItsMe);
+ break;
+ case Enr_REMOVE_USR: // Remove administrator from current degree
+ Enr_EffectivelyRemAdmFromDeg (&Gbl.Usrs.Other.UsrDat);
+ break;
+ }
+ }
+ else // The other user is not an administrator of current degree
+ {
+ sprintf (Gbl.Message,Txt_THE_USER_X_is_not_an_administrator_of_the_degree_Y,
+ Gbl.Usrs.Other.UsrDat.FullName,Gbl.CurrentDeg.Deg.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+ }
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+ }
+
+/*****************************************************************************/
+/********* Request definite removing of a user from the platform *************/
+/*****************************************************************************/
+
+void Enr_ReqRemUsrGbl (void)
+ {
+ Enr_ReqDelOrDelUsrGbl (Enr_REQUEST_REMOVE_USR);
+ }
+
+/*****************************************************************************/
+/************** Definite removing of a user from the platform ****************/
+/*****************************************************************************/
+
+void Enr_RemUsrGbl (void)
+ {
+ Enr_ReqDelOrDelUsrGbl (Enr_REMOVE_USR);
+ }
+
+/*****************************************************************************/
+/**************************** Removing of a user *****************************/
+/*****************************************************************************/
+
+void Enr_ReqDelOrDelUsrGbl (Enr_ReqDelOrDelUsr_t ReqDelOrDelUsr)
+ {
+ extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
+ bool ItsMe;
+
+ /***** Get user to be removed *****/
+ if (Usr_GetParamOtherUsrCodEncryptedAndGetUsrData ())
+ {
+ ItsMe = (Gbl.Usrs.Me.UsrDat.UsrCod == Gbl.Usrs.Other.UsrDat.UsrCod);
+ if (Enr_CheckIfICanEliminateAccount (ItsMe))
+ switch (ReqDelOrDelUsr)
+ {
+ case Enr_REQUEST_REMOVE_USR: // Ask if eliminate completely the user from the platform
+ Enr_AskIfCompletelyEliminateUsrFromPlatform (ItsMe);
+ break;
+ case Enr_REMOVE_USR: // Eliminate completely the user from the platform
+ if (Pwd_GetConfirmationOnDangerousAction ())
+ {
+ Enr_DeleteUsrFromPlatform (&Gbl.Usrs.Other.UsrDat,Cns_VERBOSE);
+
+ /***** Move unused contents of messages to table of deleted contents of messages *****/
+ Msg_MoveUnusedMsgsContentToDeleted ();
+ }
+ break;
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+ else
+ Lay_ShowAlert (Lay_WARNING,Txt_User_not_found_or_you_do_not_have_permission_);
+ }
+
+/*****************************************************************************/
+/******************* Ask if really wanted to remove a user *******************/
+/*****************************************************************************/
+
+static void Enr_AskIfRemoveUsrFromCrs (struct UsrData *UsrDat,bool ItsMe)
+ {
+ extern const char *Txt_Do_you_really_want_to_be_removed_from_the_course_X;
+ extern const char *Txt_Do_you_really_want_to_remove_the_following_user_from_the_course_X;
+ extern const char *Txt_Remove_me_from_this_course;
+ extern const char *Txt_Remove_user_from_this_course;
+ extern const char *Txt_User_not_found_or_you_do_not_have_permission_;
+
+ if (Usr_CheckIfUsrBelongsToCrs (UsrDat->UsrCod,Gbl.CurrentCrs.Crs.CrsCod))
+ {
+ sprintf (Gbl.Message,
+ ItsMe ? Txt_Do_you_really_want_to_be_removed_from_the_course_X :
+ Txt_Do_you_really_want_to_remove_the_following_user_from_the_course_X,
+ Gbl.CurrentCrs.Crs.FullName);
+ Lay_ShowAlert (Lay_WARNING,Gbl.Message);
+
+ Rec_ShowCommonRecordUnmodifiable (UsrDat);
+
+ fprintf (Gbl.F.Out,"