diff --git a/css/swad16.119.4.css b/css/swad16.119.4.css index 6fb642937..040c041f0 100644 --- a/css/swad16.119.4.css +++ b/css/swad16.119.4.css @@ -293,7 +293,7 @@ a:hover /* Default ==> underlined */ #current_day { color:#606060; - margin:2px 0 -4px 0; + margin:2px 0 -2px 0; font-size:20pt; font-weight:bold; line-height:100%; diff --git a/swad_changelog.h b/swad_changelog.h index 4793da15a..da39d702f 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -187,17 +187,20 @@ // TODO: Fix bug when creating a new attendance event: if title is repeated, form is cleared // TODO: Fix bug: When registering an administrator, the user's name changes are ignored +// TODO: Link to agenda in current time (left-top date-time) + /*****************************************************************************/ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 16.119.4 (2017-01-18)" +#define Log_PLATFORM_VERSION "SWAD 16.120 (2017-01-19)" #define CSS_FILE "swad16.119.4.css" #define JS_FILE "swad16.119.3.js" // Number of lines (includes comments but not blank lines) has been got with the following command: // nl swad*.c swad*.h css/swad*.css py/swad*.py js/swad*.js soap/swad*?.h sql/swad*.sql | tail -1 /* + Version 16.120: Jan 19, 2017 Fixed bug when limiting length of links. (211934 lines) Version 16.119.4: Jan 18, 2017 Changes in layout of current data and time. (211882 lines) Version 16.119.3: Jan 17, 2017 Changes in layout of current data and time. (211881 lines) Version 16.119.2: Jan 17, 2017 Fixed bug in web service related to attendance. (211879 lines) diff --git a/swad_message.c b/swad_message.c index bb63d73ff..934940dd8 100644 --- a/swad_message.c +++ b/swad_message.c @@ -769,7 +769,7 @@ void Msg_RecMsgFromUsr (void) (UsrDstData.Prefs.EmailNtfEvents & (1 << Ntf_EVENT_MESSAGE)); /***** Create the received message for this recipient - and ncrement number of new messages received by this recipient *****/ + and increment number of new messages received by this recipient *****/ Msg_InsertReceivedMsgIntoDB (NewMsgCod,UsrDstData.UsrCod,NotifyByEmail); /***** Create notification for this recipient. diff --git a/swad_string.c b/swad_string.c index 181078499..8c0665c4f 100644 --- a/swad_string.c +++ b/swad_string.c @@ -52,6 +52,9 @@ extern struct Globals Gbl; // Declaration in swad.c /*****************************************************************************/ static unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch); + +static unsigned Str_FindHTMLEntity (const char *Ptr); + static int Str_ReadCharAndSkipComments (FILE *FileSrc,Str_SkipHTMLComments_t SkipHTMLComments); static int Str_ReadCharAndSkipCommentsWriting (FILE *FileSrc,FILE *FileTgt,Str_SkipHTMLComments_t SkipHTMLComments); static int Str_ReadCharAndSkipCommentsBackward (FILE *FileSrc,Str_SkipHTMLComments_t SkipHTMLComments); @@ -499,7 +502,7 @@ static unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch) for (NumChars = 2, Num = 0; *Ptr >= '0' && *Ptr <= '9'; Ptr++, NumChars++) - if (Num < 256) // To avoid overflow + if (Num < 100000) // To avoid overflow Num = Num * 10 + (unsigned) (*Ptr - '0'); if (*Ptr == ';') // &#num; found { @@ -539,7 +542,7 @@ static unsigned Str_GetNextASCIICharFromStr (const char *Ptr,unsigned char *Ch) case 124: *Ch = '|'; return NumChars; case 125: *Ch = '}'; return NumChars; case 126: *Ch = '~'; return NumChars; - default: *Ch = ' '; return NumChars; // Unknown character + default: *Ch = '?'; return NumChars; // Unknown character } } else @@ -571,6 +574,7 @@ size_t Str_LimitLengthHTMLStr (char *Str,size_t MaxCharsOnScreen) char *Ptr; size_t NumCharsOnScreen; size_t Length; + size_t LengthHTMLEntity; if (MaxCharsOnScreen < 3) MaxCharsOnScreen = 3; // Length of "..." @@ -579,10 +583,14 @@ size_t Str_LimitLengthHTMLStr (char *Str,size_t MaxCharsOnScreen) for (Ptr = Str, NumCharsOnScreen = 0, Length = 0; *Ptr; Ptr++, NumCharsOnScreen++, Length++) - if (*Ptr == '&') // Special character - for (Ptr++, Length++; - *Ptr && *Ptr != ';'; - Ptr++, Length++); // While not end of special character + /* Check if an HTML entity is present */ + if (*Ptr == '&') // Possible HTML entity + if ((LengthHTMLEntity = Str_FindHTMLEntity (Ptr))) + { + /* if Ptr points to ñ ==> Length = 8 */ + Ptr += LengthHTMLEntity - 1; // Now Ptr point to ';' + Length += LengthHTMLEntity - 1; + } if (NumCharsOnScreen <= MaxCharsOnScreen) // Don't limit string return Length; @@ -601,19 +609,69 @@ size_t Str_LimitLengthHTMLStr (char *Str,size_t MaxCharsOnScreen) Length += 3; break; } - if (*Ptr == '&') // Special character - for (Ptr++, Length++; - *Ptr && *Ptr != ';'; - Ptr++, Length++); // While not end of special character - else if (*Ptr == '<') // HTML entity + /* Check if an HTML entity or directive is present */ + if (*Ptr == '&') // Possible HTML entity + { + if ((LengthHTMLEntity = Str_FindHTMLEntity (Ptr))) + { + /* if Ptr points to ñ ==> Length = 8 */ + Ptr += LengthHTMLEntity - 1; // Now Ptr point to ';' + Length += LengthHTMLEntity - 1; + } + } + else if (*Ptr == '<') // HTML directive "<...>" for (Ptr++, Length++; *Ptr && *Ptr != '>'; - Ptr++, Length++); // While not end of HTML entity + Ptr++, Length++); // While not end of HTML directive "<...>" } return Length; } +/*****************************************************************************/ +/******** Return the length of a possible HTML entity inside a string ********/ +/*****************************************************************************/ +// For example, if Ptr points to "ñ..." or "面...", return 8 +// If Ptr points to no HTML entity, return 0 + +static unsigned Str_FindHTMLEntity (const char *Ptr) + { + size_t Length = 0; + char Ch; + + /***** Check first character *****/ + if (Ptr[Length] != '&') + return 0; // No HTML entity found + + /***** Check second character *****/ + Length++; + if (Ptr[Length] == '#') + /* Go to third character */ + Length++; + + /***** Now some alphanumeric characters are expected *****/ + /* Check second/third character */ + Ch = Ptr[Length]; + if (!((Ch >= '0' && Ch <= '9') || + (Ch >= 'a' && Ch <= 'z') || + (Ch >= 'A' && Ch <= 'Z'))) + return 0; // No HTML entity found + + /* Go to first non alphanumeric character */ + do + { + Length++; + Ch = Ptr[Length]; + } + while ((Ch >= '0' && Ch <= '9') || + (Ch >= 'a' && Ch <= 'z') || + (Ch >= 'A' && Ch <= 'Z')); + + /***** An HTML entity must end by ';' *****/ + return (Ptr[Length] == ';') ? Length + 1 : // HTML entity found (return Length including the final ';') + 0; // No HTML entity found + } + /*****************************************************************************/ /**************** Check if a URL adreess looks as** valid ********************/ /*****************************************************************************/ @@ -1173,8 +1231,8 @@ void Str_ChangeFormat (Str_ChangeFrom_t ChangeFrom,Str_ChangeTo_t ChangeTo, NumPrintableCharsFromReturn++; ThereIsSpaceChar = false; break; - case 0x26: /* "%26" --> "&" (&) */ - StrSpecialChar[0] = '&'; + case 0x26: /* "%26" --> "&" */ + StrSpecialChar[0] = '&'; // '&' must be converted to '&' to allow HTML entities like 分 StrSpecialChar[1] = '\0'; NumPrintableCharsFromReturn++; ThereIsSpaceChar = false; @@ -1187,7 +1245,7 @@ void Str_ChangeFormat (Str_ChangeFrom_t ChangeFrom,Str_ChangeTo_t ChangeTo, StrSpecialChar[2] = '\0'; // End of string } else - sprintf (StrSpecialChar,"'"); // Single comilla is stored as HTML code to avoid problem when querying database (SQL code injection) + sprintf (StrSpecialChar,"'"); // Single comilla is stored as HTML entity to avoid problem when querying database (SQL code injection) NumPrintableCharsFromReturn++; ThereIsSpaceChar = false; break;