mirror of https://github.com/acanas/swad-core.git
Version 15.234
This commit is contained in:
parent
9ebfc85f69
commit
f104cf00de
|
@ -410,9 +410,11 @@ int swad__getTests (char *wsKey,int courseCode,long beginTime,
|
|||
int swad__getTrivialQuestion (char *wsKey,char *degrees,float lowerScore,float upperScore,
|
||||
struct swad__getTrivialQuestionOutput *getTrivialQuestionOut);
|
||||
|
||||
/* List of users of a course / group */
|
||||
int swad__getUsers (char *wsKey,int courseCode,int groupCode,int userRole,
|
||||
/* List of users */
|
||||
int swad__getUsers (char *wsKey,int courseCode,char *groups,int userRole,
|
||||
struct swad__getUsersOutput *getUsersOut);
|
||||
int swad__findUsers (char *wsKey,int courseCode,char *filter,int userRole,
|
||||
struct swad__getUsersOutput *getUsersOut);
|
||||
|
||||
/* Control of attendance */
|
||||
int swad__getAttendanceEvents (char *wsKey,int courseCode,
|
||||
|
|
|
@ -70,7 +70,6 @@ typedef enum
|
|||
|
||||
static bool ID_CheckIfUsrIDIsValidUsingMinDigits (const char *UsrID,unsigned MinDigits);
|
||||
|
||||
static bool ID_ICanSeeAnotherUsrID (struct UsrData *UsrDat);
|
||||
static void ID_PutButtonToReqConfirmID (struct UsrData *UsrDat,unsigned NumID);
|
||||
static void ID_PutButtonToConfirmID (struct UsrData *UsrDat,unsigned NumID);
|
||||
|
||||
|
@ -405,7 +404,7 @@ void ID_WriteUsrIDs (struct UsrData *UsrDat)
|
|||
/*****************************************************************************/
|
||||
// This function should not be called when UsrDat->UsrCod == Gbl.Usrs.Me.UsrDat.UsrCod
|
||||
|
||||
static bool ID_ICanSeeAnotherUsrID (struct UsrData *UsrDat)
|
||||
bool ID_ICanSeeAnotherUsrID (struct UsrData *UsrDat)
|
||||
{
|
||||
/***** Check if I have permission to see another user's IDs *****/
|
||||
switch (Gbl.Usrs.Me.LoggedRole)
|
||||
|
|
|
@ -65,6 +65,7 @@ bool ID_CheckIfUsrIDIsValid (const char *UsrID);
|
|||
bool ID_CheckIfUsrIDSeemsAValidID (const char *UsrID);
|
||||
|
||||
void ID_WriteUsrIDs (struct UsrData *UsrDat);
|
||||
bool ID_ICanSeeAnotherUsrID (struct UsrData *UsrDat);
|
||||
|
||||
void ID_PutLinkToChangeUsrIDs (void);
|
||||
void ID_ShowFormOthIDs (void);
|
||||
|
|
|
@ -121,6 +121,11 @@
|
|||
// TODO: Messages in msg_content_deleted older than a certain time should be deleted to ensure the protection of personal data
|
||||
// TODO: FIX BUG: A teacher uploads a document in course documents zone, then he/she unregister from course, then he/she search for his/her documents, a document is shown in results but he/she can not view it
|
||||
// TODO: Add Stack Exchange to webs/networks
|
||||
// TODO: Optimize slow query searching messages received
|
||||
// TODO: FIX BUG: Searching messages received gives unordered list
|
||||
|
||||
// TODO: Add file size to summary in notifications of new files.
|
||||
// TODO: Put Raúl Hinojosa (iSWAD developer) in a row of marks file of EC (B,C) and publish file
|
||||
|
||||
// TODO: Modify WS function getUsers changing: userRole to indicate all users, and a new parameter filter (search string (name, @nickname, mail)) to restring number of users
|
||||
// TODO: Add a new WS function to count the nunmber of users to return in call to function getUsers
|
||||
|
@ -129,13 +134,14 @@
|
|||
/****************************** Public constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Log_PLATFORM_VERSION "SWAD 15.233.4 (2016-06-27)"
|
||||
#define Log_PLATFORM_VERSION "SWAD 15.234 (2016-06-29)"
|
||||
#define CSS_FILE "swad15.229.css"
|
||||
#define JS_FILE "swad15.226.js"
|
||||
|
||||
// Number of lines (includes comments but not blank lines) has been got with the following command:
|
||||
// nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*.h sql/swad*.sql | tail -1
|
||||
/*
|
||||
Version 15.234: Jun 29, 2015 New web service functions getUsers and findUsers. (203169 lines)
|
||||
Version 15.233.4: Jun 27, 2015 Changes in links in list of notifications. (203065 lines)
|
||||
Version 15.233.3: Jun 27, 2015 Fixed bug in list of admins. (203074 lines)
|
||||
Version 15.233.2: Jun 27, 2015 Code refactoring in search of users. (203072 lines)
|
||||
|
|
164
swad_search.c
164
swad_search.c
|
@ -41,11 +41,8 @@
|
|||
/***************************** Internal constants ****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Sch_MAX_WORDS_IN_SEARCH 10
|
||||
#define Sch_MAX_LENGTH_SEARCH_WORD 255
|
||||
#define Sch_MIN_LENGTH_LONGEST_WORD 3
|
||||
#define Sch_MIN_LENGTH_TOTAL 7 // "A An Ann" is not valid; "A An Ann Anna" is valid
|
||||
#define Sch_MAX_LENGTH_SEARCH_QUERY (10*Sch_MAX_LENGTH_STRING_TO_FIND)
|
||||
|
||||
/*****************************************************************************/
|
||||
/****************************** Internal types *******************************/
|
||||
|
@ -77,8 +74,6 @@ static unsigned Sch_SearchUsrsInDB (Rol_Role_t Role);
|
|||
static unsigned Sch_SearchOpenDocumentsInDB (const char *RangeQuery);
|
||||
static unsigned Sch_SearchDocumentsInMyCoursesInDB (const char *RangeQuery);
|
||||
static unsigned Sch_SearchMyDocumentsInDB (const char *RangeQuery);
|
||||
static bool Sch_BuildSearchQuery (char *SearchQuery,const char *FieldName,
|
||||
const char *CharSet,const char *Collate);
|
||||
|
||||
static void Sch_SaveLastSearchIntoSession (void);
|
||||
|
||||
|
@ -793,25 +788,29 @@ static unsigned Sch_SearchCoursesInDB (const char *RangeQuery)
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/************************* Search teachers in database ***********************/
|
||||
/*************************** Search users in database ************************/
|
||||
/*****************************************************************************/
|
||||
// Returns number of teachers found
|
||||
// Returns number of users found
|
||||
|
||||
static unsigned Sch_SearchUsrsInDB (Rol_Role_t Role)
|
||||
{
|
||||
extern const char *Txt_The_search_text_must_be_longer;
|
||||
static bool WarningMessageWritten = false;
|
||||
char SearchQuery[Sch_MAX_LENGTH_SEARCH_QUERY+1];
|
||||
|
||||
/***** Check user's permission *****/
|
||||
if (Sch_CheckIfIHavePermissionToSearch ( Role == Rol_UNKNOWN ? Sch_SEARCH_USERS :
|
||||
(Role == Rol_TEACHER ? Sch_SEARCH_TEACHERS :
|
||||
(Role == Rol_STUDENT ? Sch_SEARCH_STUDENTS :
|
||||
Sch_SEARCH_GUESTS))))
|
||||
/***** Split user string into words *****/
|
||||
if (Sch_BuildSearchQuery (SearchQuery,
|
||||
"CONCAT_WS(' ',usr_data.FirstName,usr_data.Surname1,usr_data.Surname2)",
|
||||
NULL,NULL))
|
||||
/***** Query database and list users found *****/
|
||||
return Usr_ListUsrsFound (Role,SearchQuery);
|
||||
/***** Split user string into words *****/
|
||||
if (Sch_BuildSearchQuery (SearchQuery,
|
||||
"CONCAT_WS(' ',FirstName,Surname1,Surname2)",
|
||||
NULL,NULL))
|
||||
/***** Query database and list users found *****/
|
||||
return Usr_ListUsrsFound (Role,SearchQuery);
|
||||
else
|
||||
// Too short
|
||||
if (!WarningMessageWritten) // To avoid repetitions
|
||||
{
|
||||
Lay_ShowAlert (Lay_WARNING,Txt_The_search_text_must_be_longer);
|
||||
WarningMessageWritten = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1215,11 +1214,9 @@ static unsigned Sch_SearchMyDocumentsInDB (const char *RangeQuery)
|
|||
// Returns true if a valid search query is built
|
||||
// Returns false when no valid search query
|
||||
|
||||
static bool Sch_BuildSearchQuery (char *SearchQuery,const char *FieldName,
|
||||
const char *CharSet,const char *Collate)
|
||||
bool Sch_BuildSearchQuery (char *SearchQuery,const char *FieldName,
|
||||
const char *CharSet,const char *Collate)
|
||||
{
|
||||
extern const char *Txt_The_search_text_must_be_longer;
|
||||
static bool WarningMessageWritten = false;
|
||||
const char *Ptr;
|
||||
unsigned NumWords;
|
||||
unsigned NumWord;
|
||||
|
@ -1229,74 +1226,71 @@ static bool Sch_BuildSearchQuery (char *SearchQuery,const char *FieldName,
|
|||
char SearchWords[Sch_MAX_WORDS_IN_SEARCH][Sch_MAX_LENGTH_SEARCH_WORD+1];
|
||||
bool SearchWordIsValid = true;
|
||||
|
||||
SearchQuery[0] = '\0';
|
||||
Ptr = Gbl.Search.Str;
|
||||
for (NumWords = 0;
|
||||
NumWords < Sch_MAX_WORDS_IN_SEARCH && *Ptr;
|
||||
NumWords++)
|
||||
if (Gbl.Search.Str[0])
|
||||
{
|
||||
/* Get next word */
|
||||
Str_GetNextStringUntilSpace (&Ptr,SearchWords[NumWords],Sch_MAX_LENGTH_SEARCH_WORD);
|
||||
|
||||
/* Is this word valid? */
|
||||
switch (Gbl.Search.WhatToSearch)
|
||||
{
|
||||
case Sch_SEARCH_OPEN_DOCUMENTS:
|
||||
case Sch_SEARCH_DOCUM_IN_MY_COURSES:
|
||||
case Sch_SEARCH_MY_DOCUMENTS:
|
||||
SearchWordIsValid = Str_ConvertFilFolLnkNameToValid (SearchWords[NumWords]);
|
||||
break;
|
||||
default:
|
||||
SearchWordIsValid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if this word is repeated (case insensitive) */
|
||||
for (NumWord = 0;
|
||||
SearchWordIsValid && NumWord < NumWords;
|
||||
NumWord++)
|
||||
if (!strcasecmp (SearchWords[NumWord],SearchWords[NumWords]))
|
||||
SearchWordIsValid = false;
|
||||
|
||||
/* Concatenate word to search string */
|
||||
if (SearchWordIsValid)
|
||||
SearchQuery[0] = '\0';
|
||||
Ptr = Gbl.Search.Str;
|
||||
for (NumWords = 0;
|
||||
NumWords < Sch_MAX_WORDS_IN_SEARCH && *Ptr;
|
||||
NumWords++)
|
||||
{
|
||||
LengthWord = strlen (SearchWords[NumWords]);
|
||||
LengthTotal += LengthWord;
|
||||
if (LengthWord > MaxLengthWord)
|
||||
MaxLengthWord = LengthWord;
|
||||
if (strlen (SearchQuery) + LengthWord + 512 > Sch_MAX_LENGTH_SEARCH_QUERY) // Prevent string overflow
|
||||
break;
|
||||
if (NumWords)
|
||||
strcat (SearchQuery," AND ");
|
||||
strcat (SearchQuery,FieldName);
|
||||
strcat (SearchQuery," LIKE ");
|
||||
if (CharSet)
|
||||
if (CharSet[0])
|
||||
strcat (SearchQuery,CharSet);
|
||||
strcat (SearchQuery,"'%");
|
||||
strcat (SearchQuery,SearchWords[NumWords]);
|
||||
strcat (SearchQuery,"%'");
|
||||
if (Collate)
|
||||
if (Collate[0])
|
||||
strcat (SearchQuery,Collate);
|
||||
}
|
||||
}
|
||||
/* Get next word */
|
||||
Str_GetNextStringUntilSpace (&Ptr,SearchWords[NumWords],Sch_MAX_LENGTH_SEARCH_WORD);
|
||||
|
||||
/***** If search string valid? *****/
|
||||
if (LengthTotal < Sch_MIN_LENGTH_TOTAL ||
|
||||
MaxLengthWord < Sch_MIN_LENGTH_LONGEST_WORD)
|
||||
{
|
||||
// Too short
|
||||
if (!WarningMessageWritten) // To avoid repetitions
|
||||
{
|
||||
Lay_ShowAlert (Lay_WARNING,Txt_The_search_text_must_be_longer);
|
||||
WarningMessageWritten = true;
|
||||
/* Is this word valid? */
|
||||
switch (Gbl.Search.WhatToSearch)
|
||||
{
|
||||
case Sch_SEARCH_OPEN_DOCUMENTS:
|
||||
case Sch_SEARCH_DOCUM_IN_MY_COURSES:
|
||||
case Sch_SEARCH_MY_DOCUMENTS:
|
||||
SearchWordIsValid = Str_ConvertFilFolLnkNameToValid (SearchWords[NumWords]);
|
||||
break;
|
||||
default:
|
||||
SearchWordIsValid = true;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if this word is repeated (case insensitive) */
|
||||
for (NumWord = 0;
|
||||
SearchWordIsValid && NumWord < NumWords;
|
||||
NumWord++)
|
||||
if (!strcasecmp (SearchWords[NumWord],SearchWords[NumWords]))
|
||||
SearchWordIsValid = false;
|
||||
|
||||
/* Concatenate word to search string */
|
||||
if (SearchWordIsValid)
|
||||
{
|
||||
LengthWord = strlen (SearchWords[NumWords]);
|
||||
LengthTotal += LengthWord;
|
||||
if (LengthWord > MaxLengthWord)
|
||||
MaxLengthWord = LengthWord;
|
||||
if (strlen (SearchQuery) + LengthWord + 512 > Sch_MAX_LENGTH_SEARCH_QUERY) // Prevent string overflow
|
||||
break;
|
||||
if (NumWords)
|
||||
strcat (SearchQuery," AND ");
|
||||
strcat (SearchQuery,FieldName);
|
||||
strcat (SearchQuery," LIKE ");
|
||||
if (CharSet)
|
||||
if (CharSet[0])
|
||||
strcat (SearchQuery,CharSet);
|
||||
strcat (SearchQuery,"'%");
|
||||
strcat (SearchQuery,SearchWords[NumWords]);
|
||||
strcat (SearchQuery,"%'");
|
||||
if (Collate)
|
||||
if (Collate[0])
|
||||
strcat (SearchQuery,Collate);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
/***** If search string valid? *****/
|
||||
if (LengthTotal < Sch_MIN_LENGTH_TOTAL ||
|
||||
MaxLengthWord < Sch_MIN_LENGTH_LONGEST_WORD)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
@ -31,7 +31,10 @@
|
|||
/****************************** Public constants *****************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
#define Sch_MAX_LENGTH_STRING_TO_FIND 255
|
||||
#define Sch_MAX_LENGTH_STRING_TO_FIND 255
|
||||
#define Sch_MAX_WORDS_IN_SEARCH 10
|
||||
#define Sch_MAX_LENGTH_SEARCH_WORD 255
|
||||
#define Sch_MAX_LENGTH_SEARCH_QUERY (Sch_MAX_WORDS_IN_SEARCH*Sch_MAX_LENGTH_SEARCH_WORD)
|
||||
|
||||
/*****************************************************************************/
|
||||
/******************************** Public types *******************************/
|
||||
|
@ -78,4 +81,7 @@ void Sch_CtrSearch (void);
|
|||
void Sch_DegSearch (void);
|
||||
void Sch_CrsSearch (void);
|
||||
|
||||
bool Sch_BuildSearchQuery (char *SearchQuery,const char *FieldName,
|
||||
const char *CharSet,const char *Collate);
|
||||
|
||||
#endif
|
||||
|
|
21
swad_user.c
21
swad_user.c
|
@ -142,9 +142,6 @@ static void Usr_WriteUsrData (const char *BgColor,
|
|||
bool NonBreak,bool Accepted);
|
||||
|
||||
static void Usr_BuildQueryToGetUsrsLstCrs (Rol_Role_t Role,char *Query);
|
||||
static void Usr_SearchListUsrs (Rol_Role_t Role);
|
||||
static void Usr_CreateTmpTableAndSearchCandidateUsrs (const char *UsrQuery);
|
||||
static void Usr_DropTmpTableWithCandidateUsrs (void);
|
||||
|
||||
static void Usr_GetAdmsLst (Sco_Scope_t Scope);
|
||||
static void Usr_GetGstsLst (Sco_Scope_t Scope);
|
||||
|
@ -3802,7 +3799,7 @@ void Usr_GetListUsrs (Rol_Role_t Role,Sco_Scope_t Scope)
|
|||
/********* Search list of users with a given role in current scope ***********/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Usr_SearchListUsrs (Rol_Role_t Role)
|
||||
void Usr_SearchListUsrs (Rol_Role_t Role)
|
||||
{
|
||||
char Query[4*1024];
|
||||
const char *OrderQuery = "candidate_users.UsrCod=usr_data.UsrCod"
|
||||
|
@ -4011,7 +4008,7 @@ static void Usr_SearchListUsrs (Rol_Role_t Role)
|
|||
/*************** Create temporary table with candidate users *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Usr_CreateTmpTableAndSearchCandidateUsrs (const char *UsrQuery)
|
||||
void Usr_CreateTmpTableAndSearchCandidateUsrs (const char *SearchQuery)
|
||||
{
|
||||
char Query[16*1024];
|
||||
|
||||
|
@ -4024,7 +4021,7 @@ static void Usr_CreateTmpTableAndSearchCandidateUsrs (const char *UsrQuery)
|
|||
sprintf (Query,"CREATE TEMPORARY TABLE candidate_users"
|
||||
" (UsrCod INT NOT NULL,UNIQUE INDEX(UsrCod)) ENGINE=MEMORY"
|
||||
" SELECT UsrCod FROM usr_data WHERE %s",
|
||||
UsrQuery);
|
||||
SearchQuery);
|
||||
if (mysql_query (&Gbl.mysql,Query))
|
||||
DB_ExitOnMySQLError ("can not create temporary table");
|
||||
}
|
||||
|
@ -4033,7 +4030,7 @@ static void Usr_CreateTmpTableAndSearchCandidateUsrs (const char *UsrQuery)
|
|||
/***************** Drop temporary table with candidate users *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Usr_DropTmpTableWithCandidateUsrs (void)
|
||||
void Usr_DropTmpTableWithCandidateUsrs (void)
|
||||
{
|
||||
char Query[128];
|
||||
|
||||
|
@ -5802,24 +5799,24 @@ void Usr_ListAllDataTchs (void)
|
|||
/*****************************************************************************/
|
||||
// Returns number of users found
|
||||
|
||||
unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char *UsrQuery)
|
||||
unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char *SearchQuery)
|
||||
{
|
||||
extern const char *Txt_user[Usr_NUM_SEXS];
|
||||
extern const char *Txt_users[Usr_NUM_SEXS];
|
||||
extern const char *Txt_ROLES_PLURAL_Abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
|
||||
extern const char *Txt_ROLES_SINGUL_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
|
||||
extern const char *Txt_ROLES_PLURAL_abc[Rol_NUM_ROLES][Usr_NUM_SEXS];
|
||||
Usr_Sex_t Sex;
|
||||
unsigned NumUsrs;
|
||||
unsigned NumUsr;
|
||||
struct UsrData UsrDat;
|
||||
unsigned NumUsrs;
|
||||
Usr_Sex_t Sex;
|
||||
|
||||
/***** Initialize field names *****/
|
||||
Usr_SetUsrDatMainFieldNames ();
|
||||
|
||||
/***** Create temporary table with candidate users *****/
|
||||
// Search is faster (aproximately x2) using temporary tables
|
||||
Usr_CreateTmpTableAndSearchCandidateUsrs (UsrQuery);
|
||||
Usr_CreateTmpTableAndSearchCandidateUsrs (SearchQuery);
|
||||
|
||||
/***** Search for users *****/
|
||||
Usr_SearchListUsrs (Role);
|
||||
|
@ -5884,7 +5881,7 @@ unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char *UsrQuery)
|
|||
/***** Free memory for teachers list *****/
|
||||
Usr_FreeUsrsList (Role);
|
||||
|
||||
/***** Drop temporary tables *****/
|
||||
/***** Drop temporary table with candidate users *****/
|
||||
Usr_DropTmpTableWithCandidateUsrs ();
|
||||
|
||||
return NumUsrs;
|
||||
|
|
|
@ -305,6 +305,10 @@ unsigned Usr_GetNumberOfTeachersInCentre (long CtrCod);
|
|||
|
||||
void Usr_GetListUsrs (Rol_Role_t Role,Sco_Scope_t Scope);
|
||||
|
||||
void Usr_SearchListUsrs (Rol_Role_t Role);
|
||||
void Usr_CreateTmpTableAndSearchCandidateUsrs (const char *UsrQuery);
|
||||
void Usr_DropTmpTableWithCandidateUsrs (void);
|
||||
|
||||
void Usr_GetUnorderedStdsCodesInDeg (long DegCod);
|
||||
void Usr_FreeUsrsList (Rol_Role_t Role);
|
||||
bool Usr_GetIfShowBigList (unsigned NumUsrs);
|
||||
|
@ -332,7 +336,7 @@ void Usr_ListAllDataGsts (void);
|
|||
void Usr_ListAllDataStds (void);
|
||||
void Usr_ListUsrsForSelection (Rol_Role_t Role);
|
||||
void Usr_ListAllDataTchs (void);
|
||||
unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char *UsrQuery);
|
||||
unsigned Usr_ListUsrsFound (Rol_Role_t Role,const char *SearchQuery);
|
||||
void Usr_ListDataAdms (void);
|
||||
|
||||
void Usr_GetAndUpdatePrefsAboutUsrList (void);
|
||||
|
|
|
@ -109,6 +109,7 @@ cp -f /home/acanas/swad/swad/swad /var/www/cgi-bin/
|
|||
#include "swad_notice.h"
|
||||
#include "swad_notification.h"
|
||||
#include "swad_password.h"
|
||||
#include "swad_search.h"
|
||||
#include "swad_user.h"
|
||||
#include "swad_web_service.h"
|
||||
|
||||
|
@ -179,13 +180,15 @@ static int Svc_CheckParamsNewAccount (char *NewNicknameWithArroba, // Input
|
|||
char *NewPlainPassword, // Input
|
||||
char *NewEncryptedPassword); // Output
|
||||
|
||||
static void Svc_CopyListUsers (Rol_Role_t Role,struct swad__getUsersOutput *getUsersOut);
|
||||
static void Svc_CopyUsrData (struct swad__user *Usr,struct UsrData *UsrDat,bool UsrIDIsVisible);
|
||||
|
||||
static void Svc_GetListGrpsInAttendanceEvent (long AttCod,char **ListGroups);
|
||||
static void Svc_GetListGrpsInAttendanceEventFromDB (long AttCod,char **ListGroups);
|
||||
static void Svc_GetLstGrpsSel (const char *Groups);
|
||||
|
||||
static int Svc_GetMyLanguage (void);
|
||||
|
||||
static int Svc_sendMessageToUsr (long OriginalMsgCod,long SenderUsrCod,long ReplyUsrCod,long RecipientUsrCod,bool NotifyByEmail,const char *Subject,const char *Content);
|
||||
static int Svc_SendMessageToUsr (long OriginalMsgCod,long SenderUsrCod,long ReplyUsrCod,long RecipientUsrCod,bool NotifyByEmail,const char *Subject,const char *Content);
|
||||
|
||||
static int Svc_GetTstConfig (long CrsCod);
|
||||
static int Svc_GetNumTestQuestionsInCrs (long CrsCod);
|
||||
|
@ -1340,25 +1343,20 @@ int swad__getCourseInfo (struct soap *soap,
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Return students in a course **************************/
|
||||
/************* Get users in a course (and optionally in groups) **************/
|
||||
/*****************************************************************************/
|
||||
// If groupCode <= 0 ==> get users from the whole course
|
||||
|
||||
int swad__getUsers (struct soap *soap,
|
||||
char *wsKey,int courseCode,int groupCode,int userRole, // input
|
||||
char *wsKey,int courseCode,char *groups,int userRole, // input
|
||||
struct swad__getUsersOutput *getUsersOut) // output
|
||||
{
|
||||
int ReturnCode;
|
||||
char Query[512];
|
||||
MYSQL_RES *mysql_res;
|
||||
MYSQL_ROW row;
|
||||
unsigned NumRow,NumRows;
|
||||
bool UsrIDIsVisible;
|
||||
Rol_Role_t Role;
|
||||
|
||||
Gbl.soap = soap;
|
||||
Gbl.WebService.Function = Svc_getUsers;
|
||||
Gbl.CurrentCrs.Crs.CrsCod = (long) courseCode;
|
||||
Gbl.CurrentCrs.Grps.GrpCod = (long) groupCode;
|
||||
Gbl.CurrentCrs.Crs.CrsCod = (courseCode > 0) ? (long) courseCode :
|
||||
-1L;
|
||||
|
||||
/***** Check web service key *****/
|
||||
if ((ReturnCode = Svc_CheckWSKey (wsKey)) != SOAP_OK)
|
||||
|
@ -1368,8 +1366,8 @@ int swad__getUsers (struct soap *soap,
|
|||
"Bad web service key",
|
||||
"Web service key does not exist in database");
|
||||
|
||||
/***** Check course and group codes *****/
|
||||
if ((ReturnCode = Svc_CheckCourseAndGroupCodes (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Grps.GrpCod)) != SOAP_OK)
|
||||
/***** Check course *****/
|
||||
if ((ReturnCode = Svc_CheckCourseAndGroupCodes (Gbl.CurrentCrs.Crs.CrsCod,-1L)) != SOAP_OK)
|
||||
return ReturnCode;
|
||||
|
||||
/***** Get some of my data *****/
|
||||
|
@ -1382,78 +1380,194 @@ int swad__getUsers (struct soap *soap,
|
|||
if (Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB != Rol_STUDENT &&
|
||||
Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB != Rol_TEACHER)
|
||||
return soap_receiver_fault (Gbl.soap,
|
||||
"Request forbidden",
|
||||
"Requester must belong to course");
|
||||
"Request forbidden",
|
||||
"Requester must belong to course");
|
||||
|
||||
/***** Get degree of current course *****/
|
||||
if ((ReturnCode = Svc_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK)
|
||||
if ((ReturnCode = Svc_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) // TODO: Is this necessary?
|
||||
return ReturnCode;
|
||||
|
||||
/***** Check requested users' type *****/
|
||||
if (userRole != 2 && // student
|
||||
userRole != 3) // teacher
|
||||
{
|
||||
sprintf (Gbl.Message,"Only students (user's type = %u) or teachers (user's type = %u) are allowed",
|
||||
(unsigned) 2, // student
|
||||
(unsigned) 3); // teacher
|
||||
/***** Check requested users' role *****/
|
||||
if (userRole < 2 || // Students
|
||||
userRole > 3) // Teachers
|
||||
return soap_sender_fault (Gbl.soap,
|
||||
"Bad requested users' type",
|
||||
Gbl.Message);
|
||||
}
|
||||
"User roles allowed are 2 (students) or 3 (teachers)");
|
||||
Role = (Rol_Role_t) userRole;
|
||||
|
||||
/***** Query users beloging to course or group from database *****/
|
||||
if (groupCode <= 0) // Users belonging to the whole course
|
||||
sprintf (Query,"SELECT usr_data.UsrCod"
|
||||
" FROM crs_usr,usr_data"
|
||||
" WHERE crs_usr.CrsCod='%ld' AND crs_usr.UsrCod=usr_data.UsrCod AND crs_usr.Role='%d'"
|
||||
" ORDER BY usr_data.Surname1,usr_data.Surname2,usr_data.FirstName,usr_data.UsrCod",
|
||||
(long) courseCode,
|
||||
userRole == 2 ? (unsigned) Rol_STUDENT :
|
||||
(unsigned) Rol_TEACHER);
|
||||
else // Users belonging to the group
|
||||
sprintf (Query,"SELECT usr_data.UsrCod"
|
||||
" FROM crs_grp_usr,crs_usr,usr_data"
|
||||
" WHERE crs_grp_usr.GrpCod='%ld' AND crs_grp_usr.UsrCod=crs_usr.UsrCod AND crs_grp_usr.UsrCod=usr_data.UsrCod AND crs_usr.Role='%d'"
|
||||
" ORDER BY usr_data.Surname1,usr_data.Surname2,usr_data.FirstName,usr_data.UsrCod",
|
||||
(long) groupCode,
|
||||
userRole == 2 ? (unsigned) Rol_STUDENT :
|
||||
(unsigned) Rol_TEACHER);
|
||||
NumRows = (unsigned) DB_QuerySELECT (Query,&mysql_res,"can not get users");
|
||||
/***** Create a list of groups selected *****/
|
||||
Svc_GetLstGrpsSel (groups);
|
||||
if (Gbl.CurrentCrs.Grps.LstGrpsSel.NumGrps)
|
||||
/***** Get list of groups types and groups in current course *****/
|
||||
Grp_GetListGrpTypesInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
|
||||
|
||||
getUsersOut->numUsers = (int) NumRows;
|
||||
getUsersOut->usersArray.__size = (int) NumRows;
|
||||
/***** Get list of users *****/
|
||||
Usr_GetListUsrs (Role,Sco_SCOPE_CRS);
|
||||
Svc_CopyListUsers (Role,getUsersOut);
|
||||
Usr_FreeUsrsList (Role);
|
||||
|
||||
if (NumRows == 0)
|
||||
getUsersOut->usersArray.__ptr = NULL;
|
||||
else // Users found
|
||||
if (Gbl.CurrentCrs.Grps.LstGrpsSel.NumGrps)
|
||||
{
|
||||
getUsersOut->usersArray.__ptr = soap_malloc (Gbl.soap,(getUsersOut->usersArray.__size) * sizeof (*(getUsersOut->usersArray.__ptr)));
|
||||
/***** Free list of groups types and groups in current course *****/
|
||||
Grp_FreeListGrpTypesAndGrps ();
|
||||
|
||||
/***** Users' IDs are visible? *****/
|
||||
UsrIDIsVisible = (Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB == Rol_STUDENT &&
|
||||
userRole == 2); // get students in the course
|
||||
for (NumRow = 0;
|
||||
NumRow < NumRows;
|
||||
NumRow++)
|
||||
{
|
||||
/* Get next user */
|
||||
row = mysql_fetch_row (mysql_res);
|
||||
|
||||
/* Get user's code (row[0]) */
|
||||
if ((Gbl.Usrs.Other.UsrDat.UsrCod = (long) Str_ConvertStrCodToLongCod (row[0])) > 0)
|
||||
/* Get user's data */
|
||||
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat))
|
||||
/* Copy user's data into output structure */
|
||||
Svc_CopyUsrData (&(getUsersOut->usersArray.__ptr[NumRow]),&Gbl.Usrs.Other.UsrDat,UsrIDIsVisible);
|
||||
}
|
||||
/***** Free memory for list of selected groups *****/
|
||||
Grp_FreeListCodSelectedGrps ();
|
||||
}
|
||||
|
||||
/***** Free structure that stores the query result *****/
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
|
||||
return SOAP_OK;
|
||||
}
|
||||
|
||||
int swad__findUsers (struct soap *soap,
|
||||
char *wsKey,int courseCode,char *filter,int userRole, // input
|
||||
struct swad__getUsersOutput *getUsersOut) // output
|
||||
{
|
||||
int ReturnCode;
|
||||
char SearchQuery[Sch_MAX_LENGTH_SEARCH_QUERY+1];
|
||||
Rol_Role_t Role;
|
||||
bool FilterTooShort = false;
|
||||
|
||||
Gbl.soap = soap;
|
||||
Gbl.WebService.Function = Svc_getUsers;
|
||||
Gbl.CurrentCrs.Crs.CrsCod = (courseCode > 0) ? (long) courseCode :
|
||||
-1L;
|
||||
|
||||
/***** Check web service key *****/
|
||||
if ((ReturnCode = Svc_CheckWSKey (wsKey)) != SOAP_OK)
|
||||
return ReturnCode;
|
||||
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
|
||||
return soap_receiver_fault (Gbl.soap,
|
||||
"Bad web service key",
|
||||
"Web service key does not exist in database");
|
||||
|
||||
if (Gbl.CurrentCrs.Crs.CrsCod > 0)
|
||||
/***** Check course *****/
|
||||
if ((ReturnCode = Svc_CheckCourseAndGroupCodes (Gbl.CurrentCrs.Crs.CrsCod,-1L)) != SOAP_OK)
|
||||
return ReturnCode;
|
||||
|
||||
/***** Get some of my data *****/
|
||||
if ((ReturnCode = Svc_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.CurrentCrs.Crs.CrsCod)) != SOAP_OK)
|
||||
return ReturnCode;
|
||||
Gbl.Usrs.Me.Logged = true;
|
||||
Gbl.Usrs.Me.LoggedRole = Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB;
|
||||
|
||||
if (Gbl.CurrentCrs.Crs.CrsCod > 0)
|
||||
/***** Check if I am a student or teacher in the course *****/
|
||||
if (Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB != Rol_STUDENT &&
|
||||
Gbl.Usrs.Me.UsrDat.RoleInCurrentCrsDB != Rol_TEACHER)
|
||||
return soap_receiver_fault (Gbl.soap,
|
||||
"Request forbidden",
|
||||
"Requester must belong to course");
|
||||
|
||||
if (Gbl.CurrentCrs.Crs.CrsCod > 0)
|
||||
{
|
||||
/***** Get degree of current course *****/
|
||||
if ((ReturnCode = Svc_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) // TODO: Is this necessary?
|
||||
return ReturnCode;
|
||||
}
|
||||
|
||||
/***** Check requested users' role *****/
|
||||
if (userRole < 0 ||
|
||||
userRole > 3)
|
||||
return soap_sender_fault (Gbl.soap,
|
||||
"Bad requested users' type",
|
||||
"User roles allowed are 0 (all),1 (guests), 2 (students) or 3 (teachers)");
|
||||
Role = (Rol_Role_t) userRole;
|
||||
|
||||
/***** Query users beloging to course or group from database *****/
|
||||
strncpy (Gbl.Search.Str,filter,Sch_MAX_LENGTH_STRING_TO_FIND);
|
||||
Gbl.Search.Str[Sch_MAX_LENGTH_STRING_TO_FIND] = '\0';
|
||||
|
||||
if (Gbl.Search.Str[0]) // Search some users
|
||||
{
|
||||
Gbl.Scope.Current = (Gbl.CurrentCrs.Crs.CrsCod > 0) ? Sco_SCOPE_CRS :
|
||||
Sco_SCOPE_SYS;
|
||||
if (Sch_BuildSearchQuery (SearchQuery,
|
||||
"CONCAT_WS(' ',FirstName,Surname1,Surname2)",
|
||||
NULL,NULL))
|
||||
{
|
||||
/***** Create temporary table with candidate users *****/
|
||||
// Search is faster (aproximately x2) using temporary tables
|
||||
Usr_CreateTmpTableAndSearchCandidateUsrs (SearchQuery);
|
||||
|
||||
/***** Search for users *****/
|
||||
Usr_SearchListUsrs (Role);
|
||||
Svc_CopyListUsers (Role,getUsersOut);
|
||||
Usr_FreeUsrsList (Role);
|
||||
|
||||
/***** Drop temporary table with candidate users *****/
|
||||
Usr_DropTmpTableWithCandidateUsrs ();
|
||||
}
|
||||
else
|
||||
FilterTooShort = true;
|
||||
}
|
||||
else
|
||||
FilterTooShort = true;
|
||||
|
||||
/***** Return error in filter? *****/
|
||||
if (FilterTooShort)
|
||||
{
|
||||
getUsersOut->numUsers = -1; // < 0 ==> filter too short
|
||||
getUsersOut->usersArray.__size = 0;
|
||||
getUsersOut->usersArray.__ptr = NULL;
|
||||
}
|
||||
|
||||
return SOAP_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/***************************** Copy users from list **************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Svc_CopyListUsers (Rol_Role_t Role,struct swad__getUsersOutput *getUsersOut)
|
||||
{
|
||||
unsigned NumUsrs;
|
||||
unsigned NumUsr;
|
||||
struct UsrData UsrDat;
|
||||
bool ICanSeeUsrID;
|
||||
|
||||
/***** Initialize result *****/
|
||||
getUsersOut->numUsers = 0;
|
||||
getUsersOut->usersArray.__size = 0;
|
||||
getUsersOut->usersArray.__ptr = NULL;
|
||||
|
||||
NumUsrs = Gbl.Usrs.LstUsrs[Role].NumUsrs;
|
||||
if (NumUsrs)
|
||||
{
|
||||
getUsersOut->numUsers = (int) NumUsrs;
|
||||
getUsersOut->usersArray.__size = (int) NumUsrs;
|
||||
getUsersOut->usersArray.__ptr = soap_malloc (Gbl.soap,(getUsersOut->usersArray.__size) * sizeof (*(getUsersOut->usersArray.__ptr)));
|
||||
|
||||
/***** Initialize structure with user's data *****/
|
||||
Usr_UsrDataConstructor (&UsrDat);
|
||||
|
||||
/***** List data of users *****/
|
||||
for (NumUsr = 0;
|
||||
NumUsr < NumUsrs;
|
||||
NumUsr++)
|
||||
{
|
||||
UsrDat.UsrCod = Gbl.Usrs.LstUsrs[Role].Lst[NumUsr].UsrCod;
|
||||
|
||||
/* Get user's data */
|
||||
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&UsrDat)) // If user's data exist...
|
||||
{
|
||||
UsrDat.Accepted = Gbl.Usrs.LstUsrs[Role].Lst[NumUsr].Accepted;
|
||||
|
||||
if (Gbl.Usrs.Me.UsrDat.UsrCod == UsrDat.UsrCod) // It's me
|
||||
ICanSeeUsrID = true;
|
||||
else // A user distinct than me
|
||||
ICanSeeUsrID = ID_ICanSeeAnotherUsrID (&UsrDat);
|
||||
|
||||
/* Copy user's data into output structure */
|
||||
Svc_CopyUsrData (&(getUsersOut->usersArray.__ptr[NumUsr]),&UsrDat,ICanSeeUsrID);
|
||||
}
|
||||
}
|
||||
|
||||
/***** Free memory used for user's data *****/
|
||||
Usr_UsrDataDestructor (&UsrDat);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Return group types in a course ***********************/
|
||||
/*****************************************************************************/
|
||||
|
@ -2026,7 +2140,7 @@ int swad__getAttendanceEvents (struct soap *soap,
|
|||
row[6]);
|
||||
|
||||
/* Get list of groups for this attendance event */
|
||||
Svc_GetListGrpsInAttendanceEvent (AttCod,&(getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].groups));
|
||||
Svc_GetListGrpsInAttendanceEventFromDB (AttCod,&(getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].groups));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2040,7 +2154,7 @@ int swad__getAttendanceEvents (struct soap *soap,
|
|||
/**************** Get lists of groups of an attendance event *****************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Svc_GetListGrpsInAttendanceEvent (long AttCod,char **ListGroups)
|
||||
static void Svc_GetListGrpsInAttendanceEventFromDB (long AttCod,char **ListGroups)
|
||||
{
|
||||
char Query[128];
|
||||
MYSQL_RES *mysql_res;
|
||||
|
@ -2093,9 +2207,6 @@ int swad__sendAttendanceEvent (struct soap *soap,
|
|||
int ReturnCode;
|
||||
struct AttendanceEvent Att;
|
||||
bool ItsANewAttEvent;
|
||||
const char *Ptr;
|
||||
char LongStr[1+10+1];
|
||||
unsigned NumGrp;
|
||||
|
||||
Gbl.soap = soap;
|
||||
Gbl.WebService.Function = Svc_sendAttendanceEvent;
|
||||
|
@ -2168,8 +2279,35 @@ int swad__sendAttendanceEvent (struct soap *soap,
|
|||
strncpy (Att.Title,title,Att_MAX_LENGTH_ATTENDANCE_EVENT_TITLE);
|
||||
Att.Title[Att_MAX_LENGTH_ATTENDANCE_EVENT_TITLE] = '\0';
|
||||
|
||||
/* Create a list of groups selected */
|
||||
Svc_GetLstGrpsSel (groups);
|
||||
|
||||
/***** Create or update attendance event *****/
|
||||
if (ItsANewAttEvent)
|
||||
Att_CreateAttEvent (&Att,text); // Add new attendance event to database
|
||||
else
|
||||
Att_UpdateAttEvent (&Att,text); // Modify existing attendance event
|
||||
|
||||
/***** Free memory for list of selected groups *****/
|
||||
Grp_FreeListCodSelectedGrps ();
|
||||
|
||||
sendAttendanceEventOut->attendanceEventCode = Att.AttCod;
|
||||
|
||||
return SOAP_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/********************** Create a list of groups selected *********************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static void Svc_GetLstGrpsSel (const char *Groups)
|
||||
{
|
||||
const char *Ptr;
|
||||
char LongStr[1+10+1];
|
||||
unsigned NumGrp;
|
||||
|
||||
/***** Count number of groups *****/
|
||||
for (Ptr = groups, NumGrp = 0;
|
||||
for (Ptr = Groups, NumGrp = 0;
|
||||
*Ptr;
|
||||
NumGrp++)
|
||||
Str_GetNextStringUntilComma (&Ptr,LongStr,1+10);
|
||||
|
@ -2184,7 +2322,7 @@ int swad__sendAttendanceEvent (struct soap *soap,
|
|||
if ((Gbl.CurrentCrs.Grps.LstGrpsSel.GrpCod = (long *) calloc (Gbl.CurrentCrs.Grps.LstGrpsSel.NumGrps,sizeof (long))) == NULL)
|
||||
Lay_ShowErrorAndExit ("Not enough memory to store the codes of the selected groups.");
|
||||
|
||||
for (Ptr = groups, NumGrp = 0;
|
||||
for (Ptr = Groups, NumGrp = 0;
|
||||
*Ptr;
|
||||
)
|
||||
{
|
||||
|
@ -2195,19 +2333,6 @@ int swad__sendAttendanceEvent (struct soap *soap,
|
|||
}
|
||||
Gbl.CurrentCrs.Grps.LstGrpsSel.NumGrps = NumGrp; // Update number of groups
|
||||
}
|
||||
|
||||
/***** Create or update attendance event *****/
|
||||
if (ItsANewAttEvent)
|
||||
Att_CreateAttEvent (&Att,text); // Add new attendance event to database
|
||||
else
|
||||
Att_UpdateAttEvent (&Att,text); // Modify existing attendance event
|
||||
|
||||
/***** Free memory for list of selected groups *****/
|
||||
Grp_FreeListCodSelectedGrps ();
|
||||
|
||||
sendAttendanceEventOut->attendanceEventCode = Att.AttCod;
|
||||
|
||||
return SOAP_OK;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -2991,7 +3116,7 @@ int swad__sendMessage (struct soap *soap,
|
|||
(Gbl.Usrs.Other.UsrDat.Prefs.EmailNtfEvents & (1 << Ntf_EVENT_MESSAGE)));
|
||||
|
||||
/* Send message to this user */
|
||||
if ((ReturnCode = Svc_sendMessageToUsr ((long) messageCode,Gbl.Usrs.Me.UsrDat.UsrCod,ReplyUsrCod,Gbl.Usrs.Other.UsrDat.UsrCod,NotifyByEmail,subject,body)) != SOAP_OK)
|
||||
if ((ReturnCode = Svc_SendMessageToUsr ((long) messageCode,Gbl.Usrs.Me.UsrDat.UsrCod,ReplyUsrCod,Gbl.Usrs.Other.UsrDat.UsrCod,NotifyByEmail,subject,body)) != SOAP_OK)
|
||||
{
|
||||
DB_FreeMySQLResult (&mysql_res);
|
||||
return ReturnCode;
|
||||
|
@ -3013,7 +3138,7 @@ int swad__sendMessage (struct soap *soap,
|
|||
/************************* Send a message to one user ************************/
|
||||
/*****************************************************************************/
|
||||
|
||||
static int Svc_sendMessageToUsr (long OriginalMsgCod,long SenderUsrCod,long ReplyUsrCod,long RecipientUsrCod,bool NotifyByEmail,const char *Subject,const char *Content)
|
||||
static int Svc_SendMessageToUsr (long OriginalMsgCod,long SenderUsrCod,long ReplyUsrCod,long RecipientUsrCod,bool NotifyByEmail,const char *Subject,const char *Content)
|
||||
{
|
||||
static bool MsgAlreadyInserted = false;
|
||||
static long NewMsgCod;
|
||||
|
|
Loading…
Reference in New Issue