From 7c0195766fdd06d0f3f338d2d2cad054dd69f15c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Fri, 27 Feb 2015 13:12:57 +0100 Subject: [PATCH] Version 14.75 --- swad_changelog.h | 3 +- swad_mark.c | 177 +++++++++++++++++++++++++++++++---------------- swad_string.c | 14 ++-- 3 files changed, 130 insertions(+), 64 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index e53fac2bd..b3e03b061 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -103,11 +103,12 @@ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 14.74.12 (2015/02/23)" +#define Log_PLATFORM_VERSION "SWAD 14.75 (2015/02/27)" // 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 | tail -1 /* + Version 14.75: Feb 27, 2015 Fixed bug when getting user's IDs from marks tables. (178172 lines) Version 14.74.12: Feb 23, 2015 Fixed bug in file browser, reported by Germán Luzón González and Javier Fernández Baldomero. (178119 lines) Version 14.74.11: Feb 10, 2015 Changes in swad.js. (178060 lines) Version 14.74.10: Feb 10, 2015 Removed meta tag. (178060 lines) diff --git a/swad_mark.c b/swad_mark.c index 4037f451b..439d88d27 100644 --- a/swad_mark.c +++ b/swad_mark.c @@ -66,12 +66,15 @@ const char *Mrk_HeadOrFootStr[2] = // Names of columns in database, so don't cha "Footer", }; +#define Mrk_MAX_BYTES_IN_CELL_CONTENT 1024 // Cell of a table containing one or several user's IDs + /*****************************************************************************/ /*************************** Internal prototypes *****************************/ /*****************************************************************************/ static void Mrk_GetNumRowsHeaderAndFooter (struct MarksProperties *Marks); static void Mrk_ChangeNumRowsHeaderOrFooter (Brw_HeadOrFoot_t HeaderOrFooter); +static bool Mrk_CheckIfCellContainsOnlyIDs (const char *CellContent); static bool Mrk_GetUsrMarks (FILE *FileUsrMarks,struct UsrData *UsrDat, const char *PathFileAllMarks, struct MarksProperties *Marks); @@ -297,9 +300,11 @@ bool Mrk_CheckFileOfMarks (const char *Path,struct MarksProperties *Marks) extern const char *Txt_There_are_more_than_one_table_in_the_file_of_marks; extern const char *Txt_Table_not_found_in_the_file_of_marks; // extern const char *Txt_X_header_rows_Y_student_rows_and_Z_footer_rows_found; + char CellContent[Mrk_MAX_BYTES_IN_CELL_CONTENT+1]; FILE *FileAllMarks; - char StrRead[ID_MAX_LENGTH_USR_ID+1]; - bool EndOfHead = false,EndOfTable = false,FileIsCorrect = true; + bool EndOfHead = false; + bool EndOfTable = false; + bool FileIsCorrect = true; unsigned NumRowsStds = 0; Marks->Header = Marks->Footer = 0; @@ -329,41 +334,46 @@ bool Mrk_CheckFileOfMarks (const char *Path,struct MarksProperties *Marks) /* We assume that the structure of the table has several rows of header until the first row of students is found, then it has a number of rows of students, including some dummy rows without students, and finally it has several rows of footer from the last row of students until the end of the table */ - /* Count rows of header */ + + /***** Count rows of header *****/ while (!EndOfHead) if (Str_FindStrInFile (FileAllMarks,"Header++; + // All user's IDs must be in the first column of the row + Str_GetCellFromHTMLTableSkipComments (FileAllMarks,CellContent,Mrk_MAX_BYTES_IN_CELL_CONTENT); + + /* Check if only user's IDs + or other stuff found in this table cell */ + if (Mrk_CheckIfCellContainsOnlyIDs (CellContent)) + { + // Only user's IDs found in this cell + EndOfHead = true; + NumRowsStds++; + } + else + // Other stuff found ==> continue in header + Marks->Header++; } else EndOfHead = true; // No more rows - /* Count rows of students and rows of footer */ + /***** Count rows of students and rows of footer *****/ while (!EndOfTable) if (Str_FindStrInFile (FileAllMarks,"Footer = 0; - } - else + } + else + // Other stuff found ==> continue in header Marks->Footer++; } else @@ -388,6 +398,38 @@ bool Mrk_CheckFileOfMarks (const char *Path,struct MarksProperties *Marks) return FileIsCorrect; } +/*****************************************************************************/ +/******* Check if only user's IDs or other stuff found in a table cell *******/ +/*****************************************************************************/ + +static bool Mrk_CheckIfCellContainsOnlyIDs (const char *CellContent) + { + char UsrIDFromTable[ID_MAX_LENGTH_USR_ID+1]; + const char *Ptr = CellContent; + bool UsrIDFound = false; + bool StuffNotUsrIDFound = false; + + /***** Get strings in this table cell + and check if they look like user's IDs or not *****/ + while (*Ptr && !StuffNotUsrIDFound) + { + /* Find next string in text until space, comma or semicolon (leading and trailing spaces are removed) */ + Str_GetNextStringUntilSeparator (&Ptr,UsrIDFromTable,ID_MAX_LENGTH_USR_ID); + + // Users' IDs are always stored internally in capitals and without leading zeros + Str_RemoveLeadingZeros (UsrIDFromTable); + Str_ConvertToUpperText (UsrIDFromTable); + if (ID_CheckIfUsrIDIsValid (UsrIDFromTable)) + UsrIDFound = true; + else + StuffNotUsrIDFound = true; + } + + /***** Check if only user's IDs + or other stuff found in this table cell *****/ + return (UsrIDFound && !StuffNotUsrIDFound); + } + /*****************************************************************************/ /*************************** Show the marks of a user ************************/ /*****************************************************************************/ @@ -398,14 +440,15 @@ static bool Mrk_GetUsrMarks (FILE *FileUsrMarks,struct UsrData *UsrDat, { extern const char *Txt_THE_USER_X_is_not_found_in_the_file_of_marks; unsigned Row; + char CellContent[Mrk_MAX_BYTES_IN_CELL_CONTENT+1]; + const char *Ptr; char UsrIDFromTable[ID_MAX_LENGTH_USR_ID+1]; FILE *FileAllMarks; unsigned NumID; - const char *UsrID = NULL; // Initialized to avoid warning - bool UsrIDFound = true; - bool EndOfTable = false; + bool UsrIDFound; + bool EndOfTable; - /***** Open file with the table of marks *****/ + /***** Open HTML file with the table of marks *****/ if (!(FileAllMarks = fopen (PathFileAllMarks,"rb"))) { // Can't open the file with the table of marks strcpy (Gbl.Message,"Can not open file of marks."); @@ -428,26 +471,29 @@ static bool Mrk_GetUsrMarks (FILE *FileUsrMarks,struct UsrData *UsrDat, while (!UsrIDFound && !EndOfTable) if (Str_FindStrInFile (FileAllMarks,"IDs.Num && !UsrIDFound; - NumID++) - if (UsrDat->IDs.List[NumID].Confirmed) - if (!strcasecmp (UsrDat->IDs.List[NumID].ID,UsrIDFromTable)) - { - UsrIDFound = true; - UsrID = UsrDat->IDs.List[NumID].ID; - } - } + // All user's IDs must be in the first column of the row + Str_GetCellFromHTMLTableSkipComments (FileAllMarks,CellContent,Mrk_MAX_BYTES_IN_CELL_CONTENT); + + /* Get user's IDs */ + Ptr = CellContent; + while (*Ptr && !UsrIDFound) + { + /* Find next string in text until comma or semicolon (leading and trailing spaces are removed) */ + Str_GetNextStringUntilSeparator (&Ptr,UsrIDFromTable,ID_MAX_LENGTH_USR_ID); + + // Users' IDs are always stored internally in capitals and without leading zeros + Str_RemoveLeadingZeros (UsrIDFromTable); + Str_ConvertToUpperText (UsrIDFromTable); + if (ID_CheckIfUsrIDIsValid (UsrIDFromTable)) + // A valid user's ID is found in the first column of table, and stored in UsrIDFromTable. + // Compare UsrIDFromTable with all the confirmed user's IDs in list + for (NumID = 0; + NumID < UsrDat->IDs.Num && !UsrIDFound; + NumID++) + if (UsrDat->IDs.List[NumID].Confirmed) + if (!strcasecmp (UsrDat->IDs.List[NumID].ID,UsrIDFromTable)) + UsrIDFound = true; + } } else EndOfTable = true; // No more rows @@ -474,16 +520,29 @@ static bool Mrk_GetUsrMarks (FILE *FileUsrMarks,struct UsrData *UsrDat, while (!UsrIDFound && !EndOfTable) if (Str_FindStrInFile (FileAllMarks,"IDs.Num && !UsrIDFound; + NumID++) + if (UsrDat->IDs.List[NumID].Confirmed) + if (!strcasecmp (UsrDat->IDs.List[NumID].ID,UsrIDFromTable)) + UsrIDFound = true; + } } else EndOfTable = true; // No more rows diff --git a/swad_string.c b/swad_string.c index e6b0decf3..db2c5b779 100644 --- a/swad_string.c +++ b/swad_string.c @@ -1585,7 +1585,7 @@ static int Str_ReadCharAndSkipCommentsBackward (FILE *FileSrc,Str_SkipHTMLCommen /*****************************************************************************/ /****** Scan next string in file FileSrc until find *******/ -/****** ( skipping comments , directives <...>, and   ) *******/ +/****** ( skipping comments and directives <...> ) *******/ /****** and write string into Str (MaxLength characters as much) *******/ /*****************************************************************************/ @@ -1596,6 +1596,7 @@ char *Str_GetCellFromHTMLTableSkipComments (FILE *FileSrc,char *Str,int MaxLengt long PosTD; int i = 0; int Ch; + bool SpaceFound; char StrAux[1+1]; // To find next "/td>" or "nbsp;" Str[0] = '\0'; @@ -1655,6 +1656,8 @@ char *Str_GetCellFromHTMLTableSkipComments (FILE *FileSrc,char *Str,int MaxLengt break; // If it's } + SpaceFound = false; + /***** Skip   *****/ if (Ch == (int) '&') { @@ -1685,14 +1688,17 @@ char *Str_GetCellFromHTMLTableSkipComments (FILE *FileSrc,char *Str,int MaxLengt Str_FindStrInFile (FileSrc,"&",Str_NO_SKIP_HTML_COMMENTS); // Skip & } else // It's   - continue; + SpaceFound = true; } /***** Skip spaces *****/ if (isspace (Ch) || Ch == 0xA0) // Microsoft Excel uses A0 also as space! - continue; + SpaceFound = true; - if (i < MaxLength) // && isprint (Ch)) + if (SpaceFound) + Ch = (int) ' '; + + if (i < MaxLength) Str[i++] = (char) Ch; } Str[i] = '\0';