swad-core/swad_info.c

2222 lines
77 KiB
C

// swad_info.c: info about course
/*
SWAD (Shared Workspace At a Distance),
is a web platform developed at the University of Granada (Spain),
and used to support university teaching.
This file is part of SWAD core.
Copyright (C) 1999-2016 Antonio Cañas Vargas
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*****************************************************************************/
/********************************* Headers ***********************************/
/*****************************************************************************/
#include <limits.h> // For maximum values
#include <linux/limits.h> // For PATH_MAX, NAME_MAX
#include <linux/stddef.h> // For NULL
#include <stdlib.h> // For getenv, etc
#include <stdsoap2.h> // For SOAP_OK and soap functions
#include <string.h> // For string functions
#include <unistd.h> // For unlink
#include "swad_action.h"
#include "swad_database.h"
#include "swad_global.h"
#include "swad_info.h"
#include "swad_parameter.h"
#include "swad_string.h"
/*****************************************************************************/
/************** External global variables from others modules ****************/
/*****************************************************************************/
extern struct Globals Gbl;
/*****************************************************************************/
/*************************** Public constants ********************************/
/*****************************************************************************/
const char *Inf_FileNamesForInfoType[Inf_NUM_INFO_TYPES] =
{
Cfg_CRS_INFO_INTRODUCTION,
Cfg_CRS_INFO_TEACHING_GUIDE,
Cfg_CRS_INFO_LECTURES,
Cfg_CRS_INFO_PRACTICALS,
Cfg_CRS_INFO_BIBLIOGRAPHY,
Cfg_CRS_INFO_FAQ,
Cfg_CRS_INFO_LINKS,
Cfg_CRS_INFO_ASSESSMENT,
};
/*****************************************************************************/
/****************************** Private types ********************************/
/*****************************************************************************/
/*****************************************************************************/
/***************************** Private constants *****************************/
/*****************************************************************************/
/* Functions to write forms in course edition (FAQ, links, etc.) */
void (*Inf_FormsForEditionTypes[Inf_NUM_INFO_SOURCES])(Inf_InfoSrc_t InfoSrc) =
{
NULL,
Inf_FormToEnterIntegratedEditor,
Inf_FormToEnterPlainTextEditor,
Inf_FormToEnterRichTextEditor,
Inf_FormToSendPage,
Inf_FormToSendURL,
};
const char *Inf_NamesInDBForInfoSrc[Inf_NUM_INFO_SOURCES] =
{
"none",
"editor",
"plain_text",
"rich_text",
"page",
"URL",
};
const Act_Action_t Inf_ActionsSeeInfo[Inf_NUM_INFO_TYPES] =
{
ActSeeCrsInf,
ActSeeTchGui,
ActSeeSylLec,
ActSeeSylPra,
ActSeeBib,
ActSeeFAQ,
ActSeeCrsLnk,
ActSeeAss,
};
const Act_Action_t Inf_ActionsEditInfo[Inf_NUM_INFO_TYPES] =
{
ActEdiCrsInf,
ActEdiTchGui,
ActEdiSylLec,
ActEdiSylPra,
ActEdiBib,
ActEdiFAQ,
ActEdiCrsLnk,
ActEdiAss,
};
const Act_Action_t Inf_ActionsChangeForceReadInfo[Inf_NUM_INFO_TYPES] =
{
ActChgFrcReaCrsInf,
ActChgFrcReaTchGui,
ActChgFrcReaSylLec,
ActChgFrcReaSylPra,
ActChgFrcReaBib,
ActChgFrcReaFAQ,
ActChgFrcReaCrsLnk,
ActChgFrcReaAss,
};
const Act_Action_t Inf_ActionsIHaveReadInfo[Inf_NUM_INFO_TYPES] =
{
ActChgHavReaCrsInf,
ActChgHavReaTchGui,
ActChgHavReaSylLec,
ActChgHavReaSylPra,
ActChgHavReaBib,
ActChgHavReaFAQ,
ActChgHavReaCrsLnk,
ActChgHavReaAss,
};
const Act_Action_t Inf_ActionsSelecInfoSrc[Inf_NUM_INFO_TYPES] =
{
ActSelInfSrcCrsInf,
ActSelInfSrcTchGui,
ActSelInfSrcSylLec,
ActSelInfSrcSylPra,
ActSelInfSrcBib,
ActSelInfSrcFAQ,
ActSelInfSrcCrsLnk,
ActSelInfSrcAss,
};
const Act_Action_t Inf_ActionsInfo[Inf_NUM_INFO_SOURCES][Inf_NUM_INFO_TYPES] =
{
{
ActUnk,
ActUnk,
ActUnk,
ActUnk,
ActUnk,
ActUnk,
ActUnk,
ActUnk,
},
{
ActEditorCrsInf,
ActEditorTchGui,
ActEditorSylLec,
ActEditorSylPra,
ActEditorBib,
ActEditorFAQ,
ActEditorCrsLnk,
ActEditorAss,
},
{
ActPlaTxtEdiCrsInf,
ActPlaTxtEdiTchGui,
ActPlaTxtEdiSylLec,
ActPlaTxtEdiSylPra,
ActPlaTxtEdiBib,
ActPlaTxtEdiFAQ,
ActPlaTxtEdiCrsLnk,
ActPlaTxtEdiAss,
},
{
ActRchTxtEdiCrsInf,
ActRchTxtEdiTchGui,
ActRchTxtEdiSylLec,
ActRchTxtEdiSylPra,
ActRchTxtEdiBib,
ActRchTxtEdiFAQ,
ActRchTxtEdiCrsLnk,
ActRchTxtEdiAss,
},
{
ActRcvPagCrsInf,
ActRcvPagTchGui,
ActRcvPagSylLec,
ActRcvPagSylPra,
ActRcvPagBib,
ActRcvPagFAQ,
ActRcvPagCrsLnk,
ActRcvPagAss,
},
{
ActRcvURLCrsInf,
ActRcvURLTchGui,
ActRcvURLSylLec,
ActRcvURLSylPra,
ActRcvURLBib,
ActRcvURLFAQ,
ActRcvURLCrsLnk,
ActRcvURLAss,
}
};
const Act_Action_t Inf_ActionsEditorInfo[Inf_NUM_INFO_TYPES] =
{
ActEditorCrsInf,
ActEditorTchGui,
ActEditorSylLec,
ActEditorSylPra,
ActEditorBib,
ActEditorFAQ,
ActEditorCrsLnk,
ActEditorAss,
};
const Act_Action_t Inf_ActionsRcvPlaTxtInfo[Inf_NUM_INFO_TYPES] =
{
ActRcvPlaTxtCrsInf,
ActRcvPlaTxtTchGui,
ActRcvPlaTxtSylLec,
ActRcvPlaTxtSylPra,
ActRcvPlaTxtBib,
ActRcvPlaTxtFAQ,
ActRcvPlaTxtCrsLnk,
ActRcvPlaTxtAss,
};
const Act_Action_t Inf_ActionsRcvRchTxtInfo[Inf_NUM_INFO_TYPES] =
{
ActRcvRchTxtCrsInf,
ActRcvRchTxtTchGui,
ActRcvRchTxtSylLec,
ActRcvRchTxtSylPra,
ActRcvRchTxtBib,
ActRcvRchTxtFAQ,
ActRcvRchTxtCrsLnk,
ActRcvRchTxtAss,
};
const Act_Action_t Inf_ActionsRcvPagBibEvEtc[Inf_NUM_INFO_TYPES] =
{
ActRcvPagCrsInf,
ActRcvPagTchGui,
ActRcvPagSylLec,
ActRcvPagSylPra,
ActRcvPagBib,
ActRcvPagFAQ,
ActRcvPagCrsLnk,
ActRcvPagAss,
};
const Act_Action_t In_ActionsRcvURLBibEvEtc[Inf_NUM_INFO_TYPES] =
{
ActRcvURLCrsInf,
ActRcvURLTchGui,
ActRcvURLSylLec,
ActRcvURLSylPra,
ActRcvURLBib,
ActRcvURLFAQ,
ActRcvURLCrsLnk,
ActRcvURLAss,
};
const char *Inf_NamesInDBForInfoType[Inf_NUM_INFO_TYPES] =
{
"intro", // TODO: Change this to "introduction"!
"description", // TODO: Change this to "guide"!
"theory", // TODO: Change this to "lectures"!
"practices", // TODO: Change this to "practicals"!
"bibliography",
"FAQ",
"links",
"assessment",
};
/*****************************************************************************/
/**************************** Private prototypes *****************************/
/*****************************************************************************/
static void Inf_PutButtonToEditInfo (void);
static void Inf_PutFormToForceStdsToReadInfo (bool MustBeRead);
static void Inf_PutFormToConfirmIHaveReadInfo (void);
static bool Inf_CheckIfIHaveReadInfo (void);
static bool Inf_GetMustBeReadFromForm (void);
static bool Inf_GetIfIHaveReadFromForm (void);
static void Inf_SetForceReadIntoDB (bool MustBeRead);
static void Inf_SetIHaveReadIntoDB (bool IHaveRead);
static void Inf_CheckAndShowPage (void);
static void Inf_CheckAndShowURL (void);
static void Inf_ShowPage (const char *URL);
static Inf_InfoType_t Inf_AsignInfoType (void);
static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD);
static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLength);
static bool Inf_CheckIfInfoTxtIsNotEmpty (long CrsCod,Inf_InfoType_t InfoType);
static void Inf_ShowPlainTxtInfo (void);
static void Inf_ShowRichTxtInfo (void);
/*****************************************************************************/
/******** Show course info (theory, practices, bibliography, etc.) ***********/
/*****************************************************************************/
void Inf_ShowInfo (void)
{
extern const char *Txt_No_information_available;
Inf_InfoSrc_t InfoSrc;
bool MustBeRead;
bool ICanEdit = (Gbl.Usrs.Me.LoggedRole == Rol_TEACHER ||
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM);
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Get info source from database *****/
Inf_GetInfoSrcFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,&InfoSrc,&MustBeRead);
switch (Gbl.CurrentCrs.Info.Type)
{
case Inf_LECTURES:
case Inf_PRACTICALS:
Syl_PutFormWhichSyllabus ();
break;
default:
break;
}
switch (Gbl.Usrs.Me.LoggedRole)
{
case Rol_STUDENT:
/* Put checkbox to force students to read this couse info */
if (MustBeRead)
Inf_PutFormToConfirmIHaveReadInfo ();
break;
case Rol_TEACHER:
case Rol_SYS_ADM:
/* Put checkbox to force students to read this couse info */
if (InfoSrc != Inf_INFO_SRC_NONE)
Inf_PutFormToForceStdsToReadInfo (MustBeRead);
break;
default:
break;
}
switch (InfoSrc)
{
case Inf_INFO_SRC_NONE:
if (Gbl.CurrentCrs.Info.Type != Inf_INTRODUCTION)
Lay_ShowAlert (Lay_INFO,Txt_No_information_available);
/* Put button to edit info */
if (ICanEdit)
Inf_PutButtonToEditInfo ();
break;
case Inf_INFO_SRC_EDITOR:
switch (Gbl.CurrentCrs.Info.Type)
{
case Inf_LECTURES:
case Inf_PRACTICALS:
Syl_EditSyllabus ();
break;
case Inf_INTRODUCTION:
case Inf_TEACHING_GUIDE:
case Inf_BIBLIOGRAPHY:
case Inf_FAQ:
case Inf_LINKS:
case Inf_ASSESSMENT:
Lay_ShowAlert (Lay_INFO,Txt_No_information_available);
/* Put button to edit info */
if (ICanEdit)
Inf_PutButtonToEditInfo ();
break;
}
break;
case Inf_INFO_SRC_PLAIN_TEXT:
Inf_ShowPlainTxtInfo ();
break;
case Inf_INFO_SRC_RICH_TEXT:
Inf_ShowRichTxtInfo ();
break;
case Inf_INFO_SRC_PAGE:
/***** Open file with web page *****/
Inf_CheckAndShowPage ();
break;
case Inf_INFO_SRC_URL:
/***** Check if file with URL exists *****/
Inf_CheckAndShowURL ();
break;
}
}
/*****************************************************************************/
/*********************** Put button to edit course info **********************/
/*****************************************************************************/
static void Inf_PutButtonToEditInfo (void)
{
extern const char *Txt_Edit;
Act_FormStart (Inf_ActionsEditInfo[Gbl.CurrentCrs.Info.Type]);
Lay_PutConfirmButton (Txt_Edit);
Act_FormEnd ();
}
/*****************************************************************************/
/************************ Put icon to edit course info ***********************/
/*****************************************************************************/
void Inf_PutIconToEditInfo (void)
{
extern const char *Txt_Edit;
Lay_PutContextualLink (Inf_ActionsEditInfo[Gbl.CurrentCrs.Info.Type],NULL,
"edit64x64.png",Txt_Edit,NULL);
}
/*****************************************************************************/
/********** Put a form (checkbox) to force students to read info *************/
/*****************************************************************************/
static void Inf_PutFormToForceStdsToReadInfo (bool MustBeRead)
{
extern const char *The_ClassForm[The_NUM_THEMES];
extern const char *Txt_Force_students_to_read_this_information;
fprintf (Gbl.F.Out,"<div class=\"%s CENTER_MIDDLE\">",
The_ClassForm[Gbl.Prefs.Theme]);
Act_FormStart (Inf_ActionsChangeForceReadInfo[Gbl.CurrentCrs.Info.Type]);
fprintf (Gbl.F.Out,"<input type=\"checkbox\"");
if (MustBeRead)
fprintf (Gbl.F.Out," checked=\"checked\"");
fprintf (Gbl.F.Out," name=\"MustBeRead\" value=\"Y\""
" onchange=\"document.getElementById('%s').submit();\" />"
" %s",
Gbl.Form.Id,
Txt_Force_students_to_read_this_information);
Act_FormEnd ();
fprintf (Gbl.F.Out,"</div>");
}
/*****************************************************************************/
/***** Put a form (checkbox) to confirm that I have read a course info *******/
/*****************************************************************************/
static void Inf_PutFormToConfirmIHaveReadInfo (void)
{
extern const char *The_ClassForm[The_NUM_THEMES];
extern const char *Txt_I_have_read_this_information;
bool IHaveRead = Inf_CheckIfIHaveReadInfo ();
fprintf (Gbl.F.Out,"<div class=\"%s CENTER_MIDDLE\">",
The_ClassForm[Gbl.Prefs.Theme]);
Act_FormStart (Inf_ActionsIHaveReadInfo[Gbl.CurrentCrs.Info.Type]);
fprintf (Gbl.F.Out,"<input type=\"checkbox\"");
if (IHaveRead)
fprintf (Gbl.F.Out," checked=\"checked\"");
fprintf (Gbl.F.Out," name=\"IHaveRead\" value=\"Y\""
" onchange=\"document.getElementById('%s').submit();\" />"
"%s",
Gbl.Form.Id,
Txt_I_have_read_this_information);
Act_FormEnd ();
fprintf (Gbl.F.Out,"</div>");
}
/*****************************************************************************/
/******************** Check I have read a course info ************************/
/*****************************************************************************/
static bool Inf_CheckIfIHaveReadInfo (void)
{
char Query[512];
/***** Get if info source is already stored in database *****/
sprintf (Query,"SELECT COUNT(*) FROM crs_info_read"
" WHERE UsrCod='%ld' AND CrsCod='%ld' AND InfoType='%s'",
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
return (DB_QueryCOUNT (Query,"can not get if I have read course info") != 0);
}
/*****************************************************************************/
/********* Get if students must read any info about current course ***********/
/*****************************************************************************/
bool Inf_GetIfIMustReadAnyCrsInfoInThisCrs (void)
{
char Query[1024];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRow,NumRows;
Inf_InfoType_t InfoType;
/***** Reset must-be-read to false for all info types *****/
for (InfoType = (Inf_InfoType_t) 0;
InfoType < Inf_NUM_INFO_TYPES;
InfoType++)
Gbl.CurrentCrs.Info.MustBeRead[InfoType] = false;
/***** Get info types where students must read info *****/
sprintf (Query,"SELECT InfoType FROM crs_info_src"
" WHERE CrsCod='%ld' AND MustBeRead='Y'"
" AND InfoType NOT IN"
" (SELECT InfoType FROM crs_info_read"
" WHERE UsrCod='%ld' AND CrsCod='%ld')",
Gbl.CurrentCrs.Crs.CrsCod,
Gbl.Usrs.Me.UsrDat.UsrCod,Gbl.CurrentCrs.Crs.CrsCod);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get if you must read any course info");
/***** Set must-be-read to true for each rown in result *****/
for (NumRow = 0;
NumRow < NumRows;
NumRow++)
{
row = mysql_fetch_row (mysql_res);
/* Get info type (row[0]) */
InfoType = Inf_ConvertFromStrDBToInfoType (row[0]);
Gbl.CurrentCrs.Info.MustBeRead[InfoType] = true;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return (NumRows != 0);
}
/*****************************************************************************/
/***** Write message if students must read any info about current course *****/
/*****************************************************************************/
void Inf_WriteMsgYouMustReadInfo (void)
{
extern const char *The_ClassForm[The_NUM_THEMES];
extern const char *Txt_You_should_read_the_following_information_on_the_course_X;
Inf_InfoType_t InfoType;
/***** Write message *****/
sprintf (Gbl.Message,Txt_You_should_read_the_following_information_on_the_course_X,
Gbl.CurrentCrs.Crs.FullName);
Lay_ShowAlert (Lay_WARNING,Gbl.Message);
/***** Write every information I must read *****/
fprintf (Gbl.F.Out,"<table style=\"margin:0 auto;\">"
"<tr>"
"<td class=\"LEFT_MIDDLE\">"
"<ul>");
for (InfoType = (Inf_InfoType_t) 0;
InfoType < Inf_NUM_INFO_TYPES;
InfoType++)
if (Gbl.CurrentCrs.Info.MustBeRead[InfoType])
{
fprintf (Gbl.F.Out,"<li>");
Act_FormStart (Inf_ActionsSeeInfo[InfoType]);
Act_LinkFormSubmit (Act_GetTitleAction (Inf_ActionsSeeInfo[InfoType]),
The_ClassForm[Gbl.Prefs.Theme]);
fprintf (Gbl.F.Out,"%s"
"</a>",
Act_GetTitleAction (Inf_ActionsSeeInfo[InfoType]));
Act_FormEnd ();
fprintf (Gbl.F.Out,"</li>");
}
fprintf (Gbl.F.Out,"</ul>"
"</td>"
"</tr>"
"</table>");
}
/*****************************************************************************/
/****** Change teacher's preference about force students to read info ********/
/*****************************************************************************/
void Inf_ChangeForceReadInfo (void)
{
extern const char *Txt_Students_now_are_required_to_read_this_information;
extern const char *Txt_Students_are_no_longer_obliged_to_read_this_information;
bool MustBeRead = Inf_GetMustBeReadFromForm ();
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Set status (if info must be read or not) into database *****/
Inf_SetForceReadIntoDB (MustBeRead);
/***** Write message of success *****/
Lay_ShowAlert (Lay_SUCCESS,
MustBeRead ? Txt_Students_now_are_required_to_read_this_information :
Txt_Students_are_no_longer_obliged_to_read_this_information);
/***** Show the selected info *****/
Inf_ShowInfo ();
}
/*****************************************************************************/
/************** Change confirmation of I have read course info ***************/
/*****************************************************************************/
void Inf_ChangeIHaveReadInfo (void)
{
extern const char *Txt_You_have_confirmed_that_you_have_read_this_information;
extern const char *Txt_You_have_eliminated_the_confirmation_that_you_have_read_this_information;
bool IHaveRead = Inf_GetIfIHaveReadFromForm ();
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Set status (if I have read or not a information) into database *****/
Inf_SetIHaveReadIntoDB (IHaveRead);
/***** Write message of success *****/
Lay_ShowAlert (Lay_SUCCESS,
IHaveRead ? Txt_You_have_confirmed_that_you_have_read_this_information :
Txt_You_have_eliminated_the_confirmation_that_you_have_read_this_information);
/***** Show the selected info *****/
Inf_ShowInfo ();
}
/*****************************************************************************/
/************* Get if info must be read by students from form ****************/
/*****************************************************************************/
static bool Inf_GetMustBeReadFromForm (void)
{
char YN[1+1];
/***** Get a parameter that indicates if info must be read by students ******/
Par_GetParToText ("MustBeRead",YN,1);
return (Str_ConvertToUpperLetter (YN[0]) == 'Y');
}
/*****************************************************************************/
/************* Get if info must be read by students from form ****************/
/*****************************************************************************/
static bool Inf_GetIfIHaveReadFromForm (void)
{
char YN[1+1];
/***** Get a parameter that indicates if I have read a course info ******/
Par_GetParToText ("IHaveRead",YN,1);
return (Str_ConvertToUpperLetter (YN[0]) == 'Y');
}
/*****************************************************************************/
/***************** Set if students must read course info *********************/
/*****************************************************************************/
static void Inf_SetForceReadIntoDB (bool MustBeRead)
{
char Query[512];
/***** Insert or replace info source for a specific type of course information *****/
sprintf (Query,"UPDATE crs_info_src SET MustBeRead='%c'"
" WHERE CrsCod='%ld' AND InfoType='%s'",
MustBeRead ? 'Y' :
'N',
Gbl.CurrentCrs.Crs.CrsCod,Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
DB_QueryUPDATE (Query,"can not update if info must be read");
}
/*****************************************************************************/
/********************* Set if I have read course info ************************/
/*****************************************************************************/
static void Inf_SetIHaveReadIntoDB (bool IHaveRead)
{
char Query[512];
if (IHaveRead)
{
/***** Insert I have read course information *****/
sprintf (Query,"REPLACE INTO crs_info_read (UsrCod,CrsCod,InfoType)"
" VALUES ('%ld','%ld','%s')",
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
DB_QueryUPDATE (Query,"can not set that I have read course info");
}
else
{
/***** Remove I have read course information *****/
sprintf (Query,"DELETE FROM crs_info_read"
" WHERE UsrCod='%ld' AND CrsCod='%ld' AND InfoType='%s'",
Gbl.Usrs.Me.UsrDat.UsrCod,
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
DB_QueryDELETE (Query,"can not set that I have not read course info");
}
}
/*****************************************************************************/
/********* Remove user's status about reading of course information **********/
/*****************************************************************************/
void Inf_RemoveUsrFromCrsInfoRead (long UsrCod,long CrsCod)
{
char Query[512];
/***** Remove user's status about reading of course information *****/
sprintf (Query,"DELETE FROM crs_info_read"
" WHERE UsrCod='%ld' AND CrsCod='%ld'",
UsrCod,CrsCod);
DB_QueryDELETE (Query,"can not set that I have not read course info");
}
/*****************************************************************************/
/**************** Check if exists and show link to a page ********************/
/*****************************************************************************/
static void Inf_CheckAndShowPage (void)
{
extern const char *Txt_No_information_available;
const char *FileNameHTML;
char PathRelFileHTML[PATH_MAX+1];
char URL[PATH_MAX+1];
// TODO !!!!!!!!!!!! If the page is hosted in server ==> it should be created a temporary public directory
// and host the page in a private directory !!!!!!!!!!!!!!!!!
/***** Open file with web page *****/
/* 1. Check if index.html exists */
FileNameHTML = "index.html";
sprintf (PathRelFileHTML,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage,FileNameHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML))
{
sprintf (URL,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].URLWebPage,FileNameHTML);
Inf_ShowPage (URL);
}
else
{
/* 2. If index.html not exists, try index.htm */
FileNameHTML = "index.htm";
sprintf (PathRelFileHTML,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage,FileNameHTML);
if (Fil_CheckIfPathExists (PathRelFileHTML))
{
sprintf (URL,"%s/%s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].URLWebPage,FileNameHTML);
Inf_ShowPage (URL);
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information_available);
}
}
/*****************************************************************************/
/************* Check if exists and write page into HTML buffer ***************/
/*****************************************************************************/
// This function is called only from web service
int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer)
{
char PathRelFileHTML[PATH_MAX+1];
FILE *FileHTML;
bool FileExists = false;
size_t Length;
/***** Initialize buffer *****/
*HTMLBuffer = NULL;
/***** Open file with web page *****/
/* 1. Check if index.html exists */
sprintf (PathRelFileHTML,"%s/index.html",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage);
if (Fil_CheckIfPathExists (PathRelFileHTML))
FileExists = true;
else
{
/* 2. If index.html not exists, try index.htm */
sprintf (PathRelFileHTML,"%s/index.htm",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage);
if (Fil_CheckIfPathExists (PathRelFileHTML))
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_ShowErrorAndExit ("Not enough memory for buffer.");
return soap_receiver_fault (Gbl.soap,
"Web page can not be copied into buffer",
"Not enough memory for buffer");
}
/* Copy file content into buffer */
if (fread ((void *) *HTMLBuffer,sizeof (char),Length,FileHTML) != Length)
{
fclose (FileHTML);
return soap_receiver_fault (Gbl.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;
}
/*****************************************************************************/
/**************** Check if exists and show link to a page ********************/
/*****************************************************************************/
static void Inf_CheckAndShowURL (void)
{
extern const char *Txt_No_information_available;
FILE *FileURL;
/***** Check if file with URL exists *****/
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL ,"rb")))
{
if (fgets (Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL,FileURL) == NULL)
Gbl.CurrentCrs.Info.URL[0] = '\0';
/* File is not longer needed ==> close it */
fclose (FileURL);
if (Gbl.CurrentCrs.Info.URL[0])
Inf_ShowPage (Gbl.CurrentCrs.Info.URL);
else
Lay_ShowAlert (Lay_INFO,Txt_No_information_available);
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information_available);
}
/*****************************************************************************/
/************* Check if exists and write URL into text buffer ****************/
/*****************************************************************************/
// This function is called only from web service
void Inf_WriteURLIntoTxtBuffer (char TxtBuffer[Cns_MAX_BYTES_URL+1])
{
FILE *FileURL;
/***** Initialize buffer *****/
TxtBuffer[0] = '\0';
/***** Check if file with URL exists *****/
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"rb")))
{
if (fgets (TxtBuffer,Cns_MAX_BYTES_URL,FileURL) == NULL)
TxtBuffer[0] = '\0';
/* File is not longer needed ==> close it */
fclose (FileURL);
}
}
/*****************************************************************************/
/*************** Show link to a internal or external a page ******************/
/*****************************************************************************/
static void Inf_ShowPage (const char *URL)
{
extern const char *The_ClassFormBold[The_NUM_THEMES];
extern const char *Txt_View_in_a_new_window;
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
bool ICanEdit = (Gbl.Usrs.Me.LoggedRole == Rol_TEACHER ||
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM);
/***** Start of frame *****/
Lay_StartRoundFrame (NULL,Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type],
ICanEdit ? Inf_PutIconToEditInfo :
NULL);
/***** Link to view in a new window *****/
fprintf (Gbl.F.Out,"<a href=\"%s\" target=\"_blank\" class=\"%s\">",
URL,The_ClassFormBold[Gbl.Prefs.Theme]);
Lay_PutIconWithText ("fullscreen16x16.gif",
Txt_View_in_a_new_window,
Txt_View_in_a_new_window);
fprintf (Gbl.F.Out,"</a>");
/***** End of frame *****/
Lay_EndRoundFrame ();
}
/*****************************************************************************/
/************************** Set course info source ***************************/
/*****************************************************************************/
void Inf_SetInfoSrc (void)
{
Inf_InfoSrc_t InfoSrcSelected = Inf_GetInfoSrcFromForm ();
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Set info source into database *****/
Inf_SetInfoSrcIntoDB (InfoSrcSelected);
/***** Show the selected info *****/
Inf_ShowInfo ();
}
/*****************************************************************************/
/************** Select course info source and send course info ***************/
/*****************************************************************************/
void Inf_FormsToSelSendInfo (void)
{
extern const char *Txt_Source_of_information;
extern const char *Txt_INFO_SRC_FULL_TEXT[Inf_NUM_INFO_SOURCES];
extern const char *Txt_INFO_SRC_HELP[Inf_NUM_INFO_SOURCES];
Inf_InfoSrc_t InfoSrc;
Inf_InfoSrc_t InfoSrcSelected;
bool MustBeRead;
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Get info source from database *****/
Inf_GetInfoSrcFromDB (Gbl.CurrentCrs.Crs.CrsCod,Gbl.CurrentCrs.Info.Type,&InfoSrcSelected,&MustBeRead);
/***** Form to choice between alternatives *****/
/* Start of table */
Lay_StartRoundFrameTable (NULL,4,Txt_Source_of_information);
/* Options */
for (InfoSrc = (Inf_InfoSrc_t) 0;
InfoSrc < Inf_NUM_INFO_SOURCES;
InfoSrc++)
{
/* Select info source */
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"DAT LEFT_TOP");
if (InfoSrc == InfoSrcSelected)
fprintf (Gbl.F.Out," LIGHT_BLUE");
fprintf (Gbl.F.Out,"\">");
Act_FormStart (Inf_ActionsSelecInfoSrc[Gbl.CurrentCrs.Info.Type]);
fprintf (Gbl.F.Out,"<input type=\"radio\" name=\"InfoSrc\" value=\"%u\"",
(unsigned) InfoSrc);
if (InfoSrc == InfoSrcSelected)
fprintf (Gbl.F.Out," checked=\"checked\"");
fprintf (Gbl.F.Out," onclick=\"document.getElementById('%s').submit();\" />",
Gbl.Form.Id);
Act_FormEnd ();
fprintf (Gbl.F.Out,"</td>");
/* Form for this info source */
fprintf (Gbl.F.Out,"<td class=\"LEFT_TOP");
if (InfoSrc == InfoSrcSelected)
fprintf (Gbl.F.Out," LIGHT_BLUE");
fprintf (Gbl.F.Out,"\">"
"<span class=\"TIT\">%s<br /></span>",
Txt_INFO_SRC_FULL_TEXT[InfoSrc]);
if (Txt_INFO_SRC_HELP[InfoSrc])
fprintf (Gbl.F.Out,"<span class=\"DAT\">(%s)</span>",
Txt_INFO_SRC_HELP[InfoSrc]);
if (Inf_FormsForEditionTypes[InfoSrc])
Inf_FormsForEditionTypes[InfoSrc] (InfoSrc);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
}
/* End of table */
Lay_EndRoundFrameTable ();
}
/*****************************************************************************/
/****************** Form to enter in integrated editor ***********************/
/*****************************************************************************/
void Inf_FormToEnterIntegratedEditor (Inf_InfoSrc_t InfoSrc)
{
extern const char *Txt_Edit;
/***** Start form *****/
Act_FormStart (Inf_ActionsInfo[InfoSrc][Gbl.CurrentCrs.Info.Type]);
/***** Send button *****/
Lay_PutConfirmButton (Txt_Edit);
/***** End form *****/
Act_FormEnd ();
}
/*****************************************************************************/
/****************** Form to enter in plain text editor ***********************/
/*****************************************************************************/
void Inf_FormToEnterPlainTextEditor (Inf_InfoSrc_t InfoSrc)
{
extern const char *Txt_Edit_plain_text;
/***** Start form *****/
Act_FormStart (Inf_ActionsInfo[InfoSrc][Gbl.CurrentCrs.Info.Type]);
/***** Send button *****/
Lay_PutConfirmButton (Txt_Edit_plain_text);
/***** End form *****/
Act_FormEnd ();
}
/*****************************************************************************/
/******************* Form to enter in rich text editor ***********************/
/*****************************************************************************/
void Inf_FormToEnterRichTextEditor (Inf_InfoSrc_t InfoSrc)
{
extern const char *Txt_Edit_rich_text;
/***** Start form *****/
Act_FormStart (Inf_ActionsInfo[InfoSrc][Gbl.CurrentCrs.Info.Type]);
/***** Send button *****/
Lay_PutConfirmButton (Txt_Edit_rich_text);
/***** End form *****/
Act_FormEnd ();
}
/*****************************************************************************/
/******************* Form to upload a file with a page ***********************/
/*****************************************************************************/
void Inf_FormToSendPage (Inf_InfoSrc_t InfoSrc)
{
extern const char *The_ClassForm[The_NUM_THEMES];
extern const char *Txt_File;
extern const char *Txt_Upload_file;
/***** Start form *****/
Act_FormStart (Inf_ActionsInfo[InfoSrc][Gbl.CurrentCrs.Info.Type]);
/***** File *****/
fprintf (Gbl.F.Out,"<table style=\"margin:0 auto;\">"
"<tr>"
"<td class=\"%s RIGHT_MIDDLE\">"
"%s:"
"</td>"
"<td class=\"LEFT_MIDDLE\">"
"<input type=\"file\" name=\"%s\""
" size=\"50\" maxlength=\"100\" value=\"\" />"
"</td>"
"</tr>"
"</table>",
The_ClassForm[Gbl.Prefs.Theme],Txt_File,
Fil_NAME_OF_PARAM_FILENAME_ORG);
/***** Send button *****/
Lay_PutCreateButton (Txt_Upload_file);
/***** End form *****/
Act_FormEnd ();
}
/*****************************************************************************/
/********************* Form to send a link to a web page *********************/
/*****************************************************************************/
void Inf_FormToSendURL (Inf_InfoSrc_t InfoSrc)
{
extern const char *The_ClassForm[The_NUM_THEMES];
extern const char *Txt_URL;
extern const char *Txt_Send_URL;
FILE *FileURL;
/***** Start form *****/
Act_FormStart (Inf_ActionsInfo[InfoSrc][Gbl.CurrentCrs.Info.Type]);
/***** Link *****/
fprintf (Gbl.F.Out,"<table style=\"margin:0 auto;\">"
"<tr>"
"<td class=\"%s RIGHT_MIDDLE\">"
"%s:"
"</td>"
"<td class=\"LEFT_MIDDLE\">"
"<input type=\"text\" name=\"InfoSrcURL\""
" size=\"50\" maxlength=\"256\" value=\"",
The_ClassForm[Gbl.Prefs.Theme],Txt_URL);
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"rb")) == NULL)
fprintf (Gbl.F.Out,"http://");
else
{
if (fgets (Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL,FileURL) == NULL)
Gbl.CurrentCrs.Info.URL[0] = '\0';
/* File is not needed now. Close it */
fclose (FileURL);
fprintf (Gbl.F.Out,"%s",Gbl.CurrentCrs.Info.URL);
}
fprintf (Gbl.F.Out,"\" />"
"</td>"
"</tr>"
"</table>");
/***** Send button *****/
Lay_PutCreateButton (Txt_Send_URL);
/***** End form *****/
Act_FormEnd ();
}
/*****************************************************************************/
/******** Returns bibliography, assessment, etc. from Gbl.Action.Act *********/
/*****************************************************************************/
static Inf_InfoType_t Inf_AsignInfoType (void)
{
switch (Gbl.Action.Act)
{
case ActSeeCrsInf:
case ActEdiCrsInf:
case ActChgFrcReaCrsInf:
case ActChgHavReaCrsInf:
case ActSelInfSrcCrsInf:
case ActEditorCrsInf:
case ActRcvURLCrsInf:
case ActRcvPagCrsInf:
case ActPlaTxtEdiCrsInf:
case ActRchTxtEdiCrsInf:
case ActRcvPlaTxtCrsInf:
case ActRcvRchTxtCrsInf:
return Inf_INTRODUCTION;
case ActSeeTchGui:
case ActEdiTchGui:
case ActChgFrcReaTchGui:
case ActChgHavReaTchGui:
case ActSelInfSrcTchGui:
case ActEditorTchGui:
case ActRcvURLTchGui:
case ActRcvPagTchGui:
case ActPlaTxtEdiTchGui:
case ActRchTxtEdiTchGui:
case ActRcvPlaTxtTchGui:
case ActRcvRchTxtTchGui:
return Inf_TEACHING_GUIDE;
case ActSeeSyl:
Syl_GetParamWhichSyllabus ();
return (Gbl.CurrentCrs.Syllabus.WhichSyllabus == Syl_LECTURES ? Inf_LECTURES :
Inf_PRACTICALS);
case ActSeeSylLec:
case ActEdiSylLec:
case ActChgFrcReaSylLec:
case ActChgHavReaSylLec:
case ActSelInfSrcSylLec:
case ActEditorSylLec:
case ActRcvURLSylLec:
case ActRcvPagSylLec:
case ActPlaTxtEdiSylLec:
case ActRchTxtEdiSylLec:
case ActRcvPlaTxtSylLec:
case ActRcvRchTxtSylLec:
Gbl.CurrentCrs.Syllabus.WhichSyllabus = Syl_LECTURES;
return Inf_LECTURES;
case ActSeeSylPra:
case ActEdiSylPra:
case ActChgFrcReaSylPra:
case ActChgHavReaSylPra:
case ActSelInfSrcSylPra:
case ActEditorSylPra:
case ActRcvURLSylPra:
case ActRcvPagSylPra:
case ActPlaTxtEdiSylPra:
case ActRchTxtEdiSylPra:
case ActRcvPlaTxtSylPra:
case ActRcvRchTxtSylPra:
Gbl.CurrentCrs.Syllabus.WhichSyllabus = Syl_PRACTICALS;
return Inf_PRACTICALS;
case ActSeeBib:
case ActEdiBib:
case ActChgFrcReaBib:
case ActChgHavReaBib:
case ActSelInfSrcBib:
case ActEditorBib:
case ActRcvURLBib:
case ActRcvPagBib:
case ActPlaTxtEdiBib:
case ActRchTxtEdiBib:
case ActRcvPlaTxtBib:
case ActRcvRchTxtBib:
return Inf_BIBLIOGRAPHY;
case ActSeeFAQ:
case ActEdiFAQ:
case ActChgFrcReaFAQ:
case ActChgHavReaFAQ:
case ActSelInfSrcFAQ:
case ActEditorFAQ:
case ActRcvURLFAQ:
case ActRcvPagFAQ:
case ActPlaTxtEdiFAQ:
case ActRchTxtEdiFAQ:
case ActRcvPlaTxtFAQ:
case ActRcvRchTxtFAQ:
return Inf_FAQ;
case ActSeeCrsLnk:
case ActEdiCrsLnk:
case ActChgFrcReaCrsLnk:
case ActChgHavReaCrsLnk:
case ActSelInfSrcCrsLnk:
case ActEditorCrsLnk:
case ActRcvURLCrsLnk:
case ActRcvPagCrsLnk:
case ActPlaTxtEdiCrsLnk:
case ActRchTxtEdiCrsLnk:
case ActRcvPlaTxtCrsLnk:
case ActRcvRchTxtCrsLnk:
return Inf_LINKS;
case ActSeeAss:
case ActEdiAss:
case ActChgFrcReaAss:
case ActChgHavReaAss:
case ActSelInfSrcAss:
case ActEditorAss:
case ActRcvURLAss:
case ActRcvPagAss:
case ActPlaTxtEdiAss:
case ActRchTxtEdiAss:
case ActRcvPlaTxtAss:
case ActRcvRchTxtAss:
return Inf_ASSESSMENT;
}
return (Inf_InfoType_t) 0; // If action is not one of the former ones, the returned value is not important
}
/*****************************************************************************/
/********** Get info source for bibliography, FAQ, etc. from form ************/
/*****************************************************************************/
Inf_InfoSrc_t Inf_GetInfoSrcFromForm (void)
{
char UnsignedStr[10+1];
int InfoSrcInt;
Inf_InfoSrc_t InfoSrc;
/***** Get info source for a specific type of course information
(introduction, teaching guide, bibliography, FAQ, links or evaluation) *****/
Par_GetParToText ("InfoSrc",UnsignedStr,2);
if (sscanf (UnsignedStr,"%d",&InfoSrcInt) != 1)
return Inf_INFO_SRC_NONE;
InfoSrc = (Inf_InfoSrc_t) InfoSrcInt;
return InfoSrc;
}
/*****************************************************************************/
/********* Set info source for a type of course info from database ***********/
/*****************************************************************************/
void Inf_SetInfoSrcIntoDB (Inf_InfoSrc_t InfoSrc)
{
char Query[512];
/***** Get if info source is already stored in database *****/
sprintf (Query,"SELECT COUNT(*) FROM crs_info_src"
" WHERE CrsCod='%ld' AND InfoType='%s'",
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
if (DB_QueryCOUNT (Query,"can not get if info source is already stored in database")) // Info is already stored in database, so update it
{ // Update info source
if (InfoSrc == Inf_INFO_SRC_NONE)
sprintf (Query,"UPDATE crs_info_src SET InfoSrc='%s',MustBeRead='N'"
" WHERE CrsCod='%ld' AND InfoType='%s'",
Inf_NamesInDBForInfoSrc[Inf_INFO_SRC_NONE],
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
else // MustBeRead remains unchanged
sprintf (Query,"UPDATE crs_info_src SET InfoSrc='%s'"
" WHERE CrsCod='%ld' AND InfoType='%s'",
Inf_NamesInDBForInfoSrc[InfoSrc],
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
DB_QueryUPDATE (Query,"can not update info source");
}
else // Info is not stored in database, so insert it
{
sprintf (Query,"INSERT INTO crs_info_src (CrsCod,InfoType,InfoSrc,MustBeRead)"
" VALUES ('%ld','%s','%s','N')",
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type],
Inf_NamesInDBForInfoSrc[InfoSrc]);
DB_QueryINSERT (Query,"can not insert info source");
}
}
/*****************************************************************************/
/********* Get info source for a type of course info from database ***********/
/*****************************************************************************/
void Inf_GetInfoSrcFromDB (long CrsCod,Inf_InfoType_t InfoType,
Inf_InfoSrc_t *InfoSrc,bool *MustBeRead)
{
char Query[512];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
char PathFile[PATH_MAX+1];
FILE *File;
char URL[Cns_MAX_BYTES_URL+1];
/***** Set default values *****/
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
/***** Get info source for a specific type of course information
(bibliography, FAQ, links or evaluation) from database *****/
sprintf (Query,"SELECT InfoSrc,MustBeRead FROM crs_info_src"
" WHERE CrsCod='%ld' AND InfoType='%s'",
CrsCod,Inf_NamesInDBForInfoType[InfoType]);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get info source");
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get row */
row = mysql_fetch_row (mysql_res);
/* Get info source (row[0]) */
*InfoSrc = Inf_ConvertFromStrDBToInfoSrc (row[0]);
/* Get if students must read info (row[1]) */
*MustBeRead = (Str_ConvertToUpperLetter (row[1][0]) == 'Y');;
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting info source.");
/***** If info is empty, return Inf_INFO_SRC_NONE *****/
switch (*InfoSrc)
{
case Inf_INFO_SRC_NONE:
*MustBeRead = false;
break;
case Inf_INFO_SRC_EDITOR:
switch (InfoType)
{
case Inf_LECTURES:
case Inf_PRACTICALS:
/***** Check if file exists *****/
sprintf (PathFile,"%s/%s/%ld/%s/%s",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_CRS,CrsCod,
InfoType == Inf_LECTURES ? Cfg_SYLLABUS_FOLDER_LECTURES :
Cfg_SYLLABUS_FOLDER_PRACTICALS,
Cfg_SYLLABUS_FILENAME);
if (!Fil_CheckIfPathExists (PathFile)) // Should be XML file checked for items!!!!
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
case Inf_INTRODUCTION:
case Inf_TEACHING_GUIDE:
case Inf_BIBLIOGRAPHY:
case Inf_FAQ:
case Inf_LINKS:
case Inf_ASSESSMENT:
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
break; // Internal editor is not yet available
}
break;
case Inf_INFO_SRC_PLAIN_TEXT:
if (!Inf_CheckIfInfoTxtIsNotEmpty (CrsCod,InfoType))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
case Inf_INFO_SRC_RICH_TEXT:
if (!Inf_CheckIfInfoTxtIsNotEmpty (CrsCod,InfoType))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
case Inf_INFO_SRC_PAGE:
/***** Check if file with web page exists *****/
sprintf (PathFile,"%s/%s/%ld/%s/index.html",
Cfg_PATH_SWAD_PUBLIC,Cfg_FOLDER_CRS,CrsCod,Inf_FileNamesForInfoType[InfoType]);
if (!Fil_CheckIfPathExists (PathFile))
{
// If index.html not exists, try index.htm
sprintf (PathFile,"%s/%s/%ld/%s/index.htm",
Cfg_PATH_SWAD_PUBLIC,Cfg_FOLDER_CRS,CrsCod,Inf_FileNamesForInfoType[InfoType]);
if (!Fil_CheckIfPathExists (PathFile))
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
}
break;
case Inf_INFO_SRC_URL:
/***** Check if URL in file is empty or not *****/
sprintf (PathFile,"%s/%s/%ld/%s.url",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_CRS,CrsCod,Inf_FileNamesForInfoType[InfoType]);
File = fopen (PathFile,"rb");
if (File)
{
if (fgets (URL,Cns_MAX_BYTES_URL,File) == NULL)
URL[0] = '\0';
/* File is not longer needed ==> close it */
fclose (File);
if (!URL[0])
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
}
else
{
*InfoSrc = Inf_INFO_SRC_NONE;
*MustBeRead = false;
}
break;
}
}
/*****************************************************************************/
/*** Convert a string with info type in database to a Inf_InfoType_t value ***/
/*****************************************************************************/
Inf_InfoType_t Inf_ConvertFromStrDBToInfoType (const char *StrInfoTypeDB)
{
Inf_InfoType_t InfoType;
for (InfoType = (Inf_InfoType_t) 0;
InfoType < Inf_NUM_INFO_TYPES;
InfoType++)
if (!strcmp (StrInfoTypeDB,Inf_NamesInDBForInfoType[InfoType]))
return InfoType;
return (Inf_InfoType_t) 0;
}
/*****************************************************************************/
/** Convert a string with info source in database to a Inf_InfoSrc_t value ***/
/*****************************************************************************/
Inf_InfoSrc_t Inf_ConvertFromStrDBToInfoSrc (const char *StrInfoSrcDB)
{
Inf_InfoSrc_t InfoSrc;
for (InfoSrc = (Inf_InfoSrc_t) 0;
InfoSrc < Inf_NUM_INFO_SOURCES;
InfoSrc++)
if (!strcmp (StrInfoSrcDB,Inf_NamesInDBForInfoSrc[InfoSrc]))
return InfoSrc;
return (Inf_InfoSrc_t) 0;
}
/*****************************************************************************/
/********** Set info text for a type of course info from database ************/
/*****************************************************************************/
static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD)
{
char Query[256+Cns_MAX_BYTES_LONG_TEXT];
/***** Insert or replace info source for a specific type of course information *****/
sprintf (Query,"REPLACE INTO crs_info_txt"
" (CrsCod,InfoType,InfoTxtHTML,InfoTxtMD)"
" VALUES ('%ld','%s','%s','%s')",
Gbl.CurrentCrs.Crs.CrsCod,
Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type],
InfoTxtHTML,InfoTxtMD);
DB_QueryREPLACE (Query,"can not update info text");
}
/*****************************************************************************/
/********** Get info text for a type of course info from database ************/
/*****************************************************************************/
static void Inf_GetInfoTxtFromDB (char *InfoTxtHTML,char *InfoTxtMD,size_t MaxLength)
{
char Query[512];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
/***** Get info source for a specific type of course information
(bibliography, FAQ, links or evaluation) from database *****/
sprintf (Query,"SELECT InfoTxtHTML,InfoTxtMD FROM crs_info_txt"
" WHERE CrsCod='%ld' AND InfoType='%s'",
Gbl.CurrentCrs.Crs.CrsCod,Inf_NamesInDBForInfoType[Gbl.CurrentCrs.Info.Type]);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get info text");
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
/* Get text in HTML format (not rigorous) */
if (InfoTxtHTML)
{
strncpy (InfoTxtHTML,row[0],MaxLength);
InfoTxtHTML[MaxLength] = '\0';
}
/* Get text in Markdown format */
if (InfoTxtMD)
{
strncpy (InfoTxtMD,row[1],MaxLength);
InfoTxtMD[MaxLength] = '\0';
}
}
else
{
if (InfoTxtHTML)
InfoTxtHTML[0] = '\0';
if (InfoTxtMD)
InfoTxtMD[0] = '\0';
}
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
if (NumRows > 1)
Lay_ShowErrorAndExit ("Error when getting info text.");
}
/*****************************************************************************/
/*** Check if info text for a type of course info is not empty in database ***/
/*****************************************************************************/
static bool Inf_CheckIfInfoTxtIsNotEmpty (long CrsCod,Inf_InfoType_t InfoType)
{
char Query[512];
MYSQL_RES *mysql_res;
MYSQL_ROW row;
unsigned long NumRows;
bool Result;
/***** Get info source for a specific type of course information
(bibliography, FAQ, links or evaluation) from database *****/
sprintf (Query,"SELECT InfoTxtHTML FROM crs_info_txt"
" WHERE CrsCod='%ld' AND InfoType='%s'",
CrsCod,Inf_NamesInDBForInfoType[InfoType]);
NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get info text");
/***** The result of the query must have one row or none *****/
if (NumRows == 1)
{
/* Get info text */
row = mysql_fetch_row (mysql_res);
Result = (row[0][0] != '\0'); // Is text empty?
}
else
Result = false;
/***** Free structure that stores the query result *****/
DB_FreeMySQLResult (&mysql_res);
return Result;
}
/*****************************************************************************/
/********************* Show information about the course *********************/
/*****************************************************************************/
static void Inf_ShowPlainTxtInfo (void)
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Txt_No_information_available;
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
bool ICanEdit = (Gbl.Usrs.Me.LoggedRole == Rol_TEACHER ||
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
if (TxtHTML[0])
{
/***** Start table *****/
Lay_StartRoundFrame (NULL,Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type],
ICanEdit ? Inf_PutIconToEditInfo :
NULL);
fprintf (Gbl.F.Out,"<table class=\"FRAME_TABLE\">");
if (Gbl.CurrentCrs.Info.Type == Inf_INTRODUCTION ||
Gbl.CurrentCrs.Info.Type == Inf_TEACHING_GUIDE)
Lay_WriteHeaderClassPhoto (3,false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod);
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"DAT LEFT_MIDDLE\">");
/***** 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 (Gbl.F.Out,"%s",TxtHTML);
/***** End table *****/
fprintf (Gbl.F.Out,"</td>"
"</tr>"
"</table>");
Lay_EndRoundFrame ();
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information_available);
}
/*****************************************************************************/
/********************* Show information about the course *********************/
/*****************************************************************************/
static void Inf_ShowRichTxtInfo (void)
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Txt_No_information_available;
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
char TxtMD[Cns_MAX_BYTES_LONG_TEXT+1];
char PathFileMD[PATH_MAX+1];
char PathFileHTML[PATH_MAX+1];
FILE *FileMD; // Temporary Markdown file
FILE *FileHTML; // Temporary HTML file
char MathJaxURL[PATH_MAX];
char Command[512+PATH_MAX*3]; // Command to call the program of preprocessing of photos
int ReturnCode;
bool ICanEdit = (Gbl.Usrs.Me.LoggedRole == Rol_TEACHER ||
Gbl.Usrs.Me.LoggedRole == Rol_SYS_ADM);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,TxtMD,Cns_MAX_BYTES_LONG_TEXT);
if (TxtMD[0])
{
/***** Start table *****/
Lay_StartRoundFrame (NULL,Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type],
ICanEdit ? Inf_PutIconToEditInfo :
NULL);
fprintf (Gbl.F.Out,"<table class=\"FRAME_TABLE\">");
if (Gbl.CurrentCrs.Info.Type == Inf_INTRODUCTION ||
Gbl.CurrentCrs.Info.Type == Inf_TEACHING_GUIDE)
Lay_WriteHeaderClassPhoto (3,false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod);
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"LEFT_MIDDLE\">"
"<div id=\"crs_info\">");
/***** Store text into a temporary .md file in HTML output directory *****/
// TODO: change to another directory?
/* Create a unique name for the .md file */
sprintf (PathFileMD,"%s/%s/%s.md",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_OUT,Gbl.UniqueNameEncrypted);
sprintf (PathFileHTML,"%s/%s/%s.md.html", // Do not use only .html because that is the output temporary file
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_OUT,Gbl.UniqueNameEncrypted);
/* Open Markdown file for writing */
if ((FileMD = fopen (PathFileMD,"wb")) == NULL)
Lay_ShowErrorAndExit ("Can not create temporary Markdown file.");
/* Write text into Markdown file */
fprintf (FileMD,"%s",TxtMD);
/* Close Markdown file */
fclose (FileMD);
/***** Convert from Markdown to HTML *****/
#ifdef Cfg_MATHJAX_LOCAL
// Use the local copy of MathJax
sprintf (MathJaxURL,"=%s/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML",
Cfg_HTTPS_URL_SWAD_PUBLIC);
#else
// Use the MathJax Content Delivery Network (CDN)
MathJaxURL[0] = '\0';
#endif
// --ascii uses only ascii characters in output
// (uses numerical entities instead of UTF-8)
// is mandatory in order to convert (with iconv) the UTF-8 output of pandoc to WINDOWS-1252
sprintf (Command,"iconv -f WINDOWS-1252 -t UTF-8 %s"
" | "
"pandoc --ascii --mathjax%s -f markdown -t html5"
" | "
"iconv -f UTF-8 -t WINDOWS-1252 -o %s",
PathFileMD,
MathJaxURL,
PathFileHTML);
ReturnCode = system (Command);
if (ReturnCode == -1)
Lay_ShowErrorAndExit ("Error when running command to convert from Markdown to HTML.");
/***** Remove Markdown file *****/
unlink (PathFileMD);
/***** Copy HTML file just created to HTML output *****/
/* Open temporary HTML file for reading */
if ((FileHTML = fopen (PathFileHTML,"rb")) == NULL)
Lay_ShowErrorAndExit ("Can not open temporary HTML file.");
/* Copy from temporary HTML file to output file */
Fil_FastCopyOfOpenFiles (FileHTML,Gbl.F.Out);
/* Close and remove temporary HTML file */
fclose (FileHTML);
unlink (PathFileHTML);
/***** Finish table *****/
fprintf (Gbl.F.Out,"</div>"
"</td>"
"</tr>"
"</table>");
Lay_EndRoundFrame ();
}
else
Lay_ShowAlert (Lay_INFO,Txt_No_information_available);
}
/*****************************************************************************/
/************* Check if exists and write page into HTML buffer ***************/
/*****************************************************************************/
// This function is called only from web service
int Inf_WritePlainTextIntoHTMLBuffer (char **HTMLBuffer)
{
extern const char *Txt_STR_LANG_ID[1+Txt_NUM_LANGUAGES];
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 (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
if (TxtHTML[0])
{
/***** Create a unique name for the file *****/
sprintf (FileNameHTMLTmp,"%s/%s/%s_info.html",
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_OUT,Gbl.UniqueNameEncrypted);
/***** Create a new temporary file for writing and reading *****/
if ((FileHTMLTmp = fopen (FileNameHTMLTmp,"w+b")) == NULL)
return soap_receiver_fault (Gbl.soap,
"Plain text can not be copied into buffer",
"Can not create temporary file");
/***** Write start of HTML code *****/
fprintf (FileHTMLTmp,"<!DOCTYPE html>\n"
"<html lang=\"%s\">\n"
"<head>\n"
"<meta http-equiv=\"Content-Type\""
" content=\"text/html;charset=windows-1252\" />\n"
"<title>%s</title>\n"
"</head>\n"
"<body>\n",
Txt_STR_LANG_ID[Gbl.Prefs.Language], // Language
Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type]); // Page title
/***** Write plain text into text buffer *****/
fprintf (FileHTMLTmp,"<div class=\"DAT LEFT_MIDDLE\">\n");
/* 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 (Gbl.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 ((void *) *HTMLBuffer,sizeof (char),Length,FileHTMLTmp) != Length)
{
fclose (FileHTMLTmp);
unlink (FileNameHTMLTmp);
return soap_receiver_fault (Gbl.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;
}
/*****************************************************************************/
/************** Edit plain text information about the course *****************/
/*****************************************************************************/
void Inf_EditPlainTxtInfo (void)
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Txt_Save;
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Start table *****/
Act_FormStart (Inf_ActionsRcvPlaTxtInfo[Gbl.CurrentCrs.Info.Type]);
Lay_StartRoundFrameTable (NULL,0,Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type]);
if (Gbl.CurrentCrs.Info.Type == Inf_INTRODUCTION ||
Gbl.CurrentCrs.Info.Type == Inf_TEACHING_GUIDE)
Lay_WriteHeaderClassPhoto (1,false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
/***** Edition area *****/
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"CENTER_MIDDLE\">");
Lay_HelpPlainEditor ();
fprintf (Gbl.F.Out,"<textarea name=\"Txt\" cols=\"80\" rows=\"20\">"
"%s"
"</textarea>",
TxtHTML);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
/***** End form *****/
Lay_EndRoundFrameTableWithButton (Lay_CONFIRM_BUTTON,Txt_Save);
Act_FormEnd ();
}
/*****************************************************************************/
/*************** Edit rich text information about the course *****************/
/*****************************************************************************/
void Inf_EditRichTxtInfo (void)
{
extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES];
extern const char *Txt_Save;
char TxtHTML[Cns_MAX_BYTES_LONG_TEXT+1];
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Start form *****/
Act_FormStart (Inf_ActionsRcvRchTxtInfo[Gbl.CurrentCrs.Info.Type]);
Lay_StartRoundFrameTable (NULL,0,Txt_INFO_TITLE[Gbl.CurrentCrs.Info.Type]);
if (Gbl.CurrentCrs.Info.Type == Inf_INTRODUCTION ||
Gbl.CurrentCrs.Info.Type == Inf_TEACHING_GUIDE)
Lay_WriteHeaderClassPhoto (1,false,false,Gbl.CurrentIns.Ins.InsCod,Gbl.CurrentDeg.Deg.DegCod,Gbl.CurrentCrs.Crs.CrsCod);
/***** Get info text from database *****/
Inf_GetInfoTxtFromDB (TxtHTML,NULL,Cns_MAX_BYTES_LONG_TEXT);
/***** Edition area *****/
fprintf (Gbl.F.Out,"<tr>"
"<td class=\"CENTER_MIDDLE\">");
Lay_HelpRichEditor ();
fprintf (Gbl.F.Out,"<textarea name=\"Txt\" cols=\"80\" rows=\"20\">"
"%s"
"</textarea>",
TxtHTML);
fprintf (Gbl.F.Out,"</td>"
"</tr>");
/***** End form *****/
Lay_EndRoundFrameTableWithButton (Lay_CONFIRM_BUTTON,Txt_Save);
Act_FormEnd ();
}
/*****************************************************************************/
/*************** Receive and change plain text of course info ****************/
/*****************************************************************************/
void Inf_RecAndChangePlainTxtInfo (void)
{
char Txt_HTMLFormat[Cns_MAX_BYTES_LONG_TEXT+1];
char Txt_MarkdownFormat[Cns_MAX_BYTES_LONG_TEXT+1];
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Get text with course information from form *****/
Par_GetParameter (Par_PARAM_SINGLE,"Txt",Txt_HTMLFormat,Cns_MAX_BYTES_LONG_TEXT);
strcpy (Txt_MarkdownFormat,Txt_HTMLFormat);
Str_ChangeFormat (Str_FROM_FORM,Str_TO_HTML,
Txt_HTMLFormat,Cns_MAX_BYTES_LONG_TEXT,true); // Store in HTML format (not rigorous)
Str_ChangeFormat (Str_FROM_FORM,Str_TO_MARKDOWN,
Txt_MarkdownFormat,Cns_MAX_BYTES_LONG_TEXT,true); // Store a copy in Markdown format
/***** Update text of course info in database *****/
Inf_SetInfoTxtIntoDB (Txt_HTMLFormat,Txt_MarkdownFormat);
/***** Change info source to "plain text" in database *****/
Inf_SetInfoSrcIntoDB (Txt_HTMLFormat[0] ? Inf_INFO_SRC_PLAIN_TEXT :
Inf_INFO_SRC_NONE);
if (Txt_HTMLFormat[0])
/***** Show the updated info *****/
Inf_ShowInfo ();
else
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
/*****************************************************************************/
/*************** Receive and change rich text of course info *****************/
/*****************************************************************************/
void Inf_RecAndChangeRichTxtInfo (void)
{
char Txt_HTMLFormat[Cns_MAX_BYTES_LONG_TEXT+1];
char Txt_MarkdownFormat[Cns_MAX_BYTES_LONG_TEXT+1];
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Get text with course information from form *****/
Par_GetParameter (Par_PARAM_SINGLE,"Txt",Txt_HTMLFormat,Cns_MAX_BYTES_LONG_TEXT);
strcpy (Txt_MarkdownFormat,Txt_HTMLFormat);
Str_ChangeFormat (Str_FROM_FORM,Str_TO_HTML,
Txt_HTMLFormat,Cns_MAX_BYTES_LONG_TEXT,true); // Store in HTML format (not rigorous)
Str_ChangeFormat (Str_FROM_FORM,Str_TO_MARKDOWN,
Txt_MarkdownFormat,Cns_MAX_BYTES_LONG_TEXT,true); // Store a copy in Markdown format
/***** Update text of course info in database *****/
Inf_SetInfoTxtIntoDB (Txt_HTMLFormat,Txt_MarkdownFormat);
/***** Change info source to "rich text" in database *****/
Inf_SetInfoSrcIntoDB (Txt_HTMLFormat[0] ? Inf_INFO_SRC_RICH_TEXT :
Inf_INFO_SRC_NONE);
if (Txt_HTMLFormat[0])
/***** Show the updated info *****/
Inf_ShowInfo ();
else
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
/*****************************************************************************/
/********* Receive a link to a page of syllabus, bibliography, etc. **********/
/*****************************************************************************/
void Inf_ReceiveURLInfo (void)
{
extern const char *Txt_The_URL_X_has_been_updated;
FILE *FileURL;
bool URLIsOK = false;
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** Get parameter with URL *****/
Par_GetParToText ("InfoSrcURL",Gbl.CurrentCrs.Info.URL,Cns_MAX_BYTES_URL);
/***** Open file with URL *****/
if ((FileURL = fopen (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileURL,"wb")) != NULL)
{
/***** Write URL *****/
fprintf (FileURL,"%s",Gbl.CurrentCrs.Info.URL);
/***** Close file *****/
fclose (FileURL);
/***** Write message *****/
sprintf (Gbl.Message,Txt_The_URL_X_has_been_updated,
Gbl.CurrentCrs.Info.URL);
Lay_ShowAlert (Lay_SUCCESS,Gbl.Message);
URLIsOK = true;
}
else
Lay_ShowAlert (Lay_ERROR,"Error when saving URL to file.");
if (URLIsOK)
{
/***** Change info source to URL in database *****/
Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_URL);
/***** Show the updated info *****/
Inf_ShowInfo ();
}
else
{
/***** Change info source to none in database *****/
Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_NONE);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
}
/*****************************************************************************/
/************** Receive a page of syllabus, bibliography, etc. ***************/
/*****************************************************************************/
void Inf_ReceivePagInfo (void)
{
extern const char *Txt_The_file_type_is_X_and_should_be_HTML_or_ZIP;
extern const char *Txt_The_HTML_file_has_been_received_successfully;
extern const char *Txt_The_ZIP_file_has_been_received_successfully;
extern const char *Txt_The_ZIP_file_has_been_unzipped_successfully;
extern const char *Txt_Found_an_index_html_file;
extern const char *Txt_Found_an_index_htm_file;
extern const char *Txt_No_file_index_html_index_htm_found_within_the_ZIP_file;
extern const char *Txt_The_file_type_should_be_HTML_or_ZIP;
char SourceFileName[PATH_MAX+1];
char PathRelFileHTML[PATH_MAX+1];
char MIMEType[Brw_MAX_BYTES_MIME_TYPE+1];
char StrUnzip[100+PATH_MAX*2+1];
char *PathWebPage;
bool FileIsOK = false;
/***** Set info type *****/
Gbl.CurrentCrs.Info.Type = Inf_AsignInfoType ();
/***** First of all, store in disk the file from stdin (really from Gbl.F.Tmp) *****/
Fil_StartReceptionOfFile (SourceFileName,MIMEType);
/***** Check that MIME type is HTML or ZIP *****/
if (strcmp (MIMEType,"text/html") &&
strcmp (MIMEType,"text/plain") &&
strcmp (MIMEType,"application/x-zip-compressed") &&
strcmp (MIMEType,"application/zip") &&
strcmp (MIMEType,"application/octet-stream") &&
strcmp (MIMEType,"application/x-download"))
{
sprintf (Gbl.Message,Txt_The_file_type_is_X_and_should_be_HTML_or_ZIP,
MIMEType);
Lay_ShowAlert (Lay_INFO,Gbl.Message);
}
else
{
/***** End the reception of the data *****/
PathWebPage = Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelWebPage;
if (Str_FileIs (SourceFileName,"html") ||
Str_FileIs (SourceFileName,"htm" )) // .html or .htm file
{
Brw_RemoveTree (PathWebPage);
Fil_CreateDirIfNotExists (PathWebPage);
sprintf (PathRelFileHTML,"%s/index.html",PathWebPage);
if (Fil_EndReceptionOfFile (PathRelFileHTML))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_HTML_file_has_been_received_successfully);
FileIsOK = true;
}
else
Lay_ShowAlert (Lay_WARNING,"Error uploading file.");
}
else if (Str_FileIs (SourceFileName,"zip")) // .zip file
{
Brw_RemoveTree (PathWebPage);
Fil_CreateDirIfNotExists (PathWebPage);
if (Fil_EndReceptionOfFile (Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileZIP))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_received_successfully);
/* Uncompress ZIP */
sprintf (StrUnzip,"unzip -qq -o %s -d %s",
Gbl.CurrentCrs.Info.Links[Gbl.CurrentCrs.Info.Type].PathRelFileZIP,PathWebPage);
if (system (StrUnzip) == 0)
{
/* Check if uploaded file is index.html or index.htm */
sprintf (PathRelFileHTML,"%s/index.html",PathWebPage);
if (Fil_CheckIfPathExists (PathRelFileHTML))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully);
Lay_ShowAlert (Lay_SUCCESS,Txt_Found_an_index_html_file);
FileIsOK = true;
}
else
{
sprintf (PathRelFileHTML,"%s/index.htm",PathWebPage);
if (Fil_CheckIfPathExists (PathRelFileHTML))
{
Lay_ShowAlert (Lay_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully);
Lay_ShowAlert (Lay_SUCCESS,Txt_Found_an_index_htm_file);
FileIsOK = true;
}
else
Lay_ShowAlert (Lay_WARNING,Txt_No_file_index_html_index_htm_found_within_the_ZIP_file);
}
}
else
Lay_ShowErrorAndExit ("Can not unzip file.");
}
else
Lay_ShowAlert (Lay_WARNING,"Error uploading file.");
}
else
Lay_ShowAlert (Lay_WARNING,Txt_The_file_type_should_be_HTML_or_ZIP);
}
if (FileIsOK)
{
/***** Change info source to page in database *****/
Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_PAGE);
/***** Show the updated info *****/
Inf_ShowInfo ();
}
else
{
/***** Change info source to none in database *****/
Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_NONE);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
}
/*****************************************************************************/
/******************* Integrated editor for introduction **********************/
/*****************************************************************************/
void Inf_EditorCourseInfo (void)
{
extern const char *Txt_The_integrated_editor_is_not_yet_available;
Lay_ShowAlert (Lay_WARNING,Txt_The_integrated_editor_is_not_yet_available);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
/*****************************************************************************/
/****************** Integrated editor for teaching guide *********************/
/*****************************************************************************/
void Inf_EditorTeachingGuide (void)
{
extern const char *Txt_The_integrated_editor_is_not_yet_available;
Lay_ShowAlert (Lay_WARNING,Txt_The_integrated_editor_is_not_yet_available);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
/*****************************************************************************/
/******************* Integrated editor for bibliography **********************/
/*****************************************************************************/
void Inf_EditorBibliography (void)
{
extern const char *Txt_The_integrated_editor_is_not_yet_available;
Lay_ShowAlert (Lay_WARNING,Txt_The_integrated_editor_is_not_yet_available);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
/*****************************************************************************/
/*********************** Integrated editor for FAQ ***************************/
/*****************************************************************************/
void Inf_EditorFAQ (void)
{
extern const char *Txt_The_integrated_editor_is_not_yet_available;
Lay_ShowAlert (Lay_WARNING,Txt_The_integrated_editor_is_not_yet_available);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
/*****************************************************************************/
/********************* Integrated editor for links ***************************/
/*****************************************************************************/
void Inf_EditorLinks (void)
{
extern const char *Txt_The_integrated_editor_is_not_yet_available;
Lay_ShowAlert (Lay_WARNING,Txt_The_integrated_editor_is_not_yet_available);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}
/*****************************************************************************/
/****************** Integrated editor for assessment system ******************/
/*****************************************************************************/
void Inf_EditorAssessment (void)
{
extern const char *Txt_The_integrated_editor_is_not_yet_available;
Lay_ShowAlert (Lay_WARNING,Txt_The_integrated_editor_is_not_yet_available);
/***** Show again the form to select and send course info *****/
Inf_FormsToSelSendInfo ();
}