mirror of https://github.com/acanas/swad-core.git
Version 21.64: Nov 28, 2021 New module swad_autolink to insert links in texts.
This commit is contained in:
parent
5517a2d430
commit
c4ab84c2c7
2
Makefile
2
Makefile
|
@ -30,7 +30,7 @@ OBJS = swad_account.o swad_account_database.o swad_action.o swad_admin.o \
|
||||||
swad_admin_database.o swad_agenda.o swad_agenda_database.o swad_alert.o \
|
swad_admin_database.o swad_agenda.o swad_agenda_database.o swad_alert.o \
|
||||||
swad_announcement.o swad_announcement_database.o swad_API.o \
|
swad_announcement.o swad_announcement_database.o swad_API.o \
|
||||||
swad_API_database.o swad_assignment.o swad_assignment_database.o \
|
swad_API_database.o swad_assignment.o swad_assignment_database.o \
|
||||||
swad_attendance.o swad_attendance_database.o \
|
swad_attendance.o swad_attendance_database.o swad_autolink.o \
|
||||||
swad_banner.o swad_banner_database.o swad_box.o swad_browser.o \
|
swad_banner.o swad_banner_database.o swad_box.o swad_browser.o \
|
||||||
swad_browser_database.o swad_building.o swad_building_database.o \
|
swad_browser_database.o swad_building.o swad_building_database.o \
|
||||||
swad_button.o \
|
swad_button.o \
|
||||||
|
|
|
@ -105,6 +105,7 @@ cp -f /home/acanas/swad/swad/swad /var/www/cgi-bin/
|
||||||
#include "swad_API.h"
|
#include "swad_API.h"
|
||||||
#include "swad_API_database.h"
|
#include "swad_API_database.h"
|
||||||
#include "swad_attendance_database.h"
|
#include "swad_attendance_database.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_browser.h"
|
#include "swad_browser.h"
|
||||||
#include "swad_browser_database.h"
|
#include "swad_browser_database.h"
|
||||||
#include "swad_course_database.h"
|
#include "swad_course_database.h"
|
||||||
|
@ -1426,7 +1427,7 @@ static int API_WritePlainTextIntoHTMLBuffer (struct soap *soap,
|
||||||
/* Convert to respectful HTML and insert links */
|
/* Convert to respectful HTML and insert links */
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
TxtHTML,Cns_MAX_BYTES_LONG_TEXT,false); // Convert from HTML to recpectful HTML
|
TxtHTML,Cns_MAX_BYTES_LONG_TEXT,false); // Convert from HTML to recpectful HTML
|
||||||
Str_InsertLinks (TxtHTML,Cns_MAX_BYTES_LONG_TEXT,60); // Insert links
|
ALn_InsertLinks (TxtHTML,Cns_MAX_BYTES_LONG_TEXT,60); // Insert links
|
||||||
|
|
||||||
/* Write text */
|
/* Write text */
|
||||||
fprintf (FileHTMLTmp,"%s",TxtHTML);
|
fprintf (FileHTMLTmp,"%s",TxtHTML);
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <stddef.h> // For NULL
|
#include <stddef.h> // For NULL
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_call_for_exam_database.h"
|
#include "swad_call_for_exam_database.h"
|
||||||
#include "swad_changelog.h"
|
#include "swad_changelog.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
|
@ -199,7 +200,7 @@ static void RSS_WriteNotices (FILE *FileRSS,struct Crs_Course *Crs)
|
||||||
|
|
||||||
/* Write full content of the notice */
|
/* Write full content of the notice */
|
||||||
Str_Copy (Content,row[3],sizeof (Content) - 1);
|
Str_Copy (Content,row[3],sizeof (Content) - 1);
|
||||||
Str_InsertLinks (Content,Cns_MAX_BYTES_TEXT,40);
|
ALn_InsertLinks (Content,Cns_MAX_BYTES_TEXT,40);
|
||||||
fprintf (FileRSS,"<description><![CDATA[<p><em>%s %s %s:</em></p><p>%s</p>]]></description>\n",
|
fprintf (FileRSS,"<description><![CDATA[<p><em>%s %s %s:</em></p><p>%s</p>]]></description>\n",
|
||||||
UsrDat.FrstName,UsrDat.Surname1,UsrDat.Surname2,Content);
|
UsrDat.FrstName,UsrDat.Surname1,UsrDat.Surname2,Content);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include "swad_agenda.h"
|
#include "swad_agenda.h"
|
||||||
#include "swad_agenda_database.h"
|
#include "swad_agenda_database.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_date.h"
|
#include "swad_date.h"
|
||||||
|
@ -860,7 +861,7 @@ static void Agd_ShowOneEvent (struct Agd_Agenda *Agenda,
|
||||||
Agd_DB_GetEventTxt (&AgdEvent,Txt);
|
Agd_DB_GetEventTxt (&AgdEvent,Txt);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
||||||
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
HTM_Txt (Txt);
|
HTM_Txt (Txt);
|
||||||
HTM_DIV_End ();
|
HTM_DIV_End ();
|
||||||
HTM_TD_End ();
|
HTM_TD_End ();
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
#include "swad_announcement.h"
|
#include "swad_announcement.h"
|
||||||
#include "swad_announcement_database.h"
|
#include "swad_announcement_database.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -123,7 +124,7 @@ void Ann_ShowAllAnnouncements (void)
|
||||||
/* Get the subject (row[3]), the content (row[4]), and insert links */
|
/* Get the subject (row[3]), the content (row[4]), and insert links */
|
||||||
Str_Copy (Subject,row[3],sizeof (Subject) - 1);
|
Str_Copy (Subject,row[3],sizeof (Subject) - 1);
|
||||||
Str_Copy (Content,row[4],sizeof (Content) - 1);
|
Str_Copy (Content,row[4],sizeof (Content) - 1);
|
||||||
Str_InsertLinks (Content,Cns_MAX_BYTES_TEXT,50);
|
ALn_InsertLinks (Content,Cns_MAX_BYTES_TEXT,50);
|
||||||
|
|
||||||
/* Show the announcement */
|
/* Show the announcement */
|
||||||
Ann_DrawAnAnnouncement (AnnCod,Status,Subject,Content,
|
Ann_DrawAnAnnouncement (AnnCod,Status,Subject,Content,
|
||||||
|
@ -203,7 +204,7 @@ void Ann_ShowMyAnnouncementsNotMarkedAsSeen (void)
|
||||||
/* Get the subject (row[1]), the content (row[2]), and insert links */
|
/* Get the subject (row[1]), the content (row[2]), and insert links */
|
||||||
Str_Copy (Subject,row[1],sizeof (Subject) - 1);
|
Str_Copy (Subject,row[1],sizeof (Subject) - 1);
|
||||||
Str_Copy (Content,row[2],sizeof (Content) - 1);
|
Str_Copy (Content,row[2],sizeof (Content) - 1);
|
||||||
Str_InsertLinks (Content,Cns_MAX_BYTES_TEXT,50);
|
ALn_InsertLinks (Content,Cns_MAX_BYTES_TEXT,50);
|
||||||
|
|
||||||
/* Show the announcement */
|
/* Show the announcement */
|
||||||
Ann_DrawAnAnnouncement (AnnCod,Ann_ACTIVE_ANNOUNCEMENT,Subject,Content,
|
Ann_DrawAnAnnouncement (AnnCod,Ann_ACTIVE_ANNOUNCEMENT,Subject,Content,
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
|
|
||||||
#include "swad_assignment.h"
|
#include "swad_assignment.h"
|
||||||
#include "swad_assignment_database.h"
|
#include "swad_assignment_database.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -491,7 +492,7 @@ static void Asg_ShowOneAssignment (struct Asg_Assignments *Assignments,
|
||||||
Asg_DB_GetAssignmentTxtByCod (Asg.AsgCod,Txt);
|
Asg_DB_GetAssignmentTxtByCod (Asg.AsgCod,Txt);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
||||||
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
if (PrintView)
|
if (PrintView)
|
||||||
HTM_TD_Begin ("colspan=\"2\" class=\"LT\"");
|
HTM_TD_Begin ("colspan=\"2\" class=\"LT\"");
|
||||||
else
|
else
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
|
|
||||||
#include "swad_attendance.h"
|
#include "swad_attendance.h"
|
||||||
#include "swad_attendance_database.h"
|
#include "swad_attendance_database.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -551,7 +552,7 @@ static void Att_ShowOneAttEvent (struct Att_Events *Events,
|
||||||
Att_DB_GetAttEventDescription (Event->AttCod,Description);
|
Att_DB_GetAttEventDescription (Event->AttCod,Description);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
Description,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
Description,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
||||||
Str_InsertLinks (Description,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Description,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
if (ShowOnlyThisAttEventComplete)
|
if (ShowOnlyThisAttEventComplete)
|
||||||
HTM_TD_Begin ("colspan=\"2\" class=\"LT\"");
|
HTM_TD_Begin ("colspan=\"2\" class=\"LT\"");
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,611 @@
|
||||||
|
// swad_autolink.c: inserting automatic links in text
|
||||||
|
|
||||||
|
/*
|
||||||
|
SWAD (Shared Workspace At a Distance),
|
||||||
|
is a web platform developed at the University of Granada (Spain),
|
||||||
|
and used to support university teaching.
|
||||||
|
|
||||||
|
This file is part of SWAD core.
|
||||||
|
Copyright (C) 1999-2021 Antonio Cañas Vargas
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/*****************************************************************************/
|
||||||
|
/********************************* Headers ***********************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE // For asprintf
|
||||||
|
#include <ctype.h> // For tolower
|
||||||
|
#include <stddef.h> // For NULL
|
||||||
|
#include <stdio.h> // For asprintf
|
||||||
|
#include <stdlib.h> // For malloc and free
|
||||||
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
|
#include "swad_config.h"
|
||||||
|
#include "swad_error.h"
|
||||||
|
#include "swad_form.h"
|
||||||
|
#include "swad_global.h"
|
||||||
|
#include "swad_nickname.h"
|
||||||
|
#include "swad_nickname_database.h"
|
||||||
|
#include "swad_photo.h"
|
||||||
|
#include "swad_string.h"
|
||||||
|
#include "swad_user.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/******************************* Private types *******************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
ALn_LINK_UNKNOWN = 0,
|
||||||
|
ALn_LINK_URL = 1,
|
||||||
|
ALn_LINK_NICK = 2,
|
||||||
|
} ALn_LinkType_t;
|
||||||
|
|
||||||
|
struct ALn_Substring
|
||||||
|
{
|
||||||
|
char *Str; // Pointer to the first char of substring
|
||||||
|
size_t Len; // Length of the substring
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ALn_Link
|
||||||
|
{
|
||||||
|
ALn_LinkType_t Type;
|
||||||
|
struct ALn_Substring URLorNick;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
struct ALn_Substring Anchor1;
|
||||||
|
struct ALn_Substring Anchor2;
|
||||||
|
struct ALn_Substring Anchor3;
|
||||||
|
} Nick;
|
||||||
|
size_t AddedLengthUntilHere; // Total length of extra HTML code added until this link (included)
|
||||||
|
struct ALn_Link *Prev;
|
||||||
|
struct ALn_Link *Next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/******************** Global variables from other modules ********************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
extern struct Globals Gbl;
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*************************** Private prototypes ******************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void ALn_CreateFirstLink (struct ALn_Link **Link,
|
||||||
|
struct ALn_Link **LastLink);
|
||||||
|
static void ALn_CreateNextLink (struct ALn_Link **Link,
|
||||||
|
struct ALn_Link **LastLink);
|
||||||
|
static void ALn_FreeLinks (struct ALn_Link *LastLink);
|
||||||
|
static ALn_LinkType_t ALn_CheckURL (char **PtrSrc,char PrevCh,
|
||||||
|
struct ALn_Link **Link,
|
||||||
|
struct ALn_Link **LastLink,
|
||||||
|
size_t MaxCharsURLOnScreen);
|
||||||
|
static ALn_LinkType_t ALn_CheckNickname (char **PtrSrc,char PrevCh,
|
||||||
|
struct ALn_Link **Link,
|
||||||
|
struct ALn_Link **LastLink);
|
||||||
|
static void ALn_CopySubstring (const struct ALn_Substring *PtrSrc,char **PtrDst);
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**************************** Private constants ******************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
// For URLs the length of anchor is fixed, so it can be calculated once
|
||||||
|
#define ALn_URL_ANCHOR_1 "<a href=\""
|
||||||
|
#define ALn_URL_ANCHOR_2 "\" target=\"_blank\">"
|
||||||
|
#define ALn_URL_ANCHOR_3 "</a>"
|
||||||
|
#define ALn_URL_ANCHOR_1_LENGTH (sizeof (ALn_URL_ANCHOR_1) - 1)
|
||||||
|
#define ALn_URL_ANCHOR_2_LENGTH (sizeof (ALn_URL_ANCHOR_2) - 1)
|
||||||
|
#define ALn_URL_ANCHOR_3_LENGTH (sizeof (ALn_URL_ANCHOR_3) - 1)
|
||||||
|
#define ALn_URL_ANCHOR_TOTAL_LENGTH (ALn_URL_ANCHOR_1_LENGTH + ALn_URL_ANCHOR_2_LENGTH + ALn_URL_ANCHOR_3_LENGTH)
|
||||||
|
|
||||||
|
static const struct ALn_Substring URLAnchor1 =
|
||||||
|
{
|
||||||
|
.Str = ALn_URL_ANCHOR_1,
|
||||||
|
.Len = ALn_URL_ANCHOR_1_LENGTH,
|
||||||
|
};
|
||||||
|
static const struct ALn_Substring URLAnchor2 =
|
||||||
|
{
|
||||||
|
.Str = ALn_URL_ANCHOR_2,
|
||||||
|
.Len = ALn_URL_ANCHOR_2_LENGTH,
|
||||||
|
};
|
||||||
|
static const struct ALn_Substring URLAnchor3 =
|
||||||
|
{
|
||||||
|
.Str = ALn_URL_ANCHOR_3,
|
||||||
|
.Len = ALn_URL_ANCHOR_3_LENGTH,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/************** Insert automatic links in every URL or nickname **************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
/*
|
||||||
|
Insertion example:
|
||||||
|
The web site of @rms is https://stallman.org/
|
||||||
|
The web site of <a href="https://openswad.org/?usr=@rms">@rms</a> is <a href="https://stallman.org/" target="_blank">https://stallman.org/</a>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
<form id="form_z7FY4oFr-yot9R9xRVwDhIntnod3geLj36nyQ6jlJJs_53"
|
||||||
|
action="https://localhost/swad/es" method="post">
|
||||||
|
<input type="hidden" name="ses" value="2jb9CGhIJ81_qhDyeQ6MWDFKQ5ZaA_F68tq22ZAjYww">
|
||||||
|
<input type="hidden" name="usr" value="@acanas">
|
||||||
|
<a href="" onclick="document.getElementById('form_z7FY4oFr-yot9R9xRVwDhIntnod3geLj36nyQ6jlJJs_53').submit();return false;">
|
||||||
|
@acanas
|
||||||
|
</a>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ALn_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScreen)
|
||||||
|
{
|
||||||
|
size_t TxtLength;
|
||||||
|
char PrevCh = '\0';
|
||||||
|
char *PtrSrc;
|
||||||
|
char *PtrDst;
|
||||||
|
struct ALn_Link *Link;
|
||||||
|
struct ALn_Link *LastLink;
|
||||||
|
size_t Length;
|
||||||
|
size_t i;
|
||||||
|
struct ALn_Substring Limited; // URL displayed on screen (may be shorter than actual length)
|
||||||
|
const struct ALn_Substring *Anchor1;
|
||||||
|
const struct ALn_Substring *Anchor2;
|
||||||
|
const struct ALn_Substring *Anchor3;
|
||||||
|
|
||||||
|
/**************************************************************/
|
||||||
|
/***** Find starts and ends of links (URLs and nicknames) *****/
|
||||||
|
/**************************************************************/
|
||||||
|
ALn_CreateFirstLink (&Link,&LastLink);
|
||||||
|
|
||||||
|
for (PtrSrc = Txt;
|
||||||
|
*PtrSrc;)
|
||||||
|
/* Check if the next char is the start of a URL */
|
||||||
|
if ((Link->Type = ALn_CheckURL (&PtrSrc,PrevCh,
|
||||||
|
&Link,&LastLink,
|
||||||
|
MaxCharsURLOnScreen)) == ALn_LINK_UNKNOWN)
|
||||||
|
/* Check if the next char is the start of a nickname */
|
||||||
|
if ((Link->Type = ALn_CheckNickname (&PtrSrc,PrevCh,
|
||||||
|
&Link,&LastLink)) == ALn_LINK_UNKNOWN)
|
||||||
|
{
|
||||||
|
/* The next char is not the start of a URL or a nickname */
|
||||||
|
PrevCh = *PtrSrc;
|
||||||
|
PtrSrc++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************/
|
||||||
|
/***** If there are one or more links (URLs or nicknames) in text *****/
|
||||||
|
/**********************************************************************/
|
||||||
|
if (LastLink) // Not null ==> one or more links found
|
||||||
|
{
|
||||||
|
/***** Insert links from end to start of text,
|
||||||
|
only if there is enough space available in text *****/
|
||||||
|
TxtLength = strlen (Txt);
|
||||||
|
if (TxtLength + LastLink->AddedLengthUntilHere <= MaxLength)
|
||||||
|
for (Link = LastLink;
|
||||||
|
Link;
|
||||||
|
Link = Link->Prev)
|
||||||
|
{
|
||||||
|
/***** Set anchors *****/
|
||||||
|
switch (Link->Type)
|
||||||
|
{
|
||||||
|
case ALn_LINK_URL:
|
||||||
|
Anchor1 = &URLAnchor1;
|
||||||
|
Anchor2 = &URLAnchor2;
|
||||||
|
Anchor3 = &URLAnchor3;
|
||||||
|
break;
|
||||||
|
case ALn_LINK_NICK:
|
||||||
|
Anchor1 = &Link->Nick.Anchor1;
|
||||||
|
Anchor2 = &Link->Nick.Anchor2;
|
||||||
|
Anchor3 = &Link->Nick.Anchor3;
|
||||||
|
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) *****/
|
||||||
|
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: Copy third part of anchor *****/
|
||||||
|
ALn_CopySubstring (Anchor3,&PtrDst);
|
||||||
|
|
||||||
|
/***** Step 3: Move forward the link (URL or nickname)
|
||||||
|
to be shown on screen *****/
|
||||||
|
switch (Link->Type)
|
||||||
|
{
|
||||||
|
case ALn_LINK_URL:
|
||||||
|
if (Link->URLorNick.Len <= MaxCharsURLOnScreen)
|
||||||
|
ALn_CopySubstring (&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);
|
||||||
|
ALn_CopySubstring (&Limited,&PtrDst);
|
||||||
|
free (Limited.Str);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALn_LINK_NICK:
|
||||||
|
ALn_CopySubstring (&Link->URLorNick,&PtrDst);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Step 4: Copy second part of anchor *****/
|
||||||
|
ALn_CopySubstring (Anchor2,&PtrDst);
|
||||||
|
|
||||||
|
/***** Step 5: Copy link into directive A
|
||||||
|
(it's mandatory to do the copy in reverse order
|
||||||
|
to avoid overwriting source URL or nickname) *****/
|
||||||
|
ALn_CopySubstring (&Link->URLorNick,&PtrDst);
|
||||||
|
|
||||||
|
/***** Step 6: Copy first part of anchor *****/
|
||||||
|
ALn_CopySubstring (Anchor1,&PtrDst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************/
|
||||||
|
/***** Free memory for anchors *****/
|
||||||
|
/***********************************/
|
||||||
|
ALn_FreeLinks (LastLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************** Create first link ******************************/
|
||||||
|
|
||||||
|
static void ALn_CreateFirstLink (struct ALn_Link **Link,
|
||||||
|
struct ALn_Link **LastLink)
|
||||||
|
{
|
||||||
|
/***** Reset last link pointer *****/
|
||||||
|
(*LastLink) = NULL;
|
||||||
|
|
||||||
|
/***** Allocate current link *****/
|
||||||
|
if (((*Link) = malloc (sizeof (struct ALn_Link))) == NULL)
|
||||||
|
Err_NotEnoughMemoryExit ();
|
||||||
|
|
||||||
|
/***** Initialize current link *****/
|
||||||
|
(*Link)->Prev = NULL;
|
||||||
|
(*Link)->Next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************** Create next link ******************************/
|
||||||
|
|
||||||
|
static void ALn_CreateNextLink (struct ALn_Link **Link,
|
||||||
|
struct ALn_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 ALn_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 ALn_FreeLinks (struct ALn_Link *LastLink)
|
||||||
|
{
|
||||||
|
struct ALn_Link *Link;
|
||||||
|
struct ALn_Link *PrevLink;
|
||||||
|
|
||||||
|
for (Link = LastLink;
|
||||||
|
Link;
|
||||||
|
Link = PrevLink)
|
||||||
|
{
|
||||||
|
PrevLink = Link->Prev;
|
||||||
|
if (Link->Type == ALn_LINK_NICK)
|
||||||
|
{
|
||||||
|
if (Link->Nick.Anchor3.Str) free (Link->Nick.Anchor3.Str);
|
||||||
|
if (Link->Nick.Anchor2.Str) free (Link->Nick.Anchor2.Str);
|
||||||
|
if (Link->Nick.Anchor1.Str) free (Link->Nick.Anchor1.Str);
|
||||||
|
}
|
||||||
|
free (Link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************** Check if a URL found ***************************/
|
||||||
|
|
||||||
|
static ALn_LinkType_t ALn_CheckURL (char **PtrSrc,char PrevCh,
|
||||||
|
struct ALn_Link **Link,
|
||||||
|
struct ALn_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)
|
||||||
|
ALn_LinkType_t Type = ALn_LINK_UNKNOWN;
|
||||||
|
|
||||||
|
/***** Check if the next char is the start of a URL *****/
|
||||||
|
if (tolower ((int) *(*PtrSrc)) == (int) 'h')
|
||||||
|
if (!Str_ChIsAlphaNum (PrevCh))
|
||||||
|
{
|
||||||
|
(*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://...
|
||||||
|
Type = ALn_LINK_URL;
|
||||||
|
}
|
||||||
|
else if (tolower ((int) *(*PtrSrc)) == (int) 's') // https...
|
||||||
|
{
|
||||||
|
if (*++(*PtrSrc) == ':') // https:...
|
||||||
|
{
|
||||||
|
if (*++(*PtrSrc) == '/') // https:/...
|
||||||
|
if (*++(*PtrSrc) == '/') // https://...
|
||||||
|
Type = ALn_LINK_URL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Type == ALn_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Compute number of bytes added until here *****/
|
||||||
|
(*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 += ALn_URL_ANCHOR_TOTAL_LENGTH +
|
||||||
|
(*Link)->URLorNick.Len;
|
||||||
|
else // If URL is too long to be displayed ==> short it
|
||||||
|
{
|
||||||
|
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 += ALn_URL_ANCHOR_TOTAL_LENGTH +
|
||||||
|
Str_LimitLengthHTMLStr (Limited,MaxCharsURLOnScreen);
|
||||||
|
free (Limited);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***** Create next link *****/
|
||||||
|
ALn_CreateNextLink (Link,LastLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************* Check if a nickname found *************************/
|
||||||
|
|
||||||
|
static ALn_LinkType_t ALn_CheckNickname (char **PtrSrc,char PrevCh,
|
||||||
|
struct ALn_Link **Link,
|
||||||
|
struct ALn_Link **LastLink)
|
||||||
|
{
|
||||||
|
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
|
||||||
|
char Ch;
|
||||||
|
size_t Length;
|
||||||
|
char ParamsStr[Frm_MAX_BYTES_PARAMS_STR];
|
||||||
|
struct UsrData UsrDat;
|
||||||
|
bool ShowPhoto = false;
|
||||||
|
char PhotoURL[PATH_MAX + 1];
|
||||||
|
char *CaptionStr;
|
||||||
|
char *ImgStr;
|
||||||
|
char NickWithoutArr[Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1];
|
||||||
|
bool NickSeemsValid;
|
||||||
|
ALn_LinkType_t Type = ALn_LINK_UNKNOWN;
|
||||||
|
|
||||||
|
/***** Check if the next char is the start of a nickname *****/
|
||||||
|
Ch = *(*PtrSrc);
|
||||||
|
if (Ch == '@') // Current is @
|
||||||
|
if (!Str_ChIsAlphaNum (PrevCh)) // Previous is not alphanumeric
|
||||||
|
if (Str_ChIsAlphaNum (*((*PtrSrc) + 1))) // Next is alphanumeric
|
||||||
|
{
|
||||||
|
(*Link)->URLorNick.Str = (*PtrSrc);
|
||||||
|
|
||||||
|
/***** Find nickname end *****/
|
||||||
|
(*PtrSrc)++; // Points to first character after @
|
||||||
|
|
||||||
|
/***** A nick can have digits, letters and '_' *****/
|
||||||
|
for (;
|
||||||
|
*(*PtrSrc);
|
||||||
|
(*PtrSrc)++)
|
||||||
|
{
|
||||||
|
Ch = *(*PtrSrc);
|
||||||
|
if (!Str_ChIsAlphaNum (Ch))
|
||||||
|
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 @
|
||||||
|
NickSeemsValid = Length >= Nck_MIN_CHARS_NICK_WITHOUT_ARROBA &&
|
||||||
|
Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA;
|
||||||
|
|
||||||
|
if (NickSeemsValid)
|
||||||
|
{
|
||||||
|
/***** Get user's code using nickname *****/
|
||||||
|
Usr_UsrDataConstructor (&UsrDat);
|
||||||
|
strncpy (NickWithoutArr,(*Link)->URLorNick.Str + 1,Length);
|
||||||
|
NickWithoutArr[Length] = '\0';
|
||||||
|
if ((UsrDat.UsrCod = Nck_DB_GetUsrCodFromNickname (NickWithoutArr)) > 0)
|
||||||
|
{
|
||||||
|
Type = ALn_LINK_NICK;
|
||||||
|
Usr_GetUsrDataFromUsrCod (&UsrDat,
|
||||||
|
Usr_DONT_GET_PREFS,
|
||||||
|
Usr_DONT_GET_ROLE_IN_CURRENT_CRS);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type == ALn_LINK_NICK)
|
||||||
|
{
|
||||||
|
/***** Reset anchors (checked on freeing) *****/
|
||||||
|
(*Link)->Nick.Anchor1.Str =
|
||||||
|
(*Link)->Nick.Anchor2.Str =
|
||||||
|
(*Link)->Nick.Anchor3.Str = 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);
|
||||||
|
if (asprintf (&(*Link)->Nick.Anchor1.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)->Nick.Anchor1.Len = strlen ((*Link)->Nick.Anchor1.Str);
|
||||||
|
|
||||||
|
/***** Store second part of anchor *****/
|
||||||
|
if (asprintf (&(*Link)->Nick.Anchor2.Str,
|
||||||
|
"\">"
|
||||||
|
"<a href=\"\""
|
||||||
|
" onclick=\"document.getElementById('%s').submit();return false;\">",
|
||||||
|
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
|
||||||
|
Gbl.Form.Id) < 0)
|
||||||
|
Err_NotEnoughMemoryExit ();
|
||||||
|
(*Link)->Nick.Anchor2.Len = strlen ((*Link)->Nick.Anchor2.Str);
|
||||||
|
|
||||||
|
/***** Store third part of anchor *****/
|
||||||
|
ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (&UsrDat,PhotoURL);
|
||||||
|
Pho_BuildHTMLUsrPhoto (&UsrDat,ShowPhoto ? PhotoURL :
|
||||||
|
NULL,
|
||||||
|
"PHOTO12x16",Pho_ZOOM,
|
||||||
|
&CaptionStr,
|
||||||
|
&ImgStr);
|
||||||
|
if (asprintf (&(*Link)->Nick.Anchor3.Str,
|
||||||
|
"</a></form>%s%s",
|
||||||
|
CaptionStr,
|
||||||
|
ImgStr) < 0)
|
||||||
|
Err_NotEnoughMemoryExit ();
|
||||||
|
free (ImgStr);
|
||||||
|
free (CaptionStr);
|
||||||
|
(*Link)->Nick.Anchor3.Len = strlen ((*Link)->Nick.Anchor3.Str);
|
||||||
|
|
||||||
|
/***** Free memory used for user's data *****/
|
||||||
|
Usr_UsrDataDestructor (&UsrDat);
|
||||||
|
|
||||||
|
/***** Compute number of bytes added until here *****/
|
||||||
|
(*Link)->AddedLengthUntilHere = (*Link)->Prev ? (*Link)->Prev->AddedLengthUntilHere :
|
||||||
|
0;
|
||||||
|
(*Link)->AddedLengthUntilHere += (*Link)->Nick.Anchor1.Len +
|
||||||
|
(*Link)->URLorNick.Len +
|
||||||
|
(*Link)->Nick.Anchor2.Len +
|
||||||
|
(*Link)->Nick.Anchor3.Len;
|
||||||
|
|
||||||
|
/***** Create next link *****/
|
||||||
|
ALn_CreateNextLink (Link,LastLink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************** Copy source substring to destination, backwards **************/
|
||||||
|
|
||||||
|
static void ALn_CopySubstring (const struct ALn_Substring *Src,char **Dst)
|
||||||
|
{
|
||||||
|
char *PtrSrc; // Local pointer optimizes access to memory
|
||||||
|
char *PtrDst; // Local pointer optimizes access to memory
|
||||||
|
size_t Len = Src->Len;
|
||||||
|
/*
|
||||||
|
Example: Src->Str = "<a href=\""
|
||||||
|
Src->Len = 9
|
||||||
|
Src->Str
|
||||||
|
|
|
||||||
|
_v_________________
|
||||||
|
|<|a|_|h|r|e|f|=|"|
|
||||||
|
| | | | | | | | |
|
||||||
|
\ \ \ \ \ \ \ \ \
|
||||||
|
\ \ \ \ \ \ \ \ \
|
||||||
|
\ \ \ \ \ \ \ \ \
|
||||||
|
\ \ \ \ \ \ \ \ \
|
||||||
|
\ \ \ \ \ \ \ \ \
|
||||||
|
| | | | | | | | |
|
||||||
|
_______v_v_v_v_v_v_v_v_v_____________
|
||||||
|
|_|_|_|<|a|_|h|r|e|f|=|"|_|_|_|_|_|_|
|
||||||
|
^ ^
|
||||||
|
| |
|
||||||
|
PtrDst (*Dst)
|
||||||
|
The copy has to be done backwards to avoid overwriting the original string
|
||||||
|
*/
|
||||||
|
if (Len)
|
||||||
|
{
|
||||||
|
PtrSrc = Src->Str + Len - 1;
|
||||||
|
PtrDst = *Dst; // Make a local copy of destination pointer
|
||||||
|
for (;
|
||||||
|
Len;
|
||||||
|
Len--)
|
||||||
|
*PtrDst-- = *PtrSrc--;
|
||||||
|
*Dst = PtrDst; // Update destination pointer
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
// swad_autolink.h: inserting automatic links in text
|
||||||
|
|
||||||
|
#ifndef _SWAD_ALN
|
||||||
|
#define _SWAD_ALN
|
||||||
|
/*
|
||||||
|
SWAD (Shared Workspace At a Distance in Spanish),
|
||||||
|
is a web platform developed at the University of Granada (Spain),
|
||||||
|
and used to support university teaching.
|
||||||
|
|
||||||
|
This file is part of SWAD core.
|
||||||
|
Copyright (C) 1999-2021 Antonio Cañas Vargas
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of the
|
||||||
|
License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/*****************************************************************************/
|
||||||
|
/***************************** Public prototypes ****************************/
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void ALn_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScreen);
|
||||||
|
|
||||||
|
#endif
|
|
@ -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.63 (2021-11-26)"
|
#define Log_PLATFORM_VERSION "SWAD 21.64 (2021-11-28)"
|
||||||
#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.64: Nov 28, 2021 New module swad_autolink to insert links in texts. (320076 lines)
|
||||||
Version 21.63: Nov 26, 2021 Fixing of corruption in test prints and match prints. (320010 lines)
|
Version 21.63: Nov 26, 2021 Fixing of corruption in test prints and match prints. (320010 lines)
|
||||||
Version 21.62.3: Nov 25, 2021 Fixed bug in test questions. Reported by Javier Fernández Baldomero and Jesús González Peñalver. (319438 lines)
|
Version 21.62.3: Nov 25, 2021 Fixed bug in test questions. Reported by Javier Fernández Baldomero and Jesús González Peñalver. (319438 lines)
|
||||||
Version 21.62.2: Nov 24, 2021 Fixed bug in forums. Reported by Javier Fernández Baldomero. (319422 lines)
|
Version 21.62.2: Nov 24, 2021 Fixed bug in forums. Reported by Javier Fernández Baldomero. (319422 lines)
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <stdlib.h> // For free
|
#include <stdlib.h> // For free
|
||||||
#include <string.h> // For string functions
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
#include "swad_exam.h"
|
#include "swad_exam.h"
|
||||||
|
@ -610,7 +611,7 @@ static void Exa_ShowOneExam (struct Exa_Exams *Exams,
|
||||||
Exa_DB_GetExamTxt (Exam->ExaCod,Txt);
|
Exa_DB_GetExamTxt (Exam->ExaCod,Txt);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to rigorous HTML
|
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to rigorous HTML
|
||||||
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
HTM_DIV_Begin ("class=\"PAR %s\"",Exam->Hidden ? "DAT_LIGHT" :
|
HTM_DIV_Begin ("class=\"PAR %s\"",Exam->Hidden ? "DAT_LIGHT" :
|
||||||
"DAT");
|
"DAT");
|
||||||
HTM_Txt (Txt);
|
HTM_Txt (Txt);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include <stdio.h> // For asprintf
|
#include <stdio.h> // For asprintf
|
||||||
#include <string.h> // For string functions
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -634,7 +635,7 @@ static void ExaPrn_GetAndWriteDescription (long ExaCod)
|
||||||
Exa_DB_GetExamTxt (ExaCod,Txt);
|
Exa_DB_GetExamTxt (ExaCod,Txt);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, // Convert from HTML to rigorous HTML
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML, // Convert from HTML to rigorous HTML
|
||||||
Txt,Cns_MAX_BYTES_TEXT,false);
|
Txt,Cns_MAX_BYTES_TEXT,false);
|
||||||
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
|
|
||||||
/***** Write description *****/
|
/***** Write description *****/
|
||||||
HTM_DIV_Begin ("class=\"EXA_PRN_DESC DAT_SMALL\"");
|
HTM_DIV_Begin ("class=\"EXA_PRN_DESC DAT_SMALL\"");
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <stdlib.h> // For free
|
#include <stdlib.h> // For free
|
||||||
#include <string.h> // For string functions
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
#include "swad_figure.h"
|
#include "swad_figure.h"
|
||||||
|
@ -661,7 +662,7 @@ static void Gam_ShowOneGame (struct Gam_Games *Games,
|
||||||
Gam_DB_GetGameTxt (Game->GamCod,Txt);
|
Gam_DB_GetGameTxt (Game->GamCod,Txt);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to rigorous HTML
|
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to rigorous HTML
|
||||||
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
HTM_DIV_Begin ("class=\"PAR %s\"",Game->Hidden ? "DAT_LIGHT" :
|
HTM_DIV_Begin ("class=\"PAR %s\"",Game->Hidden ? "DAT_LIGHT" :
|
||||||
"DAT");
|
"DAT");
|
||||||
HTM_Txt (Txt);
|
HTM_Txt (Txt);
|
||||||
|
|
|
@ -210,7 +210,7 @@ struct Globals
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned Num; // Number of institutional links
|
unsigned Num; // Number of institutional links
|
||||||
struct Str_Link *Lst; // List of institutional links
|
struct Lnk_Link *Lst; // List of institutional links
|
||||||
} Links;
|
} Links;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <unistd.h> // For unlink
|
#include <unistd.h> // For unlink
|
||||||
|
|
||||||
#include "swad_action.h"
|
#include "swad_action.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -1499,7 +1500,7 @@ static bool Inf_CheckAndShowPlainTxt (void)
|
||||||
/***** Convert to respectful HTML and insert links *****/
|
/***** Convert to respectful HTML and insert links *****/
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
TxtHTML,Cns_MAX_BYTES_LONG_TEXT,false); // Convert from HTML to recpectful HTML
|
TxtHTML,Cns_MAX_BYTES_LONG_TEXT,false); // Convert from HTML to recpectful HTML
|
||||||
Str_InsertLinks (TxtHTML,Cns_MAX_BYTES_LONG_TEXT,60); // Insert links
|
ALn_InsertLinks (TxtHTML,Cns_MAX_BYTES_LONG_TEXT,60); // Insert links
|
||||||
|
|
||||||
/***** Write text *****/
|
/***** Write text *****/
|
||||||
HTM_Txt (TxtHTML);
|
HTM_Txt (TxtHTML);
|
||||||
|
|
10
swad_link.c
10
swad_link.c
|
@ -52,7 +52,7 @@ extern struct Globals Gbl;
|
||||||
/***************************** Private variables *****************************/
|
/***************************** Private variables *****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static struct Str_Link *Lnk_EditingLnk = NULL; // Static variable to keep the link being edited
|
static struct Lnk_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 Str_Link *Lnk);
|
static void Lnk_GetDataOfLink (MYSQL_RES *mysql_res,struct Lnk_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 Str_Link *Lnk)
|
void Lnk_GetDataOfLinkByCod (struct Lnk_Link *Lnk)
|
||||||
{
|
{
|
||||||
MYSQL_RES *mysql_res;
|
MYSQL_RES *mysql_res;
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ void Lnk_GetDataOfLinkByCod (struct Str_Link *Lnk)
|
||||||
/**************************** Get data of link *******************************/
|
/**************************** Get data of link *******************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static void Lnk_GetDataOfLink (MYSQL_RES *mysql_res,struct Str_Link *Lnk)
|
static void Lnk_GetDataOfLink (MYSQL_RES *mysql_res,struct Lnk_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 Str_Link *Lnk;
|
struct Lnk_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 Str_Link
|
struct Lnk_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 Str_Link *Lnk);
|
void Lnk_GetDataOfLinkByCod (struct Lnk_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 Str_Link *Lnk)
|
void Lnk_DB_CreateLink (const struct Lnk_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 Str_Link *Lnk);
|
void Lnk_DB_CreateLink (const struct Lnk_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]);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <time.h> // For time
|
#include <time.h> // For time
|
||||||
|
|
||||||
#include "swad_action.h"
|
#include "swad_action.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_config.h"
|
#include "swad_config.h"
|
||||||
#include "swad_course.h"
|
#include "swad_course.h"
|
||||||
|
@ -2687,7 +2688,7 @@ void Msg_WriteMsgContent (char Content[Cns_MAX_BYTES_LONG_TEXT + 1],
|
||||||
{
|
{
|
||||||
/***** Insert links in URLs *****/
|
/***** Insert links in URLs *****/
|
||||||
if (InsertLinks)
|
if (InsertLinks)
|
||||||
Str_InsertLinks (Content,Cns_MAX_BYTES_LONG_TEXT,60);
|
ALn_InsertLinks (Content,Cns_MAX_BYTES_LONG_TEXT,60);
|
||||||
|
|
||||||
/***** Write message to file *****/
|
/***** Write message to file *****/
|
||||||
if (ChangeBRToRet)
|
if (ChangeBRToRet)
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <stdlib.h> // For free
|
#include <stdlib.h> // For free
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -380,7 +381,7 @@ void Not_ShowNotices (Not_Listing_t TypeNoticesListing,long HighlightNotCod)
|
||||||
Str_LimitLengthHTMLStr (Content,Not_MAX_CHARS_ON_NOTICE);
|
Str_LimitLengthHTMLStr (Content,Not_MAX_CHARS_ON_NOTICE);
|
||||||
break;
|
break;
|
||||||
case Not_LIST_FULL_NOTICES:
|
case Not_LIST_FULL_NOTICES:
|
||||||
Str_InsertLinks (Content,Cns_MAX_BYTES_TEXT,
|
ALn_InsertLinks (Content,Cns_MAX_BYTES_TEXT,
|
||||||
Not_MaxCharsURLOnScreen[TypeNoticesListing]);
|
Not_MaxCharsURLOnScreen[TypeNoticesListing]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -511,7 +512,7 @@ static void Not_GetDataAndShowNotice (long NotCod)
|
||||||
|
|
||||||
/* Get the content (row[2]) and insert links*/
|
/* Get the content (row[2]) and insert links*/
|
||||||
Str_Copy (Content,row[2],sizeof (Content) - 1);
|
Str_Copy (Content,row[2],sizeof (Content) - 1);
|
||||||
Str_InsertLinks (Content,Cns_MAX_BYTES_TEXT,
|
ALn_InsertLinks (Content,Cns_MAX_BYTES_TEXT,
|
||||||
Not_MaxCharsURLOnScreen[Not_LIST_FULL_NOTICES]);
|
Not_MaxCharsURLOnScreen[Not_LIST_FULL_NOTICES]);
|
||||||
|
|
||||||
/* Get status of the notice (row[3]) */
|
/* Get status of the notice (row[3]) */
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <stdlib.h> // For calloc
|
#include <stdlib.h> // For calloc
|
||||||
#include <string.h> // For string functions
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -439,7 +440,7 @@ static void Prg_WriteRowItem (unsigned NumItem,struct Prg_Item *Item,
|
||||||
Prg_DB_GetItemTxt (Item->Hierarchy.ItmCod,Txt);
|
Prg_DB_GetItemTxt (Item->Hierarchy.ItmCod,Txt);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to recpectful HTML
|
||||||
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
HTM_DIV_Begin ("class=\"PAR PRG_TXT%s\"",
|
HTM_DIV_Begin ("class=\"PAR PRG_TXT%s\"",
|
||||||
LightStyle ? "PRG_HIDDEN" :
|
LightStyle ? "PRG_HIDDEN" :
|
||||||
"");
|
"");
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <stdlib.h> // For calloc
|
#include <stdlib.h> // For calloc
|
||||||
#include <string.h> // For string functions
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_browser_database.h"
|
#include "swad_browser_database.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
|
@ -1857,7 +1858,7 @@ static void Prj_ShowOneProjectTxtField (struct Prj_Project *Prj,
|
||||||
{
|
{
|
||||||
case Prj_LIST_PROJECTS:
|
case Prj_LIST_PROJECTS:
|
||||||
case Prj_FILE_BROWSER_PROJECT:
|
case Prj_FILE_BROWSER_PROJECT:
|
||||||
Str_InsertLinks (TxtField,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (TxtField,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1378,7 +1378,7 @@ unsigned Qst_DB_GetTextOfAnswers (MYSQL_RES **mysql_res,long QstCod)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/********** Get answers correctness for a question in an exam set ************/
|
/*************** Get answers correctness for a question **********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
unsigned Qst_DB_GetQstAnswersCorr (MYSQL_RES **mysql_res,long QstCod)
|
unsigned Qst_DB_GetQstAnswersCorr (MYSQL_RES **mysql_res,long QstCod)
|
||||||
|
|
579
swad_string.c
579
swad_string.c
|
@ -29,79 +29,24 @@
|
||||||
#include <ctype.h> // For isprint, isspace, etc.
|
#include <ctype.h> // For isprint, isspace, etc.
|
||||||
#include <locale.h> // For setlocale
|
#include <locale.h> // For setlocale
|
||||||
#include <math.h> // For log10, floor, ceil, modf, sqrt...
|
#include <math.h> // For log10, floor, ceil, modf, sqrt...
|
||||||
#include <stddef.h> // For NULL
|
|
||||||
#include <stdio.h> // For asprintf
|
#include <stdio.h> // For asprintf
|
||||||
#include <stdlib.h> // For malloc and free
|
|
||||||
#include <string.h> // For string functions
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
#include "swad_form.h"
|
|
||||||
#include "swad_global.h"
|
#include "swad_global.h"
|
||||||
#include "swad_ID.h"
|
|
||||||
#include "swad_nickname_database.h"
|
|
||||||
#include "swad_notification_database.h"
|
#include "swad_notification_database.h"
|
||||||
#include "swad_parameter.h"
|
|
||||||
#include "swad_photo.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
|
|
||||||
{
|
|
||||||
struct Str_Substring Anchor1;
|
|
||||||
struct Str_Substring Anchor2;
|
|
||||||
struct Str_Substring Anchor3;
|
|
||||||
} Nick;
|
|
||||||
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 ********************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
extern struct Globals Gbl; // Declaration in swad.c
|
extern struct Globals Gbl;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/*************************** 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 Str_LinkType_t Str_CheckURL (char **PtrSrc,char PrevCh,
|
|
||||||
struct Str_Link **Link,
|
|
||||||
struct Str_Link **LastLink,
|
|
||||||
size_t MaxCharsURLOnScreen);
|
|
||||||
static Str_LinkType_t Str_CheckNickname (char **PtrSrc,char PrevCh,
|
|
||||||
struct Str_Link **Link,
|
|
||||||
struct Str_Link **LastLink);
|
|
||||||
static void Str_CopySubstring (const struct Str_Substring *PtrSrc,char **PtrDst);
|
|
||||||
|
|
||||||
static unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch);
|
|
||||||
|
|
||||||
static unsigned Str_FindHTMLEntity (const char *Ptr);
|
static unsigned Str_FindHTMLEntity (const char *Ptr);
|
||||||
|
|
||||||
static int Str_ReadCharAndSkipComments (FILE *FileSrc,Str_SkipHTMLComments_t SkipHTMLComments);
|
static int Str_ReadCharAndSkipComments (FILE *FileSrc,Str_SkipHTMLComments_t SkipHTMLComments);
|
||||||
|
@ -124,526 +69,6 @@ const char Str_BIN_TO_BASE64URL[64 + 1] =
|
||||||
static const char Str_LF[2] = {10,0};
|
static const char Str_LF[2] = {10,0};
|
||||||
static const char Str_CR[2] = {13,0};
|
static const char Str_CR[2] = {13,0};
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
/****************** Insert a link in every URL or nickname *******************/
|
|
||||||
/*****************************************************************************/
|
|
||||||
/*
|
|
||||||
Insertion example:
|
|
||||||
The web site of @rms is https://stallman.org/
|
|
||||||
The web site of <a href="https://openswad.org/?usr=@rms">@rms</a> is <a href="https://stallman.org/" target="_blank">https://stallman.org/</a>
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
|
|
||||||
<form id="form_z7FY4oFr-yot9R9xRVwDhIntnod3geLj36nyQ6jlJJs_53"
|
|
||||||
action="https://localhost/swad/es" method="post">
|
|
||||||
<input type="hidden" name="ses" value="2jb9CGhIJ81_qhDyeQ6MWDFKQ5ZaA_F68tq22ZAjYww">
|
|
||||||
<input type="hidden" name="usr" value="@acanas">
|
|
||||||
<a href="" onclick="document.getElementById('form_z7FY4oFr-yot9R9xRVwDhIntnod3geLj36nyQ6jlJJs_53').submit();return false;">
|
|
||||||
@acanas
|
|
||||||
</a>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// For URLs the length of anchor is fixed, so it can be calculated once
|
|
||||||
#define URL_ANCHOR_1 "<a href=\""
|
|
||||||
#define URL_ANCHOR_2 "\" target=\"_blank\">"
|
|
||||||
#define URL_ANCHOR_3 "</a>"
|
|
||||||
#define URL_ANCHOR_1_LENGTH (sizeof (URL_ANCHOR_1) - 1)
|
|
||||||
#define URL_ANCHOR_2_LENGTH (sizeof (URL_ANCHOR_2) - 1)
|
|
||||||
#define URL_ANCHOR_3_LENGTH (sizeof (URL_ANCHOR_3) - 1)
|
|
||||||
#define URL_ANCHOR_TOTAL_LENGTH (URL_ANCHOR_1_LENGTH + URL_ANCHOR_2_LENGTH + URL_ANCHOR_3_LENGTH)
|
|
||||||
|
|
||||||
// For nicknames the length of anchor is variable,
|
|
||||||
// so it can be calculated for each link,
|
|
||||||
// except the third part that is fixed
|
|
||||||
/*
|
|
||||||
#define NICK_ANCHOR_3 "</a></form>"
|
|
||||||
#define NICK_ANCHOR_3_LENGTH (sizeof (NICK_ANCHOR_3) - 1)
|
|
||||||
*/
|
|
||||||
static const struct Str_Substring URLAnchor1 =
|
|
||||||
{
|
|
||||||
.Str = URL_ANCHOR_1,
|
|
||||||
.Len = URL_ANCHOR_1_LENGTH,
|
|
||||||
};
|
|
||||||
static const struct Str_Substring URLAnchor2 =
|
|
||||||
{
|
|
||||||
.Str = URL_ANCHOR_2,
|
|
||||||
.Len = URL_ANCHOR_2_LENGTH,
|
|
||||||
};
|
|
||||||
static const struct Str_Substring URLAnchor3 =
|
|
||||||
{
|
|
||||||
.Str = URL_ANCHOR_3,
|
|
||||||
.Len = URL_ANCHOR_3_LENGTH,
|
|
||||||
};
|
|
||||||
/*
|
|
||||||
static const struct Str_Substring NickAnchor3 =
|
|
||||||
{
|
|
||||||
.Str = NICK_ANCHOR_3,
|
|
||||||
.Len = NICK_ANCHOR_3_LENGTH,
|
|
||||||
};
|
|
||||||
*/
|
|
||||||
void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScreen)
|
|
||||||
{
|
|
||||||
size_t TxtLength;
|
|
||||||
char PrevCh = '\0';
|
|
||||||
char *PtrSrc;
|
|
||||||
char *PtrDst;
|
|
||||||
struct Str_Link *Link;
|
|
||||||
struct Str_Link *LastLink;
|
|
||||||
size_t Length;
|
|
||||||
size_t i;
|
|
||||||
struct Str_Substring Limited; // URL displayed on screen (may be shorter than actual length)
|
|
||||||
const struct Str_Substring *Anchor1;
|
|
||||||
const struct Str_Substring *Anchor2;
|
|
||||||
const struct Str_Substring *Anchor3;
|
|
||||||
|
|
||||||
/**************************************************************/
|
|
||||||
/***** Find starts and ends of links (URLs and nicknames) *****/
|
|
||||||
/**************************************************************/
|
|
||||||
Str_CreateFirstLink (&Link,&LastLink);
|
|
||||||
|
|
||||||
for (PtrSrc = Txt;
|
|
||||||
*PtrSrc;)
|
|
||||||
/* Check if the next char is the start of a URL */
|
|
||||||
if ((Link->Type = Str_CheckURL (&PtrSrc,PrevCh,
|
|
||||||
&Link,&LastLink,
|
|
||||||
MaxCharsURLOnScreen)) == Str_LINK_UNKNOWN)
|
|
||||||
/* Check if the next char is the start of a nickname */
|
|
||||||
if ((Link->Type = Str_CheckNickname (&PtrSrc,PrevCh,
|
|
||||||
&Link,&LastLink)) == Str_LINK_UNKNOWN)
|
|
||||||
{
|
|
||||||
/* The next char is not the start of a URL or a nickname */
|
|
||||||
PrevCh = *PtrSrc;
|
|
||||||
PtrSrc++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**********************************************************************/
|
|
||||||
/***** If there are one or more links (URLs or nicknames) in text *****/
|
|
||||||
/**********************************************************************/
|
|
||||||
if (LastLink) // Not null ==> one or more links found
|
|
||||||
{
|
|
||||||
/***** Insert links from end to start of text,
|
|
||||||
only if there is enough space available in text *****/
|
|
||||||
TxtLength = strlen (Txt);
|
|
||||||
if (TxtLength + LastLink->AddedLengthUntilHere <= MaxLength)
|
|
||||||
for (Link = LastLink;
|
|
||||||
Link;
|
|
||||||
Link = Link->Prev)
|
|
||||||
{
|
|
||||||
/***** Set anchors *****/
|
|
||||||
switch (Link->Type)
|
|
||||||
{
|
|
||||||
case Str_LINK_URL:
|
|
||||||
Anchor1 = &URLAnchor1;
|
|
||||||
Anchor2 = &URLAnchor2;
|
|
||||||
Anchor3 = &URLAnchor3;
|
|
||||||
break;
|
|
||||||
case Str_LINK_NICK:
|
|
||||||
Anchor1 = &Link->Nick.Anchor1;
|
|
||||||
Anchor2 = &Link->Nick.Anchor2;
|
|
||||||
Anchor3 = &Link->Nick.Anchor3;
|
|
||||||
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) *****/
|
|
||||||
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: Copy third part of anchor *****/
|
|
||||||
Str_CopySubstring (Anchor3,&PtrDst);
|
|
||||||
|
|
||||||
/***** Step 3: Move forward the link (URL or nickname)
|
|
||||||
to be shown on screen *****/
|
|
||||||
switch (Link->Type)
|
|
||||||
{
|
|
||||||
case Str_LINK_URL:
|
|
||||||
if (Link->URLorNick.Len <= MaxCharsURLOnScreen)
|
|
||||||
Str_CopySubstring (&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_CopySubstring (&Limited,&PtrDst);
|
|
||||||
free (Limited.Str);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Str_LINK_NICK:
|
|
||||||
Str_CopySubstring (&Link->URLorNick,&PtrDst);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Step 4: Copy second part of anchor *****/
|
|
||||||
Str_CopySubstring (Anchor2,&PtrDst);
|
|
||||||
|
|
||||||
/***** Step 5: Copy link into directive A
|
|
||||||
(it's mandatory to do the copy in reverse order
|
|
||||||
to avoid overwriting source URL or nickname) *****/
|
|
||||||
Str_CopySubstring (&Link->URLorNick,&PtrDst);
|
|
||||||
|
|
||||||
/***** Step 6: Copy first part of anchor *****/
|
|
||||||
Str_CopySubstring (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;
|
|
||||||
if (Link->Type == Str_LINK_NICK)
|
|
||||||
{
|
|
||||||
if (Link->Nick.Anchor3.Str) free (Link->Nick.Anchor3.Str);
|
|
||||||
if (Link->Nick.Anchor2.Str) free (Link->Nick.Anchor2.Str);
|
|
||||||
if (Link->Nick.Anchor1.Str) free (Link->Nick.Anchor1.Str);
|
|
||||||
}
|
|
||||||
free (Link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************** Check if a URL found ***************************/
|
|
||||||
|
|
||||||
static Str_LinkType_t Str_CheckURL (char **PtrSrc,char PrevCh,
|
|
||||||
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)
|
|
||||||
Str_LinkType_t Type = Str_LINK_UNKNOWN;
|
|
||||||
|
|
||||||
/***** Check if the next char is the start of a URL *****/
|
|
||||||
if (tolower ((int) *(*PtrSrc)) == (int) 'h')
|
|
||||||
if (!Str_ChIsAlphaNum (PrevCh))
|
|
||||||
{
|
|
||||||
(*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://...
|
|
||||||
Type = Str_LINK_URL;
|
|
||||||
}
|
|
||||||
else if (tolower ((int) *(*PtrSrc)) == (int) 's') // https...
|
|
||||||
{
|
|
||||||
if (*++(*PtrSrc) == ':') // https:...
|
|
||||||
{
|
|
||||||
if (*++(*PtrSrc) == '/') // https:/...
|
|
||||||
if (*++(*PtrSrc) == '/') // https://...
|
|
||||||
Type = Str_LINK_URL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Compute number of bytes added until here *****/
|
|
||||||
(*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 += URL_ANCHOR_TOTAL_LENGTH +
|
|
||||||
(*Link)->URLorNick.Len;
|
|
||||||
else // If URL is too long to be displayed ==> short it
|
|
||||||
{
|
|
||||||
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 += URL_ANCHOR_TOTAL_LENGTH +
|
|
||||||
Str_LimitLengthHTMLStr (Limited,MaxCharsURLOnScreen);
|
|
||||||
free (Limited);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***** Create next link *****/
|
|
||||||
Str_CreateNextLink (Link,LastLink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************* Check if a nickname found *************************/
|
|
||||||
|
|
||||||
static Str_LinkType_t Str_CheckNickname (char **PtrSrc,char PrevCh,
|
|
||||||
struct Str_Link **Link,
|
|
||||||
struct Str_Link **LastLink)
|
|
||||||
{
|
|
||||||
extern const char *Lan_STR_LANG_ID[1 + Lan_NUM_LANGUAGES];
|
|
||||||
char Ch;
|
|
||||||
size_t Length;
|
|
||||||
char ParamsStr[Frm_MAX_BYTES_PARAMS_STR];
|
|
||||||
struct UsrData UsrDat;
|
|
||||||
bool ShowPhoto = false;
|
|
||||||
char PhotoURL[PATH_MAX + 1];
|
|
||||||
char *CaptionStr;
|
|
||||||
char *ImgStr;
|
|
||||||
char NickWithoutArr[Nck_MAX_BYTES_NICK_WITHOUT_ARROBA + 1];
|
|
||||||
bool NickSeemsValid;
|
|
||||||
Str_LinkType_t Type = Str_LINK_UNKNOWN;
|
|
||||||
|
|
||||||
/***** Check if the next char is the start of a nickname *****/
|
|
||||||
Ch = *(*PtrSrc);
|
|
||||||
if (Ch == '@') // Current is @
|
|
||||||
if (!Str_ChIsAlphaNum (PrevCh)) // Previous is not alphanumeric
|
|
||||||
if (Str_ChIsAlphaNum (*((*PtrSrc) + 1))) // Next is alphanumeric
|
|
||||||
{
|
|
||||||
(*Link)->URLorNick.Str = (*PtrSrc);
|
|
||||||
|
|
||||||
/***** Find nickname end *****/
|
|
||||||
(*PtrSrc)++; // Points to first character after @
|
|
||||||
|
|
||||||
/***** A nick can have digits, letters and '_' *****/
|
|
||||||
for (;
|
|
||||||
*(*PtrSrc);
|
|
||||||
(*PtrSrc)++)
|
|
||||||
{
|
|
||||||
Ch = *(*PtrSrc);
|
|
||||||
if (!Str_ChIsAlphaNum (Ch))
|
|
||||||
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 @
|
|
||||||
NickSeemsValid = Length >= Nck_MIN_CHARS_NICK_WITHOUT_ARROBA &&
|
|
||||||
Length <= Nck_MAX_CHARS_NICK_WITHOUT_ARROBA;
|
|
||||||
|
|
||||||
if (NickSeemsValid)
|
|
||||||
{
|
|
||||||
/***** Get user's code using nickname *****/
|
|
||||||
Usr_UsrDataConstructor (&UsrDat);
|
|
||||||
strncpy (NickWithoutArr,(*Link)->URLorNick.Str + 1,Length);
|
|
||||||
NickWithoutArr[Length] = '\0';
|
|
||||||
if ((UsrDat.UsrCod = Nck_DB_GetUsrCodFromNickname (NickWithoutArr)) > 0)
|
|
||||||
{
|
|
||||||
Type = Str_LINK_NICK;
|
|
||||||
Usr_GetUsrDataFromUsrCod (&UsrDat,
|
|
||||||
Usr_DONT_GET_PREFS,
|
|
||||||
Usr_DONT_GET_ROLE_IN_CURRENT_CRS);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Type == Str_LINK_NICK)
|
|
||||||
{
|
|
||||||
/***** Reset anchors (checked on freeing) *****/
|
|
||||||
(*Link)->Nick.Anchor1.Str =
|
|
||||||
(*Link)->Nick.Anchor2.Str =
|
|
||||||
(*Link)->Nick.Anchor3.Str = 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);
|
|
||||||
if (asprintf (&(*Link)->Nick.Anchor1.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)->Nick.Anchor1.Len = strlen ((*Link)->Nick.Anchor1.Str);
|
|
||||||
|
|
||||||
/***** Store second part of anchor *****/
|
|
||||||
if (asprintf (&(*Link)->Nick.Anchor2.Str,
|
|
||||||
"\">"
|
|
||||||
"<a href=\"\""
|
|
||||||
" onclick=\"document.getElementById('%s').submit();return false;\">",
|
|
||||||
Gbl.Usrs.Me.Logged ? Gbl.Form.UniqueId :
|
|
||||||
Gbl.Form.Id) < 0)
|
|
||||||
Err_NotEnoughMemoryExit ();
|
|
||||||
(*Link)->Nick.Anchor2.Len = strlen ((*Link)->Nick.Anchor2.Str);
|
|
||||||
|
|
||||||
/***** Store third part of anchor *****/
|
|
||||||
ShowPhoto = Pho_ShowingUsrPhotoIsAllowed (&UsrDat,PhotoURL);
|
|
||||||
Pho_BuildHTMLUsrPhoto (&UsrDat,ShowPhoto ? PhotoURL :
|
|
||||||
NULL,
|
|
||||||
"PHOTO12x16",Pho_ZOOM,
|
|
||||||
&CaptionStr,
|
|
||||||
&ImgStr);
|
|
||||||
if (asprintf (&(*Link)->Nick.Anchor3.Str,
|
|
||||||
"</a></form>%s%s",
|
|
||||||
CaptionStr,
|
|
||||||
ImgStr) < 0)
|
|
||||||
Err_NotEnoughMemoryExit ();
|
|
||||||
free (ImgStr);
|
|
||||||
free (CaptionStr);
|
|
||||||
(*Link)->Nick.Anchor3.Len = strlen ((*Link)->Nick.Anchor3.Str);
|
|
||||||
|
|
||||||
/***** Free memory used for user's data *****/
|
|
||||||
Usr_UsrDataDestructor (&UsrDat);
|
|
||||||
|
|
||||||
/***** Compute number of bytes added until here *****/
|
|
||||||
(*Link)->AddedLengthUntilHere = (*Link)->Prev ? (*Link)->Prev->AddedLengthUntilHere :
|
|
||||||
0;
|
|
||||||
(*Link)->AddedLengthUntilHere += (*Link)->Nick.Anchor1.Len +
|
|
||||||
(*Link)->URLorNick.Len +
|
|
||||||
(*Link)->Nick.Anchor2.Len +
|
|
||||||
(*Link)->Nick.Anchor3.Len;
|
|
||||||
|
|
||||||
/***** Create next link *****/
|
|
||||||
Str_CreateNextLink (Link,LastLink);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/************** Copy source substring to destination, backwards **************/
|
|
||||||
|
|
||||||
static void Str_CopySubstring (const struct Str_Substring *Src,char **Dst)
|
|
||||||
{
|
|
||||||
char *PtrSrc; // Local pointer optimizes access to memory
|
|
||||||
char *PtrDst; // Local pointer optimizes access to memory
|
|
||||||
size_t Len = Src->Len;
|
|
||||||
/*
|
|
||||||
Example: Src->Str = "<a href=\""
|
|
||||||
Src->Len = 9
|
|
||||||
Src->Str
|
|
||||||
|
|
|
||||||
_v_________________
|
|
||||||
|<|a|_|h|r|e|f|=|"|
|
|
||||||
| | | | | | | | |
|
|
||||||
\ \ \ \ \ \ \ \ \
|
|
||||||
\ \ \ \ \ \ \ \ \
|
|
||||||
\ \ \ \ \ \ \ \ \
|
|
||||||
\ \ \ \ \ \ \ \ \
|
|
||||||
\ \ \ \ \ \ \ \ \
|
|
||||||
| | | | | | | | |
|
|
||||||
_______v_v_v_v_v_v_v_v_v_____________
|
|
||||||
|_|_|_|<|a|_|h|r|e|f|=|"|_|_|_|_|_|_|
|
|
||||||
^ ^
|
|
||||||
| |
|
|
||||||
PtrDst (*Dst)
|
|
||||||
The copy has to be done backwards to avoid overwriting the original string
|
|
||||||
*/
|
|
||||||
if (Len)
|
|
||||||
{
|
|
||||||
PtrSrc = Src->Str + Len - 1;
|
|
||||||
PtrDst = *Dst; // Make a local copy of destination pointer
|
|
||||||
for (;
|
|
||||||
Len;
|
|
||||||
Len--)
|
|
||||||
*PtrDst-- = *PtrSrc--;
|
|
||||||
*Dst = PtrDst; // Update destination pointer
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/*********** Check if a character is in set { a-z, A-Z, 0-9, _ } *************/
|
/*********** Check if a character is in set { a-z, A-Z, 0-9, _ } *************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -661,7 +86,7 @@ bool Str_ChIsAlphaNum (char Ch)
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
// Returns number of char analyzed
|
// Returns number of char analyzed
|
||||||
|
|
||||||
static unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch)
|
unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch)
|
||||||
{
|
{
|
||||||
unsigned NumChars;
|
unsigned NumChars;
|
||||||
unsigned Num;
|
unsigned Num;
|
||||||
|
|
|
@ -82,10 +82,10 @@ typedef enum
|
||||||
/***************************** Public prototypes ****************************/
|
/***************************** Public prototypes ****************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
void Str_InsertLinks (char *Txt,unsigned long MaxLength,size_t MaxCharsURLOnScreen);
|
|
||||||
|
|
||||||
bool Str_ChIsAlphaNum (char Ch);
|
bool Str_ChIsAlphaNum (char Ch);
|
||||||
|
|
||||||
|
unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch);
|
||||||
|
|
||||||
size_t Str_LimitLengthHTMLStr (char *Str,size_t MaxCharsOnScreen);
|
size_t Str_LimitLengthHTMLStr (char *Str,size_t MaxCharsOnScreen);
|
||||||
|
|
||||||
void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt);
|
void Str_AnalyzeTxtAndStoreNotifyEventToMentionedUsrs (long PubCod,const char *Txt);
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include <string.h> // For string functions
|
#include <string.h> // For string functions
|
||||||
|
|
||||||
#include "swad_attendance.h"
|
#include "swad_attendance.h"
|
||||||
|
#include "swad_autolink.h"
|
||||||
#include "swad_box.h"
|
#include "swad_box.h"
|
||||||
#include "swad_database.h"
|
#include "swad_database.h"
|
||||||
#include "swad_error.h"
|
#include "swad_error.h"
|
||||||
|
@ -669,7 +670,7 @@ static void Svy_ShowOneSurvey (struct Svy_Surveys *Surveys,
|
||||||
Svy_DB_GetSurveyTxt (Svy.SvyCod,Txt);
|
Svy_DB_GetSurveyTxt (Svy.SvyCod,Txt);
|
||||||
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
Str_ChangeFormat (Str_FROM_HTML,Str_TO_RIGOROUS_HTML,
|
||||||
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to rigorous HTML
|
Txt,Cns_MAX_BYTES_TEXT,false); // Convert from HTML to rigorous HTML
|
||||||
Str_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
ALn_InsertLinks (Txt,Cns_MAX_BYTES_TEXT,60); // Insert links
|
||||||
HTM_DIV_Begin ("class=\"PAR %s\"",Svy.Status.Visible ? "DAT" :
|
HTM_DIV_Begin ("class=\"PAR %s\"",Svy.Status.Visible ? "DAT" :
|
||||||
"DAT_LIGHT");
|
"DAT_LIGHT");
|
||||||
HTM_Txt (Txt);
|
HTM_Txt (Txt);
|
||||||
|
|
Loading…
Reference in New Issue