mirror of
https://github.com/acanas/swad-core.git
synced 2024-06-29 03:45:53 +02:00
Version 21.60: Nov 24, 2021 Code refactoring inserting links in a string.
This commit is contained in:
parent
534f147a3c
commit
14f64fd450
|
@ -602,13 +602,14 @@ TODO: FIX BUG, URGENT! En las fechas como par
|
||||||
|
|
||||||
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
|
TODO: En las encuestas, que los estudiantes no puedan ver los resultados hasta que no finalice el plazo.
|
||||||
*/
|
*/
|
||||||
#define Log_PLATFORM_VERSION "SWAD 21.59 (2021-11-22)"
|
#define Log_PLATFORM_VERSION "SWAD 21.60 (2021-11-24)"
|
||||||
#define CSS_FILE "swad21.59.css"
|
#define CSS_FILE "swad21.59.css"
|
||||||
#define JS_FILE "swad21.59.js"
|
#define JS_FILE "swad21.59.js"
|
||||||
/*
|
/*
|
||||||
TODO: Rename CENTRE to CENTER in help wiki.
|
TODO: Rename CENTRE to CENTER in help wiki.
|
||||||
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
|
TODO: Rename ASSESSMENT.Announcements to ASSESSMENT.Calls_for_exams
|
||||||
|
|
||||||
|
Version 21.60: Nov 24, 2021 Code refactoring inserting links in a string. (319208 lines)
|
||||||
Version 21.59: Nov 22, 2021 Code refactoring in timeline. (319149 lines)
|
Version 21.59: Nov 22, 2021 Code refactoring in timeline. (319149 lines)
|
||||||
Version 21.58.2: Nov 21, 2021 Code refactoring in timeline. (319135 lines)
|
Version 21.58.2: Nov 21, 2021 Code refactoring in timeline. (319135 lines)
|
||||||
Version 21.58.1: Nov 21, 2021 Code refactoring in timeline. (319131 lines)
|
Version 21.58.1: Nov 21, 2021 Code refactoring in timeline. (319131 lines)
|
||||||
|
|
|
@ -169,7 +169,7 @@ void Frm_BeginFormNoAction (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frm_SetParamsForm (char ParamsStr[Frm_MAX_BYTES_PARAMS_STR + 1],Act_Action_t NextAction,
|
void Frm_SetParamsForm (char ParamsStr[Frm_MAX_BYTES_PARAMS_STR + 1],Act_Action_t NextAction,
|
||||||
bool PutParameterLocationIfNoSesion)
|
bool PutParameterLocationIfNoSession)
|
||||||
{
|
{
|
||||||
char ParamAction[Frm_MAX_BYTES_PARAM_ACTION + 1];
|
char ParamAction[Frm_MAX_BYTES_PARAM_ACTION + 1];
|
||||||
char ParamSession[Frm_MAX_BYTES_PARAM_SESSION + 1];
|
char ParamSession[Frm_MAX_BYTES_PARAM_SESSION + 1];
|
||||||
|
@ -189,7 +189,7 @@ void Frm_SetParamsForm (char ParamsStr[Frm_MAX_BYTES_PARAMS_STR + 1],Act_Action_
|
||||||
snprintf (ParamSession,sizeof (ParamSession),
|
snprintf (ParamSession,sizeof (ParamSession),
|
||||||
"<input type=\"hidden\" name=\"ses\" value=\"%s\" />",
|
"<input type=\"hidden\" name=\"ses\" value=\"%s\" />",
|
||||||
Gbl.Session.Id);
|
Gbl.Session.Id);
|
||||||
else if (PutParameterLocationIfNoSesion)
|
else if (PutParameterLocationIfNoSession)
|
||||||
// Extra parameters necessary when there's no open session
|
// Extra parameters necessary when there's no open session
|
||||||
{
|
{
|
||||||
/* If session is open, course code will be get from session data,
|
/* If session is open, course code will be get from session data,
|
||||||
|
|
|
@ -57,7 +57,7 @@ void Frm_BeginFormUniqueAnchorOnSubmit (Act_Action_t NextAction,const char *Anch
|
||||||
void Frm_BeginFormId (Act_Action_t NextAction,const char *Id);
|
void Frm_BeginFormId (Act_Action_t NextAction,const char *Id);
|
||||||
void Frm_BeginFormNoAction (void);
|
void Frm_BeginFormNoAction (void);
|
||||||
void Frm_SetParamsForm (char ParamsStr[Frm_MAX_BYTES_PARAMS_STR],Act_Action_t NextAction,
|
void Frm_SetParamsForm (char ParamsStr[Frm_MAX_BYTES_PARAMS_STR],Act_Action_t NextAction,
|
||||||
bool PutParameterLocationIfNoSesion);
|
bool PutParameterLocationIfNoSession);
|
||||||
void Frm_EndForm (void);
|
void Frm_EndForm (void);
|
||||||
|
|
||||||
void Frm_SetUniqueId (char UniqueId[Frm_MAX_BYTES_ID + 1]);
|
void Frm_SetUniqueId (char UniqueId[Frm_MAX_BYTES_ID + 1]);
|
||||||
|
|
|
@ -972,7 +972,7 @@ static void For_ShowAForumPost (struct For_Forums *Forums,
|
||||||
if (Enabled)
|
if (Enabled)
|
||||||
{
|
{
|
||||||
Str_Copy (Content,OriginalContent,sizeof (Content) - 1);
|
Str_Copy (Content,OriginalContent,sizeof (Content) - 1);
|
||||||
Msg_WriteMsgContent (Content,Cns_MAX_BYTES_LONG_TEXT,true,false);
|
Msg_WriteMsgContent (Content,true,false);
|
||||||
|
|
||||||
/***** Show image *****/
|
/***** Show image *****/
|
||||||
Med_ShowMedia (&Media,"FOR_IMG_CONT","FOR_IMG");
|
Med_ShowMedia (&Media,"FOR_IMG_CONT","FOR_IMG");
|
||||||
|
|
|
@ -210,7 +210,7 @@ struct Globals
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned Num; // Number of institutional links
|
unsigned Num; // Number of institutional links
|
||||||
struct Link *Lst; // List of institutional links
|
struct Str_Link *Lst; // List of institutional links
|
||||||
} Links;
|
} Links;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
10
swad_link.c
10
swad_link.c
|
@ -52,7 +52,7 @@ extern struct Globals Gbl;
|
||||||
/***************************** Private variables *****************************/
|
/***************************** Private variables *****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static struct Link *Lnk_EditingLnk = NULL; // Static variable to keep the link being edited
|
static struct Str_Link *Lnk_EditingLnk = NULL; // Static variable to keep the link being edited
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/***************************** Private prototypes ****************************/
|
/***************************** Private prototypes ****************************/
|
||||||
|
@ -65,7 +65,7 @@ static void Lnk_WriteListOfLinks (void);
|
||||||
static void Lnk_EditLinksInternal (void);
|
static void Lnk_EditLinksInternal (void);
|
||||||
static void Lnk_PutIconsEditingLinks (__attribute__((unused)) void *Args);
|
static void Lnk_PutIconsEditingLinks (__attribute__((unused)) void *Args);
|
||||||
|
|
||||||
static void Lnk_GetDataOfLink (MYSQL_RES *mysql_res,struct Link *Lnk);
|
static void Lnk_GetDataOfLink (MYSQL_RES *mysql_res,struct Str_Link *Lnk);
|
||||||
|
|
||||||
static void Lnk_ListLinksForEdition (void);
|
static void Lnk_ListLinksForEdition (void);
|
||||||
static void Lnk_PutParamLnkCod (void *LnkCod);
|
static void Lnk_PutParamLnkCod (void *LnkCod);
|
||||||
|
@ -309,7 +309,7 @@ void Lnk_GetListLinks (void)
|
||||||
/**************************** Get link full name *****************************/
|
/**************************** Get link full name *****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void Lnk_GetDataOfLinkByCod (struct Link *Lnk)
|
void Lnk_GetDataOfLinkByCod (struct Str_Link *Lnk)
|
||||||
{
|
{
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ void Lnk_GetDataOfLinkByCod (struct Link *Lnk)
|
||||||
/**************************** Get data of link *******************************/
|
/**************************** Get data of link *******************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Lnk_GetDataOfLink (MYSQL_RES *mysql_res,struct Link *Lnk)
|
static void Lnk_GetDataOfLink (MYSQL_RES *mysql_res,struct Str_Link *Lnk)
|
||||||
{
|
{
|
||||||
MYSQL_ROW row;
|
MYSQL_ROW row;
|
||||||
|
|
||||||
|
@ -376,7 +376,7 @@ void Lnk_FreeListLinks (void)
|
||||||
static void Lnk_ListLinksForEdition (void)
|
static void Lnk_ListLinksForEdition (void)
|
||||||
{
|
{
|
||||||
unsigned NumLnk;
|
unsigned NumLnk;
|
||||||
struct Link *Lnk;
|
struct Str_Link *Lnk;
|
||||||
|
|
||||||
/***** Begin table *****/
|
/***** Begin table *****/
|
||||||
HTM_TABLE_BeginWidePadding (2);
|
HTM_TABLE_BeginWidePadding (2);
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#define Lnk_MAX_CHARS_LINK_FULL_NAME (128 - 1) // 127
|
#define Lnk_MAX_CHARS_LINK_FULL_NAME (128 - 1) // 127
|
||||||
#define Lnk_MAX_BYTES_LINK_FULL_NAME ((Lnk_MAX_CHARS_LINK_FULL_NAME + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
#define Lnk_MAX_BYTES_LINK_FULL_NAME ((Lnk_MAX_CHARS_LINK_FULL_NAME + 1) * Str_MAX_BYTES_PER_CHAR - 1) // 2047
|
||||||
|
|
||||||
struct Link
|
struct Str_Link
|
||||||
{
|
{
|
||||||
long LnkCod;
|
long LnkCod;
|
||||||
char ShrtName[Lnk_MAX_BYTES_LINK_SHRT_NAME + 1];
|
char ShrtName[Lnk_MAX_BYTES_LINK_SHRT_NAME + 1];
|
||||||
|
@ -54,7 +54,7 @@ void Lnk_PutIconToViewLinks (void);
|
||||||
|
|
||||||
void Lnk_GetListLinks (void);
|
void Lnk_GetListLinks (void);
|
||||||
void Lnk_FreeListLinks (void);
|
void Lnk_FreeListLinks (void);
|
||||||
void Lnk_GetDataOfLinkByCod (struct Link *Lnk);
|
void Lnk_GetDataOfLinkByCod (struct Str_Link *Lnk);
|
||||||
long Lnk_GetParamLnkCod (void);
|
long Lnk_GetParamLnkCod (void);
|
||||||
void Lnk_RemoveLink (void);
|
void Lnk_RemoveLink (void);
|
||||||
void Lnk_RenameLinkShort (void);
|
void Lnk_RenameLinkShort (void);
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
/**************************** Create a new link ******************************/
|
/**************************** Create a new link ******************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void Lnk_DB_CreateLink (const struct Link *Lnk)
|
void Lnk_DB_CreateLink (const struct Str_Link *Lnk)
|
||||||
{
|
{
|
||||||
DB_QueryINSERT ("can not create institutional link",
|
DB_QueryINSERT ("can not create institutional link",
|
||||||
"INSERT INTO lnk_links"
|
"INSERT INTO lnk_links"
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
/****************************** Public prototypes ****************************/
|
/****************************** Public prototypes ****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void Lnk_DB_CreateLink (const struct Link *Lnk);
|
void Lnk_DB_CreateLink (const struct Str_Link *Lnk);
|
||||||
void Lnk_DB_UpdateLnkName (long LnkCod,const char *FieldName,const char *NewLnkName);
|
void Lnk_DB_UpdateLnkName (long LnkCod,const char *FieldName,const char *NewLnkName);
|
||||||
void Lnk_DB_UpdateLnkWWW (long LnkCod,const char NewWWW[Cns_MAX_BYTES_WWW + 1]);
|
void Lnk_DB_UpdateLnkWWW (long LnkCod,const char NewWWW[Cns_MAX_BYTES_WWW + 1]);
|
||||||
|
|
||||||
|
|
|
@ -629,7 +629,7 @@ static void Msg_WriteFormSubjectAndContentMsgToUsrs (struct Msg_Messages *Messag
|
||||||
if (!SubjectAndContentComeFromForm)
|
if (!SubjectAndContentComeFromForm)
|
||||||
HTM_TxtF ("\n\n----- %s -----\n",Txt_Original_message);
|
HTM_TxtF ("\n\n----- %s -----\n",Txt_Original_message);
|
||||||
|
|
||||||
Msg_WriteMsgContent (Content,Cns_MAX_BYTES_LONG_TEXT,false,true);
|
Msg_WriteMsgContent (Content,false,true);
|
||||||
HTM_TEXTAREA_End ();
|
HTM_TEXTAREA_End ();
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
}
|
}
|
||||||
|
@ -2156,7 +2156,7 @@ static void Msg_ShowASentOrReceivedMessage (struct Msg_Messages *Messages,
|
||||||
/***** Show content and media *****/
|
/***** Show content and media *****/
|
||||||
HTM_TD_Begin ("colspan=\"2\" class=\"MSG_TXT LT\"");
|
HTM_TD_Begin ("colspan=\"2\" class=\"MSG_TXT LT\"");
|
||||||
if (Content[0])
|
if (Content[0])
|
||||||
Msg_WriteMsgContent (Content,Cns_MAX_BYTES_LONG_TEXT,true,false);
|
Msg_WriteMsgContent (Content,true,false);
|
||||||
Med_ShowMedia (&Media,"MSG_IMG_CONT","MSG_IMG");
|
Med_ShowMedia (&Media,"MSG_IMG_CONT","MSG_IMG");
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
||||||
|
@ -2682,11 +2682,12 @@ void Msg_WriteMsgDate (time_t TimeUTC,const char *ClassBackground)
|
||||||
/********************* Write the text (content) of a message *****************/
|
/********************* Write the text (content) of a message *****************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void Msg_WriteMsgContent (char *Content,unsigned long MaxLength,bool InsertLinks,bool ChangeBRToRet)
|
void Msg_WriteMsgContent (char Content[Cns_MAX_BYTES_LONG_TEXT + 1],
|
||||||
|
bool InsertLinks,bool ChangeBRToRet)
|
||||||
{
|
{
|
||||||
/***** Insert links in URLs *****/
|
/***** Insert links in URLs *****/
|
||||||
if (InsertLinks)
|
if (InsertLinks)
|
||||||
Str_InsertLinks (Content,MaxLength,60);
|
Str_InsertLinks (Content,Cns_MAX_BYTES_LONG_TEXT,60);
|
||||||
|
|
||||||
/***** Write message to file *****/
|
/***** Write message to file *****/
|
||||||
if (ChangeBRToRet)
|
if (ChangeBRToRet)
|
||||||
|
|
|
@ -115,7 +115,8 @@ void Msg_GetNotifMessage (char SummaryStr[Ntf_MAX_BYTES_SUMMARY + 1],
|
||||||
void Msg_WriteMsgNumber (unsigned long MsgNum,bool NewMsg);
|
void Msg_WriteMsgNumber (unsigned long MsgNum,bool NewMsg);
|
||||||
void Msg_WriteMsgAuthor (struct UsrData *UsrDat,bool Enabled,const char *BgColor);
|
void Msg_WriteMsgAuthor (struct UsrData *UsrDat,bool Enabled,const char *BgColor);
|
||||||
void Msg_WriteMsgDate (time_t TimeUTC,const char *ClassBackground);
|
void Msg_WriteMsgDate (time_t TimeUTC,const char *ClassBackground);
|
||||||
void Msg_WriteMsgContent (char *Content,unsigned long MaxLength,bool InsertLinks,bool ChangeBRToRet);
|
void Msg_WriteMsgContent (char Content[Cns_MAX_BYTES_LONG_TEXT + 1],
|
||||||
|
bool InsertLinks,bool ChangeBRToRet);
|
||||||
|
|
||||||
void Msg_PutHiddenParamMsgCod (long MsgCod);
|
void Msg_PutHiddenParamMsgCod (long MsgCod);
|
||||||
|
|
||||||
|
|
667
swad_string.c
667
swad_string.c
|
@ -42,6 +42,34 @@
|
||||||
#include "swad_parameter.h"
|
#include "swad_parameter.h"
|
||||||
#include "swad_string.h"
|
#include "swad_string.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/******************************* Private types *******************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
Str_LINK_UNKNOWN = 0,
|
||||||
|
Str_LINK_URL = 1,
|
||||||
|
Str_LINK_NICK = 2,
|
||||||
|
} Str_LinkType_t;
|
||||||
|
|
||||||
|
struct Str_Substring
|
||||||
|
{
|
||||||
|
char *Str; // Pointer to the first char of substring
|
||||||
|
size_t Len; // Length of the substring
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Str_Link
|
||||||
|
{
|
||||||
|
Str_LinkType_t Type;
|
||||||
|
struct Str_Substring URLorNick;
|
||||||
|
struct Str_Substring AnchorNick1;
|
||||||
|
struct Str_Substring AnchorNick2;
|
||||||
|
size_t AddedLengthUntilHere; // Total length of extra HTML code added until this link (included)
|
||||||
|
struct Str_Link *Prev;
|
||||||
|
struct Str_Link *Next;
|
||||||
|
};
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/******************** Global variables from other modules ********************/
|
/******************** Global variables from other modules ********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -52,6 +80,20 @@ extern struct Globals Gbl; // Declaration in swad.c
|
||||||
/*************************** Private prototypes ******************************/
|
/*************************** Private prototypes ******************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void Str_CreateFirstLink (struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink);
|
||||||
|
static void Str_CreateNextLink (struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink);
|
||||||
|
static void Str_FreeLinks (struct Str_Link *LastLink);
|
||||||
|
static bool Str_CheckURL (char **PtrSrc,
|
||||||
|
struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink,
|
||||||
|
size_t MaxCharsURLOnScreen);
|
||||||
|
static bool Str_CheckNickname (char **PtrSrc,
|
||||||
|
struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink);
|
||||||
|
static void Str_InsertSubstring (const struct Str_Substring *PtrSrc,char **PtrDst);
|
||||||
|
|
||||||
static unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch);
|
static unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch);
|
||||||
|
|
||||||
static unsigned Str_FindHTMLEntity (const char *Ptr);
|
static unsigned Str_FindHTMLEntity (const char *Ptr);
|
||||||
|
@ -98,204 +140,355 @@ action="https://localhost/swad/es" method="post">
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define ANCHOR_1_URL "<a href=\""
|
// For URLs the length of anchor is fixed, so it can be calculated once
|
||||||
#define ANCHOR_2_URL "\" target=\"_blank\">"
|
#define ANCHOR_URL_1 "<a href=\""
|
||||||
#define ANCHOR_3_URL "</a>"
|
#define ANCHOR_URL_2 "\" target=\"_blank\">"
|
||||||
#define ANCHOR_3_NICK "</a></form>"
|
#define ANCHOR_URL_3 "</a>"
|
||||||
|
#define ANCHOR_URL_1_LENGTH (sizeof (ANCHOR_URL_1) - 1)
|
||||||
|
#define ANCHOR_URL_2_LENGTH (sizeof (ANCHOR_URL_2) - 1)
|
||||||
|
#define ANCHOR_URL_3_LENGTH (sizeof (ANCHOR_URL_3) - 1)
|
||||||
|
#define ANCHOR_URL_TOTAL_LENGTH (ANCHOR_URL_1_LENGTH + ANCHOR_URL_2_LENGTH + ANCHOR_URL_3_LENGTH)
|
||||||
|
|
||||||
#define MAX_LINKS 1000
|
// For nicknames the length of anchor is variable,
|
||||||
|
// so it can be calculated for each link,
|
||||||
|
// except the third part that is fixed
|
||||||
|
#define ANCHOR_NICK_3 "</a></form>"
|
||||||
|
#define ANCHOR_NICK_3_LENGTH (sizeof (ANCHOR_NICK_3) - 1)
|
||||||
|
|
||||||
#define MAX_BYTES_LIMITED_URL (1024 - 1) // Max. number of bytes of the URL shown on screen
|
static const struct Str_Substring AnchorURL1 =
|
||||||
|
{
|
||||||
|
.Str = ANCHOR_URL_1,
|
||||||
|
.Len = ANCHOR_URL_1_LENGTH,
|
||||||
|
};
|
||||||
|
static const struct Str_Substring AnchorURL2 =
|
||||||
|
{
|
||||||
|
.Str = ANCHOR_URL_2,
|
||||||
|
.Len = ANCHOR_URL_2_LENGTH,
|
||||||
|
};
|
||||||
|
static const struct Str_Substring AnchorURL3 =
|
||||||
|
{
|
||||||
|
.Str = ANCHOR_URL_3,
|
||||||
|
.Len = ANCHOR_URL_3_LENGTH,
|
||||||
|
};
|
||||||
|
static const struct Str_Substring AnchorNick3 =
|
||||||
|
{
|
||||||
|
.Str = ANCHOR_NICK_3,
|
||||||
|
.Len = ANCHOR_NICK_3_LENGTH,
|
||||||
|
};
|
||||||
|
|
||||||
void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScreen)
|
void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScreen)
|
||||||
{
|
{
|
||||||
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
|
|
||||||
char ParamsStr[Frm_MAX_BYTES_PARAMS_STR];
|
|
||||||
char Anchor1Nick[256 + 256 + 256 + Cns_BYTES_SESSION_ID + 256 + 256];
|
|
||||||
char Anchor2Nick[256 + Cry_BYTES_ENCRYPTED_STR_SHA256_BASE64];
|
|
||||||
size_t TxtLength;
|
size_t TxtLength;
|
||||||
size_t TxtLengthWithInsertedAnchors;
|
|
||||||
|
|
||||||
size_t Anchor1URLLength;
|
|
||||||
size_t Anchor2URLLength;
|
|
||||||
size_t Anchor3URLLength;
|
|
||||||
size_t AnchorURLTotalLength;
|
|
||||||
|
|
||||||
size_t Anchor1NickLength = 0; // Initialized only to avoid warning
|
|
||||||
size_t Anchor2NickLength = 0; // Initialized only to avoid warning
|
|
||||||
size_t Anchor3NickLength;
|
|
||||||
size_t AnchorNickTotalLength = 0; // Initialized only to avoid warning
|
|
||||||
|
|
||||||
char *PtrSrc;
|
char *PtrSrc;
|
||||||
char *PtrDst;
|
char *PtrDst;
|
||||||
bool URLStartFound;
|
struct Str_Link *Link;
|
||||||
bool IsNickname;
|
struct Str_Link *LastLink;
|
||||||
int NumLinks = 0;
|
|
||||||
int NumLink;
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
char *PtrStart; // Pointer to the first char of URL/nickname in original text
|
|
||||||
char *PtrEnd; // Pointer to the last char of URL/nickname in original text
|
|
||||||
size_t NumActualBytes; // Actual length of the URL/nickname
|
|
||||||
char *Anchor1Nick;
|
|
||||||
char *Anchor2Nick;
|
|
||||||
size_t Anchor1NickLength;
|
|
||||||
size_t Anchor2NickLength;
|
|
||||||
size_t AddedLengthUntilHere; // Total length of extra HTML code added until this link (included)
|
|
||||||
} Links[MAX_LINKS];
|
|
||||||
size_t LengthVisibleLink;
|
|
||||||
size_t Length;
|
size_t Length;
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t NumChars1;
|
struct Str_Substring Limited; // URL displayed on screen (may be shorter than actual length)
|
||||||
size_t NumChars2;
|
const struct Str_Substring *Anchor1;
|
||||||
size_t NumBytesToCopy;
|
const struct Str_Substring *Anchor2;
|
||||||
size_t NumBytesToShow; // Length of the link displayed on screen (may be shorter than actual length)
|
const struct Str_Substring *Anchor3;
|
||||||
char LimitedURL[MAX_BYTES_LIMITED_URL + 1];
|
|
||||||
unsigned char Ch;
|
|
||||||
|
|
||||||
/****** Initialize constant anchors and their lengths *****/
|
|
||||||
TxtLength = strlen (Txt);
|
|
||||||
|
|
||||||
// For URLs the length of anchor is fixed
|
|
||||||
// so it can be calculated once
|
|
||||||
Anchor1URLLength = strlen (ANCHOR_1_URL);
|
|
||||||
Anchor2URLLength = strlen (ANCHOR_2_URL);
|
|
||||||
Anchor3URLLength = strlen (ANCHOR_3_URL);
|
|
||||||
AnchorURLTotalLength = Anchor1URLLength +
|
|
||||||
Anchor2URLLength +
|
|
||||||
Anchor3URLLength;
|
|
||||||
|
|
||||||
// For nicknames the length of anchor is variable
|
|
||||||
// so it can be calculated for each link,
|
|
||||||
// except the third part that is fixed
|
|
||||||
Anchor3NickLength = strlen (ANCHOR_3_NICK);
|
|
||||||
|
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
/***** Find starts and ends of links (URLs and nicknames) *****/
|
/***** Find starts and ends of links (URLs and nicknames) *****/
|
||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
|
Str_CreateFirstLink (&Link,&LastLink);
|
||||||
|
|
||||||
for (PtrSrc = Txt;
|
for (PtrSrc = Txt;
|
||||||
*PtrSrc;)
|
*PtrSrc;)
|
||||||
|
{
|
||||||
|
Link->Type = Str_LINK_UNKNOWN;
|
||||||
|
|
||||||
/* Check if the next char is the start of a URL */
|
/* Check if the next char is the start of a URL */
|
||||||
if (tolower ((int) *PtrSrc) == (int) 'h')
|
if (!Str_CheckURL (&PtrSrc,&Link,&LastLink,MaxCharsURLOnScreen))
|
||||||
{
|
/* Check if the next char is the start of a nickname */
|
||||||
URLStartFound = false;
|
if (!Str_CheckNickname (&PtrSrc,&Link,&LastLink))
|
||||||
Links[NumLinks].PtrStart = PtrSrc;
|
/* The next char is not the start of a URL or a nickname */
|
||||||
if (tolower ((int) *++PtrSrc) == (int) 't') // ht...
|
|
||||||
{
|
|
||||||
if (tolower ((int) *++PtrSrc) == (int) 't') // htt...
|
|
||||||
{
|
|
||||||
if (tolower ((int) *++PtrSrc) == (int) 'p') // http...
|
|
||||||
{
|
|
||||||
PtrSrc++;
|
PtrSrc++;
|
||||||
if (*PtrSrc == ':') // http:...
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
/***** If there are one or more links (URLs or nicknames) in text *****/
|
||||||
|
/**********************************************************************/
|
||||||
|
if (LastLink) // Not null ==> one or more links found
|
||||||
{
|
{
|
||||||
if (*++PtrSrc == '/') // http:/...
|
/***** Insert links from end to start of text,
|
||||||
if (*++PtrSrc == '/') // http://...
|
only if there is enough space available in text *****/
|
||||||
URLStartFound = true;
|
TxtLength = strlen (Txt);
|
||||||
}
|
if (TxtLength + LastLink->AddedLengthUntilHere <= MaxLength)
|
||||||
else if (tolower ((int) *PtrSrc) == (int) 's') // https...
|
for (Link = LastLink;
|
||||||
|
Link;
|
||||||
|
Link = Link->Prev)
|
||||||
{
|
{
|
||||||
if (*++PtrSrc == ':') // https:...
|
/***** Set anchors *****/
|
||||||
|
switch (Link->Type)
|
||||||
{
|
{
|
||||||
if (*++PtrSrc == '/') // https:/...
|
case Str_LINK_URL:
|
||||||
if (*++PtrSrc == '/') // https://...
|
Anchor1 = &AnchorURL1;
|
||||||
URLStartFound = true;
|
Anchor2 = &AnchorURL2;
|
||||||
|
Anchor3 = &AnchorURL3;
|
||||||
|
break;
|
||||||
|
case Str_LINK_NICK:
|
||||||
|
Anchor1 = &Link->AnchorNick1;
|
||||||
|
Anchor2 = &Link->AnchorNick2;
|
||||||
|
Anchor3 = &AnchorNick3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
/***** Step 1: Move forward the text after the link (URL or nickname)
|
||||||
}
|
(it's mandatory to do the copy in reverse order
|
||||||
}
|
to avoid overwriting source) *****/
|
||||||
if (URLStartFound)
|
PtrSrc = (Link == LastLink) ? Txt + TxtLength :
|
||||||
|
Link->Next->URLorNick.Str - 1,
|
||||||
|
PtrDst = PtrSrc + Link->AddedLengthUntilHere,
|
||||||
|
Length = PtrSrc - (Link->URLorNick.Str + Link->URLorNick.Len - 1);
|
||||||
|
for (i = 0;
|
||||||
|
i < Length;
|
||||||
|
i++)
|
||||||
|
*PtrDst-- = *PtrSrc--;
|
||||||
|
|
||||||
|
/***** Step 2: Insert thirs part of anchor *****/
|
||||||
|
Str_InsertSubstring (Anchor3,&PtrDst);
|
||||||
|
|
||||||
|
/***** Step 3: Move forward the link (URL or nickname)
|
||||||
|
to be shown on screen *****/
|
||||||
|
switch (Link->Type)
|
||||||
{
|
{
|
||||||
/* Find URL end */
|
case Str_LINK_URL:
|
||||||
PtrSrc++; // Points to first character after http:// or https://
|
if (Link->URLorNick.Len <= MaxCharsURLOnScreen)
|
||||||
|
Str_InsertSubstring (&Link->URLorNick,&PtrDst);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Limit the length of URL */
|
||||||
|
if ((Limited.Str = malloc (Link->URLorNick.Len + 1)) == NULL)
|
||||||
|
Err_NotEnoughMemoryExit ();
|
||||||
|
strncpy (Limited.Str,Link->URLorNick.Str,Link->URLorNick.Len);
|
||||||
|
Limited.Str[Link->URLorNick.Len] = '\0';
|
||||||
|
Limited.Len = Str_LimitLengthHTMLStr (Limited.Str,MaxCharsURLOnScreen);
|
||||||
|
Str_InsertSubstring (&Limited,&PtrDst);
|
||||||
|
free (Limited.Str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Str_LINK_NICK:
|
||||||
|
Str_InsertSubstring (&Link->URLorNick,&PtrDst);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Step 4: Insert second part of anchor *****/
|
||||||
|
Str_InsertSubstring (Anchor2,&PtrDst);
|
||||||
|
|
||||||
|
/***** Step 5: Insert link into directive A
|
||||||
|
(it's mandatory to do the copy in reverse order
|
||||||
|
to avoid overwriting source URL or nickname) *****/
|
||||||
|
Str_InsertSubstring (&Link->URLorNick,&PtrDst);
|
||||||
|
|
||||||
|
/***** Step 6: Insert first part of anchor *****/
|
||||||
|
Str_InsertSubstring (Anchor1,&PtrDst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/***** Free memory for anchors *****/
|
||||||
|
/***********************************/
|
||||||
|
Str_FreeLinks (LastLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************** Create first link ******************************/
|
||||||
|
|
||||||
|
static void Str_CreateFirstLink (struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink)
|
||||||
|
{
|
||||||
|
/***** Reset last link pointer *****/
|
||||||
|
(*LastLink) = NULL;
|
||||||
|
|
||||||
|
/***** Allocate current link *****/
|
||||||
|
if (((*Link) = malloc (sizeof (struct Str_Link))) == NULL)
|
||||||
|
Err_NotEnoughMemoryExit ();
|
||||||
|
|
||||||
|
/***** Initialize current link *****/
|
||||||
|
(*Link)->Prev = NULL;
|
||||||
|
(*Link)->Next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************** Create next link ******************************/
|
||||||
|
|
||||||
|
static void Str_CreateNextLink (struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink)
|
||||||
|
{
|
||||||
|
/***** Current link now is pointing to a correct link,
|
||||||
|
so set last link pointer to current link *****/
|
||||||
|
(*LastLink) = (*Link);
|
||||||
|
|
||||||
|
/***** Allocate next link *****/
|
||||||
|
if (((*Link)->Next = malloc (sizeof (struct Str_Link))) == NULL)
|
||||||
|
Err_NotEnoughMemoryExit ();
|
||||||
|
|
||||||
|
/***** Initialize next link *****/
|
||||||
|
(*Link)->Next->Prev = *Link;
|
||||||
|
(*Link)->Next->Next = NULL;
|
||||||
|
|
||||||
|
/***** Change current link to just allocated link *****/
|
||||||
|
(*Link) = (*Link)->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************** Free found links ******************************/
|
||||||
|
|
||||||
|
static void Str_FreeLinks (struct Str_Link *LastLink)
|
||||||
|
{
|
||||||
|
struct Str_Link *Link;
|
||||||
|
struct Str_Link *PrevLink;
|
||||||
|
|
||||||
|
for (Link = LastLink;
|
||||||
|
Link;
|
||||||
|
Link = PrevLink)
|
||||||
|
{
|
||||||
|
PrevLink = Link->Prev;
|
||||||
|
free (Link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************** Check if a URL found ***************************/
|
||||||
|
|
||||||
|
static bool Str_CheckURL (char **PtrSrc,
|
||||||
|
struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink,
|
||||||
|
size_t MaxCharsURLOnScreen)
|
||||||
|
{
|
||||||
|
unsigned char Ch;
|
||||||
|
size_t NumChars1;
|
||||||
|
size_t NumChars2;
|
||||||
|
char *PtrEnd; // Pointer to the last char of URL/nickname in original text
|
||||||
|
char *Limited; // URL displayed on screen (may be shorter than actual length)
|
||||||
|
|
||||||
|
/***** Check if the next char is the start of a URL *****/
|
||||||
|
if (tolower ((int) *(*PtrSrc)) == (int) 'h')
|
||||||
|
{
|
||||||
|
(*Link)->URLorNick.Str = (*PtrSrc);
|
||||||
|
if (tolower ((int) *++(*PtrSrc)) == (int) 't') // ht...
|
||||||
|
{
|
||||||
|
if (tolower ((int) *++(*PtrSrc)) == (int) 't') // htt...
|
||||||
|
{
|
||||||
|
if (tolower ((int) *++(*PtrSrc)) == (int) 'p') // http...
|
||||||
|
{
|
||||||
|
(*PtrSrc)++;
|
||||||
|
if (*(*PtrSrc) == ':') // http:...
|
||||||
|
{
|
||||||
|
if (*++(*PtrSrc) == '/') // http:/...
|
||||||
|
if (*++(*PtrSrc) == '/') // http://...
|
||||||
|
(*Link)->Type = Str_LINK_URL;
|
||||||
|
}
|
||||||
|
else if (tolower ((int) *(*PtrSrc)) == (int) 's') // https...
|
||||||
|
{
|
||||||
|
if (*++(*PtrSrc) == ':') // https:...
|
||||||
|
{
|
||||||
|
if (*++(*PtrSrc) == '/') // https:/...
|
||||||
|
if (*++(*PtrSrc) == '/') // https://...
|
||||||
|
(*Link)->Type = Str_LINK_URL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((*Link)->Type == Str_LINK_URL)
|
||||||
|
{
|
||||||
|
/***** Find URL end *****/
|
||||||
|
(*PtrSrc)++; // Points to first character after http:// or https://
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
NumChars1 = Str_GetNextASCIICharFromStr (PtrSrc,&Ch);
|
NumChars1 = Str_GetNextASCIICharFromStr ((*PtrSrc),&Ch);
|
||||||
PtrSrc += NumChars1;
|
(*PtrSrc) += NumChars1;
|
||||||
if (Ch <= 32 || Ch == '<' || Ch == '"')
|
if (Ch <= 32 || Ch == '<' || Ch == '"')
|
||||||
{
|
{
|
||||||
Links[NumLinks].PtrEnd = PtrSrc - NumChars1 - 1;
|
PtrEnd = (*PtrSrc) - NumChars1 - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (Ch == ',' || Ch == '.' || Ch == ';' || Ch == ':' || Ch == ')' || Ch == ']' || Ch == '}')
|
else if (Ch == ',' || Ch == '.' || Ch == ';' || Ch == ':' ||
|
||||||
|
Ch == ')' || Ch == ']' || Ch == '}')
|
||||||
{
|
{
|
||||||
NumChars2 = Str_GetNextASCIICharFromStr (PtrSrc,&Ch);
|
NumChars2 = Str_GetNextASCIICharFromStr ((*PtrSrc),&Ch);
|
||||||
PtrSrc += NumChars2;
|
(*PtrSrc) += NumChars2;
|
||||||
if (Ch <= 32 || Ch == '<' || Ch == '"')
|
if (Ch <= 32 || Ch == '<' || Ch == '"')
|
||||||
{
|
{
|
||||||
Links[NumLinks].PtrEnd = PtrSrc - NumChars2 - NumChars1 - 1;
|
PtrEnd = (*PtrSrc) - NumChars2 - NumChars1 - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize anchors for this link */
|
/***** Calculate length of this URL *****/
|
||||||
Links[NumLinks].Anchor1Nick = NULL;
|
(*Link)->AddedLengthUntilHere = (*Link)->Prev ? (*Link)->Prev->AddedLengthUntilHere : 0;
|
||||||
Links[NumLinks].Anchor2Nick = NULL;
|
(*Link)->URLorNick.Len = (size_t) (PtrEnd + 1 - (*Link)->URLorNick.Str);
|
||||||
|
if ((*Link)->URLorNick.Len <= MaxCharsURLOnScreen)
|
||||||
/* Calculate length of this URL */
|
(*Link)->AddedLengthUntilHere += ANCHOR_URL_TOTAL_LENGTH +
|
||||||
Links[NumLinks].NumActualBytes = (size_t) (Links[NumLinks].PtrEnd + 1 - Links[NumLinks].PtrStart);
|
(*Link)->URLorNick.Len;
|
||||||
if (Links[NumLinks].NumActualBytes <= MaxCharsURLOnScreen)
|
|
||||||
LengthVisibleLink = Links[NumLinks].NumActualBytes;
|
|
||||||
else // If URL is too long to be displayed ==> short it
|
else // If URL is too long to be displayed ==> short it
|
||||||
{
|
{
|
||||||
/* Make a copy of this URL */
|
/***** Limit the length of URL and calculate its length in bytes *****/
|
||||||
NumBytesToCopy = (Links[NumLinks].NumActualBytes < MAX_BYTES_LIMITED_URL) ? Links[NumLinks].NumActualBytes :
|
if ((Limited = malloc ((*Link)->URLorNick.Len + 1)) == NULL)
|
||||||
MAX_BYTES_LIMITED_URL;
|
Err_NotEnoughMemoryExit ();
|
||||||
strncpy (LimitedURL,Links[NumLinks].PtrStart,NumBytesToCopy);
|
strncpy (Limited,(*Link)->URLorNick.Str,(*Link)->URLorNick.Len);
|
||||||
LimitedURL[NumBytesToCopy] = '\0';
|
Limited[(*Link)->URLorNick.Len] = '\0';
|
||||||
|
(*Link)->AddedLengthUntilHere += ANCHOR_URL_TOTAL_LENGTH +
|
||||||
|
Str_LimitLengthHTMLStr (Limited,MaxCharsURLOnScreen);
|
||||||
|
free (Limited);
|
||||||
|
}
|
||||||
|
|
||||||
/* Limit the number of characters on screen of the copy, and calculate its length in bytes */
|
/***** Create next link *****/
|
||||||
LengthVisibleLink = Str_LimitLengthHTMLStr (LimitedURL,MaxCharsURLOnScreen);
|
Str_CreateNextLink (Link,LastLink);
|
||||||
}
|
}
|
||||||
if (NumLinks == 0)
|
|
||||||
Links[NumLinks].AddedLengthUntilHere = AnchorURLTotalLength + LengthVisibleLink;
|
|
||||||
else
|
|
||||||
Links[NumLinks].AddedLengthUntilHere = Links[NumLinks - 1].AddedLengthUntilHere +
|
|
||||||
AnchorURLTotalLength + LengthVisibleLink;
|
|
||||||
|
|
||||||
/* Increment number of found links */
|
return true;
|
||||||
NumLinks++;
|
|
||||||
if (NumLinks == MAX_LINKS)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
/* Check if the next char is the start of a nickname */
|
|
||||||
else if ((int) *PtrSrc == (int) '@')
|
/************************* Check if a nickname found *************************/
|
||||||
|
|
||||||
|
static bool Str_CheckNickname (char **PtrSrc,
|
||||||
|
struct Str_Link **Link,
|
||||||
|
struct Str_Link **LastLink)
|
||||||
{
|
{
|
||||||
Links[NumLinks].PtrStart = PtrSrc;
|
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
|
||||||
|
size_t Length;
|
||||||
|
char ParamsStr[Frm_MAX_BYTES_PARAMS_STR];
|
||||||
|
|
||||||
/* Find nickname end */
|
/***** Check if the next char is the start of a nickname *****/
|
||||||
PtrSrc++; // Points to first character after @
|
if ((int) *(*PtrSrc) == (int) '@')
|
||||||
|
{
|
||||||
|
(*Link)->URLorNick.Str = (*PtrSrc);
|
||||||
|
|
||||||
/* A nick can have digits, letters and '_' */
|
/***** Find nickname end *****/
|
||||||
|
(*PtrSrc)++; // Points to first character after @
|
||||||
|
|
||||||
|
/***** A nick can have digits, letters and '_' *****/
|
||||||
for (;
|
for (;
|
||||||
*PtrSrc;
|
*(*PtrSrc);
|
||||||
PtrSrc++)
|
(*PtrSrc)++)
|
||||||
if (!((*PtrSrc >= 'a' && *PtrSrc <= 'z') ||
|
if (!((*(*PtrSrc) >= 'a' && *(*PtrSrc) <= 'z') ||
|
||||||
(*PtrSrc >= 'A' && *PtrSrc <= 'Z') ||
|
(*(*PtrSrc) >= 'A' && *(*PtrSrc) <= 'Z') ||
|
||||||
(*PtrSrc >= '0' && *PtrSrc <= '9') ||
|
(*(*PtrSrc) >= '0' && *(*PtrSrc) <= '9') ||
|
||||||
(*PtrSrc == '_')))
|
(*(*PtrSrc) == '_')))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Calculate length of this nickname */
|
/***** Calculate length of this nickname *****/
|
||||||
Links[NumLinks].PtrEnd = PtrSrc - 1;
|
(*Link)->URLorNick.Len = (size_t) ((*PtrSrc) - (*Link)->URLorNick.Str);
|
||||||
Links[NumLinks].NumActualBytes = (size_t) (PtrSrc - Links[NumLinks].PtrStart);
|
|
||||||
|
|
||||||
/* A nick (without arroba) must have a number of characters
|
/***** A nick (without arroba) must have a number of characters
|
||||||
Nck_MIN_CHARS_NICK_WITHOUT_ARROBA <= Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA */
|
Nck_MIN_CHARS_NICK_WITHOUT_ARROBA <= Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA *****/
|
||||||
Length = Links[NumLinks].NumActualBytes - 1; // Do not count the initial @
|
Length = (*Link)->URLorNick.Len - 1; // Do not count the initial @
|
||||||
IsNickname = (Length >= Nck_MIN_CHARS_NICK_WITHOUT_ARROBA &&
|
if (Length >= Nck_MIN_CHARS_NICK_WITHOUT_ARROBA &&
|
||||||
Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA);
|
Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA)
|
||||||
|
(*Link)->Type = Str_LINK_NICK;
|
||||||
|
|
||||||
if (IsNickname)
|
if ((*Link)->Type == Str_LINK_NICK)
|
||||||
{
|
{
|
||||||
/* Initialize anchors for this link */
|
/***** Create id for this form *****/
|
||||||
Links[NumLinks].Anchor1Nick = NULL;
|
|
||||||
Links[NumLinks].Anchor2Nick = NULL;
|
|
||||||
|
|
||||||
/* Create id for this form */
|
|
||||||
Gbl.Form.Num++;
|
Gbl.Form.Num++;
|
||||||
if (Gbl.Usrs.Me.Logged)
|
if (Gbl.Usrs.Me.Logged)
|
||||||
snprintf (Gbl.Form.UniqueId,sizeof (Gbl.Form.UniqueId),
|
snprintf (Gbl.Form.UniqueId,sizeof (Gbl.Form.UniqueId),
|
||||||
|
@ -304,178 +497,62 @@ void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScre
|
||||||
snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),
|
snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),
|
||||||
"form_%d",Gbl.Form.Num);
|
"form_%d",Gbl.Form.Num);
|
||||||
|
|
||||||
/* Store first part of anchor */
|
/***** Store first part of anchor *****/
|
||||||
Frm_SetParamsForm (ParamsStr,ActSeeOthPubPrf,true);
|
Frm_SetParamsForm (ParamsStr,ActSeeOthPubPrf,true);
|
||||||
snprintf (Anchor1Nick,sizeof (Anchor1Nick),
|
if (asprintf (&(*Link)->AnchorNick1.Str,
|
||||||
"<form method=\"post\" action=\"%s/%s\" id=\"%s\">"
|
"<form method=\"post\" action=\"%s/%s\" id=\"%s\">"
|
||||||
"%s"
|
"%s" // Parameters
|
||||||
"<input type=\"hidden\" name=\"usr\" value=\"",
|
"<input type=\"hidden\" name=\"usr\" value=\"",
|
||||||
Cfg_URL_SWAD_CGI,
|
Cfg_URL_SWAD_CGI,
|
||||||
Lan_STR_LANG_ID[Gbl.Prefs.Language],
|
Lan_STR_LANG_ID[Gbl.Prefs.Language],
|
||||||
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
|
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
|
||||||
Gbl.Form.Id,
|
Gbl.Form.Id,
|
||||||
ParamsStr);
|
ParamsStr) < 0)
|
||||||
Anchor1NickLength = strlen (Anchor1Nick);
|
|
||||||
if ((Links[NumLinks].Anchor1Nick = malloc (Anchor1NickLength + 1)) == NULL)
|
|
||||||
Err_NotEnoughMemoryExit ();
|
Err_NotEnoughMemoryExit ();
|
||||||
strcpy (Links[NumLinks].Anchor1Nick,Anchor1Nick);
|
(*Link)->AnchorNick1.Len = strlen ((*Link)->AnchorNick1.Str);
|
||||||
Links[NumLinks].Anchor1NickLength = Anchor1NickLength;
|
|
||||||
|
|
||||||
/* Store second part of anchor */
|
/***** Store second part of anchor *****/
|
||||||
snprintf (Anchor2Nick,sizeof (Anchor2Nick),
|
if (asprintf (&(*Link)->AnchorNick2.Str,
|
||||||
"\">"
|
"\">"
|
||||||
"<a href=\"\""
|
"<a href=\"\""
|
||||||
" onclick=\"document.getElementById('%s').submit();return false;\">",
|
" onclick=\"document.getElementById('%s').submit();return false;\">",
|
||||||
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
|
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
|
||||||
Gbl.Form.Id);
|
Gbl.Form.Id) < 0)
|
||||||
Anchor2NickLength = strlen (Anchor2Nick);
|
|
||||||
if ((Links[NumLinks].Anchor2Nick = malloc (Anchor2NickLength + 1)) == NULL)
|
|
||||||
Err_NotEnoughMemoryExit ();
|
Err_NotEnoughMemoryExit ();
|
||||||
strcpy (Links[NumLinks].Anchor2Nick,Anchor2Nick);
|
(*Link)->AnchorNick2.Len = strlen ((*Link)->AnchorNick2.Str);
|
||||||
Links[NumLinks].Anchor2NickLength = Anchor2NickLength;
|
|
||||||
|
|
||||||
AnchorNickTotalLength = Anchor1NickLength + Anchor2NickLength + Anchor3NickLength;
|
(*Link)->AddedLengthUntilHere = (*Link)->Prev ? (*Link)->Prev->AddedLengthUntilHere : 0;
|
||||||
|
(*Link)->AddedLengthUntilHere += (*Link)->AnchorNick1.Len +
|
||||||
|
(*Link)->AnchorNick2.Len +
|
||||||
|
AnchorNick3.Len +
|
||||||
|
(*Link)->URLorNick.Len;
|
||||||
|
|
||||||
LengthVisibleLink = Links[NumLinks].NumActualBytes;
|
/***** Create next link *****/
|
||||||
if (NumLinks == 0)
|
Str_CreateNextLink (Link,LastLink);
|
||||||
Links[NumLinks].AddedLengthUntilHere = AnchorNickTotalLength + LengthVisibleLink;
|
|
||||||
else
|
|
||||||
Links[NumLinks].AddedLengthUntilHere = Links[NumLinks - 1].AddedLengthUntilHere +
|
|
||||||
AnchorNickTotalLength + LengthVisibleLink;
|
|
||||||
|
|
||||||
/* Increment number of found links */
|
|
||||||
NumLinks++;
|
|
||||||
if (NumLinks == MAX_LINKS)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/* The next char is not the start of URL or nickname */
|
|
||||||
else // Character distinct to 'h' or '@'
|
|
||||||
PtrSrc++;
|
|
||||||
|
|
||||||
/**********************************************************************/
|
return true;
|
||||||
/***** If there are one or more links (URLs or nicknames) in text *****/
|
|
||||||
/**********************************************************************/
|
|
||||||
if (NumLinks)
|
|
||||||
{
|
|
||||||
/***** Insert links from end to start of text,
|
|
||||||
only if there is enough space available in text *****/
|
|
||||||
TxtLengthWithInsertedAnchors = TxtLength + Links[NumLinks - 1].AddedLengthUntilHere;
|
|
||||||
if (TxtLengthWithInsertedAnchors <= MaxLength)
|
|
||||||
for (NumLink = NumLinks - 1;
|
|
||||||
NumLink >= 0;
|
|
||||||
NumLink--)
|
|
||||||
{
|
|
||||||
IsNickname = (*(Links[NumLink].PtrStart) == '@');
|
|
||||||
|
|
||||||
/***** Step 1: Move forward the text after the link (URL or nickname)
|
|
||||||
(it's mandatory to do the copy in reverse order
|
|
||||||
to avoid overwriting source) *****/
|
|
||||||
for (i = 0,
|
|
||||||
PtrSrc = (NumLink == NumLinks - 1) ? Txt + TxtLength :
|
|
||||||
Links[NumLink + 1].PtrStart - 1,
|
|
||||||
PtrDst = PtrSrc + Links[NumLink].AddedLengthUntilHere,
|
|
||||||
Length = PtrSrc - Links[NumLink].PtrEnd;
|
|
||||||
i < Length;
|
|
||||||
i++)
|
|
||||||
*PtrDst-- = *PtrSrc--;
|
|
||||||
|
|
||||||
/***** Step 2: Insert ANCHOR_3_NICK or ANCHOR_3_URL *****/
|
|
||||||
if (IsNickname)
|
|
||||||
{
|
|
||||||
Length = Anchor3NickLength;
|
|
||||||
PtrSrc = ANCHOR_3_NICK + Length - 1;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return false;
|
||||||
Length = Anchor3URLLength;
|
|
||||||
PtrSrc = ANCHOR_3_URL + Length - 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************** Copy source substring to destination, backwards **************/
|
||||||
|
|
||||||
|
static void Str_InsertSubstring (const struct Str_Substring *PtrSrc,char **PtrDst)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
char *PtrSrcStart;
|
||||||
|
char *PtrDstStart;
|
||||||
|
size_t Len = PtrSrc->Len;
|
||||||
|
|
||||||
|
*PtrDst -= Len; // Update destination pointer
|
||||||
|
PtrSrcStart = PtrSrc->Str;
|
||||||
|
PtrDstStart = *PtrDst + 1;
|
||||||
for (i = 0;
|
for (i = 0;
|
||||||
i < Length;
|
i < Len;
|
||||||
i++)
|
i++)
|
||||||
*PtrDst-- = *PtrSrc--;
|
*PtrDstStart++ = *PtrSrcStart++;
|
||||||
|
|
||||||
/***** Step 3: Move forward the link (URL or nickname)
|
|
||||||
to be shown on screen *****/
|
|
||||||
if (IsNickname ||
|
|
||||||
Links[NumLink].NumActualBytes <= MaxCharsURLOnScreen)
|
|
||||||
{
|
|
||||||
NumBytesToShow = Links[NumLink].NumActualBytes;
|
|
||||||
PtrSrc = Links[NumLink].PtrEnd; // PtrSrc must point to end of complete nickname
|
|
||||||
}
|
|
||||||
else // If URL is too long to be displayed ==> short it
|
|
||||||
{
|
|
||||||
/* Make a copy of this URL */
|
|
||||||
NumBytesToCopy = (Links[NumLink].NumActualBytes < MAX_BYTES_LIMITED_URL) ? Links[NumLink].NumActualBytes :
|
|
||||||
MAX_BYTES_LIMITED_URL;
|
|
||||||
strncpy (LimitedURL,Links[NumLink].PtrStart,NumBytesToCopy);
|
|
||||||
LimitedURL[NumBytesToCopy] = '\0';
|
|
||||||
|
|
||||||
/* Limit the length of the copy */
|
|
||||||
NumBytesToShow = Str_LimitLengthHTMLStr (LimitedURL,MaxCharsURLOnScreen);
|
|
||||||
|
|
||||||
PtrSrc = LimitedURL + NumBytesToShow - 1; // PtrSrc must point to end of limited URL
|
|
||||||
}
|
|
||||||
for (i = 0;
|
|
||||||
i < NumBytesToShow;
|
|
||||||
i++)
|
|
||||||
*PtrDst-- = *PtrSrc--;
|
|
||||||
|
|
||||||
/***** Step 4: Insert Anchor2Nick or ANCHOR_2_URL *****/
|
|
||||||
if (IsNickname)
|
|
||||||
{
|
|
||||||
Length = Links[NumLink].Anchor2NickLength;
|
|
||||||
PtrSrc = Links[NumLink].Anchor2Nick + Length - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Length = Anchor2URLLength;
|
|
||||||
PtrSrc = ANCHOR_2_URL + Length - 1;
|
|
||||||
}
|
|
||||||
for (i = 0;
|
|
||||||
i < Length;
|
|
||||||
i++)
|
|
||||||
*PtrDst-- = *PtrSrc--;
|
|
||||||
|
|
||||||
/***** Step 5: Insert link into directive A
|
|
||||||
(it's mandatory to do the copy in reverse order
|
|
||||||
to avoid overwriting source URL or nickname) *****/
|
|
||||||
for (i = 0, PtrSrc = Links[NumLink].PtrEnd;
|
|
||||||
i < Links[NumLink].NumActualBytes;
|
|
||||||
i++)
|
|
||||||
*PtrDst-- = *PtrSrc--;
|
|
||||||
|
|
||||||
/***** Step 6: Insert Anchor1Nick or ANCHOR_1_URL *****/
|
|
||||||
if (IsNickname)
|
|
||||||
{
|
|
||||||
Length = Links[NumLink].Anchor1NickLength;
|
|
||||||
PtrSrc = Links[NumLink].Anchor1Nick + Length - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Length = Anchor1URLLength;
|
|
||||||
PtrSrc = ANCHOR_1_URL + Length - 1;
|
|
||||||
}
|
|
||||||
for (i = 0;
|
|
||||||
i < Length;
|
|
||||||
i++)
|
|
||||||
*PtrDst-- = *PtrSrc--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************/
|
|
||||||
/***** Free memory for anchors *****/
|
|
||||||
/***********************************/
|
|
||||||
for (NumLink = 0;
|
|
||||||
NumLink < NumLinks;
|
|
||||||
NumLink++)
|
|
||||||
{
|
|
||||||
if (Links[NumLink].Anchor1Nick)
|
|
||||||
free (Links[NumLink].Anchor1Nick);
|
|
||||||
if (Links[NumLink].Anchor2Nick)
|
|
||||||
free (Links[NumLink].Anchor2Nick);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
@ -304,7 +304,7 @@ void Tml_RefreshNewTimelineGbl (void)
|
||||||
/***** Get which users *****/
|
/***** Get which users *****/
|
||||||
Timeline.Who = Tml_Who_GetGlobalWho ();
|
Timeline.Who = Tml_Who_GetGlobalWho ();
|
||||||
|
|
||||||
/***** Get list of pubications to show in timeline *****/
|
/***** Get list of publications to show in timeline *****/
|
||||||
Timeline.UsrOrGbl = Tml_Usr_TIMELINE_GBL;
|
Timeline.UsrOrGbl = Tml_Usr_TIMELINE_GBL;
|
||||||
Timeline.WhatToGet = Tml_GET_NEW_PUBS;
|
Timeline.WhatToGet = Tml_GET_NEW_PUBS;
|
||||||
Tml_Pub_GetListPubsToShowInTimeline (&Timeline);
|
Tml_Pub_GetListPubsToShowInTimeline (&Timeline);
|
||||||
|
|
|
@ -631,7 +631,7 @@ static void Tml_Com_WriteContent (struct Tml_Com_Comment *Com)
|
||||||
if (Com->Content.Txt[0])
|
if (Com->Content.Txt[0])
|
||||||
{
|
{
|
||||||
HTM_DIV_Begin ("class=\"Tml_TXT\"");
|
HTM_DIV_Begin ("class=\"Tml_TXT\"");
|
||||||
Msg_WriteMsgContent (Com->Content.Txt,Cns_MAX_BYTES_LONG_TEXT,true,false);
|
Msg_WriteMsgContent (Com->Content.Txt,true,false);
|
||||||
HTM_DIV_End ();
|
HTM_DIV_End ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -290,14 +290,13 @@ static void Tml_Not_WriteNote (const struct Tml_Timeline *Timeline,
|
||||||
|
|
||||||
void Tml_Not_ShowAuthorPhoto (struct UsrData *UsrDat,bool FormUnique)
|
void Tml_Not_ShowAuthorPhoto (struct UsrData *UsrDat,bool FormUnique)
|
||||||
{
|
{
|
||||||
/***** Show author's photo *****/
|
/***** Begin container *****/
|
||||||
/* Begin container */
|
|
||||||
HTM_DIV_Begin ("class=\"Tml_LEFT_PHOTO\"");
|
HTM_DIV_Begin ("class=\"Tml_LEFT_PHOTO\"");
|
||||||
|
|
||||||
/* Photo */
|
/***** Photo *****/
|
||||||
Pho_ShowUsrPhotoIfAllowed (UsrDat,"PHOTO45x60",Pho_ZOOM,FormUnique);
|
Pho_ShowUsrPhotoIfAllowed (UsrDat,"PHOTO45x60",Pho_ZOOM,FormUnique);
|
||||||
|
|
||||||
/* End container */
|
/***** End container *****/
|
||||||
HTM_DIV_End ();
|
HTM_DIV_End ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ static void Tml_Pst_ShowPostContent (struct Tml_Pst_Content *Content)
|
||||||
if (Content->Txt[0])
|
if (Content->Txt[0])
|
||||||
{
|
{
|
||||||
HTM_DIV_Begin ("class=\"Tml_TXT\"");
|
HTM_DIV_Begin ("class=\"Tml_TXT\"");
|
||||||
Msg_WriteMsgContent (Content->Txt,Cns_MAX_BYTES_LONG_TEXT,true,false);
|
Msg_WriteMsgContent (Content->Txt,true,false);
|
||||||
HTM_DIV_End ();
|
HTM_DIV_End ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user