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,386 +140,421 @@ 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... PtrSrc++;
{ }
if (tolower ((int) *++PtrSrc) == (int) 't') // htt...
{
if (tolower ((int) *++PtrSrc) == (int) 'p') // http...
{
PtrSrc++;
if (*PtrSrc == ':') // http:...
{
if (*++PtrSrc == '/') // http:/...
if (*++PtrSrc == '/') // http://...
URLStartFound = true;
}
else if (tolower ((int) *PtrSrc) == (int) 's') // https...
{
if (*++PtrSrc == ':') // https:...
{
if (*++PtrSrc == '/') // https:/...
if (*++PtrSrc == '/') // https://...
URLStartFound = true;
}
}
}
}
}
if (URLStartFound)
{
/* Find URL end */
PtrSrc++; // Points to first character after http:// or https://
for (;;)
{
NumChars1 = Str_GetNextASCIICharFromStr (PtrSrc,&Ch);
PtrSrc += NumChars1;
if (Ch <= 32 || Ch == '<' || Ch == '"')
{
Links[NumLinks].PtrEnd = PtrSrc - NumChars1 - 1;
break;
}
else if (Ch == ',' || Ch == '.' || Ch == ';' || Ch == ':' || Ch == ')' || Ch == ']' || Ch == '}')
{
NumChars2 = Str_GetNextASCIICharFromStr (PtrSrc,&Ch);
PtrSrc += NumChars2;
if (Ch <= 32 || Ch == '<' || Ch == '"')
{
Links[NumLinks].PtrEnd = PtrSrc - NumChars2 - NumChars1 - 1;
break;
}
}
}
/* Initialize anchors for this link */
Links[NumLinks].Anchor1Nick = NULL;
Links[NumLinks].Anchor2Nick = NULL;
/* Calculate length of this URL */
Links[NumLinks].NumActualBytes = (size_t) (Links[NumLinks].PtrEnd + 1 - Links[NumLinks].PtrStart);
if (Links[NumLinks].NumActualBytes <= MaxCharsURLOnScreen)
LengthVisibleLink = Links[NumLinks].NumActualBytes;
else // If URL is too long to be displayed ==> short it
{
/* Make a copy of this URL */
NumBytesToCopy = (Links[NumLinks].NumActualBytes < MAX_BYTES_LIMITED_URL) ? Links[NumLinks].NumActualBytes :
MAX_BYTES_LIMITED_URL;
strncpy (LimitedURL,Links[NumLinks].PtrStart,NumBytesToCopy);
LimitedURL[NumBytesToCopy] = '\0';
/* Limit the number of characters on screen of the copy, and calculate its length in bytes */
LengthVisibleLink = Str_LimitLengthHTMLStr (LimitedURL,MaxCharsURLOnScreen);
}
if (NumLinks == 0)
Links[NumLinks].AddedLengthUntilHere = AnchorURLTotalLength + LengthVisibleLink;
else
Links[NumLinks].AddedLengthUntilHere = Links[NumLinks - 1].AddedLengthUntilHere +
AnchorURLTotalLength + LengthVisibleLink;
/* Increment number of found links */
NumLinks++;
if (NumLinks == MAX_LINKS)
break;
}
}
/* Check if the next char is the start of a nickname */
else if ((int) *PtrSrc == (int) '@')
{
Links[NumLinks].PtrStart = PtrSrc;
/* Find nickname end */
PtrSrc++; // Points to first character after @
/* A nick can have digits, letters and '_' */
for (;
*PtrSrc;
PtrSrc++)
if (!((*PtrSrc >= 'a' && *PtrSrc <= 'z') ||
(*PtrSrc >= 'A' && *PtrSrc <= 'Z') ||
(*PtrSrc >= '0' && *PtrSrc <= '9') ||
(*PtrSrc == '_')))
break;
/* Calculate length of this nickname */
Links[NumLinks].PtrEnd = PtrSrc - 1;
Links[NumLinks].NumActualBytes = (size_t) (PtrSrc - Links[NumLinks].PtrStart);
/* A nick (without arroba) must have a number of characters
Nck_MIN_CHARS_NICK_WITHOUT_ARROBA <= Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA */
Length = Links[NumLinks].NumActualBytes - 1; // Do not count the initial @
IsNickname = (Length >= Nck_MIN_CHARS_NICK_WITHOUT_ARROBA &&
Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA);
if (IsNickname)
{
/* Initialize anchors for this link */
Links[NumLinks].Anchor1Nick = NULL;
Links[NumLinks].Anchor2Nick = NULL;
/* Create id for this form */
Gbl.Form.Num++;
if (Gbl.Usrs.Me.Logged)
snprintf (Gbl.Form.UniqueId,sizeof (Gbl.Form.UniqueId),
"form_%s_%d",Gbl.UniqueNameEncrypted,Gbl.Form.Num);
else
snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),
"form_%d",Gbl.Form.Num);
/* Store first part of anchor */
Frm_SetParamsForm (ParamsStr,ActSeeOthPubPrf,true);
snprintf (Anchor1Nick,sizeof (Anchor1Nick),
"<form method=\"post\" action=\"%s/%s\" id=\"%s\">"
"%s"
"<input type=\"hidden\" name=\"usr\" value=\"",
Cfg_URL_SWAD_CGI,
Lan_STR_LANG_ID[Gbl.Prefs.Language],
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
Gbl.Form.Id,
ParamsStr);
Anchor1NickLength = strlen (Anchor1Nick);
if ((Links[NumLinks].Anchor1Nick = malloc (Anchor1NickLength + 1)) == NULL)
Err_NotEnoughMemoryExit ();
strcpy (Links[NumLinks].Anchor1Nick,Anchor1Nick);
Links[NumLinks].Anchor1NickLength = Anchor1NickLength;
/* Store second part of anchor */
snprintf (Anchor2Nick,sizeof (Anchor2Nick),
"\">"
"<a href=\"\""
" onclick=\"document.getElementById('%s').submit();return false;\">",
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
Gbl.Form.Id);
Anchor2NickLength = strlen (Anchor2Nick);
if ((Links[NumLinks].Anchor2Nick = malloc (Anchor2NickLength + 1)) == NULL)
Err_NotEnoughMemoryExit ();
strcpy (Links[NumLinks].Anchor2Nick,Anchor2Nick);
Links[NumLinks].Anchor2NickLength = Anchor2NickLength;
AnchorNickTotalLength = Anchor1NickLength + Anchor2NickLength + Anchor3NickLength;
LengthVisibleLink = Links[NumLinks].NumActualBytes;
if (NumLinks == 0)
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++;
/**********************************************************************/ /**********************************************************************/
/***** If there are one or more links (URLs or nicknames) in text *****/ /***** If there are one or more links (URLs or nicknames) in text *****/
/**********************************************************************/ /**********************************************************************/
if (NumLinks) if (LastLink) // Not null ==> one or more links found
{ {
/***** Insert links from end to start of text, /***** Insert links from end to start of text,
only if there is enough space available in text *****/ only if there is enough space available in text *****/
TxtLengthWithInsertedAnchors = TxtLength + Links[NumLinks - 1].AddedLengthUntilHere; TxtLength = strlen (Txt);
if (TxtLengthWithInsertedAnchors <= MaxLength) if (TxtLength + LastLink->AddedLengthUntilHere <= MaxLength)
for (NumLink = NumLinks - 1; for (Link = LastLink;
NumLink >= 0; Link;
NumLink--) Link = Link->Prev)
{ {
IsNickname = (*(Links[NumLink].PtrStart) == '@'); /***** Set anchors *****/
switch (Link->Type)
{
case Str_LINK_URL:
Anchor1 = &AnchorURL1;
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) /***** Step 1: Move forward the text after the link (URL or nickname)
(it's mandatory to do the copy in reverse order (it's mandatory to do the copy in reverse order
to avoid overwriting source) *****/ to avoid overwriting source) *****/
for (i = 0, PtrSrc = (Link == LastLink) ? Txt + TxtLength :
PtrSrc = (NumLink == NumLinks - 1) ? Txt + TxtLength : Link->Next->URLorNick.Str - 1,
Links[NumLink + 1].PtrStart - 1, PtrDst = PtrSrc + Link->AddedLengthUntilHere,
PtrDst = PtrSrc + Links[NumLink].AddedLengthUntilHere, Length = PtrSrc - (Link->URLorNick.Str + Link->URLorNick.Len - 1);
Length = PtrSrc - Links[NumLink].PtrEnd; for (i = 0;
i < Length; i < Length;
i++) i++)
*PtrDst-- = *PtrSrc--; *PtrDst-- = *PtrSrc--;
/***** Step 2: Insert ANCHOR_3_NICK or ANCHOR_3_URL *****/ /***** Step 2: Insert thirs part of anchor *****/
if (IsNickname) Str_InsertSubstring (Anchor3,&PtrDst);
{
Length = Anchor3NickLength;
PtrSrc = ANCHOR_3_NICK + Length - 1;
}
else
{
Length = Anchor3URLLength;
PtrSrc = ANCHOR_3_URL + Length - 1;
}
for (i = 0;
i < Length;
i++)
*PtrDst-- = *PtrSrc--;
/***** Step 3: Move forward the link (URL or nickname) /***** Step 3: Move forward the link (URL or nickname)
to be shown on screen *****/ to be shown on screen *****/
if (IsNickname || switch (Link->Type)
Links[NumLink].NumActualBytes <= MaxCharsURLOnScreen)
{ {
NumBytesToShow = Links[NumLink].NumActualBytes; case Str_LINK_URL:
PtrSrc = Links[NumLink].PtrEnd; // PtrSrc must point to end of complete nickname 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;
} }
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 */ /***** Step 4: Insert second part of anchor *****/
NumBytesToShow = Str_LimitLengthHTMLStr (LimitedURL,MaxCharsURLOnScreen); Str_InsertSubstring (Anchor2,&PtrDst);
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 /***** Step 5: Insert link into directive A
(it's mandatory to do the copy in reverse order (it's mandatory to do the copy in reverse order
to avoid overwriting source URL or nickname) *****/ to avoid overwriting source URL or nickname) *****/
for (i = 0, PtrSrc = Links[NumLink].PtrEnd; Str_InsertSubstring (&Link->URLorNick,&PtrDst);
i < Links[NumLink].NumActualBytes;
i++)
*PtrDst-- = *PtrSrc--;
/***** Step 6: Insert Anchor1Nick or ANCHOR_1_URL *****/ /***** Step 6: Insert first part of anchor *****/
if (IsNickname) Str_InsertSubstring (Anchor1,&PtrDst);
{
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 *****/ /***** Free memory for anchors *****/
/***********************************/ /***********************************/
for (NumLink = 0; Str_FreeLinks (LastLink);
NumLink < NumLinks; }
NumLink++)
/***************************** 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)
{ {
if (Links[NumLink].Anchor1Nick) PrevLink = Link->Prev;
free (Links[NumLink].Anchor1Nick); free (Link);
if (Links[NumLink].Anchor2Nick)
free (Links[NumLink].Anchor2Nick);
} }
} }
/**************************** 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 (;;)
{
NumChars1 = Str_GetNextASCIICharFromStr ((*PtrSrc),&Ch);
(*PtrSrc) += NumChars1;
if (Ch <= 32 || Ch == '<' || Ch == '"')
{
PtrEnd = (*PtrSrc) - NumChars1 - 1;
break;
}
else if (Ch == ',' || Ch == '.' || Ch == ';' || Ch == ':' ||
Ch == ')' || Ch == ']' || Ch == '}')
{
NumChars2 = Str_GetNextASCIICharFromStr ((*PtrSrc),&Ch);
(*PtrSrc) += NumChars2;
if (Ch <= 32 || Ch == '<' || Ch == '"')
{
PtrEnd = (*PtrSrc) - NumChars2 - NumChars1 - 1;
break;
}
}
}
/***** Calculate length of this URL *****/
(*Link)->AddedLengthUntilHere = (*Link)->Prev ? (*Link)->Prev->AddedLengthUntilHere : 0;
(*Link)->URLorNick.Len = (size_t) (PtrEnd + 1 - (*Link)->URLorNick.Str);
if ((*Link)->URLorNick.Len <= MaxCharsURLOnScreen)
(*Link)->AddedLengthUntilHere += ANCHOR_URL_TOTAL_LENGTH +
(*Link)->URLorNick.Len;
else // If URL is too long to be displayed ==> short it
{
/***** Limit the length of URL and calculate its length in bytes *****/
if ((Limited = malloc ((*Link)->URLorNick.Len + 1)) == NULL)
Err_NotEnoughMemoryExit ();
strncpy (Limited,(*Link)->URLorNick.Str,(*Link)->URLorNick.Len);
Limited[(*Link)->URLorNick.Len] = '\0';
(*Link)->AddedLengthUntilHere += ANCHOR_URL_TOTAL_LENGTH +
Str_LimitLengthHTMLStr (Limited,MaxCharsURLOnScreen);
free (Limited);
}
/***** Create next link *****/
Str_CreateNextLink (Link,LastLink);
}
return true;
}
return false;
}
/************************* Check if a nickname found *************************/
static bool Str_CheckNickname (char **PtrSrc,
struct Str_Link **Link,
struct Str_Link **LastLink)
{
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
size_t Length;
char ParamsStr[Frm_MAX_BYTES_PARAMS_STR];
/***** Check if the next char is the start of a nickname *****/
if ((int) *(*PtrSrc) == (int) '@')
{
(*Link)->URLorNick.Str = (*PtrSrc);
/***** Find nickname end *****/
(*PtrSrc)++; // Points to first character after @
/***** A nick can have digits, letters and '_' *****/
for (;
*(*PtrSrc);
(*PtrSrc)++)
if (!((*(*PtrSrc) >= 'a' && *(*PtrSrc) <= 'z') ||
(*(*PtrSrc) >= 'A' && *(*PtrSrc) <= 'Z') ||
(*(*PtrSrc) >= '0' && *(*PtrSrc) <= '9') ||
(*(*PtrSrc) == '_')))
break;
/***** Calculate length of this nickname *****/
(*Link)->URLorNick.Len = (size_t) ((*PtrSrc) - (*Link)->URLorNick.Str);
/***** A nick (without arroba) must have a number of characters
Nck_MIN_CHARS_NICK_WITHOUT_ARROBA <= Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA *****/
Length = (*Link)->URLorNick.Len - 1; // Do not count the initial @
if (Length >= Nck_MIN_CHARS_NICK_WITHOUT_ARROBA &&
Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA)
(*Link)->Type = Str_LINK_NICK;
if ((*Link)->Type == Str_LINK_NICK)
{
/***** Create id for this form *****/
Gbl.Form.Num++;
if (Gbl.Usrs.Me.Logged)
snprintf (Gbl.Form.UniqueId,sizeof (Gbl.Form.UniqueId),
"form_%s_%d",Gbl.UniqueNameEncrypted,Gbl.Form.Num);
else
snprintf (Gbl.Form.Id,sizeof (Gbl.Form.Id),
"form_%d",Gbl.Form.Num);
/***** Store first part of anchor *****/
Frm_SetParamsForm (ParamsStr,ActSeeOthPubPrf,true);
if (asprintf (&(*Link)->AnchorNick1.Str,
"<form method=\"post\" action=\"%s/%s\" id=\"%s\">"
"%s" // Parameters
"<input type=\"hidden\" name=\"usr\" value=\"",
Cfg_URL_SWAD_CGI,
Lan_STR_LANG_ID[Gbl.Prefs.Language],
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
Gbl.Form.Id,
ParamsStr) < 0)
Err_NotEnoughMemoryExit ();
(*Link)->AnchorNick1.Len = strlen ((*Link)->AnchorNick1.Str);
/***** Store second part of anchor *****/
if (asprintf (&(*Link)->AnchorNick2.Str,
"\">"
"<a href=\"\""
" onclick=\"document.getElementById('%s').submit();return false;\">",
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
Gbl.Form.Id) < 0)
Err_NotEnoughMemoryExit ();
(*Link)->AnchorNick2.Len = strlen ((*Link)->AnchorNick2.Str);
(*Link)->AddedLengthUntilHere = (*Link)->Prev ? (*Link)->Prev->AddedLengthUntilHere : 0;
(*Link)->AddedLengthUntilHere += (*Link)->AnchorNick1.Len +
(*Link)->AnchorNick2.Len +
AnchorNick3.Len +
(*Link)->URLorNick.Len;
/***** Create next link *****/
Str_CreateNextLink (Link,LastLink);
}
return true;
}
return false;
}
/************** 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;
i < Len;
i++)
*PtrDstStart++ = *PtrSrcStart++;
}
/*****************************************************************************/ /*****************************************************************************/
/** Get next ASCII character from a string converting &#number; to character */ /** Get next ASCII character from a string converting &#number; to character */
/*****************************************************************************/ /*****************************************************************************/

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