swad-core/swad_API.c

5878 lines
221 KiB
C
Raw Normal View History

2019-05-16 14:02:06 +02:00
// swad_API.c: SWAD web API provided to external plugins
2014-12-01 23:55:08 +01:00
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
2020-01-01 14:53:57 +01:00
Copyright (C) 1999-2020 Antonio Ca<EFBFBD>as Vargas
2014-12-01 23:55:08 +01:00
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/******* How to use the gSOAP toolkit to create a web-service server *********/
/*****************************************************************************/
/*
This code uses the gSOAP toolkit:
http://www.cs.fsu.edu/~engelen/soap.html
http://gsoap2.sourceforge.net/
Version 2.8.8 (19/02/2012)
To install the toolkit:
1. Install g++ if not installed: yum -y install gcc-c++
2. Install yacc if not installed: yum -y install byacc
3. Install flex if not installed: yum -y install flex
4. Install bison if not installed: yum -y install bison
5. Install bison-devel if not installed: yum -y install bison-devel
6. unzip gsoap_2.8.8.zip
7. cd gsoap-2.8
8. ./configure
9. make
10. make install
Steps to generate swad.wsdl:
1. Go to directory soap
cd /home/acanas/swad/swad/soap
2. Inside soap, create a C header file with the web service. Example swad_web_service.h:
----------
// File: swad_web_service.h
//gsoap swad service name: swad
//gsoap swad service namespace: urn:swad
//gsoap swad service location: https://swad.ugr.es/
...
----------
3. Inside soap, execute soapcpp2 compiler:
soapcpp2 -c -S swad_web_service.h
4. Copy generated WSDL file (swad.wsdl) to public location (probably you must be root):
cp -f /home/acanas/swad/swad/soap/swad.wsdl /var/www/html/ws/
5. Put a '#include "soap/soapH.h"' line into the code of the web-service server (this file).
6. Put a '#include "soap/swad.nsmap"' into the code of the web-service server (this file).
7. Compile swad including the web service.
The makefile must include -lgsoap, and compile soapC.c and soapServer.c files generated by soapcpp2 in step 2
Example of Makefile:
---------------------
2016-10-09 22:22:47 +02:00
OBJS = list of swad object files
2014-12-01 23:55:08 +01:00
SOAPOBJS = soap/soapC.o soap/soapServer.o
CC = gcc
LIBS = -lmysqlclient -lz -L/usr/lib64/mysql -lm -lgsoap
CFLAGS = -Wall -O2 -s
swad: $(OBJS) $(SOAPOBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(SOAPOBJS) $(LIBS)
chmod a+x $@
---------------------
8. Copy CGI (swad) to the cgi directory:
cp -f /home/acanas/swad/swad/swad /var/www/cgi-bin/
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
// In Eclipse, add to include path /usr/include, /usr/local/include, /usr/include/i386-linux-gnu
2015-12-21 14:43:52 +01:00
#include <dirent.h> // For scandir, etc.
2014-12-01 23:55:08 +01:00
#include <linux/limits.h> // For PATH_MAX
2019-12-29 12:39:00 +01:00
#include <stddef.h> // For NULL
2014-12-01 23:55:08 +01:00
#include <string.h>
#include <stdsoap2.h>
2019-12-29 12:39:00 +01:00
#include <sys/stat.h> // For lstat
2014-12-01 23:55:08 +01:00
#include "soap/soapH.h" // gSOAP header
#include "soap/swad.nsmap" // Namespaces map used
2015-07-13 12:34:26 +02:00
#include "swad_account.h"
2019-05-16 14:02:06 +02:00
#include "swad_API.h"
2014-12-01 23:55:08 +01:00
#include "swad_database.h"
#include "swad_file_browser.h"
#include "swad_global.h"
2016-11-14 16:47:46 +01:00
#include "swad_hierarchy.h"
2014-12-01 23:55:08 +01:00
#include "swad_ID.h"
2019-12-02 09:57:17 +01:00
#include "swad_match.h"
2014-12-01 23:55:08 +01:00
#include "swad_notice.h"
#include "swad_notification.h"
#include "swad_password.h"
2016-06-29 18:27:49 +02:00
#include "swad_search.h"
2020-03-21 15:41:25 +01:00
#include "swad_test_config.h"
2020-02-18 09:19:33 +01:00
#include "swad_test_visibility.h"
2014-12-01 23:55:08 +01:00
#include "swad_user.h"
2016-06-30 18:14:09 +02:00
#include "swad_xml.h"
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
2019-03-15 15:25:31 +01:00
extern const char Str_BIN_TO_BASE64URL[64 + 1];
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
// Add new functions at the end
2019-05-16 14:02:06 +02:00
static const char *API_Functions[1 + API_NUM_FUNCTIONS] =
2014-12-01 23:55:08 +01:00
{
2019-12-15 01:10:36 +01:00
[API_unknown ] = "?", // 0 ==> unknown function
[API_loginBySessionKey ] = "loginBySession", // 1
[API_loginByUserPassword ] = "loginByUserPassword", // 2 (deprecated)
[API_loginByUserPasswordKey ] = "loginByUserPasswordKey", // 3
[API_getCourses ] = "getCourses", // 4
[API_getUsers ] = "getUsers", // 5
[API_getNotifications ] = "getNotifications", // 6
[API_getTestConfig ] = "getTestConfig", // 7
[API_getTests ] = "getTests", // 8
[API_sendMessage ] = "sendMessage", // 9
[API_sendNotice ] = "sendNotice", // 10
[API_getDirectoryTree ] = "getDirectoryTree", // 11
[API_getGroups ] = "getGroups", // 12
[API_getGroupTypes ] = "getGroupTypes", // 13
[API_sendMyGroups ] = "sendMyGroups", // 14
[API_getFile ] = "getFile", // 15
[API_markNotificationsAsRead] = "markNotificationsAsRead", // 16
[API_getNewPassword ] = "getNewPassword", // 17
[API_getCourseInfo ] = "getCourseInfo", // 18
[API_getAttendanceEvents ] = "getAttendanceEvents", // 19
[API_sendAttendanceEvent ] = "sendAttendanceEvent", // 20
[API_getAttendanceUsers ] = "getAttendanceUsers", // 21
[API_sendAttendanceUsers ] = "sendAttendanceUsers", // 22
[API_createAccount ] = "createAccount", // 23
[API_getMarks ] = "getMarks", // 24
[API_getTrivialQuestion ] = "getTrivialQuestion", // 25
[API_findUsers ] = "findUsers", // 26
[API_removeAttendanceEvent ] = "removeAttendanceEvent", // 27
[API_getGames ] = "getGames", // 28
[API_getMatches ] = "getMatches", // 29
[API_getMatchStatus ] = "getMatchStatus", // 30
[API_answerMatchQuestion ] = "answerMatchQuestion", // 31
2014-12-01 23:55:08 +01:00
};
2016-07-04 10:46:32 +02:00
/* Web service roles (they do not match internal swad-core roles) */
2019-05-16 14:02:06 +02:00
#define API_NUM_ROLES 4
2016-07-04 10:26:44 +02:00
typedef enum
{
2019-05-16 14:02:06 +02:00
API_ROLE_UNKNOWN = 0, // User not logged in
API_ROLE__GUEST_ = 1, // User not belonging to any course
API_ROLE_STUDENT = 2, // Student in current course
API_ROLE_TEACHER = 3, // Teacher in current course
} API_Role_t;
2016-07-04 10:26:44 +02:00
2016-07-04 10:46:32 +02:00
/* Translation from service-web-role to swad-core-role */
2019-11-21 11:39:30 +01:00
static const Rol_Role_t API_SvcRole_to_RolRole[API_NUM_ROLES] =
2016-07-04 10:26:44 +02:00
{
2019-11-20 17:53:51 +01:00
[API_ROLE_UNKNOWN] = Rol_UNK,
[API_ROLE__GUEST_] = Rol_GST,
[API_ROLE_STUDENT] = Rol_STD,
[API_ROLE_TEACHER] = Rol_TCH, // TODO: Create new web service role for non-editing teachers
2016-07-04 10:26:44 +02:00
};
2016-07-04 10:46:32 +02:00
/* Translation from swad-core-role to service-web-role */
2019-11-21 11:39:30 +01:00
static const API_Role_t API_RolRole_to_SvcRole[Rol_NUM_ROLES] =
2016-07-04 10:26:44 +02:00
{
2019-11-20 17:53:51 +01:00
[Rol_UNK ] = API_ROLE_UNKNOWN,
[Rol_GST ] = API_ROLE__GUEST_,
[Rol_USR ] = API_ROLE_UNKNOWN,
[Rol_STD ] = API_ROLE_STUDENT,
[Rol_NET ] = API_ROLE_TEACHER, // TODO: Create new web service role for non-editing teachers
[Rol_TCH ] = API_ROLE_TEACHER,
[Rol_DEG_ADM] = API_ROLE_UNKNOWN,
[Rol_CTR_ADM] = API_ROLE_UNKNOWN,
[Rol_INS_ADM] = API_ROLE_UNKNOWN,
[Rol_SYS_ADM] = API_ROLE_UNKNOWN,
2016-07-04 10:26:44 +02:00
};
2019-05-16 14:02:06 +02:00
#define API_BYTES_WS_KEY Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64
2017-01-15 18:02:52 +01:00
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/***************************** Private prototypes ****************************/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static void API_Set_gSOAP_RuntimeEnv (struct soap *soap);
2020-02-24 20:34:06 +01:00
static void API_FreeSoapContext (struct soap *soap);
2020-02-24 19:31:55 +01:00
static int API_GetPlgCodFromAppKey (struct soap *soap,
const char *appKey);
static int API_CheckIdSession (struct soap *soap,
const char *IdSession);
2019-05-16 14:02:06 +02:00
static int API_CheckWSKey (char WSKey[API_BYTES_WS_KEY + 1]);
2014-12-01 23:55:08 +01:00
2020-02-24 19:31:55 +01:00
static int API_CheckCourseAndGroupCodes (struct soap *soap,
long CrsCod,long GrpCod);
static int API_GenerateNewWSKey (struct soap *soap,
long UsrCod,
2019-05-16 14:02:06 +02:00
char WSKey[API_BYTES_WS_KEY + 1]);
2020-02-24 19:31:55 +01:00
static int API_RemoveOldWSKeys (struct soap *soap);
2019-05-16 14:02:06 +02:00
static int API_GetCurrentDegCodFromCurrentCrsCod (void);
static bool API_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod);
2015-07-13 12:34:26 +02:00
2019-05-16 14:02:06 +02:00
static int API_CheckParamsNewAccount (char *NewNicknameWithArroba, // Input
2017-01-17 03:10:43 +01:00
char NewNicknameWithoutArroba[Nck_MAX_BYTES_NICKNAME_FROM_FORM + 1], // Output
2015-07-13 12:34:26 +02:00
char *NewEmail, // Input-output
char *NewPlainPassword, // Input
char *NewEncryptedPassword); // Output
2020-02-24 19:31:55 +01:00
static int API_WriteSyllabusIntoHTMLBuffer (struct soap *soap,
char **HTMLBuffer);
static int API_WritePlainTextIntoHTMLBuffer (struct soap *soap,
char **HTMLBuffer);
static int API_WritePageIntoHTMLBuffer (struct soap *soap,
char **HTMLBuffer);
static void API_CopyListUsers (struct soap *soap,
Rol_Role_t Role,
struct swad__getUsersOutput *getUsersOut);
static void API_CopyUsrData (struct soap *soap,
struct swad__user *Usr,struct UsrData *UsrDat,
bool UsrIDIsVisible);
static void API_GetListGrpsInAttendanceEventFromDB (struct soap *soap,
long AttCod,char **ListGroups);
2019-05-16 14:02:06 +02:00
static void API_GetLstGrpsSel (const char *Groups);
2014-12-01 23:55:08 +01:00
2020-02-24 19:31:55 +01:00
static int API_GetMyLanguage (struct soap *soap);
2014-12-01 23:55:08 +01:00
2019-05-16 14:02:06 +02:00
static int API_SendMessageToUsr (long OriginalMsgCod,long SenderUsrCod,long ReplyUsrCod,long RecipientUsrCod,bool NotifyByEmail,const char *Subject,const char *Content);
2014-12-01 23:55:08 +01:00
2019-05-16 14:02:06 +02:00
static int API_GetTstConfig (long CrsCod);
static int API_GetNumTestQuestionsInCrs (long CrsCod);
2020-02-24 19:31:55 +01:00
static int API_GetTstTags (struct soap *soap,
long CrsCod,struct swad__getTestsOutput *getTestsOut);
static int API_GetTstQuestions (struct soap *soap,
long CrsCod,long BeginTime,
struct swad__getTestsOutput *getTestsOut);
static int API_GetTstAnswers (struct soap *soap,
long CrsCod,long BeginTime,
struct swad__getTestsOutput *getTestsOut);
static int API_GetTstQuestionTags (struct soap *soap,
long CrsCod,long BeginTime,
struct swad__getTestsOutput *getTestsOut);
static void API_GetListGrpsInGameFromDB (struct soap *soap,
long MchCod,char **ListGroups);
2019-05-16 14:02:06 +02:00
static void API_ListDir (unsigned Level,const char *Path,const char *PathInTree);
static bool API_WriteRowFileBrowser (unsigned Level,Brw_FileType_t FileType,const char *FileName);
static void API_IndentXMLLine (unsigned Level);
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/******* Function called when a web service if required by a plugin **********/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static struct soap *API_soap = NULL; // gSOAP runtime environment
static void API_Set_gSOAP_RuntimeEnv (struct soap *soap)
{
API_soap = soap;
}
struct soap *API_Get_gSOAP_RuntimeEnv (void)
{
return API_soap;
}
/*****************************************************************************/
/******* Function called when a web service if required by a plugin **********/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
void API_WebService (void)
2014-12-01 23:55:08 +01:00
{
struct soap *soap;
if ((soap = soap_new ())) // Allocate and initialize runtime context
{
soap_serve (soap);
2020-02-24 20:34:06 +01:00
API_FreeSoapContext (soap);
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/******* Function called to exit on error when executing web service *********/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
void API_Exit (const char *DetailErrorMessage)
2014-12-01 23:55:08 +01:00
{
2020-02-24 19:31:55 +01:00
struct soap *soap = API_Get_gSOAP_RuntimeEnv ();
int ReturnCode = 0;
if (soap)
{
ReturnCode = (DetailErrorMessage ? soap_receiver_fault (soap,
"Error in swad web service",
DetailErrorMessage) :
0);
2014-12-01 23:55:08 +01:00
2020-02-24 20:34:06 +01:00
API_FreeSoapContext (soap);
2020-02-24 19:31:55 +01:00
}
2014-12-01 23:55:08 +01:00
exit (ReturnCode);
}
/*****************************************************************************/
2020-02-24 20:34:06 +01:00
/****************************** Free SOAP context ****************************/
/*****************************************************************************/
static void API_FreeSoapContext (struct soap *soap)
{
soap_destroy (soap); // delete managed C++ objects
soap_end (soap); // delete managed memory
soap_free (soap); // free the context
API_Set_gSOAP_RuntimeEnv (NULL); // set pointer to NULL in order to not try to free the context again
}
/*****************************************************************************/
2014-12-01 23:55:08 +01:00
/****** Check if the application key of the requester of a web service *******/
/****** is one of the application keys allowed in the plugins *******/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_GetPlgCodFromAppKey (struct soap *soap,
const char *appKey)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
Gbl.WebService.PlgCod = -1L;
/***** Get number of plugins with a IP address *****/
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not check application key",
"SELECT PlgCod FROM plugins WHERE AppKey='%s'",
appKey)) // Session found in table of sessions
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
Gbl.WebService.PlgCod = Str_ConvertStrCodToLongCod (row[0]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (Gbl.WebService.PlgCod < 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Unknown application key",
"Unknown application");
return SOAP_OK;
}
/*****************************************************************************/
/****** Get the name of a web service function given the function code *******/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
const char *API_GetFunctionNameFromFunCod (long FunCod)
2014-12-01 23:55:08 +01:00
{
2019-05-16 14:02:06 +02:00
if (FunCod < 0 || FunCod > API_NUM_FUNCTIONS)
return API_Functions[0];
return API_Functions[FunCod];
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****** Check if a session identifier is valid and exists in database ********/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_CheckIdSession (struct soap *soap,
const char *IdSession)
2014-12-01 23:55:08 +01:00
{
const char *Ptr;
unsigned i;
/***** Check if pointer is NULL *****/
if (IdSession == NULL)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad session identifier",
"Session identifier is a null pointer");
/***** Check length of session identifier *****/
2018-10-17 01:08:42 +02:00
if (strlen (IdSession) != Cns_BYTES_SESSION_ID)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad session identifier",
"The length of the session identifier is wrong");
/***** Check if session identifier is in base64url *****/
for (Ptr = IdSession;
*Ptr;
Ptr++)
{
for (i = 0;
i < 64;
i++) // Check if this character is one of the allowed characters
if (*Ptr == Str_BIN_TO_BASE64URL[i])
break;
if (i == 64) // Character not found
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad session identifier",
"The session identifier must contain only base64url characters");
}
/***** Query if session identifier already exists in database *****/
2018-11-03 22:08:45 +01:00
if (DB_QueryCOUNT ("can not get session data",
2018-11-04 20:51:38 +01:00
"SELECT COUNT(*) FROM sessions"
" WHERE SessionId='%s'",
2018-11-03 22:08:45 +01:00
IdSession) != 1)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad session identifier",
"Session identifier does not exist in database");
return SOAP_OK;
}
/*****************************************************************************/
/************** Check if a web service key exists in database ****************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
static int API_CheckWSKey (char WSKey[API_BYTES_WS_KEY + 1])
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Set default user's code *****/
Gbl.Usrs.Me.UsrDat.UsrCod = -1L;
Gbl.Usrs.Me.Logged = false;
Gbl.WebService.PlgCod = -1L;
/***** Check that key does not exist in database *****/
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get existence of key",
"SELECT UsrCod,PlgCod FROM ws_keys WHERE WSKey='%s'",
WSKey)) // Session found in table of sessions
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
Gbl.Usrs.Me.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
Gbl.Usrs.Me.Logged = true;
Gbl.WebService.PlgCod = Str_ConvertStrCodToLongCod (row[1]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/** Check if a course code and a group code are valid and exist in database **/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_CheckCourseAndGroupCodes (struct soap *soap,
long CrsCod,long GrpCod)
2014-12-01 23:55:08 +01:00
{
/***** Check if course code is correct *****/
if (CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Query if course code already exists in database *****/
2018-11-03 22:08:45 +01:00
if (DB_QueryCOUNT ("can not get course",
2018-11-04 20:51:38 +01:00
"SELECT COUNT(*) FROM courses"
" WHERE CrsCod=%ld",
2018-11-03 22:08:45 +01:00
CrsCod) != 1)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code does not exist in database");
/***** Course code exists in database, so check if group code exists in database and belongs to course *****/
if (GrpCod > 0) // <=0 means "the whole course"
{
/***** Query if group code already exists in database *****/
2018-11-03 22:08:45 +01:00
if (DB_QueryCOUNT ("can not get group",
"SELECT COUNT(*) FROM crs_grp_types,crs_grp"
" WHERE crs_grp_types.CrsCod=%ld"
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
" AND crs_grp.GrpCod=%ld",
CrsCod,GrpCod) != 1)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad group code",
"Group code does not exist in database or it's not a group of the specified course");
}
return SOAP_OK;
}
/*****************************************************************************/
/***** Generate a key used in subsequents calls to other web services ********/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_GenerateNewWSKey (struct soap *soap,
long UsrCod,
2019-05-16 14:02:06 +02:00
char WSKey[API_BYTES_WS_KEY + 1])
2014-12-01 23:55:08 +01:00
{
int ReturnCode;
/***** Remove expired web service keys *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_RemoveOldWSKeys (soap)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Create a unique name for the key *****/
2017-01-15 22:58:26 +01:00
Str_Copy (WSKey,Gbl.UniqueNameEncrypted,
2019-05-16 14:02:06 +02:00
API_BYTES_WS_KEY);
2014-12-01 23:55:08 +01:00
/***** Check that key does not exist in database *****/
2018-11-03 22:08:45 +01:00
if (DB_QueryCOUNT ("can not get existence of key",
2018-11-04 20:51:38 +01:00
"SELECT COUNT(*) FROM ws_keys"
" WHERE WSKey='%s'",
2018-11-03 22:08:45 +01:00
WSKey))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Error when generating key",
"Generated key already existed in database");
/***** Insert key into database *****/
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not insert new key",
"INSERT INTO ws_keys"
" (WSKey,UsrCod,PlgCod,LastTime)"
" VALUES"
" ('%s',%ld,%ld,NOW())",
WSKey,UsrCod,Gbl.WebService.PlgCod);
2014-12-01 23:55:08 +01:00
return SOAP_OK;
}
/*****************************************************************************/
/************************ Remove old web service keys ************************/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_RemoveOldWSKeys (struct soap *soap)
2014-12-01 23:55:08 +01:00
{
char Query[512];
/***** Remove expired sessions *****/
/* A session expire when last click (LastTime) is too old,
or when there was at least one refresh (navigator supports AJAX) and last refresh is too old (browser probably was closed) */
2019-02-13 13:32:11 +01:00
sprintf (Query,"DELETE LOW_PRIORITY FROM ws_keys"
" WHERE LastTime<FROM_UNIXTIME(UNIX_TIMESTAMP()-%lu)",
2015-12-21 00:53:56 +01:00
Cfg_TIME_TO_DELETE_WEB_SERVICE_KEY);
2014-12-01 23:55:08 +01:00
if (mysql_query (&Gbl.mysql,Query))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not remove old web service keys from database",
mysql_error (&Gbl.mysql));
return SOAP_OK;
}
/*****************************************************************************/
/********************* Get degree code from course code **********************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
static int API_GetCurrentDegCodFromCurrentCrsCod (void)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Set default degree code *****/
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.DegCod = -1L;
2014-12-01 23:55:08 +01:00
/***** Check that key does not exist in database *****/
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get the degree of a course",
"SELECT DegCod FROM courses WHERE CrsCod=%ld",
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod)) // Course found in table of courses
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.DegCod = Str_ConvertStrCodToLongCod (row[0]);
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/************ Get user's data from database giving a user's code *************/
/*****************************************************************************/
2016-07-20 20:24:16 +02:00
// Return false if UsrDat->UsrCod does not exist ini database
2014-12-01 23:55:08 +01:00
2019-05-16 14:02:06 +02:00
static bool API_GetSomeUsrDataFromUsrCod (struct UsrData *UsrDat,long CrsCod)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2016-07-20 20:24:16 +02:00
/***** Check if user's code is valid *****/
if (UsrDat->UsrCod <= 0)
return false;
2014-12-01 23:55:08 +01:00
/***** Get some user's data *****/
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get user's data",
"SELECT Surname1,Surname2,FirstName,Photo,DATE_FORMAT(Birthday,'%%Y%%m%%d')"
" FROM usr_data WHERE UsrCod=%ld",
UsrDat->UsrCod) != 1)
2016-07-20 20:24:16 +02:00
return false;
2014-12-01 23:55:08 +01:00
/* Read some user's data */
row = mysql_fetch_row (mysql_res);
/* Get user's name */
2017-01-17 03:10:43 +01:00
Str_Copy (UsrDat->Surname1,row[0],
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2017-01-17 03:10:43 +01:00
Str_Copy (UsrDat->Surname2,row[1],
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2017-01-17 03:10:43 +01:00
Str_Copy (UsrDat->FirstName,row[2],
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2014-12-01 23:55:08 +01:00
/* Get user's photo */
2017-01-17 03:10:43 +01:00
Str_Copy (UsrDat->Photo,row[3],
2017-03-07 01:56:41 +01:00
Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64);
2014-12-01 23:55:08 +01:00
/* Get user's brithday */
2017-01-15 22:58:26 +01:00
Dat_GetDateFromYYYYMMDD (&(UsrDat->Birthday),row[4]);
2014-12-01 23:55:08 +01:00
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
/***** Get list of user's IDs *****/
ID_GetListIDsFromUsrCod (UsrDat);
/***** Get user's nickname *****/
Nck_GetNicknameFromUsrCod (UsrDat->UsrCod,UsrDat->Nickname);
/***** Get user's role *****/
/* Query database */
if (CrsCod > 0)
2016-07-20 20:24:16 +02:00
{
/* Get the role in the given course */
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get user's role",
"SELECT Role FROM crs_usr"
" WHERE CrsCod=%ld AND UsrCod=%ld",
CrsCod,UsrDat->UsrCod)) // User belongs to course
2016-07-20 20:24:16 +02:00
{
row = mysql_fetch_row (mysql_res);
if (row[0])
{
2017-06-23 15:12:49 +02:00
if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) == 1)
UsrDat->Roles.InCurrentCrs.Valid = true;
else
{
2017-06-08 15:32:33 +02:00
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
2017-06-23 15:12:49 +02:00
UsrDat->Roles.InCurrentCrs.Valid = false;
}
2016-07-20 20:24:16 +02:00
}
else // Impossible
2017-06-08 15:32:33 +02:00
{
2017-06-23 15:12:49 +02:00
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.Valid = false;
2017-06-08 15:32:33 +02:00
}
2016-07-20 20:24:16 +02:00
}
else // User does not belong to course
2017-06-08 15:32:33 +02:00
{
2017-06-23 15:12:49 +02:00
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.Valid = true;
2017-06-08 15:32:33 +02:00
}
2016-07-20 20:24:16 +02:00
}
2014-12-01 23:55:08 +01:00
else
2016-07-20 20:24:16 +02:00
{
/* Get the maximum role in any course */
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get user's role",
"SELECT MAX(Role)"
" FROM crs_usr WHERE UsrCod=%ld",
UsrDat->UsrCod) == 1)
2016-07-20 20:24:16 +02:00
{
row = mysql_fetch_row (mysql_res);
if (row[0])
{
2017-06-23 15:12:49 +02:00
if (sscanf (row[0],"%u",&UsrDat->Roles.InCurrentCrs.Role) == 1)
UsrDat->Roles.InCurrentCrs.Valid = true;
else
{
2017-06-08 15:32:33 +02:00
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
2017-06-23 15:12:49 +02:00
UsrDat->Roles.InCurrentCrs.Valid = false;
}
2016-07-20 20:24:16 +02:00
}
else
// MAX(Role) == NULL if user does not belong to any course
2017-06-08 15:32:33 +02:00
{
2017-06-23 15:12:49 +02:00
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.Valid = true;
2017-06-08 15:32:33 +02:00
}
2016-07-20 20:24:16 +02:00
}
else // Impossible
2017-06-08 15:32:33 +02:00
{
2017-06-23 15:12:49 +02:00
UsrDat->Roles.InCurrentCrs.Role = Rol_UNK;
UsrDat->Roles.InCurrentCrs.Valid = false;
2017-06-08 15:32:33 +02:00
}
2014-12-01 23:55:08 +01:00
}
/* Free structure that stores the query result */
DB_FreeMySQLResult (&mysql_res);
2016-07-20 20:24:16 +02:00
return true;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/**************************** Get info of my marks ***************************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
#define API_CHECK_NEW_ACCOUNT_OK 0
#define API_CHECK_NEW_ACCOUNT_NICKNAME_NOT_VALID -1
#define API_CHECK_NEW_ACCOUNT_NICKNAME_REGISTERED_BY_ANOTHER_USER -2
#define API_CHECK_NEW_ACCOUNT_EMAIL_NOT_VALID -3
#define API_CHECK_NEW_ACCOUNT_EMAIL_REGISTERED_BY_ANOTHER_USER -4
#define API_CHECK_NEW_ACCOUNT_PASSWORD_NOT_VALID -5
2015-07-13 12:34:26 +02:00
2014-12-01 23:55:08 +01:00
int swad__createAccount (struct soap *soap,
2015-07-13 12:34:26 +02:00
char *userNickname,char *userEmail,char *userPassword,char *appKey, // input
2016-11-08 00:58:32 +01:00
struct swad__createAccountOutput *createAccountOut) // output
2014-12-01 23:55:08 +01:00
{
2017-01-17 03:10:43 +01:00
char NewNicknameWithoutArroba[Nck_MAX_BYTES_NICKNAME_FROM_FORM + 1];
2017-03-13 14:22:36 +01:00
char NewEncryptedPassword[Pwd_BYTES_ENCRYPTED_PASSWORD + 1];
2015-07-13 12:34:26 +02:00
int Result;
2014-12-01 23:55:08 +01:00
int ReturnCode;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_createAccount;
2014-12-01 23:55:08 +01:00
2015-07-13 12:34:26 +02:00
/***** Allocate space for strings *****/
2020-02-24 19:31:55 +01:00
createAccountOut->wsKey = (char *) soap_malloc (soap,API_BYTES_WS_KEY + 1);
2015-07-13 12:34:26 +02:00
/***** Default values returned on error *****/
createAccountOut->userCode = 0; // Undefined error
createAccountOut->wsKey[0] = '\0';
2014-12-01 23:55:08 +01:00
/***** Get plugin code *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetPlgCodFromAppKey (soap,(const char *) appKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2015-07-13 12:34:26 +02:00
/***** Check parameters used to create the new account *****/
2019-05-16 14:02:06 +02:00
Result = API_CheckParamsNewAccount (userNickname, // Input
2015-07-13 12:34:26 +02:00
NewNicknameWithoutArroba,// Output
userEmail, // Input-output
userPassword, // Input
NewEncryptedPassword); // Output
if (Result < 0)
{
createAccountOut->userCode = Result;
return SOAP_OK;
}
2014-12-01 23:55:08 +01:00
2015-07-13 12:34:26 +02:00
/***** User's has no ID *****/
Gbl.Usrs.Me.UsrDat.IDs.Num = 0;
Gbl.Usrs.Me.UsrDat.IDs.List = NULL;
2014-12-01 23:55:08 +01:00
2015-07-13 12:34:26 +02:00
/***** Set password to the password typed by the user *****/
2017-01-15 22:58:26 +01:00
Str_Copy (Gbl.Usrs.Me.UsrDat.Password,NewEncryptedPassword,
2017-03-13 14:22:36 +01:00
Pwd_BYTES_ENCRYPTED_PASSWORD);
2014-12-01 23:55:08 +01:00
2015-07-13 12:34:26 +02:00
/***** User does not exist in the platform, so create him/her! *****/
2016-11-08 00:58:32 +01:00
Acc_CreateNewUsr (&Gbl.Usrs.Me.UsrDat,
true); // I am creating my own account
2014-12-01 23:55:08 +01:00
2015-07-13 12:34:26 +02:00
/***** Save nickname *****/
2018-10-16 01:36:13 +02:00
Nck_UpdateNickInDB (Gbl.Usrs.Me.UsrDat.UsrCod,NewNicknameWithoutArroba);
2017-01-15 22:58:26 +01:00
Str_Copy (Gbl.Usrs.Me.UsrDat.Nickname,NewNicknameWithoutArroba,
2017-03-07 01:56:41 +01:00
Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA);
2014-12-01 23:55:08 +01:00
2016-11-16 23:19:52 +01:00
/***** Save email *****/
2015-07-13 12:34:26 +02:00
if (Mai_UpdateEmailInDB (&Gbl.Usrs.Me.UsrDat,userEmail))
{
2016-11-16 23:19:52 +01:00
/* Email updated sucessfully */
2017-01-17 03:10:43 +01:00
Str_Copy (Gbl.Usrs.Me.UsrDat.Email,userEmail,
2017-03-13 13:17:53 +01:00
Cns_MAX_BYTES_EMAIL_ADDRESS);
2015-07-13 12:34:26 +02:00
Gbl.Usrs.Me.UsrDat.EmailConfirmed = false;
}
2014-12-01 23:55:08 +01:00
2015-07-13 12:34:26 +02:00
/***** Copy new user's code *****/
createAccountOut->userCode = Gbl.Usrs.Me.UsrDat.UsrCod;
/***** Generate a key used in subsequents calls to other web services *****/
2020-02-24 19:31:55 +01:00
return API_GenerateNewWSKey (soap,
(long) createAccountOut->userCode,
2015-07-13 12:34:26 +02:00
createAccountOut->wsKey);
}
/*****************************************************************************/
/************* Get parameters for the creation of a new account **************/
/*****************************************************************************/
// Return false on error
//char *userNickname,char *userEmail,char *userID,char *userPassword
2019-05-16 14:02:06 +02:00
static int API_CheckParamsNewAccount (char *NewNicknameWithArroba, // Input
2017-01-17 03:10:43 +01:00
char NewNicknameWithoutArroba[Nck_MAX_BYTES_NICKNAME_FROM_FORM + 1], // Output
2015-07-13 12:34:26 +02:00
char *NewEmail, // Input-output
char *NewPlainPassword, // Input
char *NewEncryptedPassword) // Output
{
/***** Step 1/3: Check new nickname *****/
/* Make a copy without possible starting arrobas */
2017-01-15 18:02:52 +01:00
Str_Copy (NewNicknameWithoutArroba,NewNicknameWithArroba,
2017-01-17 03:10:43 +01:00
Nck_MAX_BYTES_NICKNAME_FROM_FORM);
2015-07-13 12:34:26 +02:00
if (Nck_CheckIfNickWithArrobaIsValid (NewNicknameWithArroba)) // If new nickname is valid
{
/***** Remove arrobas at the beginning *****/
Str_RemoveLeadingArrobas (NewNicknameWithoutArroba);
/***** Check if the new nickname matches any of the nicknames of other users *****/
2018-11-03 22:08:45 +01:00
if (DB_QueryCOUNT ("can not check if nickname already existed",
"SELECT COUNT(*) FROM usr_nicknames"
" WHERE Nickname='%s'",
NewNicknameWithoutArroba)) // A nickname of another user is the same that this nickname
2019-05-16 14:02:06 +02:00
return API_CHECK_NEW_ACCOUNT_NICKNAME_REGISTERED_BY_ANOTHER_USER;
2015-07-13 12:34:26 +02:00
}
else // New nickname is not valid
2019-05-16 14:02:06 +02:00
return API_CHECK_NEW_ACCOUNT_NICKNAME_NOT_VALID;
2015-07-13 12:34:26 +02:00
2016-11-16 23:19:52 +01:00
/***** Step 2/3: Check new email *****/
if (Mai_CheckIfEmailIsValid (NewEmail)) // New email is valid
2015-07-13 12:34:26 +02:00
{
2016-11-16 23:19:52 +01:00
/***** Check if the new email matches any of the confirmed emails of other users *****/
2018-11-03 22:08:45 +01:00
if (DB_QueryCOUNT ("can not check if email already existed",
"SELECT COUNT(*) FROM usr_emails"
" WHERE E_mail='%s' AND Confirmed='Y'",
NewEmail)) // An email of another user is the same that my email
2019-05-16 14:02:06 +02:00
return API_CHECK_NEW_ACCOUNT_EMAIL_REGISTERED_BY_ANOTHER_USER;
2015-07-13 12:34:26 +02:00
}
2016-11-16 23:19:52 +01:00
else // New email is not valid
2019-05-16 14:02:06 +02:00
return API_CHECK_NEW_ACCOUNT_EMAIL_NOT_VALID;
2015-07-13 12:34:26 +02:00
/***** Step 3/3: Check new password *****/
Cry_EncryptSHA512Base64 (NewPlainPassword,NewEncryptedPassword);
if (!Pwd_SlowCheckIfPasswordIsGood (NewPlainPassword,NewEncryptedPassword,-1L)) // New password is good?
2019-05-16 14:02:06 +02:00
return API_CHECK_NEW_ACCOUNT_PASSWORD_NOT_VALID;
2015-07-13 12:34:26 +02:00
2019-05-16 14:02:06 +02:00
return API_CHECK_NEW_ACCOUNT_OK;
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/****************** Login user by user, password and key *********************/
/*****************************************************************************/
int swad__loginByUserPasswordKey (struct soap *soap,
char *userID,char *userPassword,char *appKey, // input
struct swad__loginByUserPasswordKeyOutput *loginByUserPasswordKeyOut) // output
{
2017-03-13 13:17:53 +01:00
char UsrIDNickOrEmail[Cns_MAX_BYTES_EMAIL_ADDRESS + 1];
2014-12-01 23:55:08 +01:00
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRows;
2017-03-07 01:56:41 +01:00
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2016-07-20 20:24:16 +02:00
bool UsrFound;
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_loginByUserPasswordKey;
2014-12-01 23:55:08 +01:00
/***** Allocate space for strings *****/
2020-02-24 19:31:55 +01:00
loginByUserPasswordKeyOut->wsKey = (char *) soap_malloc (soap,API_BYTES_WS_KEY + 1);
loginByUserPasswordKeyOut->userNickname = (char *) soap_malloc (soap,Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA + 1);
loginByUserPasswordKeyOut->userID = (char *) soap_malloc (soap,ID_MAX_BYTES_USR_ID + 1);
loginByUserPasswordKeyOut->userFirstname = (char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
loginByUserPasswordKeyOut->userSurname1 = (char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
loginByUserPasswordKeyOut->userSurname2 = (char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
loginByUserPasswordKeyOut->userPhoto = (char *) soap_malloc (soap,Cns_MAX_BYTES_WWW + 1);
loginByUserPasswordKeyOut->userBirthday = (char *) soap_malloc (soap,Dat_LENGTH_YYYYMMDD + 1);
2014-12-01 23:55:08 +01:00
/***** Default values returned on error *****/
loginByUserPasswordKeyOut->userCode = -1;
loginByUserPasswordKeyOut->wsKey[0] = '\0';
loginByUserPasswordKeyOut->userNickname[0] = '\0';
loginByUserPasswordKeyOut->userID[0] = '\0';
loginByUserPasswordKeyOut->userFirstname[0] = '\0';
loginByUserPasswordKeyOut->userSurname1[0] = '\0';
loginByUserPasswordKeyOut->userSurname2[0] = '\0';
loginByUserPasswordKeyOut->userPhoto[0] = '\0';
loginByUserPasswordKeyOut->userBirthday[0] = '\0';
loginByUserPasswordKeyOut->userRole = 0; // unknown
/***** Get plugin code *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetPlgCodFromAppKey (soap,
(const char *) appKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2016-11-16 23:19:52 +01:00
/***** Check if user's email, @nickname or ID are valid *****/
2017-01-17 03:10:43 +01:00
Str_Copy (UsrIDNickOrEmail,userID,
2017-03-13 13:17:53 +01:00
Cns_MAX_BYTES_EMAIL_ADDRESS);
2014-12-01 23:55:08 +01:00
if (Nck_CheckIfNickWithArrobaIsValid (UsrIDNickOrEmail)) // 1: It's a nickname
{
Str_RemoveLeadingArrobas (UsrIDNickOrEmail);
/* User has typed a nickname */
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's data",
"SELECT usr_nicknames.UsrCod"
" FROM usr_nicknames,usr_data"
" WHERE usr_nicknames.Nickname='%s'"
" AND usr_nicknames.UsrCod=usr_data.UsrCod"
" AND usr_data.Password='%s'",
UsrIDNickOrEmail,userPassword);
2014-12-01 23:55:08 +01:00
}
2020-04-06 23:18:02 +02:00
else if (Mai_CheckIfEmailIsValid (UsrIDNickOrEmail)) // 2: It's an email
2014-12-01 23:55:08 +01:00
{
2016-11-16 23:19:52 +01:00
/* User has typed an email */
2014-12-01 23:55:08 +01:00
// TODO: Get only if email confirmed?
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's data",
"SELECT usr_emails.UsrCod"
" FROM usr_emails,usr_data"
" WHERE usr_emails.E_mail='%s'"
" AND usr_emails.UsrCod=usr_data.UsrCod"
" AND usr_data.Password='%s'",
UsrIDNickOrEmail,userPassword);
2014-12-01 23:55:08 +01:00
}
2016-11-16 23:19:52 +01:00
else // 3: It's not a nickname nor email
2014-12-01 23:55:08 +01:00
{
// Users' IDs are always stored internally in capitals and without leading zeros
Str_RemoveLeadingZeros (UsrIDNickOrEmail);
Str_ConvertToUpperText (UsrIDNickOrEmail);
if (ID_CheckIfUsrIDIsValid (UsrIDNickOrEmail))
{
/* User has typed a valid user's ID (existing or not) */
// TODO: Get only if ID confirmed?
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's data",
"SELECT usr_IDs.UsrCod"
" FROM usr_IDs,usr_data"
" WHERE usr_IDs.UsrID='%s'"
" AND usr_IDs.UsrCod=usr_data.UsrCod"
" AND usr_data.Password='%s'",
UsrIDNickOrEmail,userPassword);
2014-12-01 23:55:08 +01:00
}
2016-11-16 23:19:52 +01:00
else // String is not a valid user's nickname, email or ID
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad log in",
"User's ID or nickname don't exist or password is wrong");
}
/***** Get user's data from database *****/
2018-11-02 01:23:05 +01:00
if (NumRows == 1) // User found in table of users' data
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
/***** Get user code (row[0]) *****/
Gbl.Usrs.Me.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
2016-07-20 20:24:16 +02:00
/***** Get user's data *****/
2019-05-16 14:02:06 +02:00
UsrFound = API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,-1L); // Get some user's data from database
2016-07-20 20:24:16 +02:00
}
else
UsrFound = false;
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
if (UsrFound)
{
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
loginByUserPasswordKeyOut->userCode = (int) Gbl.Usrs.Me.UsrDat.UsrCod;
2014-12-01 23:55:08 +01:00
2017-01-15 18:02:52 +01:00
Str_Copy (loginByUserPasswordKeyOut->userNickname,
Gbl.Usrs.Me.UsrDat.Nickname,
2017-03-07 01:56:41 +01:00
Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA);
2014-12-01 23:55:08 +01:00
2016-07-24 12:17:03 +02:00
if (Gbl.Usrs.Me.UsrDat.IDs.Num)
2017-01-15 18:02:52 +01:00
Str_Copy (loginByUserPasswordKeyOut->userID,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.IDs.List[0].ID, // TODO: What user's ID?
2017-03-07 01:56:41 +01:00
ID_MAX_BYTES_USR_ID);
2014-12-01 23:55:08 +01:00
2017-01-15 18:02:52 +01:00
Str_Copy (loginByUserPasswordKeyOut->userSurname1,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.Surname1,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2017-01-15 18:02:52 +01:00
Str_Copy (loginByUserPasswordKeyOut->userSurname2,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.Surname2,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2017-01-15 18:02:52 +01:00
Str_Copy (loginByUserPasswordKeyOut->userFirstname,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.FirstName,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
Pho_BuildLinkToPhoto (&Gbl.Usrs.Me.UsrDat,PhotoURL);
2017-01-17 03:10:43 +01:00
Str_Copy (loginByUserPasswordKeyOut->userPhoto,PhotoURL,
2017-03-07 01:56:41 +01:00
Cns_MAX_BYTES_WWW);
2014-12-01 23:55:08 +01:00
2017-01-15 18:02:52 +01:00
Str_Copy (loginByUserPasswordKeyOut->userBirthday,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.Birthday.YYYYMMDD,
Dat_LENGTH_YYYYMMDD);
2016-07-20 20:24:16 +02:00
2019-05-16 14:02:06 +02:00
loginByUserPasswordKeyOut->userRole = API_RolRole_to_SvcRole[Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role];
2014-12-01 23:55:08 +01:00
/***** Generate a key used in subsequents calls to other web services *****/
2020-02-24 19:31:55 +01:00
return API_GenerateNewWSKey (soap,
(long) loginByUserPasswordKeyOut->userCode,
2015-07-13 12:34:26 +02:00
loginByUserPasswordKeyOut->wsKey);
2016-07-20 20:24:16 +02:00
}
2014-12-01 23:55:08 +01:00
else
2016-07-20 20:24:16 +02:00
{
loginByUserPasswordKeyOut->userCode = -1;
loginByUserPasswordKeyOut->userID = NULL;
loginByUserPasswordKeyOut->userSurname1 = NULL;
loginByUserPasswordKeyOut->userSurname2 = NULL;
loginByUserPasswordKeyOut->userFirstname = NULL;
loginByUserPasswordKeyOut->userPhoto = NULL;
loginByUserPasswordKeyOut->userRole = 0;
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad log in",
"User's ID or nickname don't exist or password is wrong");
2016-07-20 20:24:16 +02:00
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************** Login user by session ****************************/
/*****************************************************************************/
int swad__loginBySessionKey (struct soap *soap,
char *sessionID,char *appKey, // input
struct swad__loginBySessionKeyOutput *loginBySessionKeyOut) // output
{
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRows;
2017-03-07 01:56:41 +01:00
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2016-07-20 20:24:16 +02:00
bool UsrFound;
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_loginBySessionKey;
2014-12-01 23:55:08 +01:00
/***** Allocate space for strings *****/
2020-02-24 19:31:55 +01:00
loginBySessionKeyOut->wsKey = (char *) soap_malloc (soap,API_BYTES_WS_KEY + 1);
loginBySessionKeyOut->userNickname = (char *) soap_malloc (soap,Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA + 1);
loginBySessionKeyOut->userID = (char *) soap_malloc (soap,ID_MAX_BYTES_USR_ID + 1);
loginBySessionKeyOut->userFirstname = (char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
loginBySessionKeyOut->userSurname1 = (char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
loginBySessionKeyOut->userSurname2 = (char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
loginBySessionKeyOut->userPhoto = (char *) soap_malloc (soap,Cns_MAX_BYTES_WWW + 1);
loginBySessionKeyOut->userBirthday = (char *) soap_malloc (soap,Dat_LENGTH_YYYYMMDD + 1);
loginBySessionKeyOut->degreeName = (char *) soap_malloc (soap,Hie_MAX_BYTES_FULL_NAME + 1);
loginBySessionKeyOut->courseName = (char *) soap_malloc (soap,Hie_MAX_BYTES_FULL_NAME + 1);
2014-12-01 23:55:08 +01:00
/***** Default values returned on error *****/
loginBySessionKeyOut->userCode = -1;
loginBySessionKeyOut->degreeCode = -1;
loginBySessionKeyOut->courseCode = -1;
loginBySessionKeyOut->wsKey[0] = '\0';
loginBySessionKeyOut->userNickname[0] = '\0';
loginBySessionKeyOut->userID[0] = '\0';
loginBySessionKeyOut->userFirstname[0] = '\0';
loginBySessionKeyOut->userSurname1[0] = '\0';
loginBySessionKeyOut->userSurname2[0] = '\0';
loginBySessionKeyOut->userPhoto[0] = '\0';
loginBySessionKeyOut->userBirthday[0] = '\0';
2017-05-18 19:13:41 +02:00
loginBySessionKeyOut->userRole = Rol_UNK;
2014-12-01 23:55:08 +01:00
loginBySessionKeyOut->degreeName[0] = '\0';
loginBySessionKeyOut->courseName[0] = '\0';
/***** Get plugin code *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetPlgCodFromAppKey (soap,
(const char *) appKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Check length of session identifier *****/
if (sessionID == NULL)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"SessionID is null",
"Login by session");
/***** Check session identifier coming from an external plugin *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckIdSession (soap,sessionID)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
// Now, we know that sessionID is a valid session identifier
/***** Query data of the session from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get session data",
"SELECT UsrCod,DegCod,CrsCod FROM sessions"
" WHERE SessionId='%s'",
sessionID);
if (NumRows == 1) // Session found in table of sessions
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
/***** Get course (row[2]) *****/
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = Str_ConvertStrCodToLongCod (row[2]);
2020-01-05 14:09:28 +01:00
Crs_GetDataOfCourseByCod (&Gbl.Hierarchy.Crs);
2019-04-04 10:45:15 +02:00
loginBySessionKeyOut->courseCode = (int) Gbl.Hierarchy.Crs.CrsCod;
Str_Copy (loginBySessionKeyOut->courseName,Gbl.Hierarchy.Crs.FullName,
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_FULL_NAME);
2014-12-01 23:55:08 +01:00
/***** Get user code (row[0]) *****/
Gbl.Usrs.Me.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
2019-05-16 14:02:06 +02:00
UsrFound = API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod); // Get some user's data from database
2014-12-01 23:55:08 +01:00
/***** Get degree (row[1]) *****/
2019-04-03 20:57:04 +02:00
Gbl.Hierarchy.Deg.DegCod = Str_ConvertStrCodToLongCod (row[1]);
2020-01-05 12:52:03 +01:00
Deg_GetDataOfDegreeByCod (&Gbl.Hierarchy.Deg);
2019-04-03 20:57:04 +02:00
loginBySessionKeyOut->degreeCode = (int) Gbl.Hierarchy.Deg.DegCod;
Str_Copy (loginBySessionKeyOut->degreeName,Gbl.Hierarchy.Deg.FullName,
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_FULL_NAME);
2014-12-01 23:55:08 +01:00
}
2016-07-20 20:24:16 +02:00
else
UsrFound = false;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
/***** Get degree of current course *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2016-07-20 20:24:16 +02:00
if (UsrFound)
{
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2016-07-20 20:24:16 +02:00
loginBySessionKeyOut->userCode = (int) Gbl.Usrs.Me.UsrDat.UsrCod;
2017-01-15 18:02:52 +01:00
Str_Copy (loginBySessionKeyOut->userNickname,Gbl.Usrs.Me.UsrDat.Nickname,
2017-03-07 01:56:41 +01:00
Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA);
2016-07-20 20:24:16 +02:00
2016-07-24 12:17:03 +02:00
if (Gbl.Usrs.Me.UsrDat.IDs.Num)
2017-01-15 18:02:52 +01:00
Str_Copy (loginBySessionKeyOut->userID,
Gbl.Usrs.Me.UsrDat.IDs.List[0].ID, // TODO: What user's ID?
2017-03-07 01:56:41 +01:00
ID_MAX_BYTES_USR_ID);
2016-07-20 20:24:16 +02:00
2017-01-15 18:02:52 +01:00
Str_Copy (loginBySessionKeyOut->userSurname1,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.Surname1,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2017-01-15 18:02:52 +01:00
Str_Copy (loginBySessionKeyOut->userSurname2,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.Surname2,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2017-01-15 18:02:52 +01:00
Str_Copy (loginBySessionKeyOut->userFirstname,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.FirstName,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2016-07-20 20:24:16 +02:00
Pho_BuildLinkToPhoto (&Gbl.Usrs.Me.UsrDat,PhotoURL);
2017-01-17 03:10:43 +01:00
Str_Copy (loginBySessionKeyOut->userPhoto,PhotoURL,
2017-03-07 01:56:41 +01:00
Cns_MAX_BYTES_WWW);
2016-07-20 20:24:16 +02:00
2017-01-15 18:02:52 +01:00
Str_Copy (loginBySessionKeyOut->userBirthday,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Me.UsrDat.Birthday.YYYYMMDD,
Dat_LENGTH_YYYYMMDD);
2016-07-20 20:24:16 +02:00
2019-05-16 14:02:06 +02:00
loginBySessionKeyOut->userRole = API_RolRole_to_SvcRole[Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role];
2016-07-20 20:24:16 +02:00
2014-12-01 23:55:08 +01:00
/***** Generate a key used in subsequents calls to other web services *****/
2020-02-24 19:31:55 +01:00
return API_GenerateNewWSKey (soap,
(long) loginBySessionKeyOut->userCode,
2015-07-13 12:34:26 +02:00
loginBySessionKeyOut->wsKey);
2016-07-20 20:24:16 +02:00
}
2014-12-01 23:55:08 +01:00
else
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad session identifier",
"Session identifier does not exist in database");
}
/*****************************************************************************/
2016-11-16 23:19:52 +01:00
/*********************** Send a new password by email ************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
int swad__getNewPassword (struct soap *soap,
char *userID,char *appKey, // input
struct swad__getNewPasswordOutput *getNewPasswordOut) // output
{
int ReturnCode;
2017-03-13 13:17:53 +01:00
char UsrIDNickOrEmail[Cns_MAX_BYTES_EMAIL_ADDRESS + 1];
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRows;
2017-03-07 01:56:41 +01:00
char NewRandomPlainPassword[Pwd_MAX_BYTES_PLAIN_PASSWORD + 1];
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getNewPassword;
2014-12-01 23:55:08 +01:00
/***** Default values returned on error *****/
getNewPasswordOut->success = 0; // error
/***** Get plugin code *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetPlgCodFromAppKey (soap,
(const char *) appKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2016-11-16 23:19:52 +01:00
/***** Check if user's email, @nickname or ID are valid *****/
2017-01-17 03:10:43 +01:00
Str_Copy (UsrIDNickOrEmail,userID,
2017-03-13 13:17:53 +01:00
Cns_MAX_BYTES_EMAIL_ADDRESS);
2014-12-01 23:55:08 +01:00
if (Nck_CheckIfNickWithArrobaIsValid (UsrIDNickOrEmail)) // 1: It's a nickname
{
Str_RemoveLeadingArrobas (UsrIDNickOrEmail);
/* User has typed a nickname */
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's data",
"SELECT UsrCod FROM usr_nicknames"
" WHERE Nickname='%s'",
UsrIDNickOrEmail);
2014-12-01 23:55:08 +01:00
}
2016-11-16 23:19:52 +01:00
else if (Mai_CheckIfEmailIsValid (Gbl.Usrs.Me.UsrIdLogin)) // 2: It's an email
2014-12-01 23:55:08 +01:00
{
2016-11-16 23:19:52 +01:00
/* User has typed an email */
2014-12-01 23:55:08 +01:00
// TODO: Get only if email confirmed?
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's data",
"SELECT UsrCod FROM usr_emails"
" WHERE E_mail='%s'",
UsrIDNickOrEmail);
2014-12-01 23:55:08 +01:00
}
2016-11-16 23:19:52 +01:00
else // 3: It's not a nickname nor email
2014-12-01 23:55:08 +01:00
{
// Users' IDs are always stored internally in capitals and without leading zeros
Str_RemoveLeadingZeros (UsrIDNickOrEmail);
Str_ConvertToUpperText (UsrIDNickOrEmail);
if (ID_CheckIfUsrIDIsValid (UsrIDNickOrEmail))
{
/* User has typed a valid user's ID (existing or not) */
// TODO: Get only if ID confirmed?
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's data",
"SELECT UsrCod FROM usr_IDs"
" WHERE UsrID='%s'",
UsrIDNickOrEmail);
2014-12-01 23:55:08 +01:00
}
2016-11-16 23:19:52 +01:00
else // String is not a valid user's nickname, email or ID
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad log in",
2016-11-16 23:19:52 +01:00
"User's email, nickname or ID don't exist");
2014-12-01 23:55:08 +01:00
}
/***** Get user's data from database *****/
2018-11-02 01:23:05 +01:00
if (NumRows == 1) // One unique user found in table of users' data
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
/***** Get user code (row[0]) *****/
Gbl.Usrs.Me.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
2019-03-19 13:22:14 +01:00
Usr_GetUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Usr_DONT_GET_PREFS); // Get my data
2014-12-01 23:55:08 +01:00
if (Gbl.Usrs.Me.UsrDat.Email[0])
if (Pwd_SendNewPasswordByEmail (NewRandomPlainPassword) == 0) // Message sent successfully
{
Pwd_SetMyPendingPassword (NewRandomPlainPassword);
getNewPasswordOut->success = 1;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/************************ Return courses of a user ***************************/
/*****************************************************************************/
int swad__getCourses (struct soap *soap,
char *wsKey, // input
struct swad__getCoursesOutput *getCoursesOut) // output
{
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2017-01-15 18:02:52 +01:00
unsigned NumRow;
unsigned NumRows;
2014-12-01 23:55:08 +01:00
Rol_Role_t Role;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getCourses;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,-1L))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Query my courses from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's courses",
"SELECT courses.CrsCod,"
"courses.ShortName,"
"courses.FullName,"
"crs_usr.Role"
" FROM crs_usr,courses"
" WHERE crs_usr.UsrCod=%ld"
" AND crs_usr.CrsCod=courses.CrsCod"
" ORDER BY courses.FullName",
Gbl.Usrs.Me.UsrDat.UsrCod);
2014-12-01 23:55:08 +01:00
getCoursesOut->numCourses = (int) NumRows;
getCoursesOut->coursesArray.__size = (int) NumRows;
if (NumRows == 0)
getCoursesOut->coursesArray.__ptr = NULL;
else // Courses found
{
2020-02-24 19:31:55 +01:00
getCoursesOut->coursesArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getCoursesOut->coursesArray.__size) *
sizeof (*(getCoursesOut->coursesArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next course */
row = mysql_fetch_row (mysql_res);
/* Get course code (row[0]) */
getCoursesOut->coursesArray.__ptr[NumRow].courseCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get course short name (row[1]) */
2019-12-06 11:53:14 +01:00
getCoursesOut->coursesArray.__ptr[NumRow].courseShortName =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Hie_MAX_BYTES_SHRT_NAME + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getCoursesOut->coursesArray.__ptr[NumRow].courseShortName,row[1],
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_SHRT_NAME);
2014-12-01 23:55:08 +01:00
/* Get course full name (row[2]) */
2019-12-06 11:53:14 +01:00
getCoursesOut->coursesArray.__ptr[NumRow].courseFullName =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Hie_MAX_BYTES_FULL_NAME + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getCoursesOut->coursesArray.__ptr[NumRow].courseFullName,row[2],
2017-03-08 14:12:33 +01:00
Hie_MAX_BYTES_FULL_NAME);
2014-12-01 23:55:08 +01:00
/* Get role (row[3]) */
if (sscanf (row[3],"%u",&Role) != 1) // Role in this course
2017-05-18 19:13:41 +02:00
Role = Rol_UNK;
2019-05-16 14:02:06 +02:00
getCoursesOut->coursesArray.__ptr[NumRow].userRole = API_RolRole_to_SvcRole[Role];
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/************************ Return course information **************************/
/*****************************************************************************/
// TODO: Not completely implemented
int swad__getCourseInfo (struct soap *soap,
char *wsKey,int courseCode,char *infoType, // input
struct swad__getCourseInfoOutput *getCourseInfo) // output
{
int ReturnCode;
Inf_InfoType_t InfoType;
2017-01-15 22:58:26 +01:00
size_t Length;
2014-12-01 23:55:08 +01:00
Inf_InfoSrc_t InfoSrc;
bool MustBeRead;
int Result = SOAP_OK;
const char *NamesInWSForInfoType[Inf_NUM_INFO_TYPES] =
{
2019-12-15 01:10:36 +01:00
[Inf_INTRODUCTION ] = "introduction",
[Inf_TEACHING_GUIDE] = "guide",
[Inf_LECTURES ] = "lectures",
[Inf_PRACTICALS ] = "practicals",
[Inf_BIBLIOGRAPHY ] = "bibliography",
[Inf_FAQ ] = "FAQ",
[Inf_LINKS ] = "links",
[Inf_ASSESSMENT ] = "assessment",
2014-12-01 23:55:08 +01:00
};
const char *NamesInWSForInfoSrc[Inf_NUM_INFO_SOURCES] =
{
2019-12-15 01:10:36 +01:00
[Inf_INFO_SRC_NONE ] = "none",
[Inf_INFO_SRC_EDITOR ] = "editor",
[Inf_INFO_SRC_PLAIN_TEXT] = "plainText",
[Inf_INFO_SRC_RICH_TEXT ] = "richText",
[Inf_INFO_SRC_PAGE ] = "page",
[Inf_INFO_SRC_URL ] = "URL",
2014-12-01 23:55:08 +01:00
};
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getCourseInfo;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Check course and group codes *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckCourseAndGroupCodes (soap,
Gbl.Hierarchy.Crs.CrsCod,
-1L)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Get info source *****/
2019-12-15 01:10:36 +01:00
for (InfoType = (Inf_InfoType_t) 0;
InfoType <= (Inf_InfoType_t) (Inf_NUM_INFO_TYPES - 1);
2014-12-01 23:55:08 +01:00
InfoType++)
if (!strcmp (infoType,NamesInWSForInfoType[InfoType]))
break;
if (InfoType == Inf_NUM_INFO_TYPES) // Not found!
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad info type",
"Unknown requested info type");
2019-04-04 10:45:15 +02:00
Gbl.Crs.Info.Type = InfoType;
Inf_GetAndCheckInfoSrcFromDB (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,&InfoSrc,&MustBeRead);
2017-01-15 22:58:26 +01:00
Length = strlen (NamesInWSForInfoSrc[InfoSrc]);
2020-02-24 19:31:55 +01:00
getCourseInfo->infoSrc = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getCourseInfo->infoSrc,NamesInWSForInfoSrc[InfoSrc],
Length);
2014-12-01 23:55:08 +01:00
/***** Set paths *****/
2016-11-14 17:26:32 +01:00
Hie_InitHierarchy ();
2014-12-01 23:55:08 +01:00
/***** Get info text *****/
getCourseInfo->infoTxt = NULL;
switch (InfoSrc)
{
case Inf_INFO_SRC_NONE: // No info available
break;
case Inf_INFO_SRC_EDITOR: // Internal editor (only for syllabus)
2019-04-04 10:45:15 +02:00
switch (Gbl.Crs.Info.Type)
2014-12-01 23:55:08 +01:00
{
case Inf_LECTURES: // Syllabus (lectures)
case Inf_PRACTICALS: // Syllabys (practicals)
2020-02-24 19:31:55 +01:00
Result = API_WriteSyllabusIntoHTMLBuffer (soap,&(getCourseInfo->infoTxt));
2014-12-01 23:55:08 +01:00
break;
default:
break;
}
break;
case Inf_INFO_SRC_PLAIN_TEXT: // Plain text
case Inf_INFO_SRC_RICH_TEXT: // Rich text (not yet available)
2020-02-24 19:31:55 +01:00
Result = API_WritePlainTextIntoHTMLBuffer (soap,&(getCourseInfo->infoTxt));
2014-12-01 23:55:08 +01:00
break;
case Inf_INFO_SRC_PAGE: // Web page hosted in SWAD server
2020-02-24 19:31:55 +01:00
Result = API_WritePageIntoHTMLBuffer (soap,&(getCourseInfo->infoTxt));
2014-12-01 23:55:08 +01:00
break;
case Inf_INFO_SRC_URL: // Link to a web page
2020-02-24 19:31:55 +01:00
getCourseInfo->infoTxt = (char *) soap_malloc (soap,Cns_MAX_BYTES_WWW + 1);
2016-03-17 10:39:23 +01:00
Inf_WriteURLIntoTxtBuffer (getCourseInfo->infoTxt);
2014-12-01 23:55:08 +01:00
break;
}
/***** Return empty text if pointer is null *****/
if (getCourseInfo->infoTxt == NULL)
{
2020-02-24 19:31:55 +01:00
getCourseInfo->infoTxt = (char *) soap_malloc (soap,1);
2014-12-01 23:55:08 +01:00
getCourseInfo->infoTxt[0] = '\0';
}
return Result;
}
2020-02-24 19:31:55 +01:00
/*****************************************************************************/
/************** Write the syllabus into a temporary HTML file ****************/
/*****************************************************************************/
static int API_WriteSyllabusIntoHTMLBuffer (struct soap *soap,
char **HTMLBuffer)
{
extern struct LstItemsSyllabus Syl_LstItemsSyllabus;
char FileNameHTMLTmp[PATH_MAX + 1];
FILE *FileHTMLTmp;
size_t Length;
/***** Initialize buffer *****/
*HTMLBuffer = NULL;
/***** Load syllabus from XML file to list of items in memory *****/
Syl_LoadListItemsSyllabusIntoMemory (Gbl.Hierarchy.Crs.CrsCod);
if (Syl_LstItemsSyllabus.NumItems)
{
/***** Create a unique name for the file *****/
snprintf (FileNameHTMLTmp,sizeof (FileNameHTMLTmp),
"%s/%s_syllabus.html",
Cfg_PATH_OUT_PRIVATE,Gbl.UniqueNameEncrypted);
/***** Create a new temporary file for writing and reading *****/
if ((FileHTMLTmp = fopen (FileNameHTMLTmp,"w+b")) == NULL)
{
Syl_FreeListItemsSyllabus ();
return soap_receiver_fault (soap,
"Syllabus can not be copied into buffer",
"Can not create temporary file");
}
/***** Write syllabus in HTML into a temporary file *****/
Syl_WriteSyllabusIntoHTMLTmpFile (FileHTMLTmp);
/***** Write syllabus from list of items in memory to text buffer *****/
/* Compute length of file */
Length = (size_t) ftell (FileHTMLTmp);
/* Allocate memory for buffer */
if ((*HTMLBuffer = (char *) malloc (Length + 1)) == NULL)
{
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
Syl_FreeListItemsSyllabus ();
return soap_receiver_fault (soap,
"Syllabus can not be copied into buffer",
"Not enough memory for buffer");
}
/* Copy file content into buffer */
fseek (FileHTMLTmp,0L,SEEK_SET);
if (fread (*HTMLBuffer,sizeof (char),Length,FileHTMLTmp) != Length)
{
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
Syl_FreeListItemsSyllabus ();
return soap_receiver_fault (soap,
"Syllabus can not be copied into buffer",
"Error reading file into buffer");
}
(*HTMLBuffer)[Length] = '\0';
/***** Close and remove temporary file *****/
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
}
/***** Free list of items *****/
Syl_FreeListItemsSyllabus ();
return SOAP_OK;
}
/*****************************************************************************/
/************* Check if exists and write page into HTML buffer ***************/
/*****************************************************************************/
static int API_WritePlainTextIntoHTMLBuffer (struct soap *soap,
char **HTMLBuffer)
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1];
char FileNameHTMLTmp[PATH_MAX + 1];
FILE *FileHTMLTmp;
size_t Length;
/***** Initialize buffer *****/
*HTMLBuffer = NULL;
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,
TxtHTML,NULL);
if (TxtHTML[0])
{
/***** Create a unique name for the file *****/
snprintf (FileNameHTMLTmp,sizeof (FileNameHTMLTmp),
"%s/%s_info.html",
Cfg_PATH_OUT_PRIVATE,Gbl.UniqueNameEncrypted);
/***** Create a new temporary file for writing and reading *****/
if ((FileHTMLTmp = fopen (FileNameHTMLTmp,"w+b")) == NULL)
return soap_receiver_fault (soap,
"Plain text can not be copied into buffer",
"Can not create temporary file");
/***** Write start of HTML code *****/
Lay_StartHTMLFile (FileHTMLTmp,Txt_INFO_TITLE[Gbl.Crs.Info.Type]);
fprintf (FileHTMLTmp,"<body>\n"
"<div class=\"DAT LM\">\n");
/***** Write plain text into text buffer *****/
/* Convert to respectful HTML and insert links */
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
TxtHTML,Cns_MAX_BYTES_LONG_TEXT,false); // Convert from HTML to recpectful HTML
Str_InsertLinks (TxtHTML,Cns_MAX_BYTES_LONG_TEXT,60); // Insert links
/* Write text */
fprintf (FileHTMLTmp,"%s",TxtHTML);
/***** Write end of page into file *****/
fprintf (FileHTMLTmp,"</div>\n"
"</html>\n"
"</body>\n");
/***** Compute length of file *****/
Length = (size_t) ftell (FileHTMLTmp);
/***** Allocate memory for buffer *****/
if ((*HTMLBuffer = (char *) malloc (Length + 1)) == NULL)
{
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
return soap_receiver_fault (soap,
"Plain text can not be copied into buffer",
"Not enough memory for buffer");
}
/***** Copy file content into buffer *****/
fseek (FileHTMLTmp,0L,SEEK_SET);
if (fread (*HTMLBuffer,sizeof (char),Length,FileHTMLTmp) != Length)
{
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
return soap_receiver_fault (soap,
"Plain text can not be copied into buffer",
"Error reading file into buffer");
}
(*HTMLBuffer)[Length] = '\0';
/***** Close and remove temporary file *****/
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
}
return SOAP_OK;
}
/*****************************************************************************/
/************* Check if exists and write page into HTML buffer ***************/
/*****************************************************************************/
static int API_WritePageIntoHTMLBuffer (struct soap *soap,
char **HTMLBuffer)
{
char PathRelDirHTML[PATH_MAX + 1];
char PathRelFileHTML[PATH_MAX + 1 + 10 + 1];
FILE *FileHTML;
bool FileExists = false;
size_t Length;
/***** Initialize buffer *****/
*HTMLBuffer = NULL;
/***** Build path of directory containing web page *****/
Inf_BuildPathPage (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathRelDirHTML);
/***** Open file with web page *****/
/* 1. Check if index.html exists */
snprintf (PathRelFileHTML,sizeof (PathRelFileHTML),
"%s/index.html",
PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
FileExists = true;
else
{
/* 2. If index.html not exists, try index.htm */
snprintf (PathRelFileHTML,sizeof (PathRelFileHTML),
"%s/index.htm",
PathRelDirHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty?
FileExists = true;
}
if (FileExists)
{
/***** Write page from file to text buffer *****/
/* Open file */
if ((FileHTML = fopen (PathRelFileHTML,"rb")) == NULL)
Lay_ShowErrorAndExit ("Can not open XML file.");
/* Compute file size */
fseek (FileHTML,0L,SEEK_END);
Length = (size_t) ftell (FileHTML);
fseek (FileHTML,0L,SEEK_SET);
/* Allocate memory for buffer */
if ((*HTMLBuffer = (char *) malloc (Length + 1)) == NULL)
{
fclose (FileHTML);
Lay_NotEnoughMemoryExit ();
return soap_receiver_fault (soap,
"Web page can not be copied into buffer",
"Not enough memory for buffer");
}
/* Copy file content into buffer */
if (fread (*HTMLBuffer,sizeof (char),Length,FileHTML) != Length)
{
fclose (FileHTML);
return soap_receiver_fault (soap,
"Web page can not be copied into buffer",
"Error reading web page into buffer");
}
(*HTMLBuffer)[Length] = '\0';
/***** Close HTML file *****/
fclose (FileHTML);
}
return SOAP_OK;
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2016-06-29 18:27:49 +02:00
/************* Get users in a course (and optionally in groups) **************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
int swad__getUsers (struct soap *soap,
2016-06-29 18:27:49 +02:00
char *wsKey,int courseCode,char *groups,int userRole, // input
2014-12-01 23:55:08 +01:00
struct swad__getUsersOutput *getUsersOut) // output
{
int ReturnCode;
2016-06-29 18:27:49 +02:00
Rol_Role_t Role;
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getUsers;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (courseCode > 0) ? (long) courseCode :
2016-06-29 18:27:49 +02:00
-1L;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
2016-06-29 18:27:49 +02:00
/***** Check course *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckCourseAndGroupCodes (soap,
Gbl.Hierarchy.Crs.CrsCod,
-1L)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-06-29 18:27:49 +02:00
"Request forbidden",
"Requester must belong to course");
2014-12-01 23:55:08 +01:00
/***** Get degree of current course *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) // TODO: Is this necessary?
2014-12-01 23:55:08 +01:00
return ReturnCode;
2016-06-29 18:27:49 +02:00
/***** Check requested users' role *****/
2019-05-16 14:02:06 +02:00
if (userRole != API_ROLE_STUDENT && // Students
userRole != API_ROLE_TEACHER) // Teachers
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad requested users' type",
2016-06-29 18:27:49 +02:00
"User roles allowed are 2 (students) or 3 (teachers)");
2019-05-16 14:02:06 +02:00
Role = API_SvcRole_to_RolRole[userRole];
2016-06-29 18:27:49 +02:00
/***** Create a list of groups selected *****/
2019-05-16 14:02:06 +02:00
API_GetLstGrpsSel (groups);
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
2016-06-29 18:27:49 +02:00
/***** Get list of groups types and groups in current course *****/
Grp_GetListGrpTypesInThisCrs (Grp_ONLY_GROUP_TYPES_WITH_GROUPS);
/***** Get list of users *****/
2019-04-03 20:57:04 +02:00
Usr_GetListUsrs (Hie_CRS,Role);
2020-02-24 19:31:55 +01:00
API_CopyListUsers (soap,
Role,getUsersOut);
2016-06-29 18:27:49 +02:00
Usr_FreeUsrsList (Role);
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
2016-06-29 18:27:49 +02:00
{
/***** Free list of groups types and groups in current course *****/
Grp_FreeListGrpTypesAndGrps ();
/***** Free memory for list of selected groups *****/
Grp_FreeListCodSelectedGrps ();
}
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;
2017-03-07 11:03:05 +01:00
char SearchQuery[Sch_MAX_BYTES_SEARCH_QUERY + 1];
2016-06-29 18:27:49 +02:00
Rol_Role_t Role;
bool FilterTooShort = false;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_findUsers;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (courseCode > 0) ? (long) courseCode :
2016-06-29 18:27:49 +02:00
-1L;
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2016-06-29 18:27:49 +02:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-06-29 18:27:49 +02:00
"Bad web service key",
"Web service key does not exist in database");
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Level == Hie_CRS) // Course selected
2016-06-29 18:27:49 +02:00
/***** Check course *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckCourseAndGroupCodes (soap,
Gbl.Hierarchy.Crs.CrsCod,
-1L)) != SOAP_OK)
2016-06-29 18:27:49 +02:00
return ReturnCode;
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2016-06-29 18:27:49 +02:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2016-06-29 18:27:49 +02:00
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Level == Hie_CRS) // Course selected
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-06-29 18:27:49 +02:00
"Request forbidden",
"Requester must belong to course");
2019-04-03 20:57:04 +02:00
if (Gbl.Hierarchy.Level == Hie_CRS)
2016-06-29 18:27:49 +02:00
{
/***** Get degree of current course *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK) // TODO: Is this necessary?
2016-06-29 18:27:49 +02:00
return ReturnCode;
2014-12-01 23:55:08 +01:00
}
2016-06-29 18:27:49 +02:00
/***** Check requested users' role *****/
2019-05-16 14:02:06 +02:00
if (userRole < API_ROLE_UNKNOWN ||
userRole > API_ROLE_TEACHER)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2016-06-29 18:27:49 +02:00
"Bad requested users' type",
2016-07-04 10:26:44 +02:00
"User roles allowed are 0 (all), 1 (guests), 2 (students) or 3 (teachers)");
2019-05-16 14:02:06 +02:00
Role = API_SvcRole_to_RolRole[userRole];
2016-06-29 18:27:49 +02:00
2014-12-01 23:55:08 +01:00
/***** Query users beloging to course or group from database *****/
2017-01-17 03:10:43 +01:00
Str_Copy (Gbl.Search.Str,filter,
2017-03-07 11:03:05 +01:00
Sch_MAX_BYTES_STRING_TO_FIND);
2014-12-01 23:55:08 +01:00
2016-06-29 18:27:49 +02:00
if (Gbl.Search.Str[0]) // Search some users
2014-12-01 23:55:08 +01:00
{
2019-04-03 20:57:04 +02:00
Gbl.Scope.Current = (Gbl.Hierarchy.Level == Hie_CRS) ? Hie_CRS :
Hie_SYS;
2016-06-29 18:27:49 +02:00
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);
2014-12-01 23:55:08 +01:00
2016-06-29 18:27:49 +02:00
/***** Search for users *****/
Usr_SearchListUsrs (Role);
2020-02-24 19:31:55 +01:00
API_CopyListUsers (soap,
Role,getUsersOut);
2016-06-29 18:27:49 +02:00
Usr_FreeUsrsList (Role);
2014-12-01 23:55:08 +01:00
2016-06-29 18:27:49 +02:00
/***** Drop temporary table with candidate users *****/
Usr_DropTmpTableWithCandidateUsrs ();
2014-12-01 23:55:08 +01:00
}
2016-06-29 18:27:49 +02:00
else
FilterTooShort = true;
2014-12-01 23:55:08 +01:00
}
2016-06-29 18:27:49 +02:00
else
FilterTooShort = true;
2014-12-01 23:55:08 +01:00
2016-06-29 18:27:49 +02:00
/***** Return error in filter? *****/
if (FilterTooShort)
{
getUsersOut->numUsers = -1; // < 0 ==> filter too short
getUsersOut->usersArray.__size = 0;
getUsersOut->usersArray.__ptr = NULL;
}
2014-12-01 23:55:08 +01:00
return SOAP_OK;
}
2016-06-29 18:27:49 +02:00
/*****************************************************************************/
/***************************** Copy users from list **************************/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static void API_CopyListUsers (struct soap *soap,
Rol_Role_t Role,
struct swad__getUsersOutput *getUsersOut)
2016-06-29 18:27:49 +02:00
{
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;
2020-02-24 19:31:55 +01:00
getUsersOut->usersArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getUsersOut->usersArray.__size) *
sizeof (*(getUsersOut->usersArray.__ptr)));
2016-06-29 18:27:49 +02:00
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
/***** List data of users *****/
for (NumUsr = 0;
NumUsr < NumUsrs;
NumUsr++)
{
2016-07-26 12:48:52 +02:00
/* Copy user's basic data from list */
Usr_CopyBasicUsrDataFromList (&UsrDat,&Gbl.Usrs.LstUsrs[Role].Lst[NumUsr]);
2016-06-29 18:27:49 +02:00
2016-07-26 12:48:52 +02:00
/* Get list of user's IDs */
ID_GetListIDsFromUsrCod (&UsrDat);
2017-01-27 01:02:52 +01:00
ICanSeeUsrID = ID_ICanSeeOtherUsrIDs (&UsrDat);
2016-06-29 18:27:49 +02:00
2016-07-26 12:48:52 +02:00
/* Get nickname */
Nck_GetNicknameFromUsrCod (UsrDat.UsrCod,UsrDat.Nickname);
2016-06-29 18:27:49 +02:00
2016-07-26 12:48:52 +02:00
/* Copy user's data into output structure */
2020-02-24 19:31:55 +01:00
API_CopyUsrData (soap,
&(getUsersOut->usersArray.__ptr[NumUsr]),
&UsrDat,
ICanSeeUsrID);
2016-06-29 18:27:49 +02:00
}
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
}
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/********************** Return group types in a course ***********************/
/*****************************************************************************/
int swad__getGroupTypes (struct soap *soap,
char *wsKey,int courseCode, // input
struct swad__getGroupTypesOutput *getGroupTypesOut) // output
{
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2017-01-15 18:02:52 +01:00
unsigned NumRow;
unsigned NumRows;
2014-12-01 23:55:08 +01:00
long OpenTime;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getGroupTypes;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Open groups of this course that must be opened
if open time is in the past *****/
Grp_OpenGroupsAutomatically ();
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Query group types in a course from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get group types",
"SELECT GrpTypCod,"
"GrpTypName,"
"Mandatory,"
"Multiple,"
"UNIX_TIMESTAMP(OpenTime)"
" FROM crs_grp_types"
" WHERE CrsCod=%d"
" ORDER BY GrpTypName",
courseCode);
2014-12-01 23:55:08 +01:00
getGroupTypesOut->numGroupTypes = (int) NumRows;
getGroupTypesOut->groupTypesArray.__size = (int) NumRows;
if (NumRows == 0)
getGroupTypesOut->groupTypesArray.__ptr = NULL;
else // Groups found
{
2020-02-24 19:31:55 +01:00
getGroupTypesOut->groupTypesArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getGroupTypesOut->groupTypesArray.__size) *
sizeof (*(getGroupTypesOut->groupTypesArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
/* Get group type code (row[0]) */
getGroupTypesOut->groupTypesArray.__ptr[NumRow].groupTypeCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get group type name (row[1]) */
2019-12-06 11:53:14 +01:00
getGroupTypesOut->groupTypesArray.__ptr[NumRow].groupTypeName =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Grp_MAX_BYTES_GROUP_TYPE_NAME + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getGroupTypesOut->groupTypesArray.__ptr[NumRow].groupTypeName,row[1],
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME);
2014-12-01 23:55:08 +01:00
2017-03-30 11:20:06 +02:00
/* Get whether enrolment is mandatory ('Y') or voluntary ('N') (row[2]) */
2014-12-01 23:55:08 +01:00
getGroupTypesOut->groupTypesArray.__ptr[NumRow].mandatory = (row[2][0] == 'Y') ? 1 :
0;
2017-03-30 11:20:06 +02:00
/* Get whether user can enrol in multiple groups ('Y') or only in one group ('N') (row[3]) */
2014-12-01 23:55:08 +01:00
getGroupTypesOut->groupTypesArray.__ptr[NumRow].multiple = (row[3][0] == 'Y') ? 1 :
0;
/* Get time of opening (row[4]) */
OpenTime = 0L;
if (row[4])
sscanf (row[4],"%ld",&OpenTime);
getGroupTypesOut->groupTypesArray.__ptr[NumRow].openTime = OpenTime;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/************************** Return groups in a course ************************/
/*****************************************************************************/
int swad__getGroups (struct soap *soap,
char *wsKey,int courseCode, // input
struct swad__getGroupsOutput *getGroupsOut) // output
{
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRow,NumRows;
long GrpCod;
unsigned MaxStudents;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getGroups;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Open groups of this course that must be opened
if open time is in the past *****/
Grp_OpenGroupsAutomatically ();
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Query groups in a course from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's groups",
"SELECT crs_grp_types.GrpTypCod,"
"crs_grp_types.GrpTypName,"
"crs_grp.GrpCod,"
"crs_grp.GrpName,"
"crs_grp.MaxStudents,"
"crs_grp.Open,"
"crs_grp.FileZones"
" FROM crs_grp_types,crs_grp"
" WHERE crs_grp_types.CrsCod=%d"
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
" ORDER BY crs_grp_types.GrpTypName,"
"crs_grp.GrpName",
courseCode);
2014-12-01 23:55:08 +01:00
getGroupsOut->numGroups = (int) NumRows;
getGroupsOut->groupsArray.__size = (int) NumRows;
if (NumRows == 0)
getGroupsOut->groupsArray.__ptr = NULL;
else // Groups found
{
2020-02-24 19:31:55 +01:00
getGroupsOut->groupsArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getGroupsOut->groupsArray.__size) *
sizeof (*(getGroupsOut->groupsArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
/* Get group type code (row[0]) */
getGroupsOut->groupsArray.__ptr[NumRow].groupTypeCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get group type name (row[1]) */
2019-12-06 11:53:14 +01:00
getGroupsOut->groupsArray.__ptr[NumRow].groupTypeName =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Grp_MAX_BYTES_GROUP_TYPE_NAME + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getGroupsOut->groupsArray.__ptr[NumRow].groupTypeName,row[1],
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME);
2014-12-01 23:55:08 +01:00
/* Get group code (row[2]) */
GrpCod = Str_ConvertStrCodToLongCod (row[2]);
getGroupsOut->groupsArray.__ptr[NumRow].groupCode = (int) GrpCod;
/* Get group name (row[3]) */
2019-12-06 11:53:14 +01:00
getGroupsOut->groupsArray.__ptr[NumRow].groupName =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Grp_MAX_BYTES_GROUP_NAME + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getGroupsOut->groupsArray.__ptr[NumRow].groupName,row[3],
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME);
2014-12-01 23:55:08 +01:00
/* Get max number of students of group (row[4]) and number of current students */
MaxStudents = Grp_ConvertToNumMaxStdsGrp (row[4]);
getGroupsOut->groupsArray.__ptr[NumRow].maxStudents = (MaxStudents > Grp_MAX_STUDENTS_IN_A_GROUP) ? -1 :
(int) MaxStudents;
/* Get number of current students */
2017-05-30 21:43:05 +02:00
getGroupsOut->groupsArray.__ptr[NumRow].numStudents = (int) Grp_CountNumUsrsInGrp (Rol_STD,GrpCod);
2014-12-01 23:55:08 +01:00
/* Get whether group is open ('Y') or closed ('N') (row[5]) */
getGroupsOut->groupsArray.__ptr[NumRow].open = (row[5][0] == 'Y') ? 1 :
0;
/* Get whether group have file zones ('Y') or not ('N') (row[6]) */
getGroupsOut->groupsArray.__ptr[NumRow].fileZones = (row[6][0] == 'Y') ? 1 :
0;
/* Get whether I belong to this group or not */
getGroupsOut->groupsArray.__ptr[NumRow].member = Grp_GetIfIBelongToGrp (GrpCod) ? 1 :
0;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/************************* Send my groups in a course ************************/
/*****************************************************************************/
int swad__sendMyGroups (struct soap *soap,
char *wsKey,int courseCode,char *myGroups, // input
struct swad__sendMyGroupsOutput *SendMyGroupsOut) // output
{
int ReturnCode;
struct ListCodGrps LstGrpsIWant;
const char *Ptr;
2019-11-08 01:10:32 +01:00
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2014-12-01 23:55:08 +01:00
unsigned NumGrp;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2018-11-02 01:23:05 +01:00
unsigned NumRow;
unsigned NumRows;
2014-12-01 23:55:08 +01:00
long GrpCod;
unsigned MaxStudents;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_sendMyGroups;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Get the group codes which I want to join to *****/
LstGrpsIWant.NumGrps = 0;
2017-01-19 20:55:31 +01:00
LstGrpsIWant.GrpCods = NULL;
2014-12-01 23:55:08 +01:00
if (myGroups[0])
{
/***** Count number of desired groups *****/
for (NumGrp = 0, Ptr = myGroups;
*Ptr;
NumGrp++)
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2014-12-01 23:55:08 +01:00
LstGrpsIWant.NumGrps = NumGrp;
if (LstGrpsIWant.NumGrps) // If I have selected groups...
{
/***** Create a list of groups selected from myGroups *****/
2017-01-19 20:55:31 +01:00
if ((LstGrpsIWant.GrpCods = (long *) calloc (LstGrpsIWant.NumGrps,sizeof (long))) == NULL)
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
for (NumGrp = 0, Ptr = myGroups;
*Ptr;
NumGrp++)
{
/* Find next string in text until comma (leading and trailing spaces are removed) */
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2017-01-19 20:55:31 +01:00
LstGrpsIWant.GrpCods[NumGrp] = Str_ConvertStrCodToLongCod (LongStr);
2014-12-01 23:55:08 +01:00
}
}
}
/***** Change my groups *****/
SendMyGroupsOut->success = Grp_ChangeMyGrpsAtomically (&LstGrpsIWant);
/***** Free memory with the list of groups which I want to belong to *****/
Grp_FreeListCodGrp (&LstGrpsIWant);
/***** Query groups in a course from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's groups",
"SELECT crs_grp_types.GrpTypCod,"
"crs_grp_types.GrpTypName,"
"crs_grp.GrpCod,"
"crs_grp.GrpName,"
"crs_grp.MaxStudents,"
"crs_grp.Open,"
"crs_grp.FileZones"
" FROM crs_grp_types,crs_grp"
" WHERE crs_grp_types.CrsCod=%d"
" AND crs_grp_types.GrpTypCod=crs_grp.GrpTypCod"
" ORDER BY crs_grp_types.GrpTypName,crs_grp.GrpName",
courseCode);
2014-12-01 23:55:08 +01:00
SendMyGroupsOut->numGroups = (int) NumRows;
SendMyGroupsOut->groupsArray.__size = (int) NumRows;
if (NumRows == 0)
SendMyGroupsOut->groupsArray.__ptr = NULL;
else // Groups found
{
2020-02-24 19:31:55 +01:00
SendMyGroupsOut->groupsArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(SendMyGroupsOut->groupsArray.__size) *
sizeof (*(SendMyGroupsOut->groupsArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
/* Get group type code (row[0]) */
SendMyGroupsOut->groupsArray.__ptr[NumRow].groupTypeCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get group type name (row[1]) */
2019-12-06 11:53:14 +01:00
SendMyGroupsOut->groupsArray.__ptr[NumRow].groupTypeName =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Grp_MAX_BYTES_GROUP_TYPE_NAME + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (SendMyGroupsOut->groupsArray.__ptr[NumRow].groupTypeName,row[1],
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_TYPE_NAME);
2014-12-01 23:55:08 +01:00
/* Get group code (row[2]) */
GrpCod = Str_ConvertStrCodToLongCod (row[2]);
SendMyGroupsOut->groupsArray.__ptr[NumRow].groupCode = (int) GrpCod;
/* Get group name (row[3]) */
2019-12-06 11:53:14 +01:00
SendMyGroupsOut->groupsArray.__ptr[NumRow].groupName =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Grp_MAX_BYTES_GROUP_NAME + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (SendMyGroupsOut->groupsArray.__ptr[NumRow].groupName,row[3],
2017-03-07 11:03:05 +01:00
Grp_MAX_BYTES_GROUP_NAME);
2014-12-01 23:55:08 +01:00
/* Get max number of students of group (row[4]) and number of current students */
MaxStudents = Grp_ConvertToNumMaxStdsGrp (row[4]);
SendMyGroupsOut->groupsArray.__ptr[NumRow].maxStudents = (MaxStudents > Grp_MAX_STUDENTS_IN_A_GROUP) ? -1 :
(int) MaxStudents;
/* Get number of current students */
2017-05-30 21:43:05 +02:00
SendMyGroupsOut->groupsArray.__ptr[NumRow].numStudents = (int) Grp_CountNumUsrsInGrp (Rol_STD,GrpCod);
2014-12-01 23:55:08 +01:00
/* Get whether group is open ('Y') or closed ('N') (row[5]) */
SendMyGroupsOut->groupsArray.__ptr[NumRow].open = (row[5][0] == 'Y') ? 1 :
0;
/* Get whether group have file zones ('Y') or not ('N') (row[6]) */
SendMyGroupsOut->groupsArray.__ptr[NumRow].fileZones = (row[6][0] == 'Y') ? 1 :
0;
/* Get whether I belong to this group or not */
SendMyGroupsOut->groupsArray.__ptr[NumRow].member = Grp_GetIfIBelongToGrp (GrpCod) ? 1 :
0;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/*********** Copy data of a user from database to soap structure *************/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static void API_CopyUsrData (struct soap *soap,
struct swad__user *Usr,struct UsrData *UsrDat,
bool UsrIDIsVisible)
2014-12-01 23:55:08 +01:00
{
2017-03-07 01:56:41 +01:00
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2016-07-26 12:48:52 +02:00
const char *FirstID;
2017-01-15 22:58:26 +01:00
size_t Length;
2014-12-01 23:55:08 +01:00
/* Copy user's code */
Usr->userCode = UsrDat->UsrCod;
/* Copy user's nickname */
2017-01-15 22:58:26 +01:00
Length = strlen (UsrDat->Nickname);
2020-02-24 19:31:55 +01:00
Usr->userNickname = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (Usr->userNickname,UsrDat->Nickname,
Length);
2014-12-01 23:55:08 +01:00
2016-07-26 12:48:52 +02:00
/* Copy user's first ID */
2014-12-01 23:55:08 +01:00
if (UsrIDIsVisible && UsrDat->IDs.List)
2016-07-26 12:48:52 +02:00
FirstID = UsrDat->IDs.List[0].ID;
2014-12-01 23:55:08 +01:00
else // Hide user's ID
2016-07-26 12:48:52 +02:00
FirstID = "********";
2017-01-15 22:58:26 +01:00
Length = strlen (FirstID);
2020-02-24 19:31:55 +01:00
Usr->userID = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (Usr->userID,FirstID,
Length);
2014-12-01 23:55:08 +01:00
/* Copy user's surname1 */
2017-01-15 22:58:26 +01:00
Length = strlen (UsrDat->Surname1);
2020-02-24 19:31:55 +01:00
Usr->userSurname1 = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (Usr->userSurname1,UsrDat->Surname1,
Length);
2014-12-01 23:55:08 +01:00
/* Copy user's surname2 */
2017-01-15 22:58:26 +01:00
Length = strlen (UsrDat->Surname2);
2020-02-24 19:31:55 +01:00
Usr->userSurname2 = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (Usr->userSurname2,UsrDat->Surname2,
Length);
2014-12-01 23:55:08 +01:00
/* Copy user's first name */
2017-01-15 22:58:26 +01:00
Length = strlen (UsrDat->FirstName);
2020-02-24 19:31:55 +01:00
Usr->userFirstname = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (Usr->userFirstname,UsrDat->FirstName,
Length);
2014-12-01 23:55:08 +01:00
/* User's photo URL */
2016-07-08 12:43:48 +02:00
Pho_BuildLinkToPhoto (UsrDat,PhotoURL);
2017-01-15 22:58:26 +01:00
Length = strlen (PhotoURL);
2020-02-24 19:31:55 +01:00
Usr->userPhoto = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (Usr->userPhoto,PhotoURL,
Length);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/***************** Return list of attendance events in a course **************/
/*****************************************************************************/
int swad__getAttendanceEvents (struct soap *soap,
char *wsKey,int courseCode, // input
struct swad__getAttendanceEventsOutput *getAttendanceEventsOut) // output
{
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2018-11-02 01:23:05 +01:00
unsigned NumRows;
2014-12-01 23:55:08 +01:00
int NumAttEvent;
long AttCod;
2017-03-07 01:56:41 +01:00
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2014-12-01 23:55:08 +01:00
long StartTime;
long EndTime;
size_t Length;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getAttendanceEvents;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check if I am a teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must be a teacher");
/***** Query list of attendance events *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get attendance events",
"SELECT AttCod,Hidden,UsrCod,"
"UNIX_TIMESTAMP(StartTime) AS ST,"
"UNIX_TIMESTAMP(EndTime) AS ET,"
"CommentTchVisible,Title,Txt"
" FROM att_events"
" WHERE CrsCod=%d"
" ORDER BY ST DESC,ET DESC,Title DESC",
courseCode);
2014-12-01 23:55:08 +01:00
getAttendanceEventsOut->eventsArray.__size =
2018-11-02 01:23:05 +01:00
getAttendanceEventsOut->numEvents = (int) NumRows;
2014-12-01 23:55:08 +01:00
if (getAttendanceEventsOut->numEvents == 0)
getAttendanceEventsOut->eventsArray.__ptr = NULL;
else // Events found
{
2020-02-24 19:31:55 +01:00
getAttendanceEventsOut->eventsArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getAttendanceEventsOut->eventsArray.__size) *
sizeof (*(getAttendanceEventsOut->eventsArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumAttEvent = 0;
NumAttEvent < getAttendanceEventsOut->numEvents;
NumAttEvent++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
/* Get attendance event code (row[0]) */
AttCod = Str_ConvertStrCodToLongCod (row[0]);
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].attendanceEventCode = (int) AttCod;
2016-09-07 18:02:25 +02:00
/* Get whether the attendance event is hidden or not (row[1]) */
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].hidden = (row[1][0] == 'Y') ? 1 :
0;
/* Get user's code of the user who created the event (row[2]) */
Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[2]);
2019-05-16 14:02:06 +02:00
if (API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Gbl.Hierarchy.Crs.CrsCod)) // Get some user's data from database
2014-12-01 23:55:08 +01:00
{
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname1);
2019-12-06 11:53:14 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userSurname1 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userSurname1,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.Surname1,
Length);
2014-12-01 23:55:08 +01:00
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname2);
2019-12-06 11:53:14 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userSurname2 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userSurname2,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.Surname2,
Length);
2014-12-01 23:55:08 +01:00
Length = strlen (Gbl.Usrs.Other.UsrDat.FirstName);
2019-12-06 11:53:14 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userFirstname =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userFirstname,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.FirstName,
Length);
2014-12-01 23:55:08 +01:00
2016-07-08 12:43:48 +02:00
Pho_BuildLinkToPhoto (&Gbl.Usrs.Other.UsrDat,PhotoURL);
2014-12-01 23:55:08 +01:00
Length = strlen (PhotoURL);
2019-12-06 11:53:14 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userPhoto =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userPhoto,
2017-01-17 03:10:43 +01:00
PhotoURL,
Length);
2014-12-01 23:55:08 +01:00
}
else
{
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userSurname1 = NULL;
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userSurname2 = NULL;
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userFirstname = NULL;
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].userPhoto = NULL;
}
2016-09-07 18:02:25 +02:00
/* Get event start time (row[3]) */
2014-12-01 23:55:08 +01:00
StartTime = 0L;
2016-09-07 18:02:25 +02:00
if (row[3])
sscanf (row[3],"%ld",&StartTime);
2014-12-01 23:55:08 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].startTime = StartTime;
2016-09-07 18:02:25 +02:00
/* Get event end time (row[4]) */
2014-12-01 23:55:08 +01:00
EndTime = 0L;
2016-09-07 18:02:25 +02:00
if (row[4])
sscanf (row[4],"%ld",&EndTime);
2014-12-01 23:55:08 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].endTime = EndTime;
2016-09-07 18:02:25 +02:00
/* Get whether teachers comments are visible ('Y') or hidden ('N') (row[5]) */
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].commentsTeachersVisible = (row[5][0] == 'Y') ? 1 :
2014-12-01 23:55:08 +01:00
0;
2016-09-07 18:02:25 +02:00
/* Get title of the event (row[6]) */
Length = strlen (row[6]);
2019-12-06 11:53:14 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].title =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].title,row[6],
Length);
2014-12-01 23:55:08 +01:00
2016-09-07 18:02:25 +02:00
/* Get Txt (row[7]) */
Length = strlen (row[7]);
2019-12-06 11:53:14 +01:00
getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].text =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].text,row[7],
Length);
2014-12-01 23:55:08 +01:00
/* Get list of groups for this attendance event */
2020-02-24 19:31:55 +01:00
API_GetListGrpsInAttendanceEventFromDB (soap,
AttCod,
&(getAttendanceEventsOut->eventsArray.__ptr[NumAttEvent].groups));
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/**************** Get lists of groups of an attendance event *****************/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static void API_GetListGrpsInAttendanceEventFromDB (struct soap *soap,
long AttCod,char **ListGroups)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
long NumGrps;
long NumGrp;
long GrpCod;
2019-11-08 01:10:32 +01:00
char GrpCodStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2017-01-16 01:51:01 +01:00
size_t Length;
2014-12-01 23:55:08 +01:00
/***** Get list of groups *****/
2018-11-02 01:23:05 +01:00
NumGrps =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get groups"
" of an attendance event",
"SELECT GrpCod FROM att_grp WHERE AttCod=%ld",
AttCod);
if (NumGrps == 0)
2014-12-01 23:55:08 +01:00
*ListGroups = NULL;
else // Events found
{
2017-01-16 01:51:01 +01:00
Length = NumGrps * (10 + 1) - 1;
2020-02-24 19:31:55 +01:00
*ListGroups = soap_malloc (soap,Length + 1);
2017-01-17 16:39:38 +01:00
(*ListGroups)[0] = '\0';
2014-12-01 23:55:08 +01:00
for (NumGrp = 0;
NumGrp < NumGrps;
NumGrp++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
/* Get group code (row[0]) */
GrpCod = Str_ConvertStrCodToLongCod (row[0]);
2018-10-18 02:02:32 +02:00
snprintf (GrpCodStr,sizeof (GrpCodStr),
NumGrp ? ",%ld" :
"%ld",
GrpCod);
2017-01-17 03:33:05 +01:00
Str_Concat (*ListGroups,GrpCodStr,
Length);
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
/*****************************************************************************/
/****************** Send the data of an attendance event *********************/
/*****************************************************************************/
int swad__sendAttendanceEvent (struct soap *soap,
char *wsKey,int attendanceEventCode,int courseCode,int hidden,
int startTime,int endTime,int commentsTeachersVisible,
char *title,char *text,char *groups, // input
struct swad__sendAttendanceEventOutput *sendAttendanceEventOut) // output
{
int ReturnCode;
2020-04-06 16:00:06 +02:00
struct Att_Event Event;
2014-12-01 23:55:08 +01:00
bool ItsANewAttEvent;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_sendAttendanceEvent;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check if I am a teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must be a teacher");
/**** Get data of attendance event *****/
/* Event code */
2020-04-06 16:00:06 +02:00
Event.AttCod = (long) attendanceEventCode;
2014-12-01 23:55:08 +01:00
/* Course code */
2020-04-06 16:00:06 +02:00
if (Event.AttCod > 0) // The event already exists
2014-12-01 23:55:08 +01:00
{
2020-04-06 16:00:06 +02:00
Att_GetDataOfAttEventByCod (&Event);
if (Event.CrsCod != (long) courseCode)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Attendance event does not belong to course");
ItsANewAttEvent = false;
}
else
{
ItsANewAttEvent = true;
2020-04-06 16:00:06 +02:00
Event.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
}
/* Is event hidden? */
2020-04-06 16:00:06 +02:00
Event.Hidden = (hidden ? true :
2014-12-01 23:55:08 +01:00
false);
/* User's code (really not used) */
2020-04-06 16:00:06 +02:00
Event.UsrCod = Gbl.Usrs.Me.UsrDat.UsrCod;
2014-12-01 23:55:08 +01:00
/* startTime */
2020-04-06 16:00:06 +02:00
Event.TimeUTC[Att_START_TIME] = (time_t) startTime;
2014-12-01 23:55:08 +01:00
/* endTime */
2020-04-06 16:00:06 +02:00
Event.TimeUTC[Att_END_TIME ] = (time_t) endTime;
2014-12-01 23:55:08 +01:00
/* Are teacher's comments visible? */
2020-04-06 16:00:06 +02:00
Event.CommentTchVisible = (commentsTeachersVisible ? true :
2014-12-01 23:55:08 +01:00
false);
/* Title */
2016-09-07 18:02:25 +02:00
if (!title[0])
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-09-07 18:02:25 +02:00
"Request forbidden",
"Title of attendance event is empty");
2020-04-06 16:00:06 +02:00
Str_Copy (Event.Title,title,
2017-03-07 01:56:41 +01:00
Att_MAX_BYTES_ATTENDANCE_EVENT_TITLE);
2014-12-01 23:55:08 +01:00
2016-06-29 18:27:49 +02:00
/* Create a list of groups selected */
2019-05-16 14:02:06 +02:00
API_GetLstGrpsSel (groups);
2016-06-29 18:27:49 +02:00
/***** Create or update attendance event *****/
if (ItsANewAttEvent)
2020-04-06 16:00:06 +02:00
Att_CreateAttEvent (&Event,text); // Add new attendance event to database
2016-06-29 18:27:49 +02:00
else
2020-04-06 16:00:06 +02:00
Att_UpdateAttEvent (&Event,text); // Modify existing attendance event
2016-06-29 18:27:49 +02:00
/***** Free memory for list of selected groups *****/
Grp_FreeListCodSelectedGrps ();
2020-04-06 16:00:06 +02:00
sendAttendanceEventOut->attendanceEventCode = Event.AttCod;
2016-06-29 18:27:49 +02:00
return SOAP_OK;
}
2016-09-06 18:29:13 +02:00
/*****************************************************************************/
/************************ Remove an attendance event *************************/
/*****************************************************************************/
int swad__removeAttendanceEvent (struct soap *soap,
char *wsKey,int attendanceEventCode, // input
2016-09-19 21:42:35 +02:00
struct swad__removeAttendanceEventOutput *removeAttendanceEventOut) // output
2016-09-06 18:29:13 +02:00
{
int ReturnCode;
2020-04-06 16:00:06 +02:00
struct Att_Event Event;
2016-09-06 18:29:13 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_removeAttendanceEvent;
2016-09-19 21:42:35 +02:00
removeAttendanceEventOut->attendanceEventCode = 0;
2016-09-06 18:29:13 +02:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2016-09-06 18:29:13 +02:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-09-06 18:29:13 +02:00
"Bad web service key",
"Web service key does not exist in database");
/**** Get data of attendance event *****/
/* Event code */
2020-04-06 16:00:06 +02:00
Event.AttCod = (long) attendanceEventCode;
2016-09-06 18:29:13 +02:00
/* Course code */
2020-04-06 16:00:06 +02:00
if (Event.AttCod > 0) // The event already exists
2016-09-06 18:29:13 +02:00
{
2020-04-06 16:00:06 +02:00
Att_GetDataOfAttEventByCod (&Event);
Gbl.Hierarchy.Crs.CrsCod = Event.CrsCod;
2016-09-06 18:29:13 +02:00
}
else
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-09-06 18:29:13 +02:00
"Request forbidden",
"Attendance event does not exist");
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2016-09-06 18:29:13 +02:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-09-06 18:29:13 +02:00
"Can not get user's data from database",
"User does not exist in database");
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2016-09-06 18:29:13 +02:00
/***** Check if I am a teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-09-06 18:29:13 +02:00
"Request forbidden",
"Requester must be a teacher");
/***** Remove the attendance event from database *****/
2020-04-06 16:00:06 +02:00
Att_RemoveAttEventFromDB (Event.AttCod);
2016-09-06 18:29:13 +02:00
2020-04-06 16:00:06 +02:00
removeAttendanceEventOut->attendanceEventCode = Event.AttCod;
2016-09-06 18:29:13 +02:00
return SOAP_OK;
}
2016-06-29 18:27:49 +02:00
/*****************************************************************************/
/********************** Create a list of groups selected *********************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
static void API_GetLstGrpsSel (const char *Groups)
2016-06-29 18:27:49 +02:00
{
const char *Ptr;
2019-11-08 01:10:32 +01:00
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2016-06-29 18:27:49 +02:00
unsigned NumGrp;
2014-12-01 23:55:08 +01:00
/***** Count number of groups *****/
2016-06-29 18:27:49 +02:00
for (Ptr = Groups, NumGrp = 0;
2014-12-01 23:55:08 +01:00
*Ptr;
NumGrp++)
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2019-04-04 10:45:15 +02:00
Gbl.Crs.Grps.LstGrpsSel.NumGrps = NumGrp;
2014-12-01 23:55:08 +01:00
/***** Create a list of groups selected *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.LstGrpsSel.NumGrps)
2014-12-01 23:55:08 +01:00
{
// Here NestedCalls is always 0
2019-04-04 10:45:15 +02:00
Gbl.Crs.Grps.LstGrpsSel.NestedCalls++;
2014-12-01 23:55:08 +01:00
// Here NestedCalls is always 1
2019-04-04 10:45:15 +02:00
if ((Gbl.Crs.Grps.LstGrpsSel.GrpCods = (long *) calloc (Gbl.Crs.Grps.LstGrpsSel.NumGrps,sizeof (long))) == NULL)
2018-10-18 20:06:54 +02:00
Lay_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
2016-06-29 18:27:49 +02:00
for (Ptr = Groups, NumGrp = 0;
2014-12-01 23:55:08 +01:00
*Ptr;
)
{
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2019-04-04 10:45:15 +02:00
Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrp] = Str_ConvertStrCodToLongCod (LongStr);
if (Grp_CheckIfGroupBelongsToCourse (Gbl.Crs.Grps.LstGrpsSel.GrpCods[NumGrp],Gbl.Hierarchy.Crs.CrsCod))
2014-12-01 23:55:08 +01:00
NumGrp++;
}
2019-04-04 10:45:15 +02:00
Gbl.Crs.Grps.LstGrpsSel.NumGrps = NumGrp; // Update number of groups
2014-12-01 23:55:08 +01:00
}
}
/*****************************************************************************/
/*********** Return a list with the users in an attendance event *************/
/*****************************************************************************/
int swad__getAttendanceUsers (struct soap *soap,
char *wsKey,int attendanceEventCode, // input
struct swad__getAttendanceUsersOutput *getAttendanceUsersOut) // output
{
int ReturnCode;
2020-04-06 16:00:06 +02:00
struct Att_Event Event;
2014-12-01 23:55:08 +01:00
char SubQuery[512];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRow,NumRows;
2017-03-07 01:56:41 +01:00
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2014-12-01 23:55:08 +01:00
size_t Length;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getAttendanceUsers;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get course of this attendance event *****/
2020-04-06 16:00:06 +02:00
Event.AttCod = (long) attendanceEventCode;
Att_GetDataOfAttEventByCod (&Event);
Gbl.Hierarchy.Crs.CrsCod = Event.CrsCod;
2014-12-01 23:55:08 +01:00
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check if I am a teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must be a teacher");
/***** Query list of attendance users *****/
2020-04-06 16:00:06 +02:00
if (Att_CheckIfAttEventIsAssociatedToGrps (Event.AttCod))
2014-12-01 23:55:08 +01:00
// Event for one or more groups
// Subquery: list of users in groups of this attendance event...
// ...who have no entry in attendance list of users
sprintf (SubQuery,"SELECT DISTINCT crs_grp_usr.UsrCod AS UsrCod,'N' AS Present"
" FROM att_grp,crs_grp,crs_grp_types,crs_usr,crs_grp_usr"
2017-03-24 01:09:27 +01:00
" WHERE att_grp.AttCod=%ld"
2014-12-01 23:55:08 +01:00
" AND att_grp.GrpCod=crs_grp.GrpCod"
" AND crs_grp.GrpTypCod=crs_grp_types.GrpTypCod"
" AND crs_grp_types.CrsCod=crs_usr.CrsCod"
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u"
2014-12-01 23:55:08 +01:00
" AND crs_usr.UsrCod=crs_grp_usr.UsrCod"
" AND crs_grp_usr.GrpCod=att_grp.GrpCod"
" AND crs_grp_usr.UsrCod NOT IN"
2017-03-24 01:09:27 +01:00
" (SELECT UsrCod FROM att_usr WHERE AttCod=%ld)",
2020-04-06 16:00:06 +02:00
Event.AttCod,
2017-05-18 19:13:41 +02:00
(unsigned) Rol_STD,
2020-04-06 16:00:06 +02:00
Event.AttCod);
2014-12-01 23:55:08 +01:00
else
// Event for the whole course
// Subquery: list of users in the course of this attendance event...
// ...who have no entry in attendance list of users
sprintf (SubQuery,"SELECT crs_usr.UsrCod AS UsrCod,'N' AS Present"
" FROM att_events,crs_usr"
2017-03-24 01:09:27 +01:00
" WHERE att_events.AttCod=%ld"
2014-12-01 23:55:08 +01:00
" AND att_events.CrsCod=crs_usr.CrsCod"
2017-03-24 01:09:27 +01:00
" AND crs_usr.Role=%u"
2014-12-01 23:55:08 +01:00
" AND crs_usr.UsrCod NOT IN"
2017-03-24 01:09:27 +01:00
" (SELECT UsrCod FROM att_usr WHERE AttCod=%ld)",
2020-04-06 16:00:06 +02:00
Event.AttCod,
2017-05-18 19:13:41 +02:00
(unsigned) Rol_STD,
2020-04-06 16:00:06 +02:00
Event.AttCod);
2014-12-01 23:55:08 +01:00
// Query: list of users in attendance list + rest of users (subquery)
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get users"
" in an attendance event",
"SELECT u.UsrCod,u.Present FROM "
"(SELECT UsrCod,Present"
" FROM att_usr WHERE AttCod=%ld"
" UNION %s) AS u,usr_data"
" WHERE u.UsrCod=usr_data.UsrCod"
" ORDER BY usr_data.Surname1,"
"usr_data.Surname2,"
"usr_data.FirstName",
(long) attendanceEventCode,SubQuery);
2014-12-01 23:55:08 +01:00
getAttendanceUsersOut->numUsers = (int) NumRows;
getAttendanceUsersOut->usersArray.__size = (int) NumRows;
if (NumRows == 0)
getAttendanceUsersOut->usersArray.__ptr = NULL;
else // Events found
{
2020-02-24 19:31:55 +01:00
getAttendanceUsersOut->usersArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getAttendanceUsersOut->usersArray.__size) *
sizeof (*(getAttendanceUsersOut->usersArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next user */
row = mysql_fetch_row (mysql_res);
/* Get user's code (row[0]) */
Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[0]);
getAttendanceUsersOut->usersArray.__ptr[NumRow].userCode = (int) Gbl.Usrs.Other.UsrDat.UsrCod;
/* Get user's data */
2019-05-16 14:02:06 +02:00
if (API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,-1L)) // Get some user's data from database
2014-12-01 23:55:08 +01:00
{
Length = strlen (Gbl.Usrs.Other.UsrDat.Nickname);
2019-12-06 11:53:14 +01:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userNickname =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceUsersOut->usersArray.__ptr[NumRow].userNickname,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.Nickname,
Length);
2014-12-01 23:55:08 +01:00
2016-07-24 12:17:03 +02:00
if (Gbl.Usrs.Other.UsrDat.IDs.Num)
{
Length = strlen (Gbl.Usrs.Other.UsrDat.IDs.List[0].ID); // TODO: What user's ID?
2019-12-06 11:53:14 +01:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userID =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceUsersOut->usersArray.__ptr[NumRow].userID,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.IDs.List[0].ID,
Length);
2016-07-24 12:17:03 +02:00
}
else
{
2019-12-06 11:53:14 +01:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userID =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,1);
2016-07-24 12:17:03 +02:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userID[0] = '\0';
}
2014-12-01 23:55:08 +01:00
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname1);
2019-12-06 11:53:14 +01:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userSurname1 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceUsersOut->usersArray.__ptr[NumRow].userSurname1,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.Surname1,
Length);
2014-12-01 23:55:08 +01:00
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname2);
2019-12-06 11:53:14 +01:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userSurname2 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceUsersOut->usersArray.__ptr[NumRow].userSurname2,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.Surname2,
Length);
2014-12-01 23:55:08 +01:00
Length = strlen (Gbl.Usrs.Other.UsrDat.FirstName);
2019-12-06 11:53:14 +01:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userFirstname =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceUsersOut->usersArray.__ptr[NumRow].userFirstname,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.FirstName,
Length);
2014-12-01 23:55:08 +01:00
2016-07-08 12:43:48 +02:00
Pho_BuildLinkToPhoto (&Gbl.Usrs.Other.UsrDat,PhotoURL);
2014-12-01 23:55:08 +01:00
Length = strlen (PhotoURL);
2019-12-06 11:53:14 +01:00
getAttendanceUsersOut->usersArray.__ptr[NumRow].userPhoto =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getAttendanceUsersOut->usersArray.__ptr[NumRow].userPhoto,
2017-01-17 03:10:43 +01:00
PhotoURL,
Length);
2014-12-01 23:55:08 +01:00
}
else
{
getAttendanceUsersOut->usersArray.__ptr[NumRow].userNickname = NULL;
getAttendanceUsersOut->usersArray.__ptr[NumRow].userID = NULL;
getAttendanceUsersOut->usersArray.__ptr[NumRow].userSurname1 = NULL;
getAttendanceUsersOut->usersArray.__ptr[NumRow].userSurname2 = NULL;
getAttendanceUsersOut->usersArray.__ptr[NumRow].userFirstname = NULL;
getAttendanceUsersOut->usersArray.__ptr[NumRow].userPhoto = NULL;
}
/* Get if user is present or not (row[1]) */
getAttendanceUsersOut->usersArray.__ptr[NumRow].present = (row[1][0] == 'Y') ? 1 :
0;
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/************ Send a list with the users in an attendance event **************/
/*****************************************************************************/
int swad__sendAttendanceUsers (struct soap *soap,
char *wsKey,int attendanceEventCode,
char *users,int setOthersAsAbsent, // input
struct swad__sendAttendanceUsersOutput *sendAttendanceUsersOut) // output
{
int ReturnCode;
2020-04-06 16:00:06 +02:00
struct Att_Event Event;
2014-12-01 23:55:08 +01:00
const char *Ptr;
2019-11-08 01:10:32 +01:00
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2017-06-08 15:32:33 +02:00
struct UsrData UsrDat;
2014-12-01 23:55:08 +01:00
unsigned NumCodsInList;
2018-11-04 20:51:38 +01:00
char *SubQueryAllUsrs = NULL;
2019-11-08 01:10:32 +01:00
char SubQueryOneUsr[1 + Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2017-01-16 01:51:01 +01:00
size_t Length = 0; // Initialized to avoid warning
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_sendAttendanceUsers;
2014-12-01 23:55:08 +01:00
/***** Initialize output *****/
sendAttendanceUsersOut->success = 0;
sendAttendanceUsersOut->numUsers = 0;
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get course of this attendance event *****/
2020-04-06 16:00:06 +02:00
Event.AttCod = (long) attendanceEventCode;
if (!Att_GetDataOfAttEventByCod (&Event))
2014-12-01 23:55:08 +01:00
return SOAP_OK; // return with success = 0
2020-04-06 16:00:06 +02:00
Gbl.Hierarchy.Crs.CrsCod = Event.CrsCod;
2014-12-01 23:55:08 +01:00
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check if I am a teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must be a teacher");
2017-06-08 15:32:33 +02:00
/***** Initialize structure with user's data *****/
Usr_UsrDataConstructor (&UsrDat);
2014-12-01 23:55:08 +01:00
if (setOthersAsAbsent)
{
/* Count number of codes in list */
for (Ptr = users, NumCodsInList = 0;
*Ptr;
NumCodsInList++)
/* Find next string in text until comma (leading and trailing spaces are removed) */
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2014-12-01 23:55:08 +01:00
2018-11-04 20:51:38 +01:00
/* Allocate subquery used to mark not present users as absent */
2019-11-08 01:10:32 +01:00
Length = 256 + NumCodsInList * (1 + Cns_MAX_DECIMAL_DIGITS_LONG + 1) - 1;
2018-11-04 20:51:38 +01:00
if ((SubQueryAllUsrs = (char *) malloc (Length + 1)) == NULL)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Not enough memory",
"Not enough memory to store list of users");
2018-11-04 20:51:38 +01:00
SubQueryAllUsrs[0] = '\0';
2014-12-01 23:55:08 +01:00
}
for (Ptr = users;
*Ptr;
)
{
/* Find next string in text until comma (leading and trailing spaces are removed) */
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2017-06-08 15:32:33 +02:00
if ((UsrDat.UsrCod = Str_ConvertStrCodToLongCod (LongStr)) > 0)
if (Usr_ChkIfUsrCodExists (UsrDat.UsrCod))
2014-12-01 23:55:08 +01:00
// The user must belong to course,
// but it's not necessary he/she belongs to groups associated to the event
2017-06-09 15:04:02 +02:00
if (Usr_CheckIfUsrBelongsToCurrentCrs (&UsrDat))
2014-12-01 23:55:08 +01:00
{
/* Mark user as present */
2020-04-06 16:00:06 +02:00
Att_RegUsrInAttEventNotChangingComments (Event.AttCod,UsrDat.UsrCod);
2014-12-01 23:55:08 +01:00
/* Add this user to query used to mark not present users as absent */
if (setOthersAsAbsent)
{
2018-11-04 20:51:38 +01:00
if (sendAttendanceUsersOut->numUsers)
{
snprintf (SubQueryOneUsr,sizeof (SubQueryOneUsr),
",%ld",UsrDat.UsrCod);
Str_Concat (SubQueryAllUsrs,SubQueryOneUsr,
Length);
}
else
snprintf (SubQueryAllUsrs,Length,
" AND UsrCod NOT IN (%ld",
UsrDat.UsrCod);
2014-12-01 23:55:08 +01:00
}
sendAttendanceUsersOut->numUsers++;
}
}
if (setOthersAsAbsent)
{
/* Mark not present users as absent in table of users */
if (sendAttendanceUsersOut->numUsers)
2018-11-04 20:51:38 +01:00
Str_Concat (SubQueryAllUsrs,")",
2017-01-17 03:33:05 +01:00
Length);
2014-12-01 23:55:08 +01:00
2018-11-04 20:51:38 +01:00
DB_QueryUPDATE ("can not set other users as absent",
"UPDATE att_usr SET Present='N'"
" WHERE AttCod=%ld%s",
2020-04-06 16:00:06 +02:00
Event.AttCod,SubQueryAllUsrs);
2014-12-01 23:55:08 +01:00
2018-11-04 21:28:11 +01:00
/* Free memory for subquery string */
2019-11-06 19:45:20 +01:00
free (SubQueryAllUsrs);
2018-11-04 21:28:11 +01:00
2014-12-01 23:55:08 +01:00
/* Clean table att_usr */
2020-04-06 16:00:06 +02:00
Att_RemoveUsrsAbsentWithoutCommentsFromAttEvent (Event.AttCod);
2014-12-01 23:55:08 +01:00
}
2017-06-08 15:32:33 +02:00
/***** Free memory used for user's data *****/
Usr_UsrDataDestructor (&UsrDat);
2014-12-01 23:55:08 +01:00
sendAttendanceUsersOut->success = 1;
return SOAP_OK;
}
/*****************************************************************************/
/********************* Return notifications of a user ************************/
/*****************************************************************************/
int swad__getNotifications (struct soap *soap,
char *wsKey,long beginTime, // input
struct swad__getNotificationsOutput *getNotificationsOut) // output
{
extern const char *Ntf_WSNotifyEvents[Ntf_NUM_NOTIFY_EVENTS];
extern const char *Txt_Forum;
extern const char *Txt_Course;
extern const char *Txt_Degree;
extern const char *Txt_Centre;
extern const char *Txt_Institution;
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2016-07-20 20:24:16 +02:00
unsigned NumNotifications;
unsigned NumNotif;
2014-12-01 23:55:08 +01:00
long NtfCod;
Ntf_NotifyEvent_t NotifyEvent;
long EventTime;
2017-03-07 01:56:41 +01:00
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2016-10-28 10:03:37 +02:00
struct Instit Ins;
2014-12-01 23:55:08 +01:00
struct Centre Ctr;
struct Degree Deg;
struct Course Crs;
long Cod;
2020-04-07 03:01:41 +02:00
struct For_Forum ForumSelected;
2017-01-13 10:49:56 +01:00
char ForumName[For_MAX_BYTES_FORUM_NAME + 1];
2017-03-08 14:12:33 +01:00
char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1];
2014-12-01 23:55:08 +01:00
char *ContentStr;
Ntf_Status_t Status;
2017-01-15 22:58:26 +01:00
size_t Length;
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getNotifications;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,-1L))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2015-12-07 23:13:08 +01:00
/***** Get my language from database *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetMyLanguage (soap)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get my notifications from database *****/
2018-11-02 01:23:05 +01:00
NumNotifications =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get user's notifications",
"SELECT NtfCod," // row[0]
"NotifyEvent," // row[1]
"UNIX_TIMESTAMP(TimeNotif)," // row[2]
"FromUsrCod," // row[3]
"InsCod," // row[4]
"CtrCod," // row[5]
"DegCod," // row[6]
"CrsCod," // row[7]
"Cod," // row[8]
"Status" // row[9]
" FROM notif"
" WHERE ToUsrCod=%ld AND TimeNotif>=FROM_UNIXTIME(%ld)"
" ORDER BY TimeNotif DESC",
Gbl.Usrs.Me.UsrDat.UsrCod,beginTime);
2016-07-20 20:24:16 +02:00
if (NumNotifications) // Notifications found
2014-12-01 23:55:08 +01:00
{
2016-07-20 20:24:16 +02:00
getNotificationsOut->numNotifications = (int) NumNotifications;
getNotificationsOut->notificationsArray.__size = (int) NumNotifications;
2020-02-24 19:31:55 +01:00
getNotificationsOut->notificationsArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getNotificationsOut->notificationsArray.__size) *
sizeof (*(getNotificationsOut->notificationsArray.__ptr)));
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
for (NumNotif = 0;
NumNotif < NumNotifications;
NumNotif++)
2014-12-01 23:55:08 +01:00
{
/* Get next notification */
row = mysql_fetch_row (mysql_res);
/* Get unique notification code (row[0]) */
NtfCod = Str_ConvertStrCodToLongCod (row[0]);
2016-07-20 20:24:16 +02:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].notifCode = (int) NtfCod;
2014-12-01 23:55:08 +01:00
/* Get notification event type (row[1]) */
2019-12-17 00:36:22 +01:00
NotifyEvent = Ntf_GetNotifyEventFromStr ((const char *) row[1]);
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].eventType =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Ntf_MAX_BYTES_NOTIFY_EVENT + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].eventType,
2017-01-17 03:10:43 +01:00
Ntf_WSNotifyEvents[NotifyEvent],
2017-03-07 19:55:29 +01:00
Ntf_MAX_BYTES_NOTIFY_EVENT);
2014-12-01 23:55:08 +01:00
/* Get time of the event (row[2]) */
EventTime = 0L;
if (row[2])
sscanf (row[2],"%ld",&EventTime);
2016-07-20 20:24:16 +02:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].eventTime = EventTime;
2014-12-01 23:55:08 +01:00
/* Get course (row[7]) */
Crs.CrsCod = Str_ConvertStrCodToLongCod (row[7]);
2020-01-05 14:09:28 +01:00
Crs_GetDataOfCourseByCod (&Crs);
2014-12-01 23:55:08 +01:00
/* Get user's code of the user who caused the event (row[3]) */
Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[3]);
2016-07-20 20:24:16 +02:00
2019-05-16 14:02:06 +02:00
if (API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Crs.CrsCod)) // Get some user's data from database
2014-12-01 23:55:08 +01:00
{
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].userNickname =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].userNickname,
Gbl.Usrs.Other.UsrDat.Nickname,
2017-03-07 01:56:41 +01:00
Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA);
2014-12-01 23:55:08 +01:00
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].userSurname1 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].userSurname1,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.Surname1,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2014-12-01 23:55:08 +01:00
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].userSurname2 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].userSurname2,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.Surname2,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2014-12-01 23:55:08 +01:00
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].userFirstname =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].userFirstname,
2017-01-17 03:10:43 +01:00
Gbl.Usrs.Other.UsrDat.FirstName,
2017-03-07 19:55:29 +01:00
Usr_MAX_BYTES_FIRSTNAME_OR_SURNAME);
2014-12-01 23:55:08 +01:00
2016-07-08 12:43:48 +02:00
Pho_BuildLinkToPhoto (&Gbl.Usrs.Other.UsrDat,PhotoURL);
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].userPhoto =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_WWW + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].userPhoto,
2017-01-17 03:10:43 +01:00
PhotoURL,
2017-03-07 01:56:41 +01:00
Cns_MAX_BYTES_WWW);
2014-12-01 23:55:08 +01:00
}
else
{
2016-07-20 20:24:16 +02:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].userNickname = NULL;
getNotificationsOut->notificationsArray.__ptr[NumNotif].userSurname1 = NULL;
getNotificationsOut->notificationsArray.__ptr[NumNotif].userSurname2 = NULL;
getNotificationsOut->notificationsArray.__ptr[NumNotif].userFirstname = NULL;
getNotificationsOut->notificationsArray.__ptr[NumNotif].userPhoto = NULL;
2014-12-01 23:55:08 +01:00
}
/* Get institution (row[4]) */
Ins.InsCod = Str_ConvertStrCodToLongCod (row[4]);
2020-01-07 00:09:30 +01:00
Ins_GetDataOfInstitutionByCod (&Ins);
2014-12-01 23:55:08 +01:00
/* Get centre (row[5]) */
Ctr.CtrCod = Str_ConvertStrCodToLongCod (row[5]);
2020-01-05 02:18:20 +01:00
Ctr_GetDataOfCentreByCod (&Ctr);
2014-12-01 23:55:08 +01:00
/* Get degree (row[6]) */
Deg.DegCod = Str_ConvertStrCodToLongCod (row[6]);
2020-01-05 12:52:03 +01:00
Deg_GetDataOfDegreeByCod (&Deg);
2014-12-01 23:55:08 +01:00
/* Get message/post/... code (row[8]) */
Cod = Str_ConvertStrCodToLongCod (row[8]);
2016-07-20 20:24:16 +02:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].eventCode = (int) Cod;
2014-12-01 23:55:08 +01:00
/* Set location */
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].location =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Ntf_MAX_BYTES_NOTIFY_LOCATION + 1);
2014-12-01 23:55:08 +01:00
if (NotifyEvent == Ntf_EVENT_FORUM_POST_COURSE ||
NotifyEvent == Ntf_EVENT_FORUM_REPLY)
{
2017-04-18 01:25:44 +02:00
For_GetForumTypeAndLocationOfAPost (Cod,&ForumSelected);
For_SetForumName (&ForumSelected,
2014-12-01 23:55:08 +01:00
ForumName,Gbl.Prefs.Language,false); // Set forum name in recipient's language
2016-07-20 20:24:16 +02:00
sprintf (getNotificationsOut->notificationsArray.__ptr[NumNotif].location,"%s: %s",
2014-12-01 23:55:08 +01:00
Txt_Forum,ForumName);
}
else if (Crs.CrsCod > 0)
2016-07-20 20:24:16 +02:00
sprintf (getNotificationsOut->notificationsArray.__ptr[NumNotif].location,"%s: %s",
2016-10-28 10:03:37 +02:00
Txt_Course,Crs.ShrtName);
2014-12-01 23:55:08 +01:00
else if (Deg.DegCod > 0)
2016-07-20 20:24:16 +02:00
sprintf (getNotificationsOut->notificationsArray.__ptr[NumNotif].location,"%s: %s",
2016-10-28 10:03:37 +02:00
Txt_Degree,Deg.ShrtName);
2014-12-01 23:55:08 +01:00
else if (Ctr.CtrCod > 0)
2016-07-20 20:24:16 +02:00
sprintf (getNotificationsOut->notificationsArray.__ptr[NumNotif].location,"%s: %s",
2016-10-28 10:03:37 +02:00
Txt_Centre,Ctr.ShrtName);
2014-12-01 23:55:08 +01:00
else if (Ins.InsCod > 0)
2016-07-20 20:24:16 +02:00
sprintf (getNotificationsOut->notificationsArray.__ptr[NumNotif].location,"%s: %s",
2016-10-28 10:03:37 +02:00
Txt_Institution,Ins.ShrtName);
2014-12-01 23:55:08 +01:00
else
2017-01-17 03:10:43 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].location,"-",
2017-03-07 19:55:29 +01:00
Ntf_MAX_BYTES_NOTIFY_LOCATION);
2014-12-01 23:55:08 +01:00
/* Get status (row[9]) */
if (sscanf (row[9],"%u",&Status) != 1)
Status = (Ntf_Status_t) 0;
2016-07-20 20:24:16 +02:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].status = (int) Status;
2014-12-01 23:55:08 +01:00
/* Get summary and content */
ContentStr = NULL;
Ntf_GetNotifSummaryAndContent (SummaryStr,&ContentStr,NotifyEvent,
2016-01-22 12:05:25 +01:00
Cod,Crs.CrsCod,Gbl.Usrs.Me.UsrDat.UsrCod,
2017-03-06 13:01:16 +01:00
true);
2014-12-01 23:55:08 +01:00
2017-01-15 22:58:26 +01:00
Length = strlen (SummaryStr);
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].summary =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].summary,
2017-01-17 03:10:43 +01:00
SummaryStr,
Length);
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
if (ContentStr == NULL)
2014-12-01 23:55:08 +01:00
{
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].content =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,1);
2016-07-20 20:24:16 +02:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].content[0] = '\0';
2014-12-01 23:55:08 +01:00
}
else
{
2017-01-15 22:58:26 +01:00
Length = strlen (ContentStr);
2019-12-06 11:53:14 +01:00
getNotificationsOut->notificationsArray.__ptr[NumNotif].content =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2017-01-15 22:58:26 +01:00
Str_Copy (getNotificationsOut->notificationsArray.__ptr[NumNotif].content,
2017-01-17 03:10:43 +01:00
ContentStr,
Length);
2016-07-20 20:24:16 +02:00
/* Free memory used by content string */
2019-11-06 19:45:20 +01:00
free (ContentStr);
2016-07-20 20:24:16 +02:00
ContentStr = NULL;
2014-12-01 23:55:08 +01:00
}
}
2016-07-20 20:24:16 +02:00
}
else // No notifications found
{
getNotificationsOut->numNotifications = 0;
getNotificationsOut->notificationsArray.__size = 0;
getNotificationsOut->notificationsArray.__ptr = NULL;
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
2015-12-07 23:13:08 +01:00
/********************* Get my language from database *************************/
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_GetMyLanguage (struct soap *soap)
2014-12-01 23:55:08 +01:00
{
2018-12-08 16:43:13 +01:00
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2018-12-08 16:43:13 +01:00
Lan_Language_t Lan;
2014-12-01 23:55:08 +01:00
/***** Get user's language *****/
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get user's language",
"SELECT Language FROM usr_data"
" WHERE UsrCod=%ld",
Gbl.Usrs.Me.UsrDat.UsrCod) != 1)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not get user's language from database",
"User doen't exist in database");
/***** Get language from database *****/
row = mysql_fetch_row (mysql_res);
/* Get language (row[0]) */
2019-12-15 01:10:36 +01:00
Gbl.Prefs.Language = Lan_LANGUAGE_UNKNOWN;
for (Lan = (Lan_Language_t) 1;
Lan <= (Lan_Language_t) (Lan_NUM_LANGUAGES - 1);
2014-12-01 23:55:08 +01:00
Lan++)
2018-12-08 16:43:13 +01:00
if (!strcasecmp (row[0],Lan_STR_LANG_ID[Lan]))
2014-12-01 23:55:08 +01:00
{
Gbl.Prefs.Language = Lan;
break;
}
2018-12-08 16:43:13 +01:00
if (Gbl.Prefs.Language == Lan_LANGUAGE_UNKNOWN) // Language stored in database is unknown
2015-12-07 23:13:08 +01:00
Gbl.Prefs.Language = Cfg_DEFAULT_LANGUAGE;
2014-12-01 23:55:08 +01:00
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/************************* Send a notice to a course *************************/
/*****************************************************************************/
int swad__markNotificationsAsRead (struct soap *soap,
char *wsKey,char *notifications, // input
struct swad__markNotificationsAsReadOutput *markNotificationsAsReadOut) // output
{
int ReturnCode;
const char *Ptr;
2019-11-08 01:10:32 +01:00
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2014-12-01 23:55:08 +01:00
unsigned NumNtf;
unsigned NumNtfsMarkedAsRead = 0;
long NtfCod;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_markNotificationsAsRead;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,-1L))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
if (notifications[0])
{
/***** Mark notifications from list as read *****/
for (NumNtf = 0, Ptr = notifications;
*Ptr;
NumNtf++)
{
/* Find next string in text until comma (leading and trailing spaces are removed) */
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2014-12-01 23:55:08 +01:00
if ((NtfCod = Str_ConvertStrCodToLongCod (LongStr)) > 0)
{
/***** Mark notification as read in the database *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not mark notification as read",
"UPDATE notif SET Status=(Status | %u)"
" WHERE NtfCod=%ld AND ToUsrCod=%ld",
(unsigned) Ntf_STATUS_BIT_READ,
(long) NtfCod,Gbl.Usrs.Me.UsrDat.UsrCod);
2014-12-01 23:55:08 +01:00
NumNtfsMarkedAsRead++;
}
}
}
/***** Return notification code *****/
markNotificationsAsReadOut->numNotifications = (int) NumNtfsMarkedAsRead;
return SOAP_OK;
}
/*****************************************************************************/
/****************** Send a message to one or more users **********************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
#define API_MAX_BYTES_QUERY_RECIPIENTS (10 * 1024 - 1)
2014-12-01 23:55:08 +01:00
int swad__sendMessage (struct soap *soap,
char *wsKey,int messageCode,char *to,char *subject,char *body, // input
struct swad__sendMessageOutput *sendMessageOut) // output
{
int ReturnCode;
long ReplyUsrCod = -1L;
2017-01-28 15:58:46 +01:00
char Nickname[Nck_MAX_BYTES_NICKNAME_FROM_FORM + 1];
2018-10-30 03:29:40 +01:00
char *Query = NULL;
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2018-10-30 02:37:09 +01:00
unsigned NumRow;
unsigned NumRows;
2014-12-01 23:55:08 +01:00
bool FirstNickname = true;
bool ThereAreNicknames = false;
const char *Ptr;
2018-10-10 23:56:42 +02:00
bool ItsMe;
2014-12-01 23:55:08 +01:00
bool NotifyByEmail;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_sendMessage;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,-1L))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check if the message is a reply to a previous message *****/
if (messageCode)
{
/***** Check if the original message was really received by me *****/
2018-11-02 01:23:05 +01:00
if (!DB_QuerySELECT (&mysql_res,"can not check original message",
"SELECT SUM(N) FROM"
" (SELECT COUNT(*) AS N FROM msg_rcv"
" WHERE UsrCod=%ld AND MsgCod=%ld"
" UNION"
" SELECT COUNT(*) AS N FROM msg_rcv_deleted"
" WHERE UsrCod=%ld AND MsgCod=%ld) AS T",
Gbl.Usrs.Me.UsrDat.UsrCod,(long) messageCode,
Gbl.Usrs.Me.UsrDat.UsrCod,(long) messageCode))
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not check original message",
"Error reading from database");
/***** Get number of rows *****/
row = mysql_fetch_row (mysql_res);
if (sscanf (row[0],"%u",&NumRows) != 1)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not check original message",
"Error reading from database");
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (!NumRows)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not send reply message",
"Original message does not exist");
/***** Get the recipient of the message *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not check original message",
"SELECT UsrCod FROM msg_snt"
" WHERE MsgCod=%ld"
" UNION "
"SELECT UsrCod FROM msg_snt_deleted"
" WHERE MsgCod=%ld",
(long) messageCode,(long) messageCode);
if (NumRows) // Message found in any of the two tables of sent messages
2014-12-01 23:55:08 +01:00
{
row = mysql_fetch_row (mysql_res);
ReplyUsrCod = Str_ConvertStrCodToLongCod (row[0]);
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (!NumRows)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not send reply message",
"Original message does not exist");
}
2018-10-29 22:22:02 +01:00
/***** Allocate space for query *****/
2019-05-16 14:02:06 +02:00
if ((Query = (char *) malloc (API_MAX_BYTES_QUERY_RECIPIENTS + 1)) == NULL)
2018-10-29 22:22:02 +01:00
Lay_NotEnoughMemoryExit ();
2014-12-01 23:55:08 +01:00
/***** Build query for recipients from database *****/
if (ReplyUsrCod > 0)
2019-05-16 14:02:06 +02:00
snprintf (Query,API_MAX_BYTES_QUERY_RECIPIENTS + 1,
2018-10-29 22:22:02 +01:00
"SELECT UsrCod FROM usr_data"
" WHERE UsrCod=%ld",
ReplyUsrCod);
2014-12-01 23:55:08 +01:00
else
2018-10-30 02:37:09 +01:00
Query[0] = '\0';
2014-12-01 23:55:08 +01:00
/***** Loop over recipients' nicknames building query *****/
Ptr = to;
while (*Ptr)
{
/* Find next string in text until comma (leading and trailing spaces are removed) */
2017-01-17 03:10:43 +01:00
Str_GetNextStringUntilComma (&Ptr,Nickname,Nck_MAX_BYTES_NICKNAME_FROM_FORM);
2014-12-01 23:55:08 +01:00
/* Check if string is a valid nickname */
if (Nck_CheckIfNickWithArrobaIsValid (Nickname)) // String is a nickname?
{
Str_RemoveLeadingArrobas (Nickname);
/* Check for overflow in query */
2018-10-30 02:37:09 +01:00
if (strlen (Query) + Nck_MAX_BYTES_NICKNAME_WITHOUT_ARROBA + 32 >
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_QUERY_RECIPIENTS)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not send message",
"Too many recipients");
/* Add this nickname to query */
if (FirstNickname)
{
if (ReplyUsrCod > 0)
2018-10-30 02:37:09 +01:00
Str_Concat (Query," UNION ",
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_QUERY_RECIPIENTS);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,"SELECT UsrCod FROM usr_nicknames"
2017-01-16 01:51:01 +01:00
" WHERE Nickname IN ('",
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_QUERY_RECIPIENTS);
2014-12-01 23:55:08 +01:00
FirstNickname = false;
ThereAreNicknames = true;
}
else
2018-10-30 02:37:09 +01:00
Str_Concat (Query,",'",
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_QUERY_RECIPIENTS);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,Nickname,
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_QUERY_RECIPIENTS);
2018-10-30 02:37:09 +01:00
Str_Concat (Query,"'",
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_QUERY_RECIPIENTS);
2014-12-01 23:55:08 +01:00
}
}
if (ThereAreNicknames)
2018-10-30 02:37:09 +01:00
Str_Concat (Query,")",
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_QUERY_RECIPIENTS);
2014-12-01 23:55:08 +01:00
/***** Initialize output structure *****/
sendMessageOut->numUsers = 0;
sendMessageOut->usersArray.__size = 0;
sendMessageOut->usersArray.__ptr = NULL;
if (ReplyUsrCod > 0 || ThereAreNicknames) // There are a recipient to reply or nicknames in "to"
{
/***** Get users *****/
2018-11-14 23:40:56 +01:00
NumRows = DB_QuerySELECT (&mysql_res,"can not get users",
"%s",
Query);
2014-12-01 23:55:08 +01:00
sendMessageOut->numUsers = (int) NumRows;
sendMessageOut->usersArray.__size = (int) NumRows;
if (NumRows) // Users found
{
2020-02-24 19:31:55 +01:00
sendMessageOut->usersArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(sendMessageOut->usersArray.__size) *
sizeof (*(sendMessageOut->usersArray.__ptr)));
2014-12-01 23:55:08 +01:00
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 recipient data */
2019-03-19 13:22:14 +01:00
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS))
2014-12-01 23:55:08 +01:00
{
2016-11-16 23:19:52 +01:00
/* This received message must be notified by email? */
2018-10-10 23:56:42 +02:00
ItsMe = Usr_ItsMe (Gbl.Usrs.Other.UsrDat.UsrCod);
NotifyByEmail = (!ItsMe &&
2019-03-19 13:22:14 +01:00
(Gbl.Usrs.Other.UsrDat.NtfEvents.SendEmail & (1 << Ntf_EVENT_MESSAGE)));
2014-12-01 23:55:08 +01:00
/* Send message to this user */
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_SendMessageToUsr ((long) messageCode,Gbl.Usrs.Me.UsrDat.UsrCod,ReplyUsrCod,Gbl.Usrs.Other.UsrDat.UsrCod,NotifyByEmail,subject,body)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
{
DB_FreeMySQLResult (&mysql_res);
return ReturnCode;
}
/* Copy user's data into output structure */
2020-02-24 19:31:55 +01:00
API_CopyUsrData (soap,
&(sendMessageOut->usersArray.__ptr[NumRow]),
&Gbl.Usrs.Other.UsrDat,
false);
2014-12-01 23:55:08 +01:00
}
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
return SOAP_OK;
}
/*****************************************************************************/
/************************* Send a message to one user ************************/
/*****************************************************************************/
2016-09-19 21:30:37 +02:00
/*
2019-05-16 14:02:06 +02:00
API_SendMessageToUsr ((long) messageCode,
2016-09-19 21:30:37 +02:00
Gbl.Usrs.Me.UsrDat.UsrCod,ReplyUsrCod,Gbl.Usrs.Other.UsrDat.UsrCod,
NotifyByEmail,subject,body)) != SOAP_OK)
*/
2019-05-16 14:02:06 +02:00
static int API_SendMessageToUsr (long OriginalMsgCod,
2016-09-19 21:30:37 +02:00
long SenderUsrCod,long ReplyUsrCod,long RecipientUsrCod,
bool NotifyByEmail,
const char *Subject,const char *Content)
2014-12-01 23:55:08 +01:00
{
static bool MsgAlreadyInserted = false;
static long NewMsgCod;
/***** Create message *****/
if (!MsgAlreadyInserted) // The message is inserted only once in the table of messages sent
{
/***** Insert message subject and body in the database *****/
/* Get the code of the inserted item */
2018-11-03 01:45:36 +01:00
NewMsgCod =
DB_QueryINSERTandReturnCode ("can not create message",
"INSERT INTO msg_content"
2019-03-18 15:42:22 +01:00
" (Subject,Content,MedCod)"
2018-11-03 01:45:36 +01:00
" VALUES"
2019-03-18 15:42:22 +01:00
" ('%s','%s',-1)",
Subject,Content);
2018-11-03 01:45:36 +01:00
/* Insert message in sent messages */
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not create message",
"INSERT INTO msg_snt"
" (MsgCod,CrsCod,UsrCod,Expanded,CreatTime)"
" VALUES"
" (%ld,-1,%ld,'N',NOW())",
NewMsgCod,SenderUsrCod);
2014-12-01 23:55:08 +01:00
MsgAlreadyInserted = true;
}
/***** Insert message received in the database *****/
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not create received message",
"INSERT INTO msg_rcv"
" (MsgCod,UsrCod,Notified,Open,Replied,Expanded)"
" VALUES"
" (%ld,%ld,'%c','N','N','N')",
NewMsgCod,RecipientUsrCod,
NotifyByEmail ? 'Y' :
'N');
2014-12-01 23:55:08 +01:00
/***** Create notification for this recipient.
2016-11-16 23:19:52 +01:00
If this recipient wants to receive notifications by email, activate the sending of a notification *****/
2018-11-02 19:37:11 +01:00
DB_QueryINSERT ("can not create new notification event",
"INSERT INTO notif"
" (NotifyEvent,ToUsrCod,FromUsrCod,InsCod,DegCod,CrsCod,Cod,TimeNotif,Status)"
" VALUES"
" (%u,%ld,%ld,-1,-1,-1,%ld,NOW(),%u)",
(unsigned) Ntf_EVENT_MESSAGE,
RecipientUsrCod,
SenderUsrCod,
NewMsgCod,
(unsigned) (NotifyByEmail ? Ntf_STATUS_BIT_EMAIL :
0));
2014-12-01 23:55:08 +01:00
/***** If this recipient is the original sender of a message been replied... *****/
if (RecipientUsrCod == ReplyUsrCod)
/***** ...then update received message setting Replied field to true *****/
2018-11-03 12:16:40 +01:00
DB_QueryUPDATE ("can not update a received message",
"UPDATE msg_rcv SET Replied='Y'"
" WHERE MsgCod=%ld AND UsrCod=%ld",
OriginalMsgCod,SenderUsrCod);
2014-12-01 23:55:08 +01:00
return SOAP_OK;
}
/*****************************************************************************/
/************************* Send a notice to a course *************************/
/*****************************************************************************/
int swad__sendNotice (struct soap *soap,
char *wsKey,int courseCode,char *body, // input
struct swad__sendNoticeOutput *sendNoticeOut) // output
{
int ReturnCode;
long NotCod;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_sendNotice;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check course and group codes *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckCourseAndGroupCodes (soap,
Gbl.Hierarchy.Crs.CrsCod,
-1L)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get degree of current course *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Check if I am a teacher *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must be a teacher");
/***** Insert notice in the database *****/
/* Get the code of the inserted item */
2018-11-03 01:45:36 +01:00
NotCod =
DB_QueryINSERTandReturnCode ("can not create message",
"INSERT INTO notices"
" (CrsCod,UsrCod,CreatTime,Content,Status)"
" VALUES"
" (%ld,%ld,NOW(),'%s',%u)",
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod,Gbl.Usrs.Me.UsrDat.UsrCod,
2018-11-03 01:45:36 +01:00
body,(unsigned) Not_ACTIVE_NOTICE);
2014-12-01 23:55:08 +01:00
/***** Create notifications *****/
// TODO: create notifications
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/***** Return notification code *****/
sendNoticeOut->noticeCode = (int) NotCod;
return SOAP_OK;
}
/*****************************************************************************/
/****************** Return test configuration in a course ********************/
/*****************************************************************************/
2020-04-02 03:28:08 +02:00
#define TstExa_MAX_BYTES_FEEDBACK_TYPE 32
2020-02-17 12:27:28 +01:00
2014-12-01 23:55:08 +01:00
int swad__getTestConfig (struct soap *soap,
char *wsKey,int courseCode, // input
struct swad__getTestConfigOutput *getTestConfigOut) // output
{
int ReturnCode;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getTestConfig;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Get degree of current course *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Set default result to empty *****/
2020-02-17 12:00:39 +01:00
getTestConfigOut->numQuestions =
getTestConfigOut->minQuestions =
getTestConfigOut->defQuestions =
getTestConfigOut->maxQuestions = 0;
2020-04-02 03:28:08 +02:00
getTestConfigOut->visibility = TstVis_MIN_VISIBILITY;
2020-02-19 11:44:54 +01:00
/* TODO: Remove these lines in 2021 */
2020-04-02 03:28:08 +02:00
getTestConfigOut->feedback = (char *) soap_malloc (soap,TstExa_MAX_BYTES_FEEDBACK_TYPE + 1);
2014-12-01 23:55:08 +01:00
getTestConfigOut->feedback[0] = '\0';
/***** Get test configuration *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetTstConfig ((long) courseCode)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2020-03-21 15:41:25 +01:00
getTestConfigOut->pluggable = (TstCfg_GetConfigPluggable () == TstCfg_PLUGGABLE_YES) ? 1 :
0;
getTestConfigOut->minQuestions = (int) TstCfg_GetConfigMin ();
getTestConfigOut->defQuestions = (int) TstCfg_GetConfigDef ();
getTestConfigOut->maxQuestions = (int) TstCfg_GetConfigMax ();
getTestConfigOut->visibility = (int) TstCfg_GetConfigVisibility ();
2020-02-17 12:00:39 +01:00
/* Convert from visibility to old feedback */
/* TODO: Remove these lines in 2021 */
2020-04-02 03:28:08 +02:00
if (!TstVis_IsVisibleTotalScore (TstCfg_GetConfigVisibility ()))
2020-02-17 12:00:39 +01:00
Str_Copy (getTestConfigOut->feedback,
"nothing",
2020-04-02 03:28:08 +02:00
TstExa_MAX_BYTES_FEEDBACK_TYPE);
else if (!TstVis_IsVisibleEachQstScore (TstCfg_GetConfigVisibility ()))
2020-02-17 12:00:39 +01:00
Str_Copy (getTestConfigOut->feedback,
"totalResult",
2020-04-02 03:28:08 +02:00
TstExa_MAX_BYTES_FEEDBACK_TYPE);
else if (!TstVis_IsVisibleCorrectAns (TstCfg_GetConfigVisibility ()))
2020-02-17 12:00:39 +01:00
Str_Copy (getTestConfigOut->feedback,
"eachResult",
2020-04-02 03:28:08 +02:00
TstExa_MAX_BYTES_FEEDBACK_TYPE);
else if (!TstVis_IsVisibleFeedbackTxt (TstCfg_GetConfigVisibility ()))
2020-02-17 12:00:39 +01:00
Str_Copy (getTestConfigOut->feedback,
"eachGoodBad",
2020-04-02 03:28:08 +02:00
TstExa_MAX_BYTES_FEEDBACK_TYPE);
2020-02-17 12:00:39 +01:00
else
Str_Copy (getTestConfigOut->feedback,
"fullFeedback",
2020-04-02 03:28:08 +02:00
TstExa_MAX_BYTES_FEEDBACK_TYPE);
2014-12-01 23:55:08 +01:00
/***** Get number of tests *****/
2020-03-21 15:41:25 +01:00
if (TstCfg_GetConfigPluggable () == TstCfg_PLUGGABLE_YES &&
TstCfg_GetConfigMax () > 0)
2019-05-16 14:02:06 +02:00
getTestConfigOut->numQuestions = API_GetNumTestQuestionsInCrs ((long) courseCode);
2014-12-01 23:55:08 +01:00
return SOAP_OK;
}
/*****************************************************************************/
/****** Get configuration of tests from database giving a course code ********/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
static int API_GetTstConfig (long CrsCod)
2014-12-01 23:55:08 +01:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
/***** Query database *****/
2018-11-02 01:23:05 +01:00
if (DB_QuerySELECT (&mysql_res,"can not get test configuration",
2020-02-17 12:00:39 +01:00
"SELECT Pluggable,Min,Def,Max,MinTimeNxtTstPerQst,Visibility"
2018-11-02 01:23:05 +01:00
" FROM tst_config WHERE CrsCod=%ld",
CrsCod))
2014-12-01 23:55:08 +01:00
{
/***** Get minimun, default and maximum *****/
row = mysql_fetch_row (mysql_res);
2020-03-21 15:41:25 +01:00
TstCfg_GetConfigFromRow (row);
2014-12-01 23:55:08 +01:00
}
else // NumRows == 0
{
2020-03-21 15:41:25 +01:00
TstCfg_SetConfigPluggable (TstCfg_PLUGGABLE_UNKNOWN);
TstCfg_SetConfigMin (0);
TstCfg_SetConfigDef (0);
TstCfg_SetConfigMax (0);
2020-04-02 03:28:08 +02:00
TstCfg_SetConfigVisibility (TstVis_VISIBILITY_DEFAULT);
2014-12-01 23:55:08 +01:00
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/** Get number of visible test questions from database giving a course code **/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
static int API_GetNumTestQuestionsInCrs (long CrsCod)
2014-12-01 23:55:08 +01:00
{
/***** Get number of questions *****/
// Reject questions with any tag hidden
// Select only questions with tags
2018-11-03 22:08:45 +01:00
return
(int) DB_QueryCOUNT ("can not get number of test questions",
"SELECT COUNT(*)"
" FROM tst_questions,tst_question_tags,tst_tags"
" WHERE tst_questions.CrsCod=%ld"
" AND tst_questions.QstCod NOT IN"
" (SELECT tst_question_tags.QstCod"
" FROM tst_tags,tst_question_tags"
" WHERE tst_tags.CrsCod=%ld"
" AND tst_tags.TagHidden='Y'"
" AND tst_tags.TagCod=tst_question_tags.TagCod)"
" AND tst_questions.QstCod=tst_question_tags.QstCod"
" AND tst_question_tags.TagCod=tst_tags.TagCod"
" AND tst_tags.CrsCod=%ld",
CrsCod,CrsCod,CrsCod);
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/************************* Return tests of a course **************************/
/*****************************************************************************/
int swad__getTests (struct soap *soap,
char *wsKey,int courseCode,long beginTime, // input
struct swad__getTestsOutput *getTestsOut) // output
{
int ReturnCode;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getTests;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check if course code is correct *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Get degree of current course *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetCurrentDegCodFromCurrentCrsCod ()) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Set default result to empty *****/
getTestsOut->tagsArray.__size = 0;
getTestsOut->tagsArray.__ptr = NULL;
getTestsOut->questionsArray.__size = 0;
getTestsOut->questionsArray.__ptr = NULL;
getTestsOut->answersArray.__size = 0;
getTestsOut->answersArray.__ptr = NULL;
getTestsOut->questionTagsArray.__size = 0;
getTestsOut->questionTagsArray.__ptr = NULL;
/***** Get test configuration *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_GetTstConfig ((long) courseCode)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2020-03-21 15:41:25 +01:00
if (TstCfg_GetConfigPluggable () == TstCfg_PLUGGABLE_YES)
2014-12-01 23:55:08 +01:00
{
/***** Get tags *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetTstTags (soap,
(long) courseCode,getTestsOut)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get questions *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetTstQuestions (soap,
(long) courseCode,beginTime,getTestsOut)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get answers *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetTstAnswers (soap,
(long) courseCode,beginTime,getTestsOut)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get tags for each question *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_GetTstQuestionTags (soap,
(long) courseCode,beginTime,getTestsOut)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
}
return SOAP_OK;
}
/*****************************************************************************/
/**** Get test tags (only not hidden) from database giving a course code *****/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_GetTstTags (struct soap *soap,
long CrsCod,struct swad__getTestsOutput *getTestsOut)
2014-12-01 23:55:08 +01:00
{
2018-12-08 16:43:13 +01:00
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
2014-12-01 23:55:08 +01:00
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2017-01-15 18:02:52 +01:00
unsigned NumRow;
unsigned NumRows;
2014-12-01 23:55:08 +01:00
/***** Get available tags from database *****/
2018-11-02 01:23:05 +01:00
NumRows = DB_QuerySELECT (&mysql_res,"can not get test tags",
"SELECT TagCod,TagTxt"
" FROM tst_tags"
" WHERE CrsCod=%ld AND TagHidden='N'"
" ORDER BY TagTxt",
CrsCod);
2014-12-01 23:55:08 +01:00
getTestsOut->tagsArray.__size = (int) NumRows;
if (NumRows == 0)
getTestsOut->tagsArray.__ptr = NULL;
else // Tags found
{
2020-02-24 19:31:55 +01:00
getTestsOut->tagsArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getTestsOut->tagsArray.__size) *
sizeof (*(getTestsOut->tagsArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next tag */
row = mysql_fetch_row (mysql_res);
/* Get tag code (row[0]) */
getTestsOut->tagsArray.__ptr[NumRow].tagCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get tag text (row[1]) */
2019-12-06 11:53:14 +01:00
getTestsOut->tagsArray.__ptr[NumRow].tagText =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Tst_MAX_BYTES_TAG + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getTestsOut->tagsArray.__ptr[NumRow].tagText,row[1],
Tst_MAX_BYTES_TAG);
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/******* Get recent test questions from database giving a course code ********/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_GetTstQuestions (struct soap *soap,
long CrsCod,long BeginTime,
struct swad__getTestsOutput *getTestsOut)
2014-12-01 23:55:08 +01:00
{
extern const char *Tst_StrAnswerTypesXML[Tst_NUM_ANS_TYPES];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2015-06-16 20:12:38 +02:00
unsigned NumRow;
unsigned NumRows;
2014-12-01 23:55:08 +01:00
Tst_AnswerType_t AnswerType;
/***** Get recent test questions from database *****/
// DISTINCTROW is necessary to not repeat questions
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get test questions",
"SELECT DISTINCTROW tst_questions.QstCod,"
"tst_questions.AnsType,tst_questions.Shuffle,"
"tst_questions.Stem,tst_questions.Feedback"
" FROM tst_questions,tst_question_tags,tst_tags"
" WHERE tst_questions.CrsCod=%ld"
" AND tst_questions.QstCod NOT IN"
" (SELECT tst_question_tags.QstCod FROM tst_tags,tst_question_tags"
" WHERE tst_tags.CrsCod=%ld AND tst_tags.TagHidden='Y'"
" AND tst_tags.TagCod=tst_question_tags.TagCod)"
" AND tst_questions.QstCod=tst_question_tags.QstCod"
" AND tst_question_tags.TagCod=tst_tags.TagCod"
" AND tst_tags.CrsCod=%ld"
" AND "
"("
"tst_questions.EditTime>=FROM_UNIXTIME(%ld)"
" OR "
"tst_tags.ChangeTime>=FROM_UNIXTIME(%ld)"
")"
" ORDER BY QstCod",
CrsCod,CrsCod,CrsCod,
BeginTime,
BeginTime);
2014-12-01 23:55:08 +01:00
getTestsOut->questionsArray.__size = (int) NumRows;
if (NumRows == 0)
getTestsOut->questionsArray.__ptr = NULL;
else // Questions found
{
2020-02-24 19:31:55 +01:00
getTestsOut->questionsArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getTestsOut->questionsArray.__size) *
sizeof (*(getTestsOut->questionsArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next question */
row = mysql_fetch_row (mysql_res);
/* Get question code (row[0]) */
getTestsOut->questionsArray.__ptr[NumRow].questionCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get answer type (row[1]) */
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
2019-12-06 11:53:14 +01:00
getTestsOut->questionsArray.__ptr[NumRow].answerType =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Tst_MAX_BYTES_ANSWER_TYPE + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getTestsOut->questionsArray.__ptr[NumRow].answerType,
2017-01-17 03:10:43 +01:00
Tst_StrAnswerTypesXML[AnswerType],
2017-03-08 03:48:23 +01:00
Tst_MAX_BYTES_ANSWER_TYPE);
2014-12-01 23:55:08 +01:00
/* Get shuffle (row[2]) */
getTestsOut->questionsArray.__ptr[NumRow].shuffle = (row[2][0] == 'Y') ? 1 :
0;
/* Get question stem (row[3]) */
2019-12-06 11:53:14 +01:00
getTestsOut->questionsArray.__ptr[NumRow].stem =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getTestsOut->questionsArray.__ptr[NumRow].stem,row[3],
Cns_MAX_BYTES_TEXT);
2014-12-01 23:55:08 +01:00
2015-06-16 20:12:38 +02:00
/* Get question feedback (row[4]) */
2019-12-06 11:53:14 +01:00
getTestsOut->questionsArray.__ptr[NumRow].feedback =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getTestsOut->questionsArray.__ptr[NumRow].feedback,row[4],
Cns_MAX_BYTES_TEXT);
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/** Get answers of recent test questions from database giving a course code **/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_GetTstAnswers (struct soap *soap,
long CrsCod,long BeginTime,
struct swad__getTestsOutput *getTestsOut)
2014-12-01 23:55:08 +01:00
{
extern const char *Tst_StrAnswerTypesXML[Tst_NUM_ANS_TYPES];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRow,NumRows;
unsigned Index;
/***** Get recent test questions from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get test answers",
"SELECT QstCod,AnsInd,Correct,Answer,Feedback"
" FROM tst_answers WHERE QstCod IN "
"(SELECT tst_questions.QstCod"
" FROM tst_questions,tst_question_tags,tst_tags"
" WHERE tst_questions.CrsCod=%ld"
" AND tst_questions.QstCod NOT IN"
" (SELECT tst_question_tags.QstCod FROM tst_tags,tst_question_tags"
" WHERE tst_tags.CrsCod=%ld AND tst_tags.TagHidden='Y'"
" AND tst_tags.TagCod=tst_question_tags.TagCod)"
" AND tst_questions.QstCod=tst_question_tags.QstCod"
" AND tst_question_tags.TagCod=tst_tags.TagCod"
" AND tst_tags.CrsCod=%ld"
" AND "
"("
"tst_questions.EditTime>=FROM_UNIXTIME(%ld)"
" OR "
"tst_tags.ChangeTime>=FROM_UNIXTIME(%ld)"
")"
")"
" ORDER BY QstCod,AnsInd",
CrsCod,CrsCod,CrsCod,
BeginTime,
BeginTime);
2014-12-01 23:55:08 +01:00
getTestsOut->answersArray.__size = (int) NumRows;
if (NumRows == 0)
getTestsOut->answersArray.__ptr = NULL;
else // Answers found
{
2020-02-24 19:31:55 +01:00
getTestsOut->answersArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getTestsOut->answersArray.__size) *
sizeof (*(getTestsOut->answersArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next question */
row = mysql_fetch_row (mysql_res);
/* Get question code (row[0]) */
getTestsOut->answersArray.__ptr[NumRow].questionCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get answer index (row[1]) */
if (sscanf (row[1],"%u",&Index) == 1)
getTestsOut->answersArray.__ptr[NumRow].answerIndex = (int) Index;
else
getTestsOut->answersArray.__ptr[NumRow].answerIndex = 0; // error
/* Get correct (row[2]) */
getTestsOut->answersArray.__ptr[NumRow].correct = (row[2][0] == 'Y') ? 1 :
0;
/* Get answer (row[3]) */
2019-12-06 11:53:14 +01:00
getTestsOut->answersArray.__ptr[NumRow].answerText =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getTestsOut->answersArray.__ptr[NumRow].answerText,row[3],
Cns_MAX_BYTES_TEXT);
2014-12-01 23:55:08 +01:00
/* Get feedback (row[4]) */
2019-12-06 11:53:14 +01:00
getTestsOut->answersArray.__ptr[NumRow].answerFeedback =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getTestsOut->answersArray.__ptr[NumRow].answerFeedback,row[4],
Cns_MAX_BYTES_TEXT);
2014-12-01 23:55:08 +01:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/*** Get tags of recent test questions from database giving a course code ****/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static int API_GetTstQuestionTags (struct soap *soap,
long CrsCod,long BeginTime,
struct swad__getTestsOutput *getTestsOut)
2014-12-01 23:55:08 +01:00
{
extern const char *Tst_StrAnswerTypesXML[Tst_NUM_ANS_TYPES];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRow,NumRows;
unsigned Index;
/***** Get recent test questions from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get test question tags",
"SELECT QstCod,TagCod,TagInd"
" FROM tst_question_tags WHERE QstCod IN "
"(SELECT tst_questions.QstCod"
" FROM tst_questions,tst_question_tags,tst_tags"
" WHERE tst_questions.CrsCod=%ld"
" AND tst_questions.QstCod NOT IN"
" (SELECT tst_question_tags.QstCod FROM tst_tags,tst_question_tags"
" WHERE tst_tags.CrsCod=%ld AND tst_tags.TagHidden='Y'"
" AND tst_tags.TagCod=tst_question_tags.TagCod)"
" AND tst_questions.QstCod=tst_question_tags.QstCod"
" AND tst_question_tags.TagCod=tst_tags.TagCod"
" AND tst_tags.CrsCod=%ld"
" AND "
"("
"tst_questions.EditTime>=FROM_UNIXTIME(%ld)"
" OR "
"tst_tags.ChangeTime>=FROM_UNIXTIME(%ld)"
")"
")"
" ORDER BY QstCod,TagInd",
CrsCod,CrsCod,CrsCod,
BeginTime,
BeginTime);
2014-12-01 23:55:08 +01:00
getTestsOut->questionTagsArray.__size = (int) NumRows;
if (NumRows == 0)
getTestsOut->questionTagsArray.__ptr = NULL;
else // Answers found
{
2020-02-24 19:31:55 +01:00
getTestsOut->questionTagsArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getTestsOut->questionTagsArray.__size) *
sizeof (*(getTestsOut->questionTagsArray.__ptr)));
2014-12-01 23:55:08 +01:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next question */
row = mysql_fetch_row (mysql_res);
/* Get question code (row[0]) */
getTestsOut->questionTagsArray.__ptr[NumRow].questionCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get tag code (row[1]) */
getTestsOut->questionTagsArray.__ptr[NumRow].tagCode = (int) Str_ConvertStrCodToLongCod (row[1]);
/* Get tag index (row[2]) */
if (sscanf (row[2],"%u",&Index) == 1)
getTestsOut->questionTagsArray.__ptr[NumRow].tagIndex = (int) Index;
else
getTestsOut->questionTagsArray.__ptr[NumRow].tagIndex = 0; // error
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
2015-06-16 20:12:38 +02:00
/*****************************************************************************/
/***************** Return one test question for Trivial game *****************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
#define API_MAX_BYTES_DEGREES_STR (1024 - 1)
2017-01-16 01:51:01 +01:00
2015-06-16 20:12:38 +02:00
int swad__getTrivialQuestion (struct soap *soap,
char *wsKey,char *degrees,float lowerScore,float upperScore, // input
struct swad__getTrivialQuestionOutput *getTrivialQuestionOut) // output
{
extern const char *Tst_StrAnswerTypesXML[Tst_NUM_ANS_TYPES];
int ReturnCode;
const char *Ptr;
2019-11-08 01:10:32 +01:00
char LongStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2019-05-16 14:02:06 +02:00
char DegreesStr[API_MAX_BYTES_DEGREES_STR + 1];
2019-11-08 01:10:32 +01:00
char DegStr[ 1 + 1 + Cns_MAX_DECIMAL_DIGITS_LONG + 1 + 1];
2017-01-28 15:58:46 +01:00
// DegStr=", ' - number ' \0"
2015-06-16 20:12:38 +02:00
long DegCod;
bool FirstDegree = true;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned NumRow;
unsigned NumRows;
long QstCod = -1L;
Tst_AnswerType_t AnswerType;
unsigned Index;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getTrivialQuestion;
2015-06-16 20:12:38 +02:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2015-06-16 20:12:38 +02:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2015-06-16 20:12:38 +02:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2015-06-16 20:12:38 +02:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2015-06-16 20:12:38 +02:00
/***** Loop over recipients' nicknames building query *****/
DegreesStr[0] = '\0';
Ptr = degrees;
while (*Ptr)
{
/* Find next string in text until comma (leading and trailing spaces are removed) */
2019-11-08 01:10:32 +01:00
Str_GetNextStringUntilComma (&Ptr,LongStr,Cns_MAX_DECIMAL_DIGITS_LONG);
2015-06-16 20:12:38 +02:00
/* Check if degree code from string is a valid code */
if (sscanf (LongStr,"%ld",&DegCod) == 1) // Degree code
if (DegCod > 0)
{
/* Add this degree to query */
if (FirstDegree)
{
2018-10-18 02:02:32 +02:00
snprintf (DegreesStr,sizeof (DegreesStr),
"%ld",
DegCod);
2015-06-16 20:12:38 +02:00
FirstDegree = false;
}
else
2015-06-23 19:33:13 +02:00
{
2018-10-18 02:02:32 +02:00
snprintf (DegStr,sizeof (DegStr),
",%ld",
DegCod);
2017-01-17 03:33:05 +01:00
Str_Concat (DegreesStr,DegStr,
2019-05-16 14:02:06 +02:00
API_MAX_BYTES_DEGREES_STR);
2015-06-23 19:33:13 +02:00
}
2015-06-16 20:12:38 +02:00
}
}
if (!DegreesStr[0]) // Degrees not found
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2015-06-16 20:12:38 +02:00
"Bad list of degrees codes",
"Degrees codes must be integers greater than 0 separated by commas");
/***** Check lowerScore and upperScore *****/
if (lowerScore < -1.0 || lowerScore > 1.0 ||
upperScore < -1.0 || upperScore > 1.0 ||
upperScore < lowerScore)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2015-06-16 20:12:38 +02:00
"Bad score interval",
"lowerScore or upperScore values not valid");
/***** Start query *****/
2016-06-04 14:21:01 +02:00
Str_SetDecimalPointToUS (); // To print the floating point as a dot
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get test questions",
"SELECT DISTINCTROW tst_questions.QstCod,"
"tst_questions.AnsType,tst_questions.Shuffle,"
"tst_questions.Stem,tst_questions.Feedback,"
"tst_questions.Score/tst_questions.NumHits AS S"
" FROM courses,tst_questions"
" WHERE courses.DegCod IN (%s)"
" AND courses.CrsCod=tst_questions.CrsCod"
" AND tst_questions.AnsType='unique_choice'"
" AND tst_questions.NumHits>0"
" AND tst_questions.QstCod NOT IN"
" (SELECT tst_question_tags.QstCod"
" FROM courses,tst_tags,tst_question_tags"
" WHERE courses.DegCod IN (%s)"
" AND courses.CrsCod=tst_tags.CrsCod"
" AND tst_tags.TagHidden='Y'"
" AND tst_tags.TagCod=tst_question_tags.TagCod)"
" HAVING S>='%f' AND S<='%f'"
" ORDER BY RAND(NOW()) LIMIT 1",
DegreesStr,DegreesStr,
lowerScore,upperScore);
2016-06-04 14:21:01 +02:00
Str_SetDecimalPointToLocal (); // Return to local system
2015-06-16 20:12:38 +02:00
if (NumRows == 1) // Question found
{
/* Get next question */
row = mysql_fetch_row (mysql_res);
/* Get question code (row[0]) */
QstCod = Str_ConvertStrCodToLongCod (row[0]);
getTrivialQuestionOut->question.questionCode = (int) QstCod;
/* Get answer type (row[1]) */
AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[1]);
2019-12-06 11:53:14 +01:00
getTrivialQuestionOut->question.answerType =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Tst_MAX_BYTES_ANSWER_TYPE + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getTrivialQuestionOut->question.answerType,
2017-01-17 03:10:43 +01:00
Tst_StrAnswerTypesXML[AnswerType],
2017-03-08 03:48:23 +01:00
Tst_MAX_BYTES_ANSWER_TYPE);
2015-06-16 20:12:38 +02:00
/* Get shuffle (row[2]) */
getTrivialQuestionOut->question.shuffle = (row[2][0] == 'Y') ? 1 :
0;
/* Get question stem (row[3]) */
2019-12-06 11:53:14 +01:00
getTrivialQuestionOut->question.stem =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getTrivialQuestionOut->question.stem,row[3],
Cns_MAX_BYTES_TEXT);
2015-06-16 20:12:38 +02:00
/* Get question feedback (row[4]) */
2019-12-06 11:53:14 +01:00
getTrivialQuestionOut->question.feedback =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-15 18:02:52 +01:00
Str_Copy (getTrivialQuestionOut->question.feedback,row[4],
Cns_MAX_BYTES_TEXT);
2015-06-16 20:12:38 +02:00
}
else // Empty question
{
/* Question code (row[0]) */
QstCod = -1L;
getTrivialQuestionOut->question.questionCode = -1;
/* Answer type (row[1]) */
2020-02-24 19:31:55 +01:00
getTrivialQuestionOut->question.answerType = (char *) soap_malloc (soap,1);
2015-06-16 20:12:38 +02:00
getTrivialQuestionOut->question.answerType[0] = '\0';
/* Shuffle (row[2]) */
getTrivialQuestionOut->question.shuffle = 0;
/* Question stem (row[3]) */
2020-02-24 19:31:55 +01:00
getTrivialQuestionOut->question.stem = (char *) soap_malloc (soap,1);
2015-06-16 20:12:38 +02:00
getTrivialQuestionOut->question.stem[0] = '\0';
/* Get question feedback (row[4]) */
2020-02-24 19:31:55 +01:00
getTrivialQuestionOut->question.feedback = (char *) soap_malloc (soap,1);
2015-06-16 20:12:38 +02:00
getTrivialQuestionOut->question.feedback[0] = '\0';
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (QstCod > 0)
{
/***** Get answer from database *****/
2018-11-02 01:23:05 +01:00
NumRows =
(unsigned) DB_QuerySELECT (&mysql_res,"can not get test answers",
"SELECT QstCod,AnsInd,Correct,Answer,Feedback"
" FROM tst_answers WHERE QstCod=%ld"
" ORDER BY AnsInd",
QstCod);
2015-06-16 20:12:38 +02:00
getTrivialQuestionOut->answersArray.__size = (int) NumRows;
if (NumRows == 0)
getTrivialQuestionOut->answersArray.__ptr = NULL;
else // Answers found
{
2020-02-24 19:31:55 +01:00
getTrivialQuestionOut->answersArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getTrivialQuestionOut->answersArray.__size) *
sizeof (*(getTrivialQuestionOut->answersArray.__ptr)));
2015-06-16 20:12:38 +02:00
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
/* Get next question */
row = mysql_fetch_row (mysql_res);
/* Get question code (row[0]) */
getTrivialQuestionOut->answersArray.__ptr[NumRow].questionCode = (int) Str_ConvertStrCodToLongCod (row[0]);
/* Get answer index (row[1]) */
if (sscanf (row[1],"%u",&Index) == 1)
getTrivialQuestionOut->answersArray.__ptr[NumRow].answerIndex = (int) Index;
else
getTrivialQuestionOut->answersArray.__ptr[NumRow].answerIndex = 0; // error
/* Get correct (row[2]) */
getTrivialQuestionOut->answersArray.__ptr[NumRow].correct = (row[2][0] == 'Y') ? 1 :
0;
/* Get answer (row[3]) */
2019-12-06 11:53:14 +01:00
getTrivialQuestionOut->answersArray.__ptr[NumRow].answerText =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getTrivialQuestionOut->answersArray.__ptr[NumRow].answerText,row[3],
Cns_MAX_BYTES_TEXT);
2015-06-16 20:12:38 +02:00
/* Get feedback (row[4]) */
2019-12-06 11:53:14 +01:00
getTrivialQuestionOut->answersArray.__ptr[NumRow].answerFeedback =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Cns_MAX_BYTES_TEXT + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getTrivialQuestionOut->answersArray.__ptr[NumRow].answerFeedback,row[4],
Cns_MAX_BYTES_TEXT);
2015-06-16 20:12:38 +02:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
return SOAP_OK;
}
2019-05-16 14:02:06 +02:00
/*****************************************************************************/
/*********************** Return list of games in a course ********************/
/*****************************************************************************/
int swad__getGames (struct soap *soap,
char *wsKey,int courseCode, // input
struct swad__getGamesOutput *getGamesOut) // output
{
int ReturnCode;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
2019-12-01 21:34:50 +01:00
unsigned long NumRows;
2019-05-16 14:02:06 +02:00
int NumGame;
long GamCod;
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
long StartTime;
long EndTime;
size_t Length;
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getGames;
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
/***** Check web service key *****/
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-05-16 14:02:06 +02:00
"Bad web service key",
"Web service key does not exist in database");
/***** Check if course code is correct *****/
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2019-05-16 14:02:06 +02:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-05-16 14:02:06 +02:00
"Can not get user's data from database",
"User does not exist in database");
Gbl.Usrs.Me.Logged = true;
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2019-12-06 11:53:14 +01:00
/***** Check if I am logged as student in the course *****/
if (Gbl.Usrs.Me.Role.Logged != Rol_STD)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-06 11:53:14 +01:00
"Request forbidden",
"Requester must be a student in the course");
2019-05-16 14:02:06 +02:00
/***** Query list of games *****/
2019-12-01 21:34:50 +01:00
NumRows = DB_QuerySELECT (&mysql_res,"can not get games",
"SELECT gam_games.GamCod," // row[0]
"gam_games.UsrCod," // row[1]
"MIN(mch_matches.StartTime) AS StartTime," // row[2]
2019-12-06 11:53:14 +01:00
"MAX(mch_matches.EndTime) AS EndTime," // row[3]
2019-12-01 21:34:50 +01:00
"gam_games.MaxGrade," // row[4]
2020-02-18 15:40:04 +01:00
"gam_games.Visibility," // row[5]
"gam_games.Title," // row[6]
"gam_games.Txt" // row[7]
2019-12-01 21:34:50 +01:00
" FROM gam_games"
" LEFT JOIN mch_matches"
" ON gam_games.GamCod=mch_matches.GamCod"
" WHERE gam_games.CrsCod=%ld"
" AND Hidden='N'"
" GROUP BY gam_games.GamCod"
2020-02-18 15:40:04 +01:00
" ORDER BY StartTime DESC,"
"EndTime DESC,"
"gam_games.Title DESC",
2019-12-01 21:34:50 +01:00
Gbl.Hierarchy.Crs.CrsCod);
2019-05-16 14:02:06 +02:00
getGamesOut->gamesArray.__size =
getGamesOut->numGames = (int) NumRows;
if (getGamesOut->numGames == 0)
getGamesOut->gamesArray.__ptr = NULL;
2019-12-01 21:34:50 +01:00
else // Games found
2019-05-16 14:02:06 +02:00
{
2020-02-24 19:31:55 +01:00
getGamesOut->gamesArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getGamesOut->gamesArray.__size) *
sizeof (*(getGamesOut->gamesArray.__ptr)));
2019-05-16 14:02:06 +02:00
for (NumGame = 0;
NumGame < getGamesOut->numGames;
NumGame++)
{
2019-12-01 21:34:50 +01:00
/* Get next game */
2019-05-16 14:02:06 +02:00
row = mysql_fetch_row (mysql_res);
/* Get game code (row[0]) */
GamCod = Str_ConvertStrCodToLongCod (row[0]);
getGamesOut->gamesArray.__ptr[NumGame].gameCode = (int) GamCod;
/* Get user's code of the user who created the game (row[1]) */
Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[1]);
if (API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Gbl.Hierarchy.Crs.CrsCod)) // Get some user's data from database
{
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname1);
2019-12-06 11:53:14 +01:00
getGamesOut->gamesArray.__ptr[NumGame].userSurname1 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-05-16 14:02:06 +02:00
Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].userSurname1,
Gbl.Usrs.Other.UsrDat.Surname1,
Length);
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname2);
2019-12-06 11:53:14 +01:00
getGamesOut->gamesArray.__ptr[NumGame].userSurname2 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-05-16 14:02:06 +02:00
Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].userSurname2,
Gbl.Usrs.Other.UsrDat.Surname2,
Length);
Length = strlen (Gbl.Usrs.Other.UsrDat.FirstName);
2019-12-06 11:53:14 +01:00
getGamesOut->gamesArray.__ptr[NumGame].userFirstname =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-05-16 14:02:06 +02:00
Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].userFirstname,
Gbl.Usrs.Other.UsrDat.FirstName,
Length);
Pho_BuildLinkToPhoto (&Gbl.Usrs.Other.UsrDat,PhotoURL);
Length = strlen (PhotoURL);
2019-12-06 11:53:14 +01:00
getGamesOut->gamesArray.__ptr[NumGame].userPhoto =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-05-16 14:02:06 +02:00
Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].userPhoto,
PhotoURL,
Length);
}
else
{
getGamesOut->gamesArray.__ptr[NumGame].userSurname1 = NULL;
getGamesOut->gamesArray.__ptr[NumGame].userSurname2 = NULL;
getGamesOut->gamesArray.__ptr[NumGame].userFirstname = NULL;
getGamesOut->gamesArray.__ptr[NumGame].userPhoto = NULL;
}
/* Get game start time (row[2]) */
StartTime = 0L;
if (row[2])
sscanf (row[2],"%ld",&StartTime);
getGamesOut->gamesArray.__ptr[NumGame].startTime = StartTime;
/* Get game end time (row[3]) */
EndTime = 0L;
if (row[3])
sscanf (row[3],"%ld",&EndTime);
getGamesOut->gamesArray.__ptr[NumGame].endTime = EndTime;
2019-12-01 21:34:50 +01:00
/* Get maximum grade (row[4]) */
getGamesOut->gamesArray.__ptr[NumGame].maxGrade = Str_GetDoubleFromStr (row[4]);
if (getGamesOut->gamesArray.__ptr[NumGame].maxGrade < 0.0) // Only positive values allowed
getGamesOut->gamesArray.__ptr[NumGame].maxGrade = 0.0;
2020-02-18 15:40:04 +01:00
/* Get visibility (row[5]) */
2020-04-02 03:28:08 +02:00
getGamesOut->gamesArray.__ptr[NumGame].visibility = TstVis_GetVisibilityFromStr (row[5]);
2020-02-18 15:40:04 +01:00
/* Get title of the game (row[6]) */
Length = strlen (row[6]);
2019-12-06 11:53:14 +01:00
getGamesOut->gamesArray.__ptr[NumGame].title =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2020-02-18 15:40:04 +01:00
Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].title,row[6],
2019-05-16 14:02:06 +02:00
Length);
2020-02-18 15:40:04 +01:00
/* Get Txt (row[7]) */
Length = strlen (row[7]);
2019-12-06 11:53:14 +01:00
getGamesOut->gamesArray.__ptr[NumGame].text =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2020-02-18 15:40:04 +01:00
Str_Copy (getGamesOut->gamesArray.__ptr[NumGame].text,row[7],
2019-12-01 21:34:50 +01:00
Length);
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
/********************** Return list of matches in a game *********************/
/*****************************************************************************/
int swad__getMatches (struct soap *soap,
char *wsKey,int gameCode, // input
struct swad__getMatchesOutput *getMatchesOut) // output
{
int ReturnCode;
struct Game Game;
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
int NumMatch;
long MchCod;
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
long StartTime;
long EndTime;
size_t Length;
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-12-01 21:34:50 +01:00
Gbl.WebService.Function = API_getMatches;
/***** Check web service key *****/
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-01 21:34:50 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get game data from database *****/
Game.GamCod = (long) gameCode;
if (Game.GamCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2019-12-01 21:34:50 +01:00
"Bad game code",
"Game code must be a integer greater than 0");
Gam_GetDataOfGameByCod (&Game);
/***** Check if course code is correct *****/
Gbl.Hierarchy.Crs.CrsCod = (long) Game.CrsCod;
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2019-12-01 21:34:50 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-01 21:34:50 +01:00
"Can not get user's data from database",
"User does not exist in database");
Gbl.Usrs.Me.Logged = true;
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2019-12-06 11:53:14 +01:00
/***** Check if I am logged as student in the course *****/
if (Gbl.Usrs.Me.Role.Logged != Rol_STD)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-06 11:53:14 +01:00
"Request forbidden",
"Requester must be a student in the course");
2019-12-01 21:34:50 +01:00
/***** Query list of matches *****/
NumRows = DB_QuerySELECT (&mysql_res,"can not get matches",
"SELECT MchCod," // row[ 0]
"UsrCod," // row[ 1]
"UNIX_TIMESTAMP(StartTime)," // row[ 2]
"UNIX_TIMESTAMP(EndTime)," // row[ 3]
"Title," // row[ 4]
"QstInd" // row[ 5]
" FROM mch_matches"
" WHERE GamCod=%ld"
" AND"
"(MchCod NOT IN"
" (SELECT MchCod FROM mch_groups)"
" OR"
" MchCod IN"
" (SELECT mch_groups.MchCod"
" FROM mch_groups,crs_grp_usr"
" WHERE crs_grp_usr.UsrCod=%ld"
" AND mch_groups.GrpCod=crs_grp_usr.GrpCod))",
" ORDER BY MchCod",
Game.GamCod,
Gbl.Usrs.Me.UsrDat.UsrCod);
getMatchesOut->matchesArray.__size =
getMatchesOut->numMatches = (int) NumRows;
if (getMatchesOut->numMatches == 0)
getMatchesOut->matchesArray.__ptr = NULL;
else // Matches found
{
2020-02-24 19:31:55 +01:00
getMatchesOut->matchesArray.__ptr = soap_malloc (soap,
2019-12-06 11:53:14 +01:00
(getMatchesOut->matchesArray.__size) *
sizeof (*(getMatchesOut->matchesArray.__ptr)));
2019-12-01 21:34:50 +01:00
for (NumMatch = 0;
NumMatch < getMatchesOut->numMatches;
NumMatch++)
{
/* Get next game */
row = mysql_fetch_row (mysql_res);
/* Get match code (row[0]) */
MchCod = Str_ConvertStrCodToLongCod (row[0]);
getMatchesOut->matchesArray.__ptr[NumMatch].matchCode = (int) MchCod;
/* Get user's code of the user who created the game (row[1]) */
Gbl.Usrs.Other.UsrDat.UsrCod = Str_ConvertStrCodToLongCod (row[1]);
if (API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Gbl.Hierarchy.Crs.CrsCod)) // Get some user's data from database
{
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname1);
2019-12-06 11:53:14 +01:00
getMatchesOut->matchesArray.__ptr[NumMatch].userSurname1 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-12-01 21:34:50 +01:00
Str_Copy (getMatchesOut->matchesArray.__ptr[NumMatch].userSurname1,
Gbl.Usrs.Other.UsrDat.Surname1,
Length);
Length = strlen (Gbl.Usrs.Other.UsrDat.Surname2);
2019-12-06 11:53:14 +01:00
getMatchesOut->matchesArray.__ptr[NumMatch].userSurname2 =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-12-01 21:34:50 +01:00
Str_Copy (getMatchesOut->matchesArray.__ptr[NumMatch].userSurname2,
Gbl.Usrs.Other.UsrDat.Surname2,
Length);
Length = strlen (Gbl.Usrs.Other.UsrDat.FirstName);
2019-12-06 11:53:14 +01:00
getMatchesOut->matchesArray.__ptr[NumMatch].userFirstname =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-12-01 21:34:50 +01:00
Str_Copy (getMatchesOut->matchesArray.__ptr[NumMatch].userFirstname,
Gbl.Usrs.Other.UsrDat.FirstName,
Length);
Pho_BuildLinkToPhoto (&Gbl.Usrs.Other.UsrDat,PhotoURL);
Length = strlen (PhotoURL);
2019-12-06 11:53:14 +01:00
getMatchesOut->matchesArray.__ptr[NumMatch].userPhoto =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-12-01 21:34:50 +01:00
Str_Copy (getMatchesOut->matchesArray.__ptr[NumMatch].userPhoto,
PhotoURL,
Length);
}
else
{
getMatchesOut->matchesArray.__ptr[NumMatch].userSurname1 = NULL;
getMatchesOut->matchesArray.__ptr[NumMatch].userSurname2 = NULL;
getMatchesOut->matchesArray.__ptr[NumMatch].userFirstname = NULL;
getMatchesOut->matchesArray.__ptr[NumMatch].userPhoto = NULL;
}
/* Get match start time (row[2]) */
StartTime = 0L;
if (row[2])
sscanf (row[2],"%ld",&StartTime);
getMatchesOut->matchesArray.__ptr[NumMatch].startTime = StartTime;
/* Get match end time (row[3]) */
EndTime = 0L;
if (row[3])
sscanf (row[3],"%ld",&EndTime);
getMatchesOut->matchesArray.__ptr[NumMatch].endTime = EndTime;
/* Get title of the match (row[4]) */
Length = strlen (row[4]);
2019-12-06 11:53:14 +01:00
getMatchesOut->matchesArray.__ptr[NumMatch].title =
2020-02-24 19:31:55 +01:00
(char *) soap_malloc (soap,Length + 1);
2019-12-01 21:34:50 +01:00
Str_Copy (getMatchesOut->matchesArray.__ptr[NumMatch].title,row[4],
2019-05-16 14:02:06 +02:00
Length);
2019-12-01 21:34:50 +01:00
/* Get current question index (row[5]) */
2020-02-27 00:19:55 +01:00
getMatchesOut->matchesArray.__ptr[NumMatch].questionIndex = (int) Str_ConvertStrToUnsigned (row[5]);
2019-12-01 21:34:50 +01:00
/* Get list of groups for this match */
2020-02-24 19:31:55 +01:00
API_GetListGrpsInGameFromDB (soap,
MchCod,&(getMatchesOut->matchesArray.__ptr[NumMatch].groups));
2019-05-16 14:02:06 +02:00
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return SOAP_OK;
}
/*****************************************************************************/
2019-12-04 22:22:42 +01:00
/*********** Get match status to be refreshed in student's screen ************/
2019-12-01 21:34:50 +01:00
/*****************************************************************************/
2019-12-04 22:22:42 +01:00
int swad__getMatchStatus (struct soap *soap,
char *wsKey,int matchCode, // input
struct swad__getMatchStatusOutput *getMatchStatusOut) // output
2019-12-01 21:34:50 +01:00
{
int ReturnCode;
2019-12-02 09:57:17 +01:00
struct Match Match;
struct Game Game;
bool ICanPlayThisMatchBasedOnGrps;
2019-12-04 22:22:42 +01:00
unsigned NumOptions;
struct Mch_UsrAnswer UsrAnswer;
2019-12-01 21:34:50 +01:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-12-04 22:22:42 +01:00
Gbl.WebService.Function = API_getMatchStatus;
2019-12-01 21:34:50 +01:00
/***** Check web service key *****/
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-01 21:34:50 +01:00
"Bad web service key",
"Web service key does not exist in database");
2019-12-02 09:57:17 +01:00
/***** Get match data from database *****/
Match.MchCod = (long) matchCode;
if (Match.MchCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2019-12-02 09:57:17 +01:00
"Bad match code",
"Match code must be a integer greater than 0");
Mch_GetDataOfMatchByCod (&Match);
/***** Get game data from database *****/
Game.GamCod = Match.GamCod;
if (Game.GamCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2019-12-02 09:57:17 +01:00
"Bad game code",
"Game code must be a integer greater than 0");
Gam_GetDataOfGameByCod (&Game);
/***** Check if course code is correct *****/
Gbl.Hierarchy.Crs.CrsCod = (long) Game.CrsCod;
if (Gbl.Hierarchy.Crs.CrsCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2019-12-02 09:57:17 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/***** Get some of my data *****/
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-02 09:57:17 +01:00
"Can not get user's data from database",
"User does not exist in database");
Gbl.Usrs.Me.Logged = true;
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2019-12-06 11:53:14 +01:00
/***** Check if I am logged as student in the course *****/
if (Gbl.Usrs.Me.Role.Logged != Rol_STD)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-06 11:53:14 +01:00
"Request forbidden",
"Requester must be a student in the course");
2019-12-02 09:57:17 +01:00
/***** Can I play this match? *****/
2019-12-05 19:54:28 +01:00
ICanPlayThisMatchBasedOnGrps = Mch_CheckIfICanPlayThisMatchBasedOnGrps (&Match);
2019-12-02 09:57:17 +01:00
if (!ICanPlayThisMatchBasedOnGrps)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-02 09:57:17 +01:00
"Request forbidden",
"Requester can not join this match");
2019-12-04 22:22:42 +01:00
/***** Check question *****/
if (!Tst_CheckIfQuestionIsValidForGame (Match.Status.QstCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-04 22:22:42 +01:00
"Wrong question",
"Type of answer not valid in a game.");
2019-12-02 09:57:17 +01:00
/***** Join match *****/
2019-12-10 21:52:22 +01:00
getMatchStatusOut->matchCode = 0; // == 0 ==> wait
if (Match.Status.Playing && // Match is being played
Match.Status.Showing != Mch_END) // Unfinished
2019-12-04 22:22:42 +01:00
/* Update players */
getMatchStatusOut->matchCode = Mch_RegisterMeAsPlayerInMatch (&Match) ? matchCode : // > 0 ==> OK
-1; // < 0 ==> can not join this match
/***** Set index of question inside the game *****/
getMatchStatusOut->questionIndex = (int) Match.Status.QstInd;
/***** Set number of answers (options) in question *****/
NumOptions = Tst_GetNumAnswersQst (Match.Status.QstCod);
getMatchStatusOut->numAnswers = (int) NumOptions;
/***** Set number of selected answer *****/
if (NumOptions == 0)
getMatchStatusOut->selected = -1;
else // Answers found
2019-12-02 09:57:17 +01:00
{
2019-12-04 22:22:42 +01:00
/***** Get student's answer to this question
(<0 ==> no answer) *****/
Mch_GetQstAnsFromDB (Match.MchCod,
Gbl.Usrs.Me.UsrDat.UsrCod,
Match.Status.QstInd,
&UsrAnswer);
getMatchStatusOut->selected = UsrAnswer.NumOpt;
2019-12-02 09:57:17 +01:00
}
2019-12-01 21:34:50 +01:00
return SOAP_OK;
}
/*****************************************************************************/
/************* Send an answer to the current question in a match *************/
/*****************************************************************************/
int swad__answerMatchQuestion (struct soap *soap,
char *wsKey,int matchCode,int questionIndex,int numOption, // input
struct swad__answerMatchQuestionOutput *answerMatchQuestionOut) // output
{
int ReturnCode;
// unsigned QstInd; // 0 means that the game has not started. First question has index 1.
// unsigned NumOpt;
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-12-01 21:34:50 +01:00
Gbl.WebService.Function = API_answerMatchQuestion;
/***** Check web service key *****/
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-12-01 21:34:50 +01:00
"Bad web service key",
"Web service key does not exist in database");
// TODO: Write the code
if (questionIndex > 0 && numOption > 0)
{
// QstInd = (unsigned) questionIndex;
// NumOpt = (unsigned) numOption;
answerMatchQuestionOut->matchCode = matchCode;
}
else
{
// QstInd = 0;
// NumOpt = 0;
answerMatchQuestionOut->matchCode = -1;
}
return SOAP_OK;
}
/*****************************************************************************/
/*********************** Get lists of groups of a match **********************/
/*****************************************************************************/
2020-02-24 19:31:55 +01:00
static void API_GetListGrpsInGameFromDB (struct soap *soap,
long MchCod,char **ListGroups)
2019-05-16 14:02:06 +02:00
{
MYSQL_RES *mysql_res;
MYSQL_ROW row;
long NumGrps;
long NumGrp;
long GrpCod;
2019-11-08 01:10:32 +01:00
char GrpCodStr[Cns_MAX_DECIMAL_DIGITS_LONG + 1];
2019-05-16 14:02:06 +02:00
size_t Length;
/***** Get list of groups *****/
NumGrps =
2019-09-17 01:37:07 +02:00
(unsigned) DB_QuerySELECT (&mysql_res,"can not get groups of a match",
2019-12-01 21:34:50 +01:00
"SELECT GrpCod FROM mch_groups WHERE MchCod=%ld",
MchCod);
2019-05-16 14:02:06 +02:00
if (NumGrps == 0)
*ListGroups = NULL;
2019-12-01 21:34:50 +01:00
else // Groups found
2019-05-16 14:02:06 +02:00
{
Length = NumGrps * (10 + 1) - 1;
2020-02-24 19:31:55 +01:00
*ListGroups = soap_malloc (soap,Length + 1);
2019-05-16 14:02:06 +02:00
(*ListGroups)[0] = '\0';
for (NumGrp = 0;
NumGrp < NumGrps;
NumGrp++)
{
/* Get next group */
row = mysql_fetch_row (mysql_res);
/* Get group code (row[0]) */
GrpCod = Str_ConvertStrCodToLongCod (row[0]);
snprintf (GrpCodStr,sizeof (GrpCodStr),
NumGrp ? ",%ld" :
"%ld",
GrpCod);
Str_Concat (*ListGroups,GrpCodStr,
Length);
}
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
}
2014-12-01 23:55:08 +01:00
/*****************************************************************************/
/*************** Get a directory tree in a course or a group *****************/
/*****************************************************************************/
// TODO: should treeCode be a string with one of the followins values?
// documents
// shared
// marks
int swad__getDirectoryTree (struct soap *soap,
char *wsKey,int courseCode,int groupCode,int treeCode, // input
struct swad__getDirectoryTreeOutput *getDirectoryTreeOut) // output
{
extern const char *Brw_RootFolderInternalNames[Brw_NUM_TYPES_FILE_BROWSER];
int ReturnCode;
2017-01-28 15:58:46 +01:00
char XMLFileName[PATH_MAX + 1];
2014-12-01 23:55:08 +01:00
unsigned long FileSize;
unsigned long NumBytesRead;
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getDirectoryTree;
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (long) courseCode;
Gbl.Crs.Grps.GrpCod = (long) groupCode;
2014-12-01 23:55:08 +01:00
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check course and group codes *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckCourseAndGroupCodes (soap,
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Crs.Grps.GrpCod)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Check if I belong to course/group *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.GrpCod > 0)
if (!Grp_GetIfIBelongToGrp (Gbl.Crs.Grps.GrpCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to group");
/***** Check if tree code is correct *****/
if (treeCode <= 0 || treeCode > 3)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad tree code",
"Tree code must be 1 (documents), 2 (shared files) or 3 (marks)");
/***** Return directory tree *****/
/* Get directory tree into XML file */
if (courseCode > 0)
{
if (groupCode > 0)
switch (treeCode)
{
case 1: // Documents
2017-10-08 00:51:49 +02:00
Gbl.FileBrowser.Type = Brw_SHOW_DOC_GRP;
2014-12-01 23:55:08 +01:00
break;
case 2: // Shared files
2017-10-08 00:51:49 +02:00
Gbl.FileBrowser.Type = Brw_ADMI_SHR_GRP;
2014-12-01 23:55:08 +01:00
break;
case 3: // Marks
2017-10-08 00:51:49 +02:00
Gbl.FileBrowser.Type = Brw_SHOW_MRK_GRP;
2014-12-01 23:55:08 +01:00
break;
}
else // groupCode <= 0
switch (treeCode)
{
case 1: // Documents
2017-10-08 00:51:49 +02:00
Gbl.FileBrowser.Type = Brw_SHOW_DOC_CRS;
2014-12-01 23:55:08 +01:00
break;
case 2: // Shared files
2017-10-08 00:51:49 +02:00
Gbl.FileBrowser.Type = Brw_ADMI_SHR_CRS;
2014-12-01 23:55:08 +01:00
break;
case 3: // Marks
2017-10-08 00:51:49 +02:00
Gbl.FileBrowser.Type = Brw_SHOW_MRK_CRS;
2014-12-01 23:55:08 +01:00
break;
}
}
else
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad course code",
"Course code must be a integer greater than 0");
/* Initialize path to private directory */
2019-04-04 10:45:15 +02:00
Gbl.Hierarchy.Crs.CrsCod = (courseCode > 0) ? (long) courseCode :
2014-12-01 23:55:08 +01:00
-1L;
2019-04-04 10:45:15 +02:00
Gbl.Crs.Grps.GrpCod = (groupCode > 0) ? (long) groupCode :
2014-12-01 23:55:08 +01:00
-1L;
2019-04-04 10:45:15 +02:00
snprintf (Gbl.Crs.PathPriv,sizeof (Gbl.Crs.PathPriv),
2019-03-20 01:36:36 +01:00
"%s/%ld",
2019-04-04 10:45:15 +02:00
Cfg_PATH_CRS_PRIVATE,Gbl.Hierarchy.Crs.CrsCod);
2014-12-01 23:55:08 +01:00
Brw_InitializeFileBrowser ();
2019-04-25 14:39:51 +02:00
Str_Copy (Gbl.FileBrowser.FilFolLnk.Path,Brw_RootFolderInternalNames[Gbl.FileBrowser.Type],
PATH_MAX);
Str_Copy (Gbl.FileBrowser.FilFolLnk.Name,".",
NAME_MAX);
Brw_SetFullPathInTree ();
2014-12-01 23:55:08 +01:00
2014-12-21 14:47:04 +01:00
/* Check if exists the directory for HTML output. If not exists, create it */
2019-03-20 01:36:36 +01:00
Fil_CreateDirIfNotExists (Cfg_PATH_OUT_PRIVATE);
2014-12-01 23:55:08 +01:00
/* Create a unique name for the file */
2018-10-18 02:02:32 +02:00
snprintf (XMLFileName,sizeof (XMLFileName),
"%s/%s.xml",
2019-03-20 01:36:36 +01:00
Cfg_PATH_OUT_PRIVATE,Gbl.UniqueNameEncrypted);
2014-12-01 23:55:08 +01:00
/* Open file for writing and reading */
if ((Gbl.F.XML = fopen (XMLFileName,"w+t")) == NULL)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Can not get tree",
"Can not create temporary XML file");
/* Get directory tree into XML file */
XML_WriteStartFile (Gbl.F.XML,"tree",false);
if (!Brw_CheckIfFileOrFolderIsSetAsHiddenInDB (Brw_IS_FOLDER,
2019-04-25 14:39:51 +02:00
Gbl.FileBrowser.FilFolLnk.Full)) // If root folder is visible
2019-05-16 14:02:06 +02:00
API_ListDir (1,Gbl.FileBrowser.Priv.PathRootFolder,Brw_RootFolderInternalNames[Gbl.FileBrowser.Type]);
2014-12-01 23:55:08 +01:00
XML_WriteEndFile (Gbl.F.XML,"tree");
/* Compute file size */
// fseek (Gbl.F.XML,0L,SEEK_END);
FileSize = (unsigned long) ftell (Gbl.F.XML);
fseek (Gbl.F.XML,0L,SEEK_SET);
/* Copy XML content from file to memory */
2020-02-24 19:31:55 +01:00
getDirectoryTreeOut->tree = (char *) soap_malloc (soap,FileSize + 1);
2014-12-01 23:55:08 +01:00
NumBytesRead = fread (getDirectoryTreeOut->tree,1,FileSize,Gbl.F.XML);
getDirectoryTreeOut->tree[NumBytesRead] = '\0';
/* Close and remove XML file */
Fil_CloseXMLFile ();
unlink (XMLFileName);
return SOAP_OK;
}
/*****************************************************************************/
/************************ List a directory recursively ***********************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
static void API_ListDir (unsigned Level,const char *Path,const char *PathInTree)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_NEW_LINE;
2015-12-21 13:36:39 +01:00
struct dirent **FileList;
int NumFile;
int NumFiles;
2018-11-09 20:47:39 +01:00
char PathFileRel[PATH_MAX + 1 + NAME_MAX + 1];
char PathFileInExplTree[PATH_MAX + 1 + NAME_MAX + 1];
2014-12-01 23:55:08 +01:00
struct stat FileStatus;
/***** Scan directory *****/
2015-12-21 13:36:39 +01:00
if ((NumFiles = scandir (Path,&FileList,NULL,alphasort)) >= 0) // No error
{
/***** List files *****/
for (NumFile = 0;
NumFile < NumFiles;
NumFile++)
{
if (strcmp (FileList[NumFile]->d_name,".") &&
strcmp (FileList[NumFile]->d_name,"..")) // Skip directories "." and ".."
{
2018-10-18 02:02:32 +02:00
snprintf (PathFileRel,sizeof (PathFileRel),
"%s/%s",
Path,FileList[NumFile]->d_name);
snprintf (PathFileInExplTree,sizeof (PathFileInExplTree),
"%s/%s",
PathInTree,FileList[NumFile]->d_name);
2014-12-01 23:55:08 +01:00
2019-04-25 14:39:51 +02:00
Str_Copy (Gbl.FileBrowser.FilFolLnk.Path,PathInTree,
PATH_MAX);
Str_Copy (Gbl.FileBrowser.FilFolLnk.Name,FileList[NumFile]->d_name,
NAME_MAX);
2016-12-29 22:00:35 +01:00
if (!lstat (PathFileRel,&FileStatus)) // On success ==> 0 is returned
2014-12-01 23:55:08 +01:00
{
2016-12-29 22:00:35 +01:00
/***** Construct the full path of the file or folder *****/
2019-04-25 14:39:51 +02:00
Brw_SetFullPathInTree ();
2014-12-01 23:55:08 +01:00
2016-12-29 22:00:35 +01:00
if (S_ISDIR (FileStatus.st_mode)) // It's a directory
{
/***** Write a row for the subdirectory *****/
2019-05-16 14:02:06 +02:00
if (API_WriteRowFileBrowser (Level,Brw_IS_FOLDER,FileList[NumFile]->d_name))
2016-12-29 22:00:35 +01:00
{
/* List subtree starting at this this directory */
2019-05-16 14:02:06 +02:00
API_ListDir (Level + 1,PathFileRel,PathFileInExplTree);
2016-12-29 22:00:35 +01:00
/* Indent and end dir */
2019-05-16 14:02:06 +02:00
API_IndentXMLLine (Level);
2016-12-29 22:00:35 +01:00
fprintf (Gbl.F.XML,"</dir>%s",Txt_NEW_LINE);
}
2015-12-21 13:36:39 +01:00
}
2016-12-29 22:00:35 +01:00
else if (S_ISREG (FileStatus.st_mode)) // It's a regular file
2019-05-16 14:02:06 +02:00
API_WriteRowFileBrowser (Level,
2016-12-29 22:00:35 +01:00
Str_FileIs (FileList[NumFile]->d_name,"url") ? Brw_IS_LINK :
Brw_IS_FILE,
FileList[NumFile]->d_name);
2014-12-01 23:55:08 +01:00
}
}
2015-12-21 13:36:39 +01:00
2019-11-06 19:45:20 +01:00
free (FileList[NumFile]);
2014-12-01 23:55:08 +01:00
}
2019-11-06 19:45:20 +01:00
free (FileList);
2015-12-21 13:36:39 +01:00
}
2014-12-01 23:55:08 +01:00
}
/*****************************************************************************/
/*********************** Write a row of a file browser ***********************/
/*****************************************************************************/
// If it is the first row (root folder), always show it
// If it is not the first row, it is shown or not depending on whether it is hidden or not
// If the row is visible, return true. If it is hidden, return false
2019-05-16 14:02:06 +02:00
static bool API_WriteRowFileBrowser (unsigned Level,Brw_FileType_t FileType,const char *FileName)
2014-12-01 23:55:08 +01:00
{
extern const char *Txt_NEW_LINE;
extern const char *Txt_LICENSES[Brw_NUM_LICENSES];
struct FileMetadata FileMetadata;
2017-03-07 01:56:41 +01:00
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2014-12-01 23:55:08 +01:00
/***** Is this row hidden or visible? *****/
2017-10-08 00:51:49 +02:00
if (Gbl.FileBrowser.Type == Brw_SHOW_DOC_CRS ||
Gbl.FileBrowser.Type == Brw_SHOW_DOC_GRP)
2014-12-01 23:55:08 +01:00
if (Brw_CheckIfFileOrFolderIsSetAsHiddenInDB (FileType,
2019-04-25 14:39:51 +02:00
Gbl.FileBrowser.FilFolLnk.Full))
2014-12-01 23:55:08 +01:00
return false;
/***** XML row *****/
/* Indent */
2019-05-16 14:02:06 +02:00
API_IndentXMLLine (Level);
2014-12-01 23:55:08 +01:00
/* Write file or folder data */
if (FileType == Brw_IS_FOLDER)
fprintf (Gbl.F.XML,"<dir name=\"%s\">%s",
FileName,Txt_NEW_LINE);
else // File or link
{
/* Get file metadata */
Brw_GetFileMetadataByPath (&FileMetadata);
2015-02-23 23:45:32 +01:00
Brw_GetFileTypeSizeAndDate (&FileMetadata);
2014-12-01 23:55:08 +01:00
if (FileMetadata.FilCod <= 0) // No entry for this file in database table of files
/* Add entry to the table of files/folders */
2019-04-25 15:31:42 +02:00
FileMetadata.FilCod = Brw_AddPathToDB (-1L,FileMetadata.FilFolLnk.Type,
2019-04-25 14:39:51 +02:00
Gbl.FileBrowser.FilFolLnk.Full,false,Brw_LICENSE_DEFAULT);
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Other.UsrDat.UsrCod = FileMetadata.PublisherUsrCod;
2019-03-19 13:22:14 +01:00
Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS);
2016-07-08 12:43:48 +02:00
Pho_BuildLinkToPhoto (&Gbl.Usrs.Me.UsrDat,PhotoURL);
2014-12-01 23:55:08 +01:00
fprintf (Gbl.F.XML,"<file name=\"%s\">"
"<code>%ld</code>"
"<size>%lu</size>"
"<time>%lu</time>"
"<license>%s</license>"
"<publisher>%s</publisher>"
"<photo>%s</photo>"
"</file>%s",
FileName,
FileMetadata.FilCod,
(unsigned long) FileMetadata.Size,
(unsigned long) FileMetadata.Time,
Txt_LICENSES[FileMetadata.License],
Gbl.Usrs.Other.UsrDat.FullName,
PhotoURL,
Txt_NEW_LINE);
}
return true;
}
/*****************************************************************************/
/******************************* Indent XML line *****************************/
/*****************************************************************************/
2019-05-16 14:02:06 +02:00
static void API_IndentXMLLine (unsigned Level)
2014-12-01 23:55:08 +01:00
{
for ( ;
Level;
Level--)
fprintf (Gbl.F.XML,"\t");
}
/*****************************************************************************/
/**************************** Get info of a file *****************************/
/*****************************************************************************/
int swad__getFile (struct soap *soap,
char *wsKey,int fileCode, // input
struct swad__getFileOutput *getFileOut) // output
{
extern const char *Txt_LICENSES[Brw_NUM_LICENSES];
int ReturnCode;
struct FileMetadata FileMetadata;
2017-03-07 01:56:41 +01:00
char URL[Cns_MAX_BYTES_WWW + 1];
char PhotoURL[Cns_MAX_BYTES_WWW + 1];
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getFile;
2014-12-01 23:55:08 +01:00
/***** Allocate space for strings *****/
2020-02-24 19:31:55 +01:00
getFileOut->fileName = (char *) soap_malloc (soap,NAME_MAX + 1);
getFileOut->URL = (char *) soap_malloc (soap,Cns_MAX_BYTES_WWW + 1);
getFileOut->license = (char *) soap_malloc (soap,Brw_MAX_BYTES_LICENSE + 1);
getFileOut->publisherName = (char *) soap_malloc (soap,Usr_MAX_BYTES_FULL_NAME + 1);
getFileOut->publisherPhoto = (char *) soap_malloc (soap,Cns_MAX_BYTES_WWW + 1);
2014-12-01 23:55:08 +01:00
/***** Default values returned on error *****/
getFileOut->fileName[0] = '\0';
getFileOut->URL[0] = '\0';
getFileOut->size = 0;
getFileOut->time = 0;
getFileOut->license[0] = '\0';
getFileOut->publisherName[0] = '\0';
getFileOut->publisherPhoto[0] = '\0';
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get file metadata *****/
FileMetadata.FilCod = (long) fileCode;
if (FileMetadata.FilCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad file code",
"File code must be a integer greater than 0");
Brw_GetFileMetadataByCod (&FileMetadata);
if (FileMetadata.FilCod <= 0)
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"File does not exist, please refresh",
"The file requested does not exists");
/***** Set course and group codes *****/
2015-01-25 02:07:04 +01:00
Brw_GetCrsGrpFromFileMetadata (FileMetadata.FileBrowser,FileMetadata.Cod,
2019-04-03 20:57:04 +02:00
&Gbl.Hierarchy.Ins.InsCod,
&Gbl.Hierarchy.Ctr.CtrCod,
&Gbl.Hierarchy.Deg.DegCod,
2019-04-04 10:45:15 +02:00
&Gbl.Hierarchy.Crs.CrsCod,
&Gbl.Crs.Grps.GrpCod);
2014-12-01 23:55:08 +01:00
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
/***** Check course and group codes *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckCourseAndGroupCodes (soap,
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Crs.Grps.GrpCod)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Check if I belong to group *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.GrpCod > 0)
if (!Grp_GetIfIBelongToGrp (Gbl.Crs.Grps.GrpCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to group");
/***** Check if file is in a valid zone *****/
2019-04-25 14:39:51 +02:00
Gbl.FileBrowser.Type = FileMetadata.FileBrowser;
switch (Gbl.FileBrowser.Type)
2014-12-01 23:55:08 +01:00
{
2017-10-08 00:51:49 +02:00
case Brw_ADMI_DOC_CRS:
case Brw_ADMI_DOC_GRP:
case Brw_ADMI_SHR_CRS:
case Brw_ADMI_SHR_GRP:
2014-12-01 23:55:08 +01:00
break;
2017-10-08 00:51:49 +02:00
case Brw_ADMI_MRK_CRS:
case Brw_ADMI_MRK_GRP:
2014-12-01 23:55:08 +01:00
// Downloading a file of marks is only allowed for teachers
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2019-04-25 14:39:51 +02:00
"Wrong tree",
"Wrong file zone");
2014-12-01 23:55:08 +01:00
break;
default:
2020-02-24 19:31:55 +01:00
return soap_sender_fault (soap,
2014-12-01 23:55:08 +01:00
"Wrong tree",
"Wrong file zone");
}
/***** Set paths *****/
2016-11-14 17:26:32 +01:00
Hie_InitHierarchy ();
2014-12-01 23:55:08 +01:00
Brw_InitializeFileBrowser ();
2019-04-25 15:31:42 +02:00
Str_Copy (Gbl.FileBrowser.FilFolLnk.Path,FileMetadata.FilFolLnk.Path,
2019-04-25 14:39:51 +02:00
PATH_MAX);
2019-04-25 15:31:42 +02:00
Str_Copy (Gbl.FileBrowser.FilFolLnk.Name,FileMetadata.FilFolLnk.Name,
2019-04-25 14:39:51 +02:00
NAME_MAX);
Brw_SetFullPathInTree ();
2014-12-01 23:55:08 +01:00
/***** Get file size and date *****/
2015-02-23 23:45:32 +01:00
Brw_GetFileTypeSizeAndDate (&FileMetadata);
2014-12-01 23:55:08 +01:00
/***** Update number of views *****/
Brw_GetAndUpdateFileViews (&FileMetadata);
/***** Create and get link to download the file *****/
2019-04-25 15:31:42 +02:00
Brw_GetLinkToDownloadFile (FileMetadata.FilFolLnk.Path,
FileMetadata.FilFolLnk.Name,
2014-12-01 23:55:08 +01:00
URL);
/***** Copy data into output structure *****/
2019-04-25 15:31:42 +02:00
Str_Copy (getFileOut->fileName,FileMetadata.FilFolLnk.Name,
2017-01-17 03:10:43 +01:00
NAME_MAX);
2014-12-01 23:55:08 +01:00
2017-01-17 03:10:43 +01:00
Str_Copy (getFileOut->URL,URL,
2017-03-07 01:56:41 +01:00
Cns_MAX_BYTES_WWW);
2014-12-01 23:55:08 +01:00
getFileOut->size = (int) FileMetadata.Size;
getFileOut->time = (int) FileMetadata.Time;
2017-01-15 18:02:52 +01:00
Str_Copy (getFileOut->license,Txt_LICENSES[FileMetadata.License],
2017-03-07 11:03:05 +01:00
Brw_MAX_BYTES_LICENSE);
2014-12-01 23:55:08 +01:00
if ((Gbl.Usrs.Other.UsrDat.UsrCod = FileMetadata.PublisherUsrCod) > 0)
/* Get publisher's data */
2019-03-19 13:22:14 +01:00
if (Usr_ChkUsrCodAndGetAllUsrDataFromUsrCod (&Gbl.Usrs.Other.UsrDat,Usr_DONT_GET_PREFS))
2014-12-01 23:55:08 +01:00
/* Copy publisher's data into output structure */
{
2017-01-15 18:02:52 +01:00
Str_Copy (getFileOut->publisherName,Gbl.Usrs.Other.UsrDat.FullName,
Usr_MAX_BYTES_FULL_NAME);
2014-12-01 23:55:08 +01:00
2016-07-08 12:43:48 +02:00
Pho_BuildLinkToPhoto (&Gbl.Usrs.Other.UsrDat,PhotoURL);
2017-01-17 03:10:43 +01:00
Str_Copy (getFileOut->publisherPhoto,PhotoURL,
2017-03-07 01:56:41 +01:00
Cns_MAX_BYTES_WWW);
2014-12-01 23:55:08 +01:00
}
return SOAP_OK;
}
/*****************************************************************************/
/**************************** Get info of my marks ***************************/
/*****************************************************************************/
int swad__getMarks (struct soap *soap,
char *wsKey,int fileCode, // input
struct swad__getMarksOutput *getMarksOut) // output
{
int ReturnCode;
struct FileMetadata FileMetadata;
2017-03-08 14:12:33 +01:00
char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1]; // Not used
2014-12-01 23:55:08 +01:00
char *ContentStr;
2017-01-15 22:58:26 +01:00
size_t Length;
2014-12-01 23:55:08 +01:00
2016-07-20 20:24:16 +02:00
/***** Initializations *****/
2020-02-24 19:31:55 +01:00
API_Set_gSOAP_RuntimeEnv (soap);
2019-05-16 14:02:06 +02:00
Gbl.WebService.Function = API_getMarks;
2014-12-01 23:55:08 +01:00
getMarksOut->content = NULL;
/***** Check web service key *****/
2019-05-16 14:02:06 +02:00
if ((ReturnCode = API_CheckWSKey (wsKey)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
if (Gbl.Usrs.Me.UsrDat.UsrCod < 0) // Web service key does not exist in database
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad web service key",
"Web service key does not exist in database");
/***** Get file metadata *****/
FileMetadata.FilCod = (long) fileCode;
Brw_GetFileMetadataByCod (&FileMetadata);
2019-04-25 15:31:42 +02:00
if (FileMetadata.FilFolLnk.Type != Brw_IS_FILE ||
2014-12-01 23:55:08 +01:00
FileMetadata.IsHidden ||
2017-10-08 00:51:49 +02:00
(FileMetadata.FileBrowser != Brw_ADMI_MRK_CRS &&
FileMetadata.FileBrowser != Brw_ADMI_MRK_GRP))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Bad file code",
"You can not get marks from this file");
2015-01-25 00:58:21 +01:00
/***** Set course and group codes *****/
2015-01-25 02:07:04 +01:00
Brw_GetCrsGrpFromFileMetadata (FileMetadata.FileBrowser,FileMetadata.Cod,
2019-04-03 20:57:04 +02:00
&Gbl.Hierarchy.Ins.InsCod,
&Gbl.Hierarchy.Ctr.CtrCod,
&Gbl.Hierarchy.Deg.DegCod,
2019-04-04 10:45:15 +02:00
&Gbl.Hierarchy.Crs.CrsCod,
&Gbl.Crs.Grps.GrpCod);
2014-12-01 23:55:08 +01:00
/***** Check course and group codes *****/
2020-02-24 19:31:55 +01:00
if ((ReturnCode = API_CheckCourseAndGroupCodes (soap,
Gbl.Hierarchy.Crs.CrsCod,
Gbl.Crs.Grps.GrpCod)) != SOAP_OK)
2014-12-01 23:55:08 +01:00
return ReturnCode;
/***** Get some of my data *****/
2019-05-16 14:02:06 +02:00
if (!API_GetSomeUsrDataFromUsrCod (&Gbl.Usrs.Me.UsrDat,Gbl.Hierarchy.Crs.CrsCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2016-07-20 20:24:16 +02:00
"Can not get user's data from database",
"User does not exist in database");
2014-12-01 23:55:08 +01:00
Gbl.Usrs.Me.Logged = true;
2017-06-08 15:32:33 +02:00
Gbl.Usrs.Me.Role.Logged = Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role;
2014-12-01 23:55:08 +01:00
2017-05-23 00:40:03 +02:00
/***** Check if I am a student, non-editing teacher or teacher in the course *****/
2017-06-08 15:32:33 +02:00
if (Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_STD &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_NET &&
Gbl.Usrs.Me.UsrDat.Roles.InCurrentCrs.Role != Rol_TCH)
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to course");
/***** Check if I belong to group *****/
2019-04-04 10:45:15 +02:00
if (Gbl.Crs.Grps.GrpCod > 0)
if (!Grp_GetIfIBelongToGrp (Gbl.Crs.Grps.GrpCod))
2020-02-24 19:31:55 +01:00
return soap_receiver_fault (soap,
2014-12-01 23:55:08 +01:00
"Request forbidden",
"Requester must belong to group");
/***** Get content *****/
ContentStr = NULL;
2017-03-06 13:01:16 +01:00
Mrk_GetNotifMyMarks (SummaryStr, // Not used
&ContentStr,
FileMetadata.FilCod,Gbl.Usrs.Me.UsrDat.UsrCod,true);
2014-12-01 23:55:08 +01:00
if (ContentStr != NULL)
{
2017-01-15 22:58:26 +01:00
Length = strlen (ContentStr);
2020-02-24 19:31:55 +01:00
getMarksOut->content = (char *) soap_malloc (soap,Length + 1);
2017-01-17 03:10:43 +01:00
Str_Copy (getMarksOut->content,ContentStr,
Length);
2019-11-06 19:45:20 +01:00
free (ContentStr);
2014-12-01 23:55:08 +01:00
ContentStr = NULL;
}
else
{
2020-02-24 19:31:55 +01:00
getMarksOut->content = (char *) soap_malloc (soap,1);
2014-12-01 23:55:08 +01:00
getMarksOut->content[0] = '\0';
}
return SOAP_OK;
}