// 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-2019 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 . */ /*****************************************************************************/ /********************************* Headers ***********************************/ /*****************************************************************************/ #include // For maximum values #include // For PATH_MAX, NAME_MAX #include // For NULL #include // For getenv, etc #include // For SOAP_OK and soap functions #include // For string functions #include // For unlink #include "swad_action.h" #include "swad_box.h" #include "swad_database.h" #include "swad_form.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", }; /***** Help *****/ extern const char *Hlp_COURSE_Information_textual_information; extern const char *Hlp_COURSE_Guide; extern const char *Hlp_COURSE_Syllabus; extern const char *Hlp_COURSE_Bibliography; extern const char *Hlp_COURSE_FAQ; extern const char *Hlp_COURSE_Links; extern const char *Hlp_ASSESSMENT_System; extern const char *Hlp_COURSE_Information_edit; extern const char *Hlp_COURSE_Guide_edit; extern const char *Hlp_COURSE_Syllabus_edit; extern const char *Hlp_COURSE_Bibliography_edit; extern const char *Hlp_COURSE_FAQ_edit; extern const char *Hlp_COURSE_Links_edit; extern const char *Hlp_ASSESSMENT_System_edit; /*****************************************************************************/ /**************************** Private prototypes *****************************/ /*****************************************************************************/ static void Inf_PutButtonToEditInfo (void); static void Inf_PutIconToViewInfo (void); static void Inf_PutCheckboxForceStdsToReadInfo (bool MustBeRead,bool Disabled); static void Inf_PutCheckboxConfirmIHaveReadInfo (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 bool Inf_CheckPage (long CrsCod,Inf_InfoType_t InfoType); static bool Inf_CheckAndShowPage (void); static void Inf_BuildPathPage (long CrsCod,Inf_InfoType_t InfoType,char PathDir[PATH_MAX + 1]); static bool Inf_CheckURL (long CrsCod,Inf_InfoType_t InfoType); static bool Inf_CheckAndShowURL (void); static void Inf_BuildPathURL (long CrsCod,Inf_InfoType_t InfoType, char PathFile[PATH_MAX + 1]); static void Inf_ShowPage (const char *URL); static bool Inf_CheckIfInfoAvailable (Inf_InfoSrc_t InfoSrc); static Inf_InfoType_t Inf_AsignInfoType (void); static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD); static void Inf_GetInfoTxtFromDB (long CrsCod,Inf_InfoType_t InfoType, char InfoTxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1], char InfoTxtMD[Cns_MAX_BYTES_LONG_TEXT + 1]); static bool Inf_CheckPlainTxt (long CrsCod,Inf_InfoType_t InfoType); static bool Inf_CheckAndShowPlainTxt (void); static bool Inf_CheckRichTxt (long CrsCod,Inf_InfoType_t InfoType); static bool Inf_CheckAndShowRichTxt (void); /*****************************************************************************/ /******** Show course info (theory, practices, bibliography, etc.) ***********/ /*****************************************************************************/ void Inf_ShowInfo (void) { extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES]; extern const char *Txt_No_information; Inf_InfoSrc_t InfoSrc; bool MustBeRead; bool Disabled; bool ICanEdit = (Gbl.Usrs.Me.Role.Logged == Rol_TCH || Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM); bool ShowWarningNoInfo = false; const char *Help[Inf_NUM_INFO_TYPES] = { Hlp_COURSE_Information_textual_information, // Inf_INTRODUCTION Hlp_COURSE_Guide, // Inf_TEACHING_GUIDE Hlp_COURSE_Syllabus, // Inf_LECTURES Hlp_COURSE_Syllabus, // Inf_PRACTICALS Hlp_COURSE_Bibliography, // Inf_BIBLIOGRAPHY Hlp_COURSE_FAQ, // Inf_FAQ Hlp_COURSE_Links, // Inf_LINKS Hlp_ASSESSMENT_System, // Inf_ASSESSMENT }; /***** Set info type *****/ Gbl.Crs.Info.Type = Inf_AsignInfoType (); /***** Get info source from database *****/ Inf_GetAndCheckInfoSrcFromDB (Gbl.Hierarchy.Crs.CrsCod, Gbl.Crs.Info.Type, &InfoSrc,&MustBeRead); switch (Gbl.Crs.Info.Type) { case Inf_LECTURES: case Inf_PRACTICALS: Syl_PutFormWhichSyllabus (); break; default: break; } switch (Gbl.Usrs.Me.Role.Logged) { case Rol_STD: /* Put checkbox to force students to read this couse info */ if (MustBeRead) { fprintf (Gbl.F.Out,"
"); Inf_PutCheckboxConfirmIHaveReadInfo (); fprintf (Gbl.F.Out,"
"); } break; case Rol_NET: case Rol_TCH: case Rol_SYS_ADM: /* Put checkbox to force students to read this couse info */ if (InfoSrc != Inf_INFO_SRC_NONE) { fprintf (Gbl.F.Out,"
"); Disabled = (Gbl.Usrs.Me.Role.Logged == Rol_NET); // Non-editing teachers can not change the status of checkbox Inf_PutCheckboxForceStdsToReadInfo (MustBeRead,Disabled); fprintf (Gbl.F.Out,"
"); } break; default: break; } switch (InfoSrc) { case Inf_INFO_SRC_NONE: ShowWarningNoInfo = true; break; case Inf_INFO_SRC_EDITOR: switch (Gbl.Crs.Info.Type) { case Inf_LECTURES: case Inf_PRACTICALS: ShowWarningNoInfo = !Syl_CheckAndEditSyllabus (); break; case Inf_INTRODUCTION: case Inf_TEACHING_GUIDE: case Inf_BIBLIOGRAPHY: case Inf_FAQ: case Inf_LINKS: case Inf_ASSESSMENT: ShowWarningNoInfo = true; break; } break; case Inf_INFO_SRC_PLAIN_TEXT: ShowWarningNoInfo = !Inf_CheckAndShowPlainTxt (); break; case Inf_INFO_SRC_RICH_TEXT: ShowWarningNoInfo = !Inf_CheckAndShowRichTxt (); break; case Inf_INFO_SRC_PAGE: /***** Open file with web page *****/ ShowWarningNoInfo = !Inf_CheckAndShowPage (); break; case Inf_INFO_SRC_URL: /***** Check if file with URL exists *****/ ShowWarningNoInfo = !Inf_CheckAndShowURL (); break; } if (ShowWarningNoInfo) { Box_StartBox ("100%",Txt_INFO_TITLE[Gbl.Crs.Info.Type], ICanEdit ? Inf_PutIconToEditInfo : NULL, Help[Gbl.Crs.Info.Type],Box_NOT_CLOSABLE); Ale_ShowAlert (Ale_INFO,Txt_No_information); if (ICanEdit) Inf_PutButtonToEditInfo (); Box_EndBox (); } } /*****************************************************************************/ /*********************** Put button to edit course info **********************/ /*****************************************************************************/ static void Inf_PutButtonToEditInfo (void) { extern const char *Txt_Edit; Frm_StartForm (Inf_ActionsEditInfo[Gbl.Crs.Info.Type]); Btn_PutConfirmButton (Txt_Edit); Frm_EndForm (); } /*****************************************************************************/ /************************ Put icon to edit course info ***********************/ /*****************************************************************************/ static void Inf_PutIconToViewInfo (void) { Ico_PutContextualIconToView (Inf_ActionsSeeInfo[Gbl.Crs.Info.Type],NULL); } void Inf_PutIconToEditInfo (void) { Ico_PutContextualIconToEdit (Inf_ActionsEditInfo[Gbl.Crs.Info.Type],NULL); } /*****************************************************************************/ /********** Put a form (checkbox) to force students to read info *************/ /*****************************************************************************/ static void Inf_PutCheckboxForceStdsToReadInfo (bool MustBeRead,bool Disabled) { extern const char *Txt_Force_students_to_read_this_information; Lay_PutContextualCheckbox (Inf_ActionsChangeForceReadInfo[Gbl.Crs.Info.Type], NULL, "MustBeRead", MustBeRead,Disabled, Txt_Force_students_to_read_this_information, Txt_Force_students_to_read_this_information); } /*****************************************************************************/ /********** Put a form (checkbox) to force students to read info *************/ /*****************************************************************************/ static void Inf_PutCheckboxConfirmIHaveReadInfo (void) { extern const char *Txt_I_have_read_this_information; bool IHaveRead = Inf_CheckIfIHaveReadInfo (); Lay_PutContextualCheckbox (Inf_ActionsIHaveReadInfo[Gbl.Crs.Info.Type], NULL, "IHaveRead", IHaveRead,false, Txt_I_have_read_this_information, Txt_I_have_read_this_information); } /*****************************************************************************/ /******************** Check I have read a course info ************************/ /*****************************************************************************/ static bool Inf_CheckIfIHaveReadInfo (void) { /***** Get if info source is already stored in database *****/ return (DB_QueryCOUNT ("can not get if I have read course info", "SELECT COUNT(*) FROM crs_info_read" " WHERE UsrCod=%ld AND CrsCod=%ld AND InfoType='%s'", Gbl.Usrs.Me.UsrDat.UsrCod, Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type]) != 0); } /*****************************************************************************/ /********* Get if students must read any info about current course ***********/ /*****************************************************************************/ bool Inf_GetIfIMustReadAnyCrsInfoInThisCrs (void) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRow; unsigned long 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.Crs.Info.MustBeRead[InfoType] = false; /***** Get info types where students must read info *****/ NumRows = DB_QuerySELECT (&mysql_res,"can not get if you must read" " any course info", "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.Hierarchy.Crs.CrsCod, Gbl.Usrs.Me.UsrDat.UsrCod, Gbl.Hierarchy.Crs.CrsCod); /***** 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.Crs.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_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_Required_reading; extern const char *Txt_You_should_read_the_following_information; Inf_InfoType_t InfoType; /***** Start box *****/ Box_StartBox (NULL,Txt_Required_reading,NULL, NULL,Box_NOT_CLOSABLE); /***** Write message *****/ Ale_ShowAlert (Ale_WARNING,Txt_You_should_read_the_following_information); /***** Write every information I must read *****/ fprintf (Gbl.F.Out,"
" "
    "); for (InfoType = (Inf_InfoType_t) 0; InfoType < Inf_NUM_INFO_TYPES; InfoType++) if (Gbl.Crs.Info.MustBeRead[InfoType]) { fprintf (Gbl.F.Out,"
  • "); Frm_StartForm (Inf_ActionsSeeInfo[InfoType]); Frm_LinkFormSubmit (Act_GetTitleAction (Inf_ActionsSeeInfo[InfoType]), The_ClassFormInBox[Gbl.Prefs.Theme],NULL); fprintf (Gbl.F.Out,"%s" "", Act_GetTitleAction (Inf_ActionsSeeInfo[InfoType])); Frm_EndForm (); fprintf (Gbl.F.Out,"
  • "); } fprintf (Gbl.F.Out,"
" "
"); /***** End box *****/ Box_EndBox (); } /*****************************************************************************/ /****** 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.Crs.Info.Type = Inf_AsignInfoType (); /***** Set status (if info must be read or not) into database *****/ Inf_SetForceReadIntoDB (MustBeRead); /***** Write message of success *****/ Ale_ShowAlert (Ale_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.Crs.Info.Type = Inf_AsignInfoType (); /***** Set status (if I have read or not a information) into database *****/ Inf_SetIHaveReadIntoDB (IHaveRead); /***** Write message of success *****/ Ale_ShowAlert (Ale_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) { return Par_GetParToBool ("MustBeRead"); } /*****************************************************************************/ /************* Get if info must be read by students from form ****************/ /*****************************************************************************/ static bool Inf_GetIfIHaveReadFromForm (void) { return Par_GetParToBool ("IHaveRead"); } /*****************************************************************************/ /***************** Set if students must read course info *********************/ /*****************************************************************************/ static void Inf_SetForceReadIntoDB (bool MustBeRead) { /***** Insert or replace info source for a specific type of course information *****/ DB_QueryUPDATE ("can not update if info must be read", "UPDATE crs_info_src SET MustBeRead='%c'" " WHERE CrsCod=%ld AND InfoType='%s'", MustBeRead ? 'Y' : 'N', Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type]); } /*****************************************************************************/ /********************* Set if I have read course info ************************/ /*****************************************************************************/ static void Inf_SetIHaveReadIntoDB (bool IHaveRead) { if (IHaveRead) /***** Insert I have read course information *****/ DB_QueryREPLACE ("can not set that I have read course info", "REPLACE INTO crs_info_read" " (UsrCod,CrsCod,InfoType)" " VALUES" " (%ld,%ld,'%s')", Gbl.Usrs.Me.UsrDat.UsrCod, Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type]); else /***** Remove I have read course information *****/ DB_QueryDELETE ("can not set that I have not read course info", "DELETE FROM crs_info_read" " WHERE UsrCod=%ld AND CrsCod=%ld AND InfoType='%s'", Gbl.Usrs.Me.UsrDat.UsrCod, Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type]); } /*****************************************************************************/ /********* Remove user's status about reading of course information **********/ /*****************************************************************************/ void Inf_RemoveUsrFromCrsInfoRead (long UsrCod,long CrsCod) { /***** Remove user's status about reading of course information *****/ DB_QueryDELETE ("can not set that I have not read course info", "DELETE FROM crs_info_read" " WHERE UsrCod=%ld AND CrsCod=%ld", UsrCod,CrsCod); } /*****************************************************************************/ /************************** Check if exists a page ***************************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckPage (long CrsCod,Inf_InfoType_t InfoType) { char PathRelDirHTML[PATH_MAX + 1]; char PathRelFileHTML[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 !!!!!!!!!!!!!!!!! /***** Build path of directory containing web page *****/ Inf_BuildPathPage (CrsCod,InfoType,PathRelDirHTML); /***** Open file with web page *****/ /* 1. Check if index.html exists */ snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.html", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? return true; /* 2. If index.html does not exist, try index.htm */ snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.htm", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? return true; return false; } /*****************************************************************************/ /**************** Check if exists and show link to a page ********************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckAndShowPage (void) { char PathRelDirHTML[PATH_MAX + 1]; 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 !!!!!!!!!!!!!!!!! /***** Build path of directory containing web page *****/ Inf_BuildPathPage (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathRelDirHTML); /***** Open file with web page *****/ /* 1. Check if index.html exists */ snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.html", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? { snprintf (URL,sizeof (URL), "%s/%ld/%s/index.html", Cfg_URL_CRS_PUBLIC,Gbl.Hierarchy.Crs.CrsCod, Inf_FileNamesForInfoType[Gbl.Crs.Info.Type]); Inf_ShowPage (URL); return true; } /* 2. If index.html does not exist, try index.htm */ snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.htm", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? { snprintf (URL,sizeof (URL), "%s/%ld/%s/index.htm", Cfg_URL_CRS_PUBLIC,Gbl.Hierarchy.Crs.CrsCod, Inf_FileNamesForInfoType[Gbl.Crs.Info.Type]); Inf_ShowPage (URL); return true; } return false; } /*****************************************************************************/ /* Build path inside a course for a given a info type to store web page file */ /*****************************************************************************/ static void Inf_BuildPathPage (long CrsCod,Inf_InfoType_t InfoType,char PathDir[PATH_MAX + 1]) { snprintf (PathDir,PATH_MAX + 1, "%s/%ld/%s", Cfg_PATH_CRS_PUBLIC,CrsCod, Inf_FileNamesForInfoType[InfoType]); } /*****************************************************************************/ /************* Check if exists and write page into HTML buffer ***************/ /*****************************************************************************/ // This function is called only from web service int Inf_WritePageIntoHTMLBuffer (char **HTMLBuffer) { char PathRelDirHTML[PATH_MAX + 1]; char PathRelFileHTML[PATH_MAX + 1]; FILE *FileHTML; bool FileExists = false; size_t Length; /***** Initialize buffer *****/ *HTMLBuffer = NULL; /***** Build path of directory containing web page *****/ Inf_BuildPathPage (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathRelDirHTML); /***** Open file with web page *****/ /* 1. Check if index.html exists */ snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.html", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? FileExists = true; else { /* 2. If index.html not exists, try index.htm */ snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.htm", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) // TODO: Check if not empty? FileExists = true; } if (FileExists) { /***** Write page from file to text buffer *****/ /* Open file */ if ((FileHTML = fopen (PathRelFileHTML,"rb")) == NULL) Lay_ShowErrorAndExit ("Can not open XML file."); /* Compute file size */ fseek (FileHTML,0L,SEEK_END); Length = (size_t) ftell (FileHTML); fseek (FileHTML,0L,SEEK_SET); /* Allocate memory for buffer */ if ((*HTMLBuffer = (char *) malloc (Length + 1)) == NULL) { fclose (FileHTML); Lay_NotEnoughMemoryExit (); return soap_receiver_fault (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 link to a page ************************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckURL (long CrsCod,Inf_InfoType_t InfoType) { char PathFile[PATH_MAX + 1]; FILE *FileURL; /***** Build path to file containing URL *****/ Inf_BuildPathURL (CrsCod,InfoType,PathFile); /***** Check if file with URL exists *****/ if ((FileURL = fopen (PathFile,"rb"))) { if (fgets (Gbl.Crs.Info.URL,Cns_MAX_BYTES_WWW,FileURL) == NULL) Gbl.Crs.Info.URL[0] = '\0'; /* File is not longer needed ==> close it */ fclose (FileURL); if (Gbl.Crs.Info.URL[0]) return true; } return false; } /*****************************************************************************/ /**************** Check if exists and show link to a page ********************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckAndShowURL (void) { char PathFile[PATH_MAX + 1]; FILE *FileURL; /***** Build path to file containing URL *****/ Inf_BuildPathURL (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathFile); /***** Check if file with URL exists *****/ if ((FileURL = fopen (PathFile,"rb"))) { if (fgets (Gbl.Crs.Info.URL,Cns_MAX_BYTES_WWW,FileURL) == NULL) Gbl.Crs.Info.URL[0] = '\0'; /* File is not longer needed ==> close it */ fclose (FileURL); if (Gbl.Crs.Info.URL[0]) { Inf_ShowPage (Gbl.Crs.Info.URL); return true; } } return false; } /*****************************************************************************/ /*** Build path inside a course for a given a info type to store URL file ****/ /*****************************************************************************/ static void Inf_BuildPathURL (long CrsCod,Inf_InfoType_t InfoType, char PathFile[PATH_MAX + 1]) { snprintf (PathFile,PATH_MAX + 1, "%s/%ld/%s.url", Cfg_PATH_CRS_PRIVATE,CrsCod, Inf_FileNamesForInfoType[InfoType]); } /*****************************************************************************/ /************* 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_WWW + 1]) { char PathFile[PATH_MAX + 1]; FILE *FileURL; /***** Initialize buffer *****/ TxtBuffer[0] = '\0'; /***** Build path to file containing URL *****/ Inf_BuildPathURL (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathFile); /***** Check if file with URL exists *****/ if ((FileURL = fopen (PathFile,"rb"))) { if (fgets (TxtBuffer,Cns_MAX_BYTES_WWW,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_ClassFormOutBoxBold[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.Role.Logged == Rol_TCH || Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM); const char *Help[Inf_NUM_INFO_TYPES] = { Hlp_COURSE_Information_textual_information, // Inf_INTRODUCTION Hlp_COURSE_Guide, // Inf_TEACHING_GUIDE Hlp_COURSE_Syllabus, // Inf_LECTURES Hlp_COURSE_Syllabus, // Inf_PRACTICALS Hlp_COURSE_Bibliography, // Inf_BIBLIOGRAPHY Hlp_COURSE_FAQ, // Inf_FAQ Hlp_COURSE_Links, // Inf_LINKS Hlp_ASSESSMENT_System, // Inf_ASSESSMENT }; /***** Start box *****/ Box_StartBox (NULL,Txt_INFO_TITLE[Gbl.Crs.Info.Type], ICanEdit ? Inf_PutIconToEditInfo : NULL, Help[Gbl.Crs.Info.Type],Box_NOT_CLOSABLE); /***** Link to view in a new window *****/ fprintf (Gbl.F.Out,"", URL,The_ClassFormOutBoxBold[Gbl.Prefs.Theme]); Ico_PutIconTextLink ("expand-arrows-alt.svg", Txt_View_in_a_new_window); fprintf (Gbl.F.Out,""); /***** End box *****/ Box_EndBox (); } /*****************************************************************************/ /************************** Set course info source ***************************/ /*****************************************************************************/ void Inf_SetInfoSrc (void) { Inf_InfoSrc_t InfoSrcSelected = Inf_GetInfoSrcFromForm (); /***** Set info type *****/ Gbl.Crs.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 *The_ClassFormInBox[The_NUM_THEMES]; 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 InfoAvailable[Inf_NUM_INFO_SOURCES]; bool MustBeRead; const char *HelpEdit[Inf_NUM_INFO_TYPES] = { Hlp_COURSE_Information_edit, // Inf_INTRODUCTION Hlp_COURSE_Guide_edit, // Inf_TEACHING_GUIDE Hlp_COURSE_Syllabus_edit, // Inf_LECTURES Hlp_COURSE_Syllabus_edit, // Inf_PRACTICALS Hlp_COURSE_Bibliography_edit, // Inf_BIBLIOGRAPHY Hlp_COURSE_FAQ_edit, // Inf_FAQ Hlp_COURSE_Links_edit, // Inf_LINKS Hlp_ASSESSMENT_System_edit, // Inf_ASSESSMENT }; /***** Set info type *****/ Gbl.Crs.Info.Type = Inf_AsignInfoType (); /***** Get current info source from database *****/ Inf_GetAndCheckInfoSrcFromDB (Gbl.Hierarchy.Crs.CrsCod, Gbl.Crs.Info.Type, &InfoSrcSelected,&MustBeRead); /***** Check if info available *****/ for (InfoSrc = (Inf_InfoSrc_t) 0; InfoSrc < Inf_NUM_INFO_SOURCES; InfoSrc++) InfoAvailable[InfoSrc] = Inf_CheckIfInfoAvailable (InfoSrc); /***** Set info source to none when no info available for the current source *****/ if (InfoSrcSelected != Inf_INFO_SRC_NONE && !InfoAvailable[InfoSrcSelected]) { InfoSrcSelected = Inf_INFO_SRC_NONE; Inf_SetInfoSrcIntoDB (Inf_INFO_SRC_NONE); } /***** Form to choice between alternatives *****/ /* Start box and table */ Box_StartBoxTable (NULL,Txt_Source_of_information,Inf_PutIconToViewInfo, HelpEdit[Gbl.Crs.Info.Type],Box_NOT_CLOSABLE,4); /* Options */ for (InfoSrc = (Inf_InfoSrc_t) 0; InfoSrc < Inf_NUM_INFO_SOURCES; InfoSrc++) { /* Select info source */ fprintf (Gbl.F.Out,"" ""); Frm_StartForm (Inf_ActionsSelecInfoSrc[Gbl.Crs.Info.Type]); fprintf (Gbl.F.Out,""); Frm_EndForm (); fprintf (Gbl.F.Out,""); /* Form for this info source */ fprintf (Gbl.F.Out,"" "", (unsigned) InfoSrc,The_ClassFormInBox[Gbl.Prefs.Theme], Txt_INFO_SRC_FULL_TEXT[InfoSrc]); if (Txt_INFO_SRC_HELP[InfoSrc]) fprintf (Gbl.F.Out,"
(%s)
", Txt_INFO_SRC_HELP[InfoSrc]); if (Inf_FormsForEditionTypes[InfoSrc]) Inf_FormsForEditionTypes[InfoSrc] (InfoSrc); fprintf (Gbl.F.Out,"" ""); } /***** End table and box *****/ Box_EndBoxTable (); } /*****************************************************************************/ /* Check if there is info available for current info type and a given source */ /*****************************************************************************/ static bool Inf_CheckIfInfoAvailable (Inf_InfoSrc_t InfoSrc) { switch (InfoSrc) { case Inf_INFO_SRC_NONE: return false; case Inf_INFO_SRC_EDITOR: switch (Gbl.Crs.Info.Type) { case Inf_LECTURES: case Inf_PRACTICALS: return Syl_CheckSyllabus (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type); default: return false; } return false; // Not reached case Inf_INFO_SRC_PLAIN_TEXT: return Inf_CheckPlainTxt (Gbl.Hierarchy.Crs.CrsCod, Gbl.Crs.Info.Type); case Inf_INFO_SRC_RICH_TEXT: return Inf_CheckRichTxt (Gbl.Hierarchy.Crs.CrsCod, Gbl.Crs.Info.Type); case Inf_INFO_SRC_PAGE: return Inf_CheckPage (Gbl.Hierarchy.Crs.CrsCod, Gbl.Crs.Info.Type); case Inf_INFO_SRC_URL: return Inf_CheckURL (Gbl.Hierarchy.Crs.CrsCod, Gbl.Crs.Info.Type); } return false; // Not reached } /*****************************************************************************/ /****************** Form to enter in integrated editor ***********************/ /*****************************************************************************/ void Inf_FormToEnterIntegratedEditor (Inf_InfoSrc_t InfoSrc) { extern const char *Txt_Edit; Frm_StartForm (Inf_ActionsInfo[InfoSrc][Gbl.Crs.Info.Type]); Btn_PutConfirmButton (Txt_Edit); Frm_EndForm (); } /*****************************************************************************/ /****************** Form to enter in plain text editor ***********************/ /*****************************************************************************/ void Inf_FormToEnterPlainTextEditor (Inf_InfoSrc_t InfoSrc) { extern const char *Txt_Edit_plain_text; Frm_StartForm (Inf_ActionsInfo[InfoSrc][Gbl.Crs.Info.Type]); Btn_PutConfirmButton (Txt_Edit_plain_text); Frm_EndForm (); } /*****************************************************************************/ /******************* Form to enter in rich text editor ***********************/ /*****************************************************************************/ void Inf_FormToEnterRichTextEditor (Inf_InfoSrc_t InfoSrc) { extern const char *Txt_Edit_rich_text; Frm_StartForm (Inf_ActionsInfo[InfoSrc][Gbl.Crs.Info.Type]); Btn_PutConfirmButton (Txt_Edit_rich_text); Frm_EndForm (); } /*****************************************************************************/ /******************* Form to upload a file with a page ***********************/ /*****************************************************************************/ void Inf_FormToSendPage (Inf_InfoSrc_t InfoSrc) { extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_File; extern const char *Txt_Upload_file; /***** Start form *****/ Frm_StartForm (Inf_ActionsInfo[InfoSrc][Gbl.Crs.Info.Type]); /***** File *****/ fprintf (Gbl.F.Out,"
" "" "
", The_ClassFormInBox[Gbl.Prefs.Theme],Txt_File, Fil_NAME_OF_PARAM_FILENAME_ORG); /***** Send button *****/ Btn_PutCreateButton (Txt_Upload_file); /***** End form *****/ Frm_EndForm (); } /*****************************************************************************/ /********************* Form to send a link to a web page *********************/ /*****************************************************************************/ void Inf_FormToSendURL (Inf_InfoSrc_t InfoSrc) { extern const char *The_ClassFormInBox[The_NUM_THEMES]; extern const char *Txt_URL; extern const char *Txt_Send_URL; char PathFile[PATH_MAX + 1]; FILE *FileURL; /***** Build path to file containing URL *****/ Inf_BuildPathURL (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathFile); /***** Start form *****/ Frm_StartForm (Inf_ActionsInfo[InfoSrc][Gbl.Crs.Info.Type]); /***** Link *****/ fprintf (Gbl.F.Out,"
" "" "
"); /***** Send button *****/ Btn_PutCreateButton (Txt_Send_URL); /***** End form *****/ Frm_EndForm (); } /*****************************************************************************/ /******** 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.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.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.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) { /***** Get info source for a specific type of course information (introduction, teaching guide, bibliography, FAQ, links or evaluation) *****/ return (Inf_InfoSrc_t) Par_GetParToUnsignedLong ("InfoSrc", 0, Inf_NUM_INFO_SOURCES - 1, (unsigned long) Inf_INFO_SRC_NONE); } /*****************************************************************************/ /********* Set info source for a type of course info from database ***********/ /*****************************************************************************/ void Inf_SetInfoSrcIntoDB (Inf_InfoSrc_t InfoSrc) { /***** Get if info source is already stored in database *****/ if (DB_QueryCOUNT ("can not get if info source is already stored in database", "SELECT COUNT(*) FROM crs_info_src" " WHERE CrsCod=%ld AND InfoType='%s'", Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type])) // Info is already stored in database, so update it { // Update info source if (InfoSrc == Inf_INFO_SRC_NONE) DB_QueryUPDATE ("can not update info source", "UPDATE crs_info_src SET InfoSrc='%s',MustBeRead='N'" " WHERE CrsCod=%ld AND InfoType='%s'", Inf_NamesInDBForInfoSrc[Inf_INFO_SRC_NONE], Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type]); else // MustBeRead remains unchanged DB_QueryUPDATE ("can not update info source", "UPDATE crs_info_src SET InfoSrc='%s'" " WHERE CrsCod=%ld AND InfoType='%s'", Inf_NamesInDBForInfoSrc[InfoSrc], Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type]); } else // Info is not stored in database, so insert it DB_QueryINSERT ("can not insert info source", "INSERT INTO crs_info_src" " (CrsCod,InfoType,InfoSrc,MustBeRead)" " VALUES" " (%ld,'%s','%s','N')", Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type], Inf_NamesInDBForInfoSrc[InfoSrc]); } /*****************************************************************************/ /***** Get and check info source for a type of course info from database *****/ /*****************************************************************************/ Inf_InfoSrc_t Inf_GetInfoSrcFromDB (long CrsCod,Inf_InfoType_t InfoType) { MYSQL_RES *mysql_res; MYSQL_ROW row; Inf_InfoSrc_t InfoSrc; /***** Get info source for a specific type of info from database *****/ if (DB_QuerySELECT (&mysql_res,"can not get info source", "SELECT InfoSrc FROM crs_info_src" " WHERE CrsCod=%ld AND InfoType='%s'", CrsCod,Inf_NamesInDBForInfoType[InfoType])) { /* Get row */ row = mysql_fetch_row (mysql_res); /* Get info source (row[0]) */ InfoSrc = Inf_ConvertFromStrDBToInfoSrc (row[0]); } else InfoSrc = Inf_INFO_SRC_NONE; /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); return InfoSrc; } /*****************************************************************************/ /***** Get and check info source for a type of course info from database *****/ /*****************************************************************************/ void Inf_GetAndCheckInfoSrcFromDB (long CrsCod, Inf_InfoType_t InfoType, Inf_InfoSrc_t *InfoSrc,bool *MustBeRead) { MYSQL_RES *mysql_res; MYSQL_ROW row; unsigned long NumRows; /***** Set default values *****/ *InfoSrc = Inf_INFO_SRC_NONE; *MustBeRead = false; /***** Get info source for a specific type of info from database *****/ NumRows = DB_QuerySELECT (&mysql_res,"can not get info source", "SELECT InfoSrc,MustBeRead FROM crs_info_src" " WHERE CrsCod=%ld AND InfoType='%s'", CrsCod,Inf_NamesInDBForInfoType[InfoType]); /***** 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 = (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: if (!Syl_CheckSyllabus (CrsCod,InfoType)) { *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_CheckPlainTxt (CrsCod,InfoType)) { *InfoSrc = Inf_INFO_SRC_NONE; *MustBeRead = false; } break; case Inf_INFO_SRC_RICH_TEXT: if (!Inf_CheckRichTxt (CrsCod,InfoType)) { *InfoSrc = Inf_INFO_SRC_NONE; *MustBeRead = false; } break; case Inf_INFO_SRC_PAGE: if (!Inf_CheckPage (CrsCod,InfoType)) { *InfoSrc = Inf_INFO_SRC_NONE; *MustBeRead = false; } break; case Inf_INFO_SRC_URL: if (!Inf_CheckURL (CrsCod,InfoType)) { *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_INFO_SRC_NONE; } /*****************************************************************************/ /********** Set info text for a type of course info from database ************/ /*****************************************************************************/ static void Inf_SetInfoTxtIntoDB (const char *InfoTxtHTML,const char *InfoTxtMD) { /***** Insert or replace info source for a specific type of course information *****/ DB_QueryREPLACE ("can not update info text", "REPLACE INTO crs_info_txt" " (CrsCod,InfoType,InfoTxtHTML,InfoTxtMD)" " VALUES" " (%ld,'%s','%s','%s')", Gbl.Hierarchy.Crs.CrsCod, Inf_NamesInDBForInfoType[Gbl.Crs.Info.Type], InfoTxtHTML,InfoTxtMD); } /*****************************************************************************/ /********** Get info text for a type of course info from database ************/ /*****************************************************************************/ static void Inf_GetInfoTxtFromDB (long CrsCod,Inf_InfoType_t InfoType, char InfoTxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1], char InfoTxtMD[Cns_MAX_BYTES_LONG_TEXT + 1]) { 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 *****/ NumRows = DB_QuerySELECT (&mysql_res,"can not get info text", "SELECT InfoTxtHTML,InfoTxtMD FROM crs_info_txt" " WHERE CrsCod=%ld AND InfoType='%s'", CrsCod,Inf_NamesInDBForInfoType[InfoType]); /***** 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) Str_Copy (InfoTxtHTML,row[0], Cns_MAX_BYTES_LONG_TEXT); /* Get text in Markdown format */ if (InfoTxtMD) Str_Copy (InfoTxtMD,row[1], Cns_MAX_BYTES_LONG_TEXT); } 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 information about the course ********************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckPlainTxt (long CrsCod,Inf_InfoType_t InfoType) { char TxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1]; /***** Get info text from database *****/ Inf_GetInfoTxtFromDB (CrsCod,InfoType,TxtHTML,NULL); return (TxtHTML[0] != '\0'); } /*****************************************************************************/ /********************* Show information about the course *********************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckAndShowPlainTxt (void) { extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES]; char TxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1]; bool ICanEdit = (Gbl.Usrs.Me.Role.Logged == Rol_TCH || Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM); const char *Help[Inf_NUM_INFO_TYPES] = { Hlp_COURSE_Information_textual_information, // Inf_INTRODUCTION Hlp_COURSE_Guide, // Inf_TEACHING_GUIDE Hlp_COURSE_Syllabus, // Inf_LECTURES Hlp_COURSE_Syllabus, // Inf_PRACTICALS Hlp_COURSE_Bibliography, // Inf_BIBLIOGRAPHY Hlp_COURSE_FAQ, // Inf_FAQ Hlp_COURSE_Links, // Inf_LINKS Hlp_ASSESSMENT_System, // Inf_ASSESSMENT }; /***** Get info text from database *****/ Inf_GetInfoTxtFromDB (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type, TxtHTML,NULL); if (TxtHTML[0]) { /***** Start box *****/ Box_StartBox (NULL,Txt_INFO_TITLE[Gbl.Crs.Info.Type], ICanEdit ? Inf_PutIconToEditInfo : NULL, Help[Gbl.Crs.Info.Type],Box_NOT_CLOSABLE); if (Gbl.Crs.Info.Type == Inf_INTRODUCTION || Gbl.Crs.Info.Type == Inf_TEACHING_GUIDE) Lay_WriteHeaderClassPhoto (false,false,Gbl.Hierarchy.Ins.InsCod,Gbl.Hierarchy.Deg.DegCod,Gbl.Hierarchy.Crs.CrsCod); fprintf (Gbl.F.Out,"
"); /***** 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 box *****/ fprintf (Gbl.F.Out,"
"); Box_EndBox (); return true; } return false; } /*****************************************************************************/ /********************* Show information about the course *********************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckRichTxt (long CrsCod,Inf_InfoType_t InfoType) { char TxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1]; char TxtMD[Cns_MAX_BYTES_LONG_TEXT + 1]; /***** Get info text from database *****/ Inf_GetInfoTxtFromDB (CrsCod,InfoType, TxtHTML,TxtMD); return (TxtMD[0] != '\0'); } /*****************************************************************************/ /********************* Show information about the course *********************/ /*****************************************************************************/ // Return true if info available static bool Inf_CheckAndShowRichTxt (void) { extern const char *Txt_INFO_TITLE[Inf_NUM_INFO_TYPES]; 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 + 1]; char Command[512 + PATH_MAX * 3]; // Command to call the program of preprocessing of photos int ReturnCode; bool ICanEdit = (Gbl.Usrs.Me.Role.Logged == Rol_TCH || Gbl.Usrs.Me.Role.Logged == Rol_SYS_ADM); const char *Help[Inf_NUM_INFO_TYPES] = { Hlp_COURSE_Information_textual_information, // Inf_INTRODUCTION Hlp_COURSE_Guide, // Inf_TEACHING_GUIDE Hlp_COURSE_Syllabus, // Inf_LECTURES Hlp_COURSE_Syllabus, // Inf_PRACTICALS Hlp_COURSE_Bibliography, // Inf_BIBLIOGRAPHY Hlp_COURSE_FAQ, // Inf_FAQ Hlp_COURSE_Links, // Inf_LINKS Hlp_ASSESSMENT_System, // Inf_ASSESSMENT }; /***** Get info text from database *****/ Inf_GetInfoTxtFromDB (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type, TxtHTML,TxtMD); if (TxtMD[0]) { /***** Start box *****/ Box_StartBox (NULL,Txt_INFO_TITLE[Gbl.Crs.Info.Type], ICanEdit ? Inf_PutIconToEditInfo : NULL, Help[Gbl.Crs.Info.Type],Box_NOT_CLOSABLE); if (Gbl.Crs.Info.Type == Inf_INTRODUCTION || Gbl.Crs.Info.Type == Inf_TEACHING_GUIDE) Lay_WriteHeaderClassPhoto (false,false,Gbl.Hierarchy.Ins.InsCod,Gbl.Hierarchy.Deg.DegCod,Gbl.Hierarchy.Crs.CrsCod); fprintf (Gbl.F.Out,"
"); /***** Store text into a temporary .md file in HTML output directory *****/ // TODO: change to another directory? /* Create a unique name for the .md file */ snprintf (PathFileMD,sizeof (PathFileMD), "%s/%s.md", Cfg_PATH_OUT_PRIVATE,Gbl.UniqueNameEncrypted); snprintf (PathFileHTML,sizeof (PathFileHTML), "%s/%s.md.html", // Do not use only .html because that is the output temporary file Cfg_PATH_OUT_PRIVATE,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 snprintf (MathJaxURL,sizeof (MathJaxURL), "=%s/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML", Cfg_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 snprintf (Command,sizeof (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); /***** End box *****/ fprintf (Gbl.F.Out,"
"); Box_EndBox (); return true; } return false; } /*****************************************************************************/ /************* 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_INFO_TITLE[Inf_NUM_INFO_TYPES]; char TxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1]; char FileNameHTMLTmp[PATH_MAX + 1]; FILE *FileHTMLTmp; size_t Length; /***** Initialize buffer *****/ *HTMLBuffer = NULL; /***** Get info text from database *****/ Inf_GetInfoTxtFromDB (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type, TxtHTML,NULL); if (TxtHTML[0]) { /***** Create a unique name for the file *****/ snprintf (FileNameHTMLTmp,sizeof (FileNameHTMLTmp), "%s/%s_info.html", Cfg_PATH_OUT_PRIVATE,Gbl.UniqueNameEncrypted); /***** Create a new temporary file for writing and reading *****/ if ((FileHTMLTmp = fopen (FileNameHTMLTmp,"w+b")) == NULL) return soap_receiver_fault (Gbl.soap, "Plain text can not be copied into buffer", "Can not create temporary file"); /***** Write start of HTML code *****/ Lay_StartHTMLFile (FileHTMLTmp,Txt_INFO_TITLE[Gbl.Crs.Info.Type]); fprintf (FileHTMLTmp,"\n" "
\n"); /***** Write plain text into text buffer *****/ /* Convert to respectful HTML and insert links */ Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, TxtHTML,Cns_MAX_BYTES_LONG_TEXT,false); // Convert from HTML to recpectful HTML Str_InsertLinks (TxtHTML,Cns_MAX_BYTES_LONG_TEXT,60); // Insert links /* Write text */ fprintf (FileHTMLTmp,"%s",TxtHTML); /***** Write end of page into file *****/ fprintf (FileHTMLTmp,"
\n" "\n" "\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_changes; char TxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1]; const char *HelpEdit[Inf_NUM_INFO_TYPES] = { Hlp_COURSE_Information_edit, // Inf_INTRODUCTION Hlp_COURSE_Guide_edit, // Inf_TEACHING_GUIDE Hlp_COURSE_Syllabus_edit, // Inf_LECTURES Hlp_COURSE_Syllabus_edit, // Inf_PRACTICALS Hlp_COURSE_Bibliography_edit, // Inf_BIBLIOGRAPHY Hlp_COURSE_FAQ_edit, // Inf_FAQ Hlp_COURSE_Links_edit, // Inf_LINKS Hlp_ASSESSMENT_System_edit, // Inf_ASSESSMENT }; /***** Set info type *****/ Gbl.Crs.Info.Type = Inf_AsignInfoType (); /***** Start form and box *****/ Frm_StartForm (Inf_ActionsRcvPlaTxtInfo[Gbl.Crs.Info.Type]); Box_StartBox (NULL,Txt_INFO_TITLE[Gbl.Crs.Info.Type],NULL, HelpEdit[Gbl.Crs.Info.Type],Box_NOT_CLOSABLE); if (Gbl.Crs.Info.Type == Inf_INTRODUCTION || Gbl.Crs.Info.Type == Inf_TEACHING_GUIDE) Lay_WriteHeaderClassPhoto (false,false,Gbl.Hierarchy.Ins.InsCod,Gbl.Hierarchy.Deg.DegCod,Gbl.Hierarchy.Crs.CrsCod); /***** Get info text from database *****/ Inf_GetInfoTxtFromDB (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type, TxtHTML,NULL); /***** Edition area *****/ fprintf (Gbl.F.Out,"
"); Lay_HelpPlainEditor (); fprintf (Gbl.F.Out,"" "
", TxtHTML); /***** Send button and end box *****/ Box_EndBoxWithButton (Btn_CONFIRM_BUTTON,Txt_Save_changes); Frm_EndForm (); } /*****************************************************************************/ /*************** 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_changes; char TxtHTML[Cns_MAX_BYTES_LONG_TEXT + 1]; const char *HelpEdit[Inf_NUM_INFO_TYPES] = { Hlp_COURSE_Information_edit, // Inf_INTRODUCTION Hlp_COURSE_Guide_edit, // Inf_TEACHING_GUIDE Hlp_COURSE_Syllabus_edit, // Inf_LECTURES Hlp_COURSE_Syllabus_edit, // Inf_PRACTICALS Hlp_COURSE_Bibliography_edit, // Inf_BIBLIOGRAPHY Hlp_COURSE_FAQ_edit, // Inf_FAQ Hlp_COURSE_Links_edit, // Inf_LINKS Hlp_ASSESSMENT_System_edit, // Inf_ASSESSMENT }; /***** Set info type *****/ Gbl.Crs.Info.Type = Inf_AsignInfoType (); /***** Start form and box *****/ Frm_StartForm (Inf_ActionsRcvRchTxtInfo[Gbl.Crs.Info.Type]); Box_StartBox (NULL,Txt_INFO_TITLE[Gbl.Crs.Info.Type],NULL, HelpEdit[Gbl.Crs.Info.Type],Box_NOT_CLOSABLE); if (Gbl.Crs.Info.Type == Inf_INTRODUCTION || Gbl.Crs.Info.Type == Inf_TEACHING_GUIDE) Lay_WriteHeaderClassPhoto (false,false,Gbl.Hierarchy.Ins.InsCod,Gbl.Hierarchy.Deg.DegCod,Gbl.Hierarchy.Crs.CrsCod); /***** Get info text from database *****/ Inf_GetInfoTxtFromDB (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type, TxtHTML,NULL); /***** Edition area *****/ fprintf (Gbl.F.Out,"
"); Lay_HelpRichEditor (); fprintf (Gbl.F.Out,"" "
", TxtHTML); /***** Send button and end box *****/ Box_EndBoxWithButton (Btn_CONFIRM_BUTTON,Txt_Save_changes); Frm_EndForm (); } /*****************************************************************************/ /*************** 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.Crs.Info.Type = Inf_AsignInfoType (); /***** Get text with course information from form *****/ Par_GetParameter (Par_PARAM_SINGLE,"Txt",Txt_HTMLFormat, Cns_MAX_BYTES_LONG_TEXT,NULL); Str_Copy (Txt_MarkdownFormat,Txt_HTMLFormat, Cns_MAX_BYTES_LONG_TEXT); 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.Crs.Info.Type = Inf_AsignInfoType (); /***** Get text with course information from form *****/ Par_GetParameter (Par_PARAM_SINGLE,"Txt",Txt_HTMLFormat, Cns_MAX_BYTES_LONG_TEXT,NULL); Str_Copy (Txt_MarkdownFormat,Txt_HTMLFormat, Cns_MAX_BYTES_LONG_TEXT); 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; char PathFile[PATH_MAX + 1]; FILE *FileURL; bool URLIsOK = false; /***** Set info type *****/ Gbl.Crs.Info.Type = Inf_AsignInfoType (); /***** Get parameter with URL *****/ Par_GetParToText ("InfoSrcURL",Gbl.Crs.Info.URL,Cns_MAX_BYTES_WWW); /***** Build path to file containing URL *****/ Inf_BuildPathURL (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathFile); /***** Open file with URL *****/ if ((FileURL = fopen (PathFile,"wb")) != NULL) { /***** Write URL *****/ fprintf (FileURL,"%s",Gbl.Crs.Info.URL); /***** Close file *****/ fclose (FileURL); /***** Write message *****/ Ale_ShowAlert (Ale_SUCCESS,Txt_The_URL_X_has_been_updated, Gbl.Crs.Info.URL); URLIsOK = true; } else Ale_ShowAlert (Ale_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; struct Param *Param; char SourceFileName[PATH_MAX + 1]; char PathRelDirHTML[PATH_MAX + 1]; char PathRelFileHTML[PATH_MAX + 1]; char PathRelFileZIP[PATH_MAX + 1 + NAME_MAX + 1]; char MIMEType[Brw_MAX_BYTES_MIME_TYPE + 1]; char StrUnzip[128 + PATH_MAX * 2 + 1]; bool WrongType = false; bool FileIsOK = false; /***** Set info type *****/ Gbl.Crs.Info.Type = Inf_AsignInfoType (); /***** First of all, store in disk the file from stdin (really from Gbl.F.Tmp) *****/ Param = Fil_StartReceptionOfFile (Fil_NAME_OF_PARAM_FILENAME_ORG, SourceFileName,MIMEType); /***** Check that MIME type is HTML or ZIP *****/ if (strcmp (MIMEType,"text/html")) if (strcmp (MIMEType,"text/plain")) if (strcmp (MIMEType,"application/x-zip-compressed")) if (strcmp (MIMEType,"application/zip")) if (strcmp (MIMEType,"application/x-download")) if (strcmp (MIMEType,"application/octet-stream")) if (strcmp (MIMEType,"application/octetstream")) if (strcmp (MIMEType,"application/octet")) WrongType = true; if (WrongType) Ale_ShowAlert (Ale_INFO,Txt_The_file_type_is_X_and_should_be_HTML_or_ZIP, MIMEType); else { /***** Build path of directory containing web page *****/ Inf_BuildPathPage (Gbl.Hierarchy.Crs.CrsCod,Gbl.Crs.Info.Type,PathRelDirHTML); /***** End the reception of the data *****/ if (Str_FileIs (SourceFileName,"html") || Str_FileIs (SourceFileName,"htm" )) // .html or .htm file { Fil_RemoveTree (PathRelDirHTML); Fil_CreateDirIfNotExists (PathRelDirHTML); snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.html", PathRelDirHTML); if (Fil_EndReceptionOfFile (PathRelFileHTML,Param)) { Ale_ShowAlert (Ale_SUCCESS,Txt_The_HTML_file_has_been_received_successfully); FileIsOK = true; } else Ale_ShowAlert (Ale_ERROR,"Error uploading file."); } else if (Str_FileIs (SourceFileName,"zip")) // .zip file { Fil_RemoveTree (PathRelDirHTML); Fil_CreateDirIfNotExists (PathRelDirHTML); snprintf (PathRelFileZIP,sizeof (PathRelFileZIP), "%s/%s.zip", Gbl.Crs.PathPriv, Inf_FileNamesForInfoType[Gbl.Crs.Info.Type]); if (Fil_EndReceptionOfFile (PathRelFileZIP,Param)) { Ale_ShowAlert (Ale_SUCCESS,Txt_The_ZIP_file_has_been_received_successfully); /* Uncompress ZIP */ snprintf (StrUnzip,sizeof (StrUnzip), "unzip -qq -o %s -d %s", PathRelFileZIP,PathRelDirHTML); if (system (StrUnzip) == 0) { /* Check if uploaded file is index.html or index.htm */ snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.html", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) { Ale_ShowAlert (Ale_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully); Ale_ShowAlert (Ale_SUCCESS,Txt_Found_an_index_html_file); FileIsOK = true; } else { snprintf (PathRelFileHTML,sizeof (PathRelFileHTML), "%s/index.htm", PathRelDirHTML); if (Fil_CheckIfPathExists (PathRelFileHTML)) { Ale_ShowAlert (Ale_SUCCESS,Txt_The_ZIP_file_has_been_unzipped_successfully); Ale_ShowAlert (Ale_SUCCESS,Txt_Found_an_index_htm_file); FileIsOK = true; } else Ale_ShowAlert (Ale_WARNING,Txt_No_file_index_html_index_htm_found_within_the_ZIP_file); } } else Lay_ShowErrorAndExit ("Can not unzip file."); } else Ale_ShowAlert (Ale_ERROR,"Error uploading file."); } else Ale_ShowAlert (Ale_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; Ale_ShowAlert (Ale_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; Ale_ShowAlert (Ale_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; Ale_ShowAlert (Ale_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; Ale_ShowAlert (Ale_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; Ale_ShowAlert (Ale_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; Ale_ShowAlert (Ale_WARNING,Txt_The_integrated_editor_is_not_yet_available); /***** Show again the form to select and send course info *****/ Inf_FormsToSelSendInfo (); }