// swad_form.c: forms to go to actions /* 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-2022 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 *********************************/ /*****************************************************************************/ #define _GNU_SOURCE // For asprintf #include // For asprintf #include // For free #include "swad_error.h" #include "swad_form.h" #include "swad_global.h" #include "swad_hierarchy_level.h" #include "swad_HTML.h" /*****************************************************************************/ /************** External global variables from others modules ****************/ /*****************************************************************************/ extern struct Globals Gbl; /*****************************************************************************/ /**************************** Private prototypes *****************************/ /*****************************************************************************/ static void Frm_BeginFormInternal (Act_Action_t NextAction,bool PutParameterLocationIfNoSesion, const char *Id,const char *Anchor,const char *OnSubmit); /*****************************************************************************/ /******************************** Begin a form *******************************/ /*****************************************************************************/ void Frm_BeginFormGoTo (Act_Action_t NextAction) { Gbl.Form.Num++; // Initialized to -1. The first time it is incremented, it will be equal to 0 snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),"form_%d",Gbl.Form.Num); Frm_BeginFormInternal (NextAction,false,Gbl.Form.Id,NULL,NULL); // Do not put now parameter location } void Frm_BeginForm (Act_Action_t NextAction) { Frm_BeginFormAnchorOnSubmit (NextAction,NULL,NULL); } void Frm_BeginFormAnchor (Act_Action_t NextAction,const char *Anchor) { Frm_BeginFormAnchorOnSubmit (NextAction,Anchor,NULL); } void Frm_BeginFormOnSubmit (Act_Action_t NextAction,const char *OnSubmit) { Frm_BeginFormAnchorOnSubmit (NextAction,NULL,OnSubmit); } void Frm_BeginFormAnchorOnSubmit (Act_Action_t NextAction,const char *Anchor,const char *OnSubmit) { Gbl.Form.Num++; // Initialized to -1. The first time it is incremented, it will be equal to 0 snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),"form_%d",Gbl.Form.Num); Frm_BeginFormInternal (NextAction,true,Gbl.Form.Id,Anchor,OnSubmit); // Do put now parameter location (if no open session) } void Frm_BeginFormId (Act_Action_t NextAction,const char *Id) { Gbl.Form.Num++; // Initialized to -1. The first time it is incremented, it will be equal to 0 Frm_BeginFormInternal (NextAction,true,Id,NULL,NULL); // Do put now parameter location (if no open session) } // Id can not be NULL static void Frm_BeginFormInternal (Act_Action_t NextAction,bool PutParameterLocationIfNoSesion, const char *Id,const char *Anchor,const char *OnSubmit) { extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES]; char ParamsStr[Frm_MAX_BYTES_PARAMS_STR + 1]; if (!Gbl.Form.Inside) { /* Begin form */ HTM_TxtF ("
"); /* Put basic form parameters */ Frm_SetParamsForm (ParamsStr,NextAction,PutParameterLocationIfNoSesion); HTM_Txt (ParamsStr); Gbl.Form.Inside = true; } } /* Form without action are used in exams. The accept-charset attribute specifies the character encodings that are to be used for the form submission But this type of form is sent via AJAX ==> ==> we use the value property of input fields to build the parameters sent using XMLHttp.send ==> ==> the value property is always codified in UTF-8 ==> accept-charset is irrelevant */ void Frm_BeginFormNoAction (void) { if (!Gbl.Form.Inside) { /* Begin form */ HTM_Txt (""); // Form that can not be submitted, to avoid enter key to send it Gbl.Form.Inside = true; } } void Frm_SetParamsForm (char ParamsStr[Frm_MAX_BYTES_PARAMS_STR + 1],Act_Action_t NextAction, bool PutParameterLocationIfNoSession) { char ParamAction[Frm_MAX_BYTES_PARAM_ACTION + 1]; char ParamSession[Frm_MAX_BYTES_PARAM_SESSION + 1]; char ParamLocation[Frm_MAX_BYTES_PARAM_LOCATION + 1]; ParamAction[0] = '\0'; ParamSession[0] = '\0'; ParamLocation[0] = '\0'; if (NextAction != ActUnk) { snprintf (ParamAction,sizeof (ParamAction), "", Act_GetActCod (NextAction)); if (Gbl.Session.Id[0]) snprintf (ParamSession,sizeof (ParamSession), "", Gbl.Session.Id); else if (PutParameterLocationIfNoSession) // Extra parameters necessary when there's no open session { /* If session is open, course code will be get from session data, but if there is not an open session, and next action is known, it is necessary to send a parameter with course code */ switch (Gbl.Hierarchy.Level) { case HieLvl_CTY: // Country snprintf (ParamLocation,sizeof (ParamLocation), "", Gbl.Hierarchy.Cty.CtyCod); break; case HieLvl_INS: // Institution snprintf (ParamLocation,sizeof (ParamLocation), "", Gbl.Hierarchy.Ins.InsCod); break; case HieLvl_CTR: // Center snprintf (ParamLocation,sizeof (ParamLocation), "", Gbl.Hierarchy.Ctr.CtrCod); break; case HieLvl_DEG: // Degree snprintf (ParamLocation,sizeof (ParamLocation), "", Gbl.Hierarchy.Deg.DegCod); break; case HieLvl_CRS: // Course snprintf (ParamLocation,sizeof (ParamLocation), "", Gbl.Hierarchy.Crs.CrsCod); break; default: break; } } } snprintf (ParamsStr,Frm_MAX_BYTES_PARAMS_STR + 1,"%s%s%s", ParamAction,ParamSession,ParamLocation); } void Frm_EndForm (void) { if (Gbl.Form.Inside) { HTM_Txt ("
"); Gbl.Form.Inside = false; } } /*****************************************************************************/ /***************************** Get unique Id *********************************/ /*****************************************************************************/ void Frm_SetUniqueId (char UniqueId[Frm_MAX_BYTES_ID + 1]) { static unsigned CountForThisExecution = 0; /***** Create Id. The id must be unique, the page content may be updated via AJAX. So, Id uses: - a name for this execution (Gbl.UniqueNameEncrypted) - a number for each element in this execution (CountForThisExecution) *****/ snprintf (UniqueId,Frm_MAX_BYTES_ID + 1,"id_%s_%u", Gbl.UniqueNameEncrypted, ++CountForThisExecution); } /*****************************************************************************/ /****************** Build/free anchor string given a code ********************/ /*****************************************************************************/ void Frm_SetAnchorStr (long Cod,char **Anchor) { if (Cod > 0) { if (asprintf (Anchor,"cod_%ld", Cod) < 0) Err_NotEnoughMemoryExit (); } else *Anchor = NULL; } void Frm_FreeAnchorStr (char *Anchor) { if (Anchor) { free (Anchor); Anchor = NULL; } } /*****************************************************************************/ /************************* Show label column in form *************************/ /*****************************************************************************/ // Id == NULL ==> label class = data // Id[0] == '\0' ==> label class = form, no label for // Id[0] != '\0' ==> label class = form, label for void Frm_LabelColumn (const char *TDClass,const char *Id,const char *Label) { /***** Column/cell begin *****/ if (TDClass) HTM_TD_Begin ("class=\"%s\"",TDClass); else HTM_TD_Begin (NULL); /***** Label *****/ if (Id) { if (Id[0]) HTM_LABEL_Begin ("for=\"%s\" class=\"FORM_IN_%s\"", Id,The_GetSuffix ()); else HTM_LABEL_Begin ("class=\"FORM_IN_%s\"", The_GetSuffix ()); } else HTM_LABEL_Begin ("class=\"DAT_%s\"",The_GetSuffix ()); HTM_TxtColon (Label); HTM_LABEL_End (); /***** Column/cell end *****/ HTM_TD_End (); }