Version 21.60: Nov 24, 2021 Code refactoring inserting links in a string.

This commit is contained in:
acanas 2021-11-24 01:20:08 +01:00
parent 534f147a3c
commit 14f64fd450
16 changed files with 432 additions and 353 deletions

View File

@ -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)

View File

@ -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,

View File

@ -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]);

View File

@ -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");

View File

@ -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
{ {

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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]);

View File

@ -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)

View File

@ -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);

View File

@ -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);
}
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -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);

View File

@ -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 ();
} }

View File

@ -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 ();
} }

View File

@ -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 ();
} }