Version18.78

This commit is contained in:
Antonio Cañas Vargas 2019-03-17 14:47:58 +01:00
parent 774ff78ca6
commit 1af2a3277e
8 changed files with 191 additions and 202 deletions

View File

@ -427,6 +427,8 @@ Lo de mutear anuncios, en principio prefiero hacer una opci
// Para bloquear/desbloquear se usará un icono candado // Para bloquear/desbloquear se usará un icono candado
// Para preasignado/no preasignado usar otro icono (usuario/usuario tachado, por ej.) // Para preasignado/no preasignado usar otro icono (usuario/usuario tachado, por ej.)
// TODO: Check if Feedback is set to "(null)" when importing test questions. Change columns Feedback "(null)" to "" in test questions
// TODO: Select users individually in action to send email // TODO: Select users individually in action to send email
// TODO: Actualizar ayuda en GitHub, por ejemplo Preferencias ahora es Ajustes. // TODO: Actualizar ayuda en GitHub, por ejemplo Preferencias ahora es Ajustes.
@ -457,7 +459,7 @@ En OpenSWAD:
ps2pdf source.ps destination.pdf ps2pdf source.ps destination.pdf
*/ */
#define Log_PLATFORM_VERSION "SWAD 18.77.5 (2019-03-17)" #define Log_PLATFORM_VERSION "SWAD 18.77.6 (2019-03-17)"
#define CSS_FILE "swad18.77.css" #define CSS_FILE "swad18.77.css"
#define JS_FILE "swad18.77.js" #define JS_FILE "swad18.77.js"
/* /*
@ -473,7 +475,10 @@ Si el usuario acepta, a partir de ese momento se le mostrar
Ese bloqueo o aceptación sería una opción en Perfil > Ajustes Ese bloqueo o aceptación sería una opción en Perfil > Ajustes
que el usuario podría cambiar en cualquier momento. que el usuario podría cambiar en cualquier momento.
Version 18.77.5: Mar 16, 2019 Fixed bugs in forms to upload media. (240272 lines) Version 18.79: Mar 17, 2019 YouTube videos are not shown if user doesn't accept third party cookies. (? lines)
Version 18.78: Mar 17, 2019 Fixed bugs and code refactoring in media.
Code refactoring in tests. (240252 lines)
Version 18.77.5: Mar 17, 2019 Fixed bugs in forms to upload media. (240272 lines)
Version 18.77.4: Mar 16, 2019 Changes in form to upload media. (240256 lines) Version 18.77.4: Mar 16, 2019 Changes in form to upload media. (240256 lines)
Version 18.77.3: Mar 16, 2019 Embedded YouTube videos. Not finished. (240252 lines) Version 18.77.3: Mar 16, 2019 Embedded YouTube videos. Not finished. (240252 lines)
Version 18.77.2: Mar 14, 2019 Embedded YouTube videos. Not finished. (240267 lines) Version 18.77.2: Mar 14, 2019 Embedded YouTube videos. Not finished. (240267 lines)

View File

@ -501,9 +501,9 @@ static long For_InsertForumPst (long ThrCod,long UsrCod,
long PstCod; long PstCod;
/***** Check if image is received and processed *****/ /***** Check if image is received and processed *****/
if (Media->Action == Med_ACTION_NEW_MEDIA && // Upload new image if (Media->Action == Med_ACTION_NEW_MEDIA && // New media
Media->Status == Med_PROCESSED) // The new image received has been processed Media->Status == Med_PROCESSED) // The new media received has been processed
/* Move processed image to definitive directory */ /* Move processed media to definitive directory */
Med_MoveMediaToDefinitiveDir (Media); Med_MoveMediaToDefinitiveDir (Media);
/***** Insert forum post in the database *****/ /***** Insert forum post in the database *****/
@ -973,6 +973,7 @@ static void For_ShowPostsOfAThread (Ale_AlertType_t AlertType,const char *Messag
/***** Show alert after action *****/ /***** Show alert after action *****/
Lay_StartSection (For_FORUM_POSTS_SECTION_ID); Lay_StartSection (For_FORUM_POSTS_SECTION_ID);
Ale_ShowAlerts (For_FORUM_POSTS_SECTION_ID); // Possible pending alerts
if (Message) if (Message)
if (Message[0]) if (Message[0])
Ale_ShowAlert (AlertType,Message); Ale_ShowAlert (AlertType,Message);
@ -4053,14 +4054,15 @@ void For_ReceiveForumPost (void)
Par_GetParAndChangeFormat ("Content",Content,Cns_MAX_BYTES_LONG_TEXT, Par_GetParAndChangeFormat ("Content",Content,Cns_MAX_BYTES_LONG_TEXT,
Str_TO_RIGOROUS_HTML,false); Str_TO_RIGOROUS_HTML,false);
/***** Initialize image *****/ /***** Initialize media *****/
Med_MediaConstructor (&Media); Med_MediaConstructor (&Media);
/***** Get attached image (action, file and title) *****/ /***** Get attached media *****/
Media.Width = For_IMAGE_SAVED_MAX_WIDTH; Media.Width = For_IMAGE_SAVED_MAX_WIDTH;
Media.Height = For_IMAGE_SAVED_MAX_HEIGHT; Media.Height = For_IMAGE_SAVED_MAX_HEIGHT;
Media.Quality = For_IMAGE_SAVED_QUALITY; Media.Quality = For_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm (-1,&Media,NULL); Med_GetMediaFromForm (-1,&Media,NULL,
For_FORUM_POSTS_SECTION_ID); // Alerts will be shown later in posts section
/***** Create a new message *****/ /***** Create a new message *****/
if (IsReply) // This post is a reply to another posts in the thread if (IsReply) // This post is a reply to another posts in the thread

View File

@ -103,6 +103,10 @@ extern struct Globals Gbl;
/***************************** Internal prototypes ***************************/ /***************************** Internal prototypes ***************************/
/*****************************************************************************/ /*****************************************************************************/
static void Med_ResetMediaExceptURLAndTitle (struct Media *Media);
static void Med_FreeMediaURL (struct Media *Media);
static void Med_FreeMediaTitle (struct Media *Media);
static Med_Action_t Med_GetMediaActionFromForm (const char *ParamAction); static Med_Action_t Med_GetMediaActionFromForm (const char *ParamAction);
static Med_FormType_t Usr_GetFormTypeFromForm (struct ParamUploadMedia *ParamUploadMedia); static Med_FormType_t Usr_GetFormTypeFromForm (struct ParamUploadMedia *ParamUploadMedia);
static void Usr_GetURLFromForm (const char *ParamName,struct Media *Media); static void Usr_GetURLFromForm (const char *ParamName,struct Media *Media);
@ -153,62 +157,59 @@ static Med_Type_t Med_GetTypeFromExtAndMIME (const char *Extension,
const char *MIMEType); const char *MIMEType);
/*****************************************************************************/ /*****************************************************************************/
/********************* Reset media (image/video) fields **********************/ /********************** Media (image/video) constructor **********************/
/*****************************************************************************/ /*****************************************************************************/
// Every struct Media must be initialized with this constructor function after it is declared // Every struct Media must be initialized with this constructor function after it is declared
// Every call to constructor must have a call to destructor // Every call to constructor must have a call to destructor
void Med_MediaConstructor (struct Media *Media) void Med_MediaConstructor (struct Media *Media)
{ {
Med_ResetMediaExceptTitleAndURL (Media); Med_ResetMediaExceptURLAndTitle (Media);
Media->Title = NULL;
Media->URL = NULL; Media->URL = NULL;
Media->Title = NULL;
} }
/*****************************************************************************/ /*****************************************************************************/
/***************** Reset image fields except title and URL *******************/ /********************** Media (image/video) destructor ***********************/
/*****************************************************************************/
void Med_ResetMediaExceptTitleAndURL (struct Media *Media)
{
Media->Action = Med_ACTION_NO_MEDIA;
Media->Status = Med_STATUS_NONE;
Media->Name[0] = '\0';
Media->Type = Med_TYPE_NONE;
}
/*****************************************************************************/
/************************ Free media (image/video) ***************************/
/*****************************************************************************/ /*****************************************************************************/
// Every call to constructor must have a call to destructor // Every call to constructor must have a call to destructor
void Med_MediaDestructor (struct Media *Media) void Med_MediaDestructor (struct Media *Media)
{ {
Med_FreeMediaTitle (Media); Med_ResetMedia (Media);
Med_FreeMediaURL (Media);
} }
/*****************************************************************************/ /*****************************************************************************/
/****************************** Free image title *****************************/ /********************* Reset media (image/video) fields **********************/
/*****************************************************************************/
// Media must be constructed before calling this function
void Med_ResetMedia (struct Media *Media)
{
Med_ResetMediaExceptURLAndTitle (Media);
Med_FreeMediaURL (Media);
Med_FreeMediaTitle (Media);
}
/*****************************************************************************/
/***************** Reset media fields except URL and title *******************/
/*****************************************************************************/ /*****************************************************************************/
void Med_FreeMediaTitle (struct Media *Media) static void Med_ResetMediaExceptURLAndTitle (struct Media *Media)
{ {
// Media->Title must be initialized to NULL after declaration Media->Action = Med_ACTION_NO_MEDIA;
if (Media->Title) Media->Status = Med_STATUS_NONE;
{ Media->Name[0] = '\0';
free ((void *) Media->Title); Media->Type = Med_TYPE_NONE;
Media->Title = NULL;
}
} }
/*****************************************************************************/ /*****************************************************************************/
/******************************* Free image URL ******************************/ /******************************* Free image URL ******************************/
/*****************************************************************************/ /*****************************************************************************/
void Med_FreeMediaURL (struct Media *Media) static void Med_FreeMediaURL (struct Media *Media)
{ {
// Media->URL must be initialized to NULL after declaration // Media->URL is initialized to NULL in constructor
if (Media->URL) if (Media->URL)
{ {
free ((void *) Media->URL); free ((void *) Media->URL);
@ -216,6 +217,20 @@ void Med_FreeMediaURL (struct Media *Media)
} }
} }
/*****************************************************************************/
/****************************** Free image title *****************************/
/*****************************************************************************/
static void Med_FreeMediaTitle (struct Media *Media)
{
// Media->Title is initialized to NULL in constructor
if (Media->Title)
{
free ((void *) Media->Title);
Media->Title = NULL;
}
}
/*****************************************************************************/ /*****************************************************************************/
/**** Get media name, title and URL from a query result and copy to struct ***/ /**** Get media name, title and URL from a query result and copy to struct ***/
/*****************************************************************************/ /*****************************************************************************/
@ -391,32 +406,28 @@ void Med_PutMediaUploader (int NumMediaInForm,const char *ClassInput)
/*****************************************************************************/ /*****************************************************************************/
/******************** Get media (image/video) from form **********************/ /******************** Get media (image/video) from form **********************/
/*****************************************************************************/ /*****************************************************************************/
// Media constructor must be called before calling this function
// If NumMediaInForm < 0, params have no suffix // If NumMediaInForm < 0, params have no suffix
// If NumMediaInForm >= 0, the number is a suffix of the params // If NumMediaInForm >= 0, the number is a suffix of the params
void Med_GetMediaFromForm (int NumMediaInForm,struct Media *Media, void Med_GetMediaFromForm (int NumMediaInForm,struct Media *Media,
void (*GetMediaFromDB) (int NumMediaInForm,struct Media *Media)) void (*GetMediaFromDB) (int NumMediaInForm,struct Media *Media),
const char *SectionForAlerts)
{ {
extern const char *Txt_Error_sending_or_processing_image_video;
struct ParamUploadMedia ParamUploadMedia; struct ParamUploadMedia ParamUploadMedia;
Med_Action_t Action;
Med_FormType_t FormType; Med_FormType_t FormType;
/***** Initialize media *****/
Media->Action = Med_ACTION_NO_MEDIA;
Media->Status = Med_STATUS_NONE;
Media->Name[0] = '\0';
Media->Type = Med_TYPE_NONE;
Media->Title = NULL;
Media->URL = NULL;
/***** Set names of parameters depending on number of media in form *****/ /***** Set names of parameters depending on number of media in form *****/
Med_SetParamNames (&ParamUploadMedia,NumMediaInForm); Med_SetParamNames (&ParamUploadMedia,NumMediaInForm);
/***** Get action and initialize media (image/video) /***** Get action and initialize media (image/video)
(except title, that will be get after the media file) *****/ (except title, that will be get after the media file) *****/
Media->Action = Med_GetMediaActionFromForm (ParamUploadMedia.Action); Action = Med_GetMediaActionFromForm (ParamUploadMedia.Action);
/***** Get the media (image/video) name and the file *****/ /***** Get the media (image/video) name and the file *****/
switch (Media->Action) switch (Action)
{ {
case Med_ACTION_NEW_MEDIA: // Upload new image/video case Med_ACTION_NEW_MEDIA: // Upload new image/video
/***** Get form type *****/ /***** Get form type *****/
@ -426,76 +437,59 @@ void Med_GetMediaFromForm (int NumMediaInForm,struct Media *Media,
switch (FormType) switch (FormType)
{ {
case Med_FORM_FILE: case Med_FORM_FILE:
Media->Action = Med_ACTION_NEW_MEDIA;
/* Get image/video (if present ==> /* Get image/video (if present ==>
process and create temporary file) */ process and create temporary file) */
Med_GetAndProcessFileFromForm (ParamUploadMedia.File,Media); Med_GetAndProcessFileFromForm (ParamUploadMedia.File,Media);
switch (Media->Status)
{ /* Check status of media after getting and processing it */
case Med_STATUS_NONE: // No new image/video received if (Media->Status == Med_PROCESSED)
Media->Action = Med_ACTION_NO_MEDIA; {
Media->Name[0] = '\0'; Usr_GetURLFromForm (ParamUploadMedia.URL,Media);
Media->Type = Med_TYPE_NONE; Usr_GetTitleFromForm (ParamUploadMedia.Title,Media);
break; }
case Med_RECEIVED: // New image/video received, but not processed else
Media->Status = Med_STATUS_NONE; {
Media->Name[0] = '\0'; /* Create alert with warning */
Media->Type = Med_TYPE_NONE; Ale_CreateAlert (Ale_WARNING,SectionForAlerts,
break; Txt_Error_sending_or_processing_image_video);
case Med_PROCESSED:
Usr_GetURLFromForm (ParamUploadMedia.URL,Media); /* Reset media (no media will be saved into database) */
Usr_GetTitleFromForm (ParamUploadMedia.Title,Media); Med_ResetMedia (Media);
break;
default:
break;
} }
break; break;
case Med_FORM_EMBED: case Med_FORM_EMBED:
Media->Action = Med_ACTION_NEW_MEDIA;
/* Get and process embed URL from form */ /* Get and process embed URL from form */
Med_GetAndProcessEmbedFromForm (ParamUploadMedia.URL,Media); Med_GetAndProcessEmbedFromForm (ParamUploadMedia.URL,Media);
/* Check status of media after getting and processing it */
if (Media->Status != Med_PROCESSED)
{
/* Create alert with warning */
Ale_CreateAlert (Ale_WARNING,SectionForAlerts,
Txt_Error_sending_or_processing_image_video);
/* Reset media (no media will be saved into database) */
Med_ResetMedia (Media);
}
break; break;
default: default: // No media form selected
Media->Action = Med_ACTION_NO_MEDIA;
break; break;
} }
break; break;
case Med_ACTION_KEEP_MEDIA: // Keep current image/video unchanged case Med_ACTION_KEEP_MEDIA: // Keep current image/video unchanged
Media->Action = Med_ACTION_KEEP_MEDIA;
/***** Get media name *****/ /***** Get media name *****/
if (GetMediaFromDB != NULL) if (GetMediaFromDB != NULL)
GetMediaFromDB (NumMediaInForm,Media); GetMediaFromDB (NumMediaInForm,Media);
break; break;
case Med_ACTION_CHANGE_MEDIA: // Replace old image/video by new one default: // Unknown action
/***** Get form type *****/ Media->Action = Med_ACTION_NO_MEDIA;
FormType = Usr_GetFormTypeFromForm (&ParamUploadMedia);
/***** Get new media *****/
switch (FormType)
{
case Med_FORM_FILE:
/* Get image/video (if present ==>
process and create temporary file) */
Med_GetAndProcessFileFromForm (ParamUploadMedia.File,Media);
switch (Media->Status)
{
case Med_PROCESSED:
Usr_GetURLFromForm (ParamUploadMedia.URL,Media);
Usr_GetTitleFromForm (ParamUploadMedia.Title,Media);
break;
default:
break;
}
break;
case Med_FORM_EMBED:
/* Get and process embed URL from form */
Med_GetAndProcessEmbedFromForm (ParamUploadMedia.URL,Media);
break;
default:
break;
}
if (Media->Status != Med_PROCESSED && // No new media received-processed successfully
GetMediaFromDB != NULL)
/* Get media (image/video) name */
GetMediaFromDB (NumMediaInForm,Media);
break;
default:
break; break;
} }
} }
@ -687,8 +681,6 @@ static void Med_GetAndProcessFileFromForm (const char *ParamFile,
if (Fil_EndReceptionOfFile (PathFileOrg,Param)) // Success if (Fil_EndReceptionOfFile (PathFileOrg,Param)) // Success
{ {
Media->Status = Med_RECEIVED;
/***** Detect if animated GIF *****/ /***** Detect if animated GIF *****/
if (Media->Type == Med_GIF) if (Media->Type == Med_GIF)
if (!Med_DetectIfAnimated (Media,PathMedPrivTmp,PathFileOrg)) if (!Med_DetectIfAnimated (Media,PathMedPrivTmp,PathFileOrg))
@ -853,8 +845,9 @@ static void Med_ProcessGIF (struct Media *Media,
{ {
/* Show warning alert */ /* Show warning alert */
Fil_WriteFileSizeBrief ((double) Med_MAX_SIZE_GIF,FileSizeStr); Fil_WriteFileSizeBrief ((double) Med_MAX_SIZE_GIF,FileSizeStr);
Ale_ShowAlert (Ale_WARNING,Txt_The_size_of_the_file_exceeds_the_maximum_allowed_X, Ale_CreateAlert (Ale_WARNING,NULL,
FileSizeStr); Txt_The_size_of_the_file_exceeds_the_maximum_allowed_X,
FileSizeStr);
} }
} }
else // Error getting file data else // Error getting file data
@ -897,8 +890,9 @@ static void Med_ProcessVideo (struct Media *Media,
{ {
/* Show warning alert */ /* Show warning alert */
Fil_WriteFileSizeBrief ((double) Med_MAX_SIZE_MP4,FileSizeStr); Fil_WriteFileSizeBrief ((double) Med_MAX_SIZE_MP4,FileSizeStr);
Ale_ShowAlert (Ale_WARNING,Txt_The_size_of_the_file_exceeds_the_maximum_allowed_X, Ale_CreateAlert (Ale_WARNING,NULL,
FileSizeStr); Txt_The_size_of_the_file_exceeds_the_maximum_allowed_X,
FileSizeStr);
} }
} }
else // Error getting file data else // Error getting file data
@ -1133,8 +1127,8 @@ void Med_MoveMediaToDefinitiveDir (struct Media *Media)
char PathMedPriv[PATH_MAX + 1]; char PathMedPriv[PATH_MAX + 1];
/***** Check trivial cases *****/ /***** Check trivial cases *****/
if (Media->Type == Med_TYPE_NONE) if (Media->Status != Med_PROCESSED)
Lay_ShowErrorAndExit ("Med_MoveMediaToDefinitiveDir: Wrong media type."); return;
if (Media->Type == Med_YOUTUBE) if (Media->Type == Med_YOUTUBE)
return; // Nothing to do with files return; // Nothing to do with files
@ -1182,8 +1176,6 @@ void Med_MoveMediaToDefinitiveDir (struct Media *Media)
Lay_ShowErrorAndExit ("Wrong media type."); Lay_ShowErrorAndExit ("Wrong media type.");
break; break;
} }
Media->Status = Med_FILE_MOVED; // Success
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -44,13 +44,12 @@
/*****************************************************************************/ /*****************************************************************************/
/***** Action to perform when editing a form with an image/video *****/ /***** Action to perform when editing a form with an image/video *****/
#define Med_NUM_ACTIONS 4 #define Med_NUM_ACTIONS 3
typedef enum typedef enum
{ {
Med_ACTION_NEW_MEDIA, // Upload new media
Med_ACTION_KEEP_MEDIA, // Keep current media unchanged
Med_ACTION_CHANGE_MEDIA, // Change existing media by a new one
Med_ACTION_NO_MEDIA, // Do not use media (remove current media if exists) Med_ACTION_NO_MEDIA, // Do not use media (remove current media if exists)
Med_ACTION_KEEP_MEDIA, // Keep current media unchanged
Med_ACTION_NEW_MEDIA, // Upload new media (if current media exists, remove and change by the new one)
} Med_Action_t; } Med_Action_t;
#define Med_ACTION_DEFAULT Med_ACTION_NO_MEDIA #define Med_ACTION_DEFAULT Med_ACTION_NO_MEDIA
@ -59,22 +58,22 @@ typedef enum
No file Original file Temporary Definitive Name of the image/video No file Original file Temporary Definitive Name of the image/video
uploaded uploaded by user processed file processed file stored in database uploaded uploaded by user processed file processed file stored in database
--------- --------------------------- ------------------ ------------------ --------------------- --------- --------------------------- ------------------ ------------------ ---------------------
Med_NONE Med_FILE_RECEIVED Med_FILE_PROCESSED Med_FILE_MOVED Med_NAME_STORED_IN_DB Med_STATUS_NONE Med_PROCESSED Med_NAME_STORED_IN_DB
--------- --------------------------- ------------------ ------------------ --------------------- --------- --------------------------- ------------------ ------------------ ---------------------
-> upload-file -> -> process-file -> b -> move-file -> -> insert-name -> upload-file process file move file insert in database
--------- --------------------------- ------------------ ------------------ --------------------- --------- --------------------------- ------------------ ------------------ ---------------------
file.ext / / / xx-unique-name file.ext / / / xx-unique-name
| | | | | |
var var var var var var
| | | | | |
www www www www www www
| | | | | |
swad swad swad swad swad swad
| | | | | |
med med med med med med
| | | | | |
tmp tmp xx (2 first chars) tmp tmp xx (2 first chars)
| | | | | |
xx-unique-name_original.ext xx-unique-name.jpg xx-unique-name.jpg xx-unique-name_original.ext xx-unique-name.jpg xx-unique-name.jpg
xx-unique-name: a unique name encrypted starting by two random chars xx xx-unique-name: a unique name encrypted starting by two random chars xx
@ -82,9 +81,7 @@ xx-unique-name: a unique name encrypted starting by two random chars xx
typedef enum typedef enum
{ {
Med_STATUS_NONE, Med_STATUS_NONE,
Med_RECEIVED,
Med_PROCESSED, Med_PROCESSED,
Med_FILE_MOVED,
Med_STORED_IN_DB, Med_STORED_IN_DB,
} Med_Status_t; } Med_Status_t;
@ -107,11 +104,13 @@ struct Media
Med_Status_t Status; Med_Status_t Status;
char Name[Med_BYTES_NAME + 1]; char Name[Med_BYTES_NAME + 1];
Med_Type_t Type; Med_Type_t Type;
char *Title; // Title/attribution (it must be initialized to NULL bool URLIsAllocated;
// in order to not trying to free it when no memory allocated) bool TitleIsAllocated;
char *URL; // URL, i.e. link to original big photo or video char *URL; // URL, i.e. link to original big photo or video
// (it must be initialized to NULL // (it must be initialized to NULL
// in order to not trying to free it when no memory allocated) // in order to not trying to free it when no memory allocated)
char *Title; // Title/attribution (it must be initialized to NULL
// in order to not trying to free it when no memory allocated)
unsigned Width; unsigned Width;
unsigned Height; unsigned Height;
unsigned Quality; unsigned Quality;
@ -133,10 +132,8 @@ struct ParamUploadMedia
/*****************************************************************************/ /*****************************************************************************/
void Med_MediaConstructor (struct Media *Media); void Med_MediaConstructor (struct Media *Media);
void Med_ResetMediaExceptTitleAndURL (struct Media *Media);
void Med_MediaDestructor (struct Media *Media); void Med_MediaDestructor (struct Media *Media);
void Med_FreeMediaTitle (struct Media *Media); void Med_ResetMedia (struct Media *Media);
void Med_FreeMediaURL (struct Media *Media);
void Med_GetMediaDataFromRow (const char *Name, void Med_GetMediaDataFromRow (const char *Name,
const char *TypeStr, const char *TypeStr,
@ -146,7 +143,8 @@ void Med_GetMediaDataFromRow (const char *Name,
void Med_PutMediaUploader (int NumMediaInForm,const char *ClassInput); void Med_PutMediaUploader (int NumMediaInForm,const char *ClassInput);
void Med_GetMediaFromForm (int NumMediaInForm,struct Media *Media, void Med_GetMediaFromForm (int NumMediaInForm,struct Media *Media,
void (*GetMediaFromDB) (int NumMediaInForm,struct Media *Media)); void (*GetMediaFromDB) (int NumMediaInForm,struct Media *Media),
const char *SectionForAlerts);
void Med_SetParamNames (struct ParamUploadMedia *ParamUploadMedia,int NumMediaInForm); void Med_SetParamNames (struct ParamUploadMedia *ParamUploadMedia,int NumMediaInForm);
void Med_MoveMediaToDefinitiveDir (struct Media *Media); void Med_MoveMediaToDefinitiveDir (struct Media *Media);

View File

@ -732,7 +732,8 @@ void Msg_RecMsgFromUsr (void)
Media.Width = Msg_IMAGE_SAVED_MAX_WIDTH; Media.Width = Msg_IMAGE_SAVED_MAX_WIDTH;
Media.Height = Msg_IMAGE_SAVED_MAX_HEIGHT; Media.Height = Msg_IMAGE_SAVED_MAX_HEIGHT;
Media.Quality = Msg_IMAGE_SAVED_QUALITY; Media.Quality = Msg_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm (-1,&Media,NULL); Med_GetMediaFromForm (-1,&Media,NULL,NULL);
Ale_ShowAlerts (NULL);
/***** Loop over the list Gbl.Usrs.Selected.List[Rol_UNK], that holds the list of the /***** Loop over the list Gbl.Usrs.Selected.List[Rol_UNK], that holds the list of the
recipients, creating a received message for each recipient *****/ recipients, creating a received message for each recipient *****/
@ -1281,8 +1282,8 @@ static long Msg_InsertNewMsg (const char *Subject,const char *Content,
long MsgCod; long MsgCod;
/***** Check if image is received and processed *****/ /***** Check if image is received and processed *****/
if (Media->Action == Med_ACTION_NEW_MEDIA && // Upload new image if (Media->Action == Med_ACTION_NEW_MEDIA && // New media
Media->Status == Med_PROCESSED) // The new image received has been processed Media->Status == Med_PROCESSED) // The new media received has been processed
/* Move processed image to definitive directory */ /* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (Media); Med_MoveMediaToDefinitiveDir (Media);

View File

@ -247,7 +247,7 @@ static void Tst_PutTFInputField (const char *Label,char Value);
static void Tst_FreeTextChoiceAnswers (void); static void Tst_FreeTextChoiceAnswers (void);
static void Tst_FreeTextChoiceAnswer (unsigned NumOpt); static void Tst_FreeTextChoiceAnswer (unsigned NumOpt);
static void Tst_InitMediaOfQuestion (void); static void Tst_ResetMediaOfQuestion (void);
static void Tst_FreeMediaOfQuestion (void); static void Tst_FreeMediaOfQuestion (void);
static void Tst_GetQstDataFromDB (char Stem[Cns_MAX_BYTES_TEXT + 1], static void Tst_GetQstDataFromDB (char Stem[Cns_MAX_BYTES_TEXT + 1],
@ -1162,7 +1162,7 @@ static void Tst_PutFormToEditQstMedia (struct Media *Media,int NumMediaInForm,
" value=\"%u\"", " value=\"%u\"",
The_ClassFormInBox[Gbl.Prefs.Theme], The_ClassFormInBox[Gbl.Prefs.Theme],
UniqueId,ParamUploadMedia.Action, UniqueId,ParamUploadMedia.Action,
Med_ACTION_CHANGE_MEDIA); // Replace existing image by new image Med_ACTION_NEW_MEDIA); // Replace existing image by new image
if (OptionsDisabled) if (OptionsDisabled)
fprintf (Gbl.F.Out," disabled=\"disabled\""); fprintf (Gbl.F.Out," disabled=\"disabled\"");
fprintf (Gbl.F.Out," />" fprintf (Gbl.F.Out," />"
@ -5476,24 +5476,18 @@ static void Tst_FreeTextChoiceAnswer (unsigned NumOpt)
/***************** Initialize images of a question to zero *******************/ /***************** Initialize images of a question to zero *******************/
/*****************************************************************************/ /*****************************************************************************/
static void Tst_InitMediaOfQuestion (void) static void Tst_ResetMediaOfQuestion (void)
{ {
unsigned NumOpt; unsigned NumOpt;
/***** Initialize image *****/ /***** Reset media for stem *****/
Med_ResetMediaExceptTitleAndURL (&Gbl.Test.Media); Med_ResetMedia (&Gbl.Test.Media);
Med_FreeMediaTitle (&Gbl.Test.Media);
Med_FreeMediaURL (&Gbl.Test.Media);
/***** Reset media for every answer option *****/
for (NumOpt = 0; for (NumOpt = 0;
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION; NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
NumOpt++) NumOpt++)
{ Med_ResetMedia (&Gbl.Test.Answer.Options[NumOpt].Media);
/***** Initialize image *****/
Med_ResetMediaExceptTitleAndURL (&Gbl.Test.Answer.Options[NumOpt].Media);
Med_FreeMediaTitle (&Gbl.Test.Media);
Med_FreeMediaURL (&Gbl.Test.Media);
}
} }
/*****************************************************************************/ /*****************************************************************************/
@ -5751,7 +5745,7 @@ void Tst_ReceiveQst (void)
else // Question is wrong else // Question is wrong
{ {
/***** Whether images has been received or not, reset images *****/ /***** Whether images has been received or not, reset images *****/
Tst_InitMediaOfQuestion (); Tst_ResetMediaOfQuestion ();
/***** Put form to edit question again *****/ /***** Put form to edit question again *****/
Tst_PutFormEditOneQst (Stem,Feedback); Tst_PutFormEditOneQst (Stem,Feedback);
@ -5828,7 +5822,9 @@ static void Tst_GetQstFromForm (char *Stem,char *Feedback)
Gbl.Test.Media.Height = Tst_IMAGE_SAVED_MAX_HEIGHT; Gbl.Test.Media.Height = Tst_IMAGE_SAVED_MAX_HEIGHT;
Gbl.Test.Media.Quality = Tst_IMAGE_SAVED_QUALITY; Gbl.Test.Media.Quality = Tst_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm (-1, // < 0 ==> the image associated to the stem Med_GetMediaFromForm (-1, // < 0 ==> the image associated to the stem
&Gbl.Test.Media,Tst_GetMediaFromDB); &Gbl.Test.Media,Tst_GetMediaFromDB,
NULL);
Ale_ShowAlerts (NULL);
/***** Get answers *****/ /***** Get answers *****/
Gbl.Test.Shuffle = false; Gbl.Test.Shuffle = false;
@ -5904,7 +5900,9 @@ static void Tst_GetQstFromForm (char *Stem,char *Feedback)
Gbl.Test.Answer.Options[NumOpt].Media.Quality = Tst_IMAGE_SAVED_QUALITY; Gbl.Test.Answer.Options[NumOpt].Media.Quality = Tst_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm ((int) NumOpt, // >= 0 ==> the image associated to an answer Med_GetMediaFromForm ((int) NumOpt, // >= 0 ==> the image associated to an answer
&Gbl.Test.Answer.Options[NumOpt].Media, &Gbl.Test.Answer.Options[NumOpt].Media,
Tst_GetMediaFromDB); Tst_GetMediaFromDB,
NULL);
Ale_ShowAlerts (NULL);
} }
} }
@ -5963,7 +5961,6 @@ static void Tst_GetQstFromForm (char *Stem,char *Feedback)
bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void) bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
{ {
extern const char *Txt_Error_receiving_or_processing_image;
extern const char *Txt_You_must_type_at_least_one_tag_for_the_question; extern const char *Txt_You_must_type_at_least_one_tag_for_the_question;
extern const char *Txt_You_must_type_the_stem_of_the_question; extern const char *Txt_You_must_type_the_stem_of_the_question;
extern const char *Txt_You_must_select_a_T_F_answer; extern const char *Txt_You_must_select_a_T_F_answer;
@ -5979,14 +5976,6 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
bool ThereIsEndOfAnswers; bool ThereIsEndOfAnswers;
unsigned i; unsigned i;
if ((Gbl.Test.Media.Action == Med_ACTION_NEW_MEDIA || // Upload new image
Gbl.Test.Media.Action == Med_ACTION_CHANGE_MEDIA) && // Replace existing image by new image
Gbl.Test.Media.Status != Med_PROCESSED)
{
Ale_ShowAlert (Ale_WARNING,Txt_Error_receiving_or_processing_image);
return false;
}
/***** This function also counts the number of options. Initialize this number to 0. *****/ /***** This function also counts the number of options. Initialize this number to 0. *****/
Gbl.Test.Answer.NumOptions = 0; Gbl.Test.Answer.NumOptions = 0;
@ -6008,6 +5997,7 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
switch (Gbl.Test.AnswerType) switch (Gbl.Test.AnswerType)
{ {
case Tst_ANS_INT: case Tst_ANS_INT:
/* First option should be filled */
if (!Gbl.Test.Answer.Options[0].Text) if (!Gbl.Test.Answer.Options[0].Text)
{ {
Ale_ShowAlert (Ale_WARNING,Txt_You_must_enter_an_integer_value_as_the_correct_answer); Ale_ShowAlert (Ale_WARNING,Txt_You_must_enter_an_integer_value_as_the_correct_answer);
@ -6018,10 +6008,12 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
Ale_ShowAlert (Ale_WARNING,Txt_You_must_enter_an_integer_value_as_the_correct_answer); Ale_ShowAlert (Ale_WARNING,Txt_You_must_enter_an_integer_value_as_the_correct_answer);
return false; return false;
} }
Gbl.Test.Answer.Integer = Tst_GetIntAnsFromStr (Gbl.Test.Answer.Options[0].Text); Gbl.Test.Answer.Integer = Tst_GetIntAnsFromStr (Gbl.Test.Answer.Options[0].Text);
Gbl.Test.Answer.NumOptions = 1; Gbl.Test.Answer.NumOptions = 1;
break; break;
case Tst_ANS_FLOAT: case Tst_ANS_FLOAT:
/* First two options should be filled */
if (!Gbl.Test.Answer.Options[0].Text || if (!Gbl.Test.Answer.Options[0].Text ||
!Gbl.Test.Answer.Options[1].Text) !Gbl.Test.Answer.Options[1].Text)
{ {
@ -6034,6 +6026,8 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
Ale_ShowAlert (Ale_WARNING,Txt_You_must_enter_the_range_of_floating_point_values_allowed_as_answer); Ale_ShowAlert (Ale_WARNING,Txt_You_must_enter_the_range_of_floating_point_values_allowed_as_answer);
return false; return false;
} }
/* Lower limit should be <= upper limit */
for (i = 0; for (i = 0;
i < 2; i < 2;
i++) i++)
@ -6044,30 +6038,23 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
Ale_ShowAlert (Ale_WARNING,Txt_The_lower_limit_of_correct_answers_must_be_less_than_or_equal_to_the_upper_limit); Ale_ShowAlert (Ale_WARNING,Txt_The_lower_limit_of_correct_answers_must_be_less_than_or_equal_to_the_upper_limit);
return false; return false;
} }
Gbl.Test.Answer.NumOptions = 2; Gbl.Test.Answer.NumOptions = 2;
break; break;
case Tst_ANS_TRUE_FALSE: case Tst_ANS_TRUE_FALSE:
/* Answer should be 'T' or 'F' */
if (Gbl.Test.Answer.TF != 'T' && if (Gbl.Test.Answer.TF != 'T' &&
Gbl.Test.Answer.TF != 'F') Gbl.Test.Answer.TF != 'F')
{ {
Ale_ShowAlert (Ale_WARNING,Txt_You_must_select_a_T_F_answer); Ale_ShowAlert (Ale_WARNING,Txt_You_must_select_a_T_F_answer);
return false; return false;
} }
Gbl.Test.Answer.NumOptions = 1; Gbl.Test.Answer.NumOptions = 1;
break; break;
case Tst_ANS_UNIQUE_CHOICE: case Tst_ANS_UNIQUE_CHOICE:
case Tst_ANS_MULTIPLE_CHOICE: case Tst_ANS_MULTIPLE_CHOICE:
if (!Gbl.Test.Answer.Options[0].Text) // If the first answer is empty /* No option should be empty before a non-empty option */
{
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers);
return false;
}
if (!Gbl.Test.Answer.Options[0].Text[0]) // If the first answer is empty
{
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers);
return false;
}
for (NumOpt = 0, NumLastOpt = 0, ThereIsEndOfAnswers = false; for (NumOpt = 0, NumLastOpt = 0, ThereIsEndOfAnswers = false;
NumOpt < Tst_MAX_OPTIONS_PER_QUESTION; NumOpt < Tst_MAX_OPTIONS_PER_QUESTION;
NumOpt++) NumOpt++)
@ -6089,12 +6076,14 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
else else
ThereIsEndOfAnswers = true; ThereIsEndOfAnswers = true;
/* The two first options must be filled */
if (NumLastOpt < 1) if (NumLastOpt < 1)
{ {
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers); Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers);
return false; return false;
} }
/* Its mandatory to mark at least one option as correct */
for (NumOpt = 0; for (NumOpt = 0;
NumOpt <= NumLastOpt; NumOpt <= NumLastOpt;
NumOpt++) NumOpt++)
@ -6107,17 +6096,19 @@ bool Tst_CheckIfQstFormatIsCorrectAndCountNumOptions (void)
} }
break; break;
case Tst_ANS_TEXT: case Tst_ANS_TEXT:
/* First option should be filled */
if (!Gbl.Test.Answer.Options[0].Text) // If the first answer is empty if (!Gbl.Test.Answer.Options[0].Text) // If the first answer is empty
{ {
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_two_answers); Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_answer);
return false; return false;
} }
if (!Gbl.Test.Answer.Options[0].Text[0]) // If the first answer is empty if (!Gbl.Test.Answer.Options[0].Text[0]) // If the first answer is empty
{ {
Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_answer); Ale_ShowAlert (Ale_WARNING,Txt_You_must_type_at_least_the_first_answer);
return false; return false;
} }
/* No option should be empty before a non-empty option */
for (NumOpt=0, ThereIsEndOfAnswers=false; for (NumOpt=0, ThereIsEndOfAnswers=false;
NumOpt<Tst_MAX_OPTIONS_PER_QUESTION; NumOpt<Tst_MAX_OPTIONS_PER_QUESTION;
NumOpt++) NumOpt++)
@ -6161,9 +6152,8 @@ static void Tst_MoveMediaToDefinitiveDirectories (void)
and moved to the definitive directory) */ and moved to the definitive directory) */
Tst_RemoveMedFileFromStemOfQst (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Test.QstCod); Tst_RemoveMedFileFromStemOfQst (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Test.QstCod);
if ((Gbl.Test.Media.Action == Med_ACTION_NEW_MEDIA || // Upload new image if (Gbl.Test.Media.Action == Med_ACTION_NEW_MEDIA && // New media
Gbl.Test.Media.Action == Med_ACTION_CHANGE_MEDIA) && // Replace existing image by new image Gbl.Test.Media.Status == Med_PROCESSED) // The new media received has been processed
Gbl.Test.Media.Status == Med_PROCESSED) // The new image received has been processed
/* Move processed image to definitive directory */ /* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (&Gbl.Test.Media); Med_MoveMediaToDefinitiveDir (&Gbl.Test.Media);
@ -6181,10 +6171,9 @@ static void Tst_MoveMediaToDefinitiveDirectories (void)
and moved to the definitive directory) */ and moved to the definitive directory) */
Tst_RemoveMedFileFromAnsOfQst (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Test.QstCod,NumOpt); Tst_RemoveMedFileFromAnsOfQst (Gbl.CurrentCrs.Crs.CrsCod,Gbl.Test.QstCod,NumOpt);
if ((Gbl.Test.Answer.Options[NumOpt].Media.Action == Med_ACTION_NEW_MEDIA || // Upload new image if (Gbl.Test.Answer.Options[NumOpt].Media.Action == Med_ACTION_NEW_MEDIA && // New media
Gbl.Test.Answer.Options[NumOpt].Media.Action == Med_ACTION_CHANGE_MEDIA) && // Replace existing image by new image Gbl.Test.Answer.Options[NumOpt].Media.Status == Med_PROCESSED) // The new media received has been processed
Gbl.Test.Answer.Options[NumOpt].Media.Status == Med_PROCESSED) // The new image received has been processed /* Move processed media to definitive directory */
/* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (&Gbl.Test.Answer.Options[NumOpt].Media); Med_MoveMediaToDefinitiveDir (&Gbl.Test.Answer.Options[NumOpt].Media);
} }
} }

View File

@ -10652,25 +10652,25 @@ const char *Txt_Error_getting_data_from_a_recipient =
"Erro ao obter dados de um destinat&aacute;rio."; "Erro ao obter dados de um destinat&aacute;rio.";
#endif #endif
const char *Txt_Error_receiving_or_processing_image = const char *Txt_Error_sending_or_processing_image_video =
#if L==1 // ca #if L==1 // ca
"Error rebent o processant imatge."; "Error enviant o processant imatge / v&iacute;deo.";
#elif L==2 // de #elif L==2 // de
"Fehler beim Empfangen oder Verarbeiten von Abbild."; "Fehler beim Senden oder Verarbeiten eines Abbild / Video.";
#elif L==3 // en #elif L==3 // en
"Error receiving or processing image."; "Error sending or processing image / video.";
#elif L==4 // es #elif L==4 // es
"Error recibiendo o procesando imagen."; "Error enviando o procesando imagen / v&iacute;deo.";
#elif L==5 // fr #elif L==5 // fr
"Erreur de r&eacute;ception ou de traitement d'image."; "Erreur d'envoi ou de traitement de l'image / vid&eacute;o.";
#elif L==6 // gn #elif L==6 // gn
"Error recibiendo o procesando imagen."; // Okoteve traducción "Error enviando o procesando imagen / v&iacute;deo."; // Okoteve traducción
#elif L==7 // it #elif L==7 // it
"Errore durante la ricezione o la elaborazione delle immagini."; "Errore nell'invio o nell'elaborazione dell'immagine / video.";
#elif L==8 // pl #elif L==8 // pl
"B&lstrok;&aogon;d odbioru lub przetwarzania obrazu."; "B&lstrok;&aogon;d podczas wysy&lstrok;ania lub przetwarzania obrazu / wideo.";
#elif L==9 // pt #elif L==9 // pt
"Erro no recebimento ou processamento de imagem."; "Erro ao enviar ou processar imagem / v&iacute;deo.";
#endif #endif
const char *Txt_Event = const char *Txt_Event =

View File

@ -2470,14 +2470,15 @@ static long TL_ReceivePost (void)
Media.Width = TL_IMAGE_SAVED_MAX_WIDTH; Media.Width = TL_IMAGE_SAVED_MAX_WIDTH;
Media.Height = TL_IMAGE_SAVED_MAX_HEIGHT; Media.Height = TL_IMAGE_SAVED_MAX_HEIGHT;
Media.Quality = TL_IMAGE_SAVED_QUALITY; Media.Quality = TL_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm (-1,&Media,NULL); Med_GetMediaFromForm (-1,&Media,NULL,NULL);
Ale_ShowAlerts (NULL);
if (Content[0] || // Text not empty if (Content[0] || // Text not empty
Media.Status == Med_PROCESSED) // A media is attached Media.Status == Med_PROCESSED) // A media is attached
{ {
/***** Check if image is received and processed *****/ /***** Check if media is received and processed *****/
if (Media.Action == Med_ACTION_NEW_MEDIA && // Upload new image if (Media.Action == Med_ACTION_NEW_MEDIA && // New media
Media.Status == Med_PROCESSED) // The new image received has been processed Media.Status == Med_PROCESSED) // The new media received has been processed
/* Move processed image to definitive directory */ /* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (&Media); Med_MoveMediaToDefinitiveDir (&Media);
@ -3196,14 +3197,15 @@ static long TL_ReceiveComment (void)
Media.Width = TL_IMAGE_SAVED_MAX_WIDTH; Media.Width = TL_IMAGE_SAVED_MAX_WIDTH;
Media.Height = TL_IMAGE_SAVED_MAX_HEIGHT; Media.Height = TL_IMAGE_SAVED_MAX_HEIGHT;
Media.Quality = TL_IMAGE_SAVED_QUALITY; Media.Quality = TL_IMAGE_SAVED_QUALITY;
Med_GetMediaFromForm (-1,&Media,NULL); Med_GetMediaFromForm (-1,&Media,NULL,NULL);
Ale_ShowAlerts (NULL);
if (Content[0] || // Text not empty if (Content[0] || // Text not empty
Media.Status == Med_PROCESSED) // A media is attached Media.Status == Med_PROCESSED) // A media is attached
{ {
/***** Check if image is received and processed *****/ /***** Check if media is received and processed *****/
if (Media.Action == Med_ACTION_NEW_MEDIA && // Upload new image if (Media.Action == Med_ACTION_NEW_MEDIA && // New media
Media.Status == Med_PROCESSED) // The new image received has been processed Media.Status == Med_PROCESSED) // The new media received has been processed
/* Move processed image to definitive directory */ /* Move processed image to definitive directory */
Med_MoveMediaToDefinitiveDir (&Media); Med_MoveMediaToDefinitiveDir (&Media);