From 7cafe043f1bd8a7f3f7de974c614f3f4aae865a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20Ca=C3=B1as=20Vargas?= Date: Fri, 15 Apr 2016 02:33:16 +0200 Subject: [PATCH] Version 15.196 --- swad_changelog.h | 3 +- swad_forum.c | 15 ++-- swad_image.c | 51 ++++++++---- swad_image.h | 13 +++- swad_message.c | 19 +++-- swad_social.c | 35 +++++---- swad_test.c | 188 ++++++++++++++++++++++++++------------------- swad_test_import.c | 12 +-- 8 files changed, 208 insertions(+), 128 deletions(-) diff --git a/swad_changelog.h b/swad_changelog.h index d188d5300..01a46cd90 100644 --- a/swad_changelog.h +++ b/swad_changelog.h @@ -137,13 +137,14 @@ /****************************** Public constants *****************************/ /*****************************************************************************/ -#define Log_PLATFORM_VERSION "SWAD 15.195.1 (2016-04-15)" +#define Log_PLATFORM_VERSION "SWAD 15.196 (2016-04-15)" #define CSS_FILE "swad15.193.css" #define JS_FILE "swad15.193.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 15.196: Apr 15, 2016 Changes related to image URL. (199467 lines) Version 15.195.1: Apr 15, 2016 New fields in images to store URL when a user click in the image. (199390 lines) 7 changes necessary in database: ALTER TABLE tst_questions ADD COLUMN ImageURL VARCHAR(255) NOT NULL AFTER ImageTitle; diff --git a/swad_forum.c b/swad_forum.c index 97c1689ff..b9aee11b6 100644 --- a/swad_forum.c +++ b/swad_forum.c @@ -466,11 +466,14 @@ static long For_InsertForumPst (long ThrCod,long UsrCod, /***** Insert forum post in the database *****/ sprintf (Query,"INSERT INTO forum_post" " (ThrCod,UsrCod,CreatTime,ModifTime,NumNotif," - "Subject,Content,ImageName,ImageTitle)" + "Subject,Content,ImageName,ImageTitle,ImageURL)" " VALUES ('%ld','%ld',NOW(),NOW(),'0'," - "'%s','%s','%s','%s')", + "'%s','%s','%s','%s','%s')", ThrCod,UsrCod, - Subject,Content,Image->Name,Image->Title ? Image->Title : ""); + Subject,Content, + Image->Name, + Image->Title ? Image->Title : "", + Image->URL ? Image->URL : ""); PstCod = DB_QueryINSERTandReturnCode (Query,"can not create a new post in a forum"); /***** Free space used for query *****/ @@ -1332,7 +1335,7 @@ static void For_GetPstData (long PstCod,long *UsrCod,time_t *CreatTimeUTC, /***** Get data of a post from database *****/ sprintf (Query,"SELECT UsrCod,UNIX_TIMESTAMP(CreatTime)," - "Subject,Content,ImageName,ImageTitle" + "Subject,Content,ImageName,ImageTitle,ImageURL" " FROM forum_post WHERE PstCod='%ld'", PstCod); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get data of a post"); @@ -1358,8 +1361,8 @@ static void For_GetPstData (long PstCod,long *UsrCod,time_t *CreatTimeUTC, strncpy (Content,row[3],Cns_MAX_BYTES_LONG_TEXT); Content[Cns_MAX_BYTES_LONG_TEXT] = '\0'; - /****** Get image name (row[4]) and title (row[5]) *****/ - Img_GetImageNameAndTitleFromRow (row[4],row[5],Image); + /****** Get image name (row[4]), title (row[5]) and URL (row[6]) *****/ + Img_GetImageNameTitleAndURLFromRow (row[4],row[5],row[6],Image); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); diff --git a/swad_image.c b/swad_image.c index 7619e3ccf..379681ec3 100644 --- a/swad_image.c +++ b/swad_image.c @@ -76,15 +76,16 @@ static void Img_ProcessImage (struct Image *Image, void Img_ImageConstructor (struct Image *Image) { - Img_ResetImageExceptTitle (Image); + Img_ResetImageExceptTitleAndURL (Image); Image->Title = NULL; + Image->URL = NULL; } /*****************************************************************************/ -/********************* Reset image fields except title ***********************/ +/***************** Reset image fields except title and URL *******************/ /*****************************************************************************/ -void Img_ResetImageExceptTitle (struct Image *Image) +void Img_ResetImageExceptTitleAndURL (struct Image *Image) { Image->Action = Img_ACTION_NO_IMAGE; Image->Status = Img_FILE_NONE; @@ -98,14 +99,14 @@ void Img_ResetImageExceptTitle (struct Image *Image) void Img_ImageDestructor (struct Image *Image) { - Img_FreeImageTitle (Image); + Img_FreeImageTitleAndURL (Image); } /*****************************************************************************/ -/*************************** Reset image title *******************************/ +/*********************** Reset image title and URL ***************************/ /*****************************************************************************/ -void Img_FreeImageTitle (struct Image *Image) +void Img_FreeImageTitleAndURL (struct Image *Image) { // Image->Title must be initialized to NULL after declaration if (Image->Title) @@ -113,14 +114,22 @@ void Img_FreeImageTitle (struct Image *Image) free ((void *) Image->Title); Image->Title = NULL; } + // Image->URL must be initialized to NULL after declaration + if (Image->URL) + { + free ((void *) Image->URL); + Image->URL = NULL; + } } /*****************************************************************************/ -/****** Get image name and title from a query result and copy to struct ******/ +/**** Get image name, title and URL from a query result and copy to struct ***/ /*****************************************************************************/ -void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title, - struct Image *Image) +void Img_GetImageNameTitleAndURLFromRow (const char *Name, + const char *Title, + const char *URL, + struct Image *Image) { size_t Length; @@ -132,23 +141,37 @@ void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title, Image->Status = Image->Name[0] ? Img_NAME_STORED_IN_DB : Img_FILE_NONE; - /***** Copy image title to struct *****/ - // Image->Title can be empty or filled with a previous title + + /***** Copy image title and URL to struct *****/ + // Image->Title and Image->URL can be empty or filled with previous values // If filled ==> free it - Img_FreeImageTitle (Image); + Img_FreeImageTitleAndURL (Image); if (Title[0]) { /* Get and limit length of the title */ Length = strlen (Title); if (Length > Img_MAX_BYTES_TITLE) - Length = Img_MAX_BYTES_TITLE; + Length = Img_MAX_BYTES_TITLE; if ((Image->Title = (char *) malloc (Length+1)) == NULL) Lay_ShowErrorAndExit ("Error allocating memory for image title."); strncpy (Image->Title,Title,Length); Image->Title[Length] = '\0'; } + + if (URL[0]) + { + /* Get and limit length of the URL */ + Length = strlen (URL); + if (Length > Img_MAX_BYTES_TITLE) + Length = Img_MAX_BYTES_TITLE; + + if ((Image->URL = (char *) malloc (Length+1)) == NULL) + Lay_ShowErrorAndExit ("Error allocating memory for image URL."); + strncpy (Image->URL,URL,Length); + Image->URL[Length] = '\0'; + } } /*****************************************************************************/ @@ -263,7 +286,7 @@ void Img_GetImageFromForm (int NumImgInForm,struct Image *Image, { /* Overwrite current title (empty or coming from database) with the title coming from the form */ - Img_FreeImageTitle (Image); + Img_FreeImageTitleAndURL (Image); if ((Image->Title = (char *) malloc (Length + 1)) == NULL) Lay_ShowErrorAndExit ("Error allocating memory for image title."); strncpy (Image->Title,Title,Length); diff --git a/swad_image.h b/swad_image.h index d044d23b7..b45856d30 100644 --- a/swad_image.h +++ b/swad_image.h @@ -89,6 +89,9 @@ struct Image char Name[Cry_LENGTH_ENCRYPTED_STR_SHA256_BASE64+1]; char *Title; // Title/attribution (it must be initialized to NULL // in order to not trying to free it when no memory allocated) + char *URL; // URL, i.e. link to original big photo or video + // (it must be initialized to NULL + // in order to not trying to free it when no memory allocated) unsigned Width; unsigned Height; unsigned Quality; @@ -107,12 +110,14 @@ struct ParamUploadImg /*****************************************************************************/ void Img_ImageConstructor (struct Image *Image); -void Img_ResetImageExceptTitle (struct Image *Image); +void Img_ResetImageExceptTitleAndURL (struct Image *Image); void Img_ImageDestructor (struct Image *Image); -void Img_FreeImageTitle (struct Image *Image); +void Img_FreeImageTitleAndURL (struct Image *Image); -void Img_GetImageNameAndTitleFromRow (const char *Name,const char *Title, - struct Image *Image); +void Img_GetImageNameTitleAndURLFromRow (const char *Name, + const char *Title, + const char *URL, + struct Image *Image); void Img_PutImageUploader (int NumImgInForm,const char *ClassImgTit); void Img_GetImageFromForm (int NumImgInForm,struct Image *Image, diff --git a/swad_message.c b/swad_message.c index 623819795..23484a268 100644 --- a/swad_message.c +++ b/swad_message.c @@ -1355,9 +1355,12 @@ static long Msg_InsertNewMsg (const char *Subject,const char *Content, /***** Insert message subject and content in the database *****/ sprintf (Query,"INSERT INTO msg_content" - " (Subject,Content,ImageName,ImageTitle)" - " VALUES ('%s','%s','%s','%s')", - Subject,Content,Image->Name,Image->Title ? Image->Title : ""); + " (Subject,Content,ImageName,ImageTitle,ImageURL)" + " VALUES ('%s','%s','%s','%s','%s')", + Subject,Content, + Image->Name, + Image->Title ? Image->Title : "", + Image->URL ? Image->URL : ""); MsgCod = DB_QueryINSERTandReturnCode (Query,"can not create message"); /***** Insert message in sent messages *****/ @@ -1550,8 +1553,8 @@ static void Msg_MoveMsgContentToDeleted (long MsgCod) /***** Move message from msg_content to msg_content_deleted *****/ /* Insert message content into msg_content_deleted */ sprintf (Query,"INSERT IGNORE INTO msg_content_deleted" - " (MsgCod,Subject,Content,ImageName,ImageTitle)" - " SELECT MsgCod,Subject,Content,ImageName,ImageTitle" + " (MsgCod,Subject,Content,ImageName,ImageTitle,ImageURL)" + " SELECT MsgCod,Subject,Content,ImageName,ImageTitle,ImageURL" " FROM msg_content WHERE MsgCod='%ld'", MsgCod); DB_QueryINSERT (Query,"can not remove the content of a message"); @@ -2704,7 +2707,7 @@ static void Msg_GetMsgContent (long MsgCod,char *Content,struct Image *Image) unsigned long NumRows; /***** Get content of message from database *****/ - sprintf (Query,"SELECT Content,ImageName,ImageTitle" + sprintf (Query,"SELECT Content,ImageName,ImageTitle,ImageURL" " FROM msg_content WHERE MsgCod='%ld'", MsgCod); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get the content of a message"); @@ -2720,8 +2723,8 @@ static void Msg_GetMsgContent (long MsgCod,char *Content,struct Image *Image) strncpy (Content,row[0],Cns_MAX_BYTES_LONG_TEXT); Content[Cns_MAX_BYTES_LONG_TEXT] = '\0'; - /****** Get image name (row[1]) and title (row[2]) *****/ - Img_GetImageNameAndTitleFromRow (row[1],row[2],Image); + /****** Get image name (row[1]), title (row[2]) and URL (row[3]) *****/ + Img_GetImageNameTitleAndURLFromRow (row[1],row[2],row[3],Image); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); diff --git a/swad_social.c b/swad_social.c index 37521ffd3..273b7e13b 100644 --- a/swad_social.c +++ b/swad_social.c @@ -1456,7 +1456,7 @@ static void Soc_GetAndWriteSocialPost (long PstCod) Img_ImageConstructor (&Image); /***** Get social post from database *****/ - sprintf (Query,"SELECT Content,ImageName,ImageTitle" + sprintf (Query,"SELECT Content,ImageName,ImageTitle,ImageURL" " FROM social_posts WHERE PstCod='%ld'", PstCod); NumRows = DB_QuerySELECT (Query,&mysql_res,"can not get the content of a social post"); @@ -1470,8 +1470,8 @@ static void Soc_GetAndWriteSocialPost (long PstCod) strncpy (Content,row[0],Cns_MAX_BYTES_LONG_TEXT); Content[Cns_MAX_BYTES_LONG_TEXT] = '\0'; - /****** Get image name (row[1]) and title (row[2]) *****/ - Img_GetImageNameAndTitleFromRow (row[1],row[2],&Image); + /****** Get image name (row[1]), title (row[2]) and URL (row[3]) *****/ + Img_GetImageNameTitleAndURLFromRow (row[1],row[2],row[3],&Image); } else Content[0] = '\0'; @@ -2111,12 +2111,14 @@ static long Soc_ReceiveSocialPost (void) /***** Publish *****/ /* Insert post content in the database */ - sprintf (Query,"INSERT INTO social_posts (Content,ImageName,ImageTitle)" - " VALUES ('%s','%s','%s')", + sprintf (Query,"INSERT INTO social_posts (Content,ImageName,ImageTitle,ImageURL)" + " VALUES ('%s','%s','%s','%s')", Content, Image.Name, (Image.Name[0] && // Save image title only if image attached - Image.Title) ? Image.Title : ""); + Image.Title) ? Image.Title : "", + (Image.Name[0] && // Save image URL only if image attached + Image.URL ) ? Image.URL : ""); PstCod = DB_QueryINSERTandReturnCode (Query,"can not create post"); /* Insert post in social notes */ @@ -2263,7 +2265,9 @@ static void Soc_WriteCommentsInSocialNote (const struct SocialNote *SocNot) "social_pubs.NotCod," "UNIX_TIMESTAMP(social_pubs.TimePublish)," "social_comments.Content," - "social_comments.ImageName,social_comments.ImageTitle" + "social_comments.ImageName," + "social_comments.ImageTitle," + "social_comments.ImageURL" " FROM social_pubs,social_comments" " WHERE social_pubs.NotCod='%ld'" " AND social_pubs.PubType='%u'" @@ -2873,13 +2877,15 @@ static long Soc_ReceiveComment (void) /* Insert comment content in the database */ sprintf (Query,"INSERT INTO social_comments" - " (PubCod,Content,ImageName,ImageTitle)" - " VALUES ('%ld','%s','%s','%s')", + " (PubCod,Content,ImageName,ImageTitle,ImageURL)" + " VALUES ('%ld','%s','%s','%s','%s')", SocPub.PubCod, Content, Image.Name, (Image.Name[0] && // Save image title only if image attached - Image.Title) ? Image.Title : ""); + Image.Title) ? Image.Title : "", + (Image.Name[0] && // Save image URL only if image attached + Image.URL ) ? Image.URL : ""); DB_QueryINSERT (Query,"can not store comment content"); /***** Free space used for query *****/ @@ -4375,7 +4381,9 @@ static void Soc_GetDataOfSocialComByCod (struct SocialComment *SocCom) "social_pubs.NotCod," "UNIX_TIMESTAMP(social_pubs.TimePublish)," "social_comments.Content," - "social_comments.ImageName,social_comments.ImageTitle" + "social_comments.ImageName," + "social_comments.ImageTitle," + "social_comments.ImageURL," " FROM social_pubs,social_comments" " WHERE social_pubs.PubCod='%ld'" " AND social_pubs.PubType='%u'" @@ -4508,6 +4516,7 @@ static void Soc_GetDataOfSocialCommentFromRow (MYSQL_ROW row,struct SocialCommen row[4]: Content row[5]: ImageName row[6]: ImageTitle + row[7]: ImageURL */ /***** Get code of social comment (row[0]) *****/ SocCom->PubCod = Str_ConvertStrCodToLongCod (row[0]); @@ -4528,8 +4537,8 @@ static void Soc_GetDataOfSocialCommentFromRow (MYSQL_ROW row,struct SocialCommen /***** Get number of times this comment has been favourited *****/ SocCom->NumFavs = Soc_GetNumTimesACommHasBeenFav (SocCom); - /****** Get image name (row[5]) and title (row[6]) *****/ - Img_GetImageNameAndTitleFromRow (row[5],row[6],&SocCom->Image); + /****** Get image name (row[5]), title (row[6]) and URL (row[7]) *****/ + Img_GetImageNameTitleAndURLFromRow (row[5],row[6],row[7],&SocCom->Image); } /*****************************************************************************/ diff --git a/swad_test.c b/swad_test.c index f846572d2..b398a162f 100644 --- a/swad_test.c +++ b/swad_test.c @@ -911,9 +911,10 @@ static void Tst_ShowTstResultAfterAssess (long TstCod,unsigned *NumQstsNotBlank, row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ /***** Get the code of question (row[0]) *****/ @@ -973,9 +974,10 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row, row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ /***** Create test question *****/ @@ -995,12 +997,12 @@ static void Tst_WriteQstAndAnsExam (unsigned NumQst,long QstCod,MYSQL_ROW row, "", Txt_TST_STR_ANSWER_TYPES[Gbl.Test.AnswerType]); - /***** Write stem (row[4]), image (row[6], row[7]), + /***** Write stem (row[4]), image (row[6], row[7], row[8]), answers depending on shuffle (row[3]) and feedback (row[5]) *****/ fprintf (Gbl.F.Out,"", Gbl.RowEvenOdd); Tst_WriteQstStem (row[4],"TEST_EXA"); - Img_GetImageNameAndTitleFromRow (row[6],row[7],&Gbl.Test.Image); + Img_GetImageNameTitleAndURLFromRow (row[6],row[7],row[8],&Gbl.Test.Image); Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_SHOW_STEM"); if (Gbl.Action.Act == ActSeeTst) @@ -2294,15 +2296,18 @@ static unsigned long Tst_GetQuestionsForEdit (MYSQL_RES **mysql_res) row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ sprintf (Query,"SELECT tst_questions.QstCod," "UNIX_TIMESTAMP(tst_questions.EditTime) AS F," "tst_questions.AnsType,tst_questions.Shuffle," "tst_questions.Stem,tst_questions.Feedback," - "tst_questions.ImageName,tst_questions.ImageTitle," + "tst_questions.ImageName," + "tst_questions.ImageTitle," + "tst_questions.ImageURL," "tst_questions.NumHits,tst_questions.NumHitsNotBlank," "tst_questions.Score" " FROM tst_questions"); @@ -2432,9 +2437,10 @@ static unsigned long Tst_GetQuestionsForExam (MYSQL_RES **mysql_res) row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ /* Start query */ // Reject questions with any tag hidden @@ -2444,7 +2450,9 @@ static unsigned long Tst_GetQuestionsForExam (MYSQL_RES **mysql_res) "UNIX_TIMESTAMP(tst_questions.EditTime)," "tst_questions.AnsType,tst_questions.Shuffle," "tst_questions.Stem,tst_questions.Feedback," - "tst_questions.ImageName,tst_questions.ImageTitle," + "tst_questions.ImageName," + "tst_questions.ImageTitle," + "tst_questions.ImageURL," "tst_questions.NumHits,tst_questions.NumHitsNotBlank," "tst_questions.Score" " FROM tst_questions,tst_question_tags,tst_tags" @@ -2556,12 +2564,14 @@ static bool Tst_GetOneQuestionByCod (long QstCod,MYSQL_RES **mysql_res) row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ sprintf (Query,"SELECT QstCod,UNIX_TIMESTAMP(EditTime)," - "AnsType,Shuffle,Stem,Feedback,ImageName,ImageTitle," + "AnsType,Shuffle,Stem,Feedback," + "ImageName,ImageTitle,ImageURL," "NumHits,NumHitsNotBlank,Score" " FROM tst_questions" " WHERE QstCod='%ld'", @@ -2676,9 +2686,10 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ /***** Create test question *****/ Tst_QstConstructor (); @@ -2772,12 +2783,12 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m } fprintf (Gbl.F.Out,""); - /* Write the stem (row[4]), the image (row[6], row[7]), + /* Write the stem (row[4]), the image (row[6], row[7], row[8]), the feedback (row[5]) and the answers */ fprintf (Gbl.F.Out,"", Gbl.RowEvenOdd); Tst_WriteQstStem (row[4],"TEST_EDI"); - Img_GetImageNameAndTitleFromRow (row[6],row[7],&Gbl.Test.Image); + Img_GetImageNameTitleAndURLFromRow (row[6],row[7],row[8],&Gbl.Test.Image); Img_ShowImage (&Gbl.Test.Image,"TEST_IMG_EDIT_LIST_STEM"); Tst_WriteQstFeedback (row[5],"TEST_EDI_LIGHT"); Tst_WriteAnswersOfAQstEdit (Gbl.Test.QstCod); @@ -2785,19 +2796,19 @@ static void Tst_ListOneOrMoreQuestionsToEdit (unsigned long NumRows,MYSQL_RES *m /* Get number of hits (number of times that the question has been answered, - including blank answers) (row[8]) */ - if (sscanf (row[8],"%lu",&NumHitsThisQst) != 1) + including blank answers) (row[9]) */ + if (sscanf (row[9],"%lu",&NumHitsThisQst) != 1) Lay_ShowErrorAndExit ("Wrong number of hits to a question."); /* Get number of hits not blank (number of times that the question has been answered - with a not blank answer) (row[9]) */ - if (sscanf (row[9],"%lu",&NumHitsNotBlankThisQst) != 1) + with a not blank answer) (row[10]) */ + if (sscanf (row[10],"%lu",&NumHitsNotBlankThisQst) != 1) Lay_ShowErrorAndExit ("Wrong number of hits not blank to a question."); - /* Get the acumulated score of the question (row[10]) */ + /* Get the acumulated score of the question (row[11]) */ setlocale (LC_NUMERIC,"en_US.utf8"); // To get decimal point - if (sscanf (row[10],"%lf",&TotalScoreThisQst) != 1) + if (sscanf (row[11],"%lf",&TotalScoreThisQst) != 1) Lay_ShowErrorAndExit ("Wrong score of a question."); setlocale (LC_NUMERIC,"es_ES.utf8"); // Return to spanish system (TODO: this should be internationalized!!!!!!!) @@ -2877,7 +2888,8 @@ unsigned Tst_GetAnswersQst (long QstCod,MYSQL_RES **mysql_res,bool Shuffle) unsigned long NumRows; /***** Get answers of a question from database *****/ - sprintf (Query,"SELECT AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct" + sprintf (Query,"SELECT AnsInd,Answer,Feedback," + "ImageName,ImageTitle,ImageURL,Correct" " FROM tst_answers WHERE QstCod='%ld' ORDER BY %s", QstCod, Shuffle ? "RAND(NOW())" : @@ -2912,7 +2924,8 @@ static void Tst_WriteAnswersOfAQstEdit (long QstCod) row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Write the answers *****/ switch (Gbl.Test.AnswerType) @@ -2979,13 +2992,13 @@ static void Tst_WriteAnswersOfAQstEdit (long QstCod) } /* Copy image */ - Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); + Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image); /* Put an icon that indicates whether the answer is correct or wrong */ fprintf (Gbl.F.Out,"" "", Gbl.RowEvenOdd); - if (Str_ConvertToUpperLetter (row[5][0]) == 'Y') + if (Str_ConvertToUpperLetter (row[6][0]) == 'Y') fprintf (Gbl.F.Out,"\"%s\"", @@ -3081,7 +3094,8 @@ static void Tst_WriteAnswersOfAQstAssessExam (unsigned NumQst,long QstCod, row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Write answer depending on type *****/ switch (Gbl.Test.AnswerType) @@ -3166,7 +3180,8 @@ static void Tst_WriteTFAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Check if number of rows is correct *****/ Tst_CheckIfNumberOfAnswersIsOne (); @@ -3260,7 +3275,8 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle) row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Start of table *****/ @@ -3296,7 +3312,7 @@ static void Tst_WriteChoiceAnsSeeExam (unsigned NumQst,long QstCod,bool Shuffle) Gbl.Test.Answer.Options[NumOpt].Text,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); /***** Copy image *****/ - Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); + Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image); /***** Write selectors and letter of this option *****/ fprintf (Gbl.F.Out,"" @@ -3363,7 +3379,8 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ for (NumOpt = 0; NumOpt < Gbl.Test.Answer.NumOptions; @@ -3396,10 +3413,10 @@ static void Tst_WriteChoiceAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, } /***** Copy image *****/ - Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); + Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image); - /***** Assign correctness (row[5]) of this answer (this option) *****/ - Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y'); + /***** Assign correctness (row[6]) of this answer (this option) *****/ + Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[6][0]) == 'Y'); } /***** Get indexes for this question from string *****/ @@ -3598,7 +3615,8 @@ static void Tst_WriteTextAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Get text and correctness of answers for this question from database (one row per answer) *****/ for (NumOpt = 0; @@ -3628,8 +3646,8 @@ static void Tst_WriteTextAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, Gbl.Test.Answer.Options[NumOpt].Feedback,Tst_MAX_BYTES_ANSWER_OR_FEEDBACK,false); } - /***** Assign correctness (row[5]) of this answer (this option) *****/ - Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y'); + /***** Assign correctness (row[6]) of this answer (this option) *****/ + Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[6][0]) == 'Y'); } /***** Header with the title of each column *****/ @@ -3777,7 +3795,8 @@ static void Tst_WriteIntAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Check if number of rows is correct *****/ Tst_CheckIfNumberOfAnswersIsOne (); @@ -3890,7 +3909,8 @@ static void Tst_WriteFloatAnsAssessExam (unsigned NumQst,MYSQL_RES *mysql_res, row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Check if number of rows is correct *****/ if (Gbl.Test.Answer.NumOptions != 2) @@ -4846,16 +4866,16 @@ static void Tst_InitImagesOfQuestion (void) unsigned NumOpt; /***** Initialize image *****/ - Img_ResetImageExceptTitle (&Gbl.Test.Image); - Img_FreeImageTitle (&Gbl.Test.Image); + Img_ResetImageExceptTitleAndURL (&Gbl.Test.Image); + Img_FreeImageTitleAndURL (&Gbl.Test.Image); for (NumOpt = 0; NumOpt < Tst_MAX_OPTIONS_PER_QUESTION; NumOpt++) { /***** Initialize image *****/ - Img_ResetImageExceptTitle (&Gbl.Test.Answer.Options[NumOpt].Image); - Img_FreeImageTitle (&Gbl.Test.Image); + Img_ResetImageExceptTitleAndURL (&Gbl.Test.Answer.Options[NumOpt].Image); + Img_FreeImageTitleAndURL (&Gbl.Test.Image); } } @@ -4889,7 +4909,8 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback) /***** Get the type of answer and the stem from the database *****/ /* Get the question from database */ - sprintf (Query,"SELECT AnsType,Shuffle,Stem,Feedback,ImageName,ImageTitle" + sprintf (Query,"SELECT AnsType,Shuffle,Stem,Feedback," + "ImageName,ImageTitle,ImageURL" " FROM tst_questions" " WHERE QstCod='%ld' AND CrsCod='%ld'", Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod); @@ -4903,6 +4924,7 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback) row[ 3] Feedback row[ 4] ImageName row[ 5] ImageTitle + row[ 6] ImageURL */ /* Get the type of answer */ Gbl.Test.AnswerType = Tst_ConvertFromStrAnsTypDBToAnsTyp (row[0]); @@ -4923,8 +4945,9 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback) Feedback[Cns_MAX_BYTES_TEXT] = '\0'; } - /* Get the image name of the question from the database (row[4]) */ - Img_GetImageNameAndTitleFromRow (row[4],row[5],&Gbl.Test.Image); + /* Get the image name, title and URL of the question + from the database (row[4], row[5], row[6]) */ + Img_GetImageNameTitleAndURLFromRow (row[4],row[5],row[6],&Gbl.Test.Image); /* Free structure that stores the query result */ DB_FreeMySQLResult (&mysql_res); @@ -4951,7 +4974,8 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback) row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ for (NumOpt = 0; NumOpt < Gbl.Test.Answer.NumOptions; @@ -4995,9 +5019,9 @@ static void Tst_GetQstDataFromDB (char *Stem,char *Feedback) } /* Copy image */ - Img_GetImageNameAndTitleFromRow (row[3],row[4],&Gbl.Test.Answer.Options[NumOpt].Image); + Img_GetImageNameTitleAndURLFromRow (row[3],row[4],row[5],&Gbl.Test.Answer.Options[NumOpt].Image); - Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[5][0]) == 'Y'); + Gbl.Test.Answer.Options[NumOpt].Correct = (Str_ConvertToUpperLetter (row[6][0]) == 'Y'); break; default: break; @@ -5022,11 +5046,11 @@ static void Tst_GetImageFromDB (int NumOpt,struct Image *Image) /***** Build query depending on NumOpt *****/ if (NumOpt < 0) // Get image associated to stem - sprintf (Query,"SELECT ImageName,ImageTitle FROM tst_questions" + sprintf (Query,"SELECT ImageName,ImageTitle,ImageURL FROM tst_questions" " WHERE QstCod='%ld' AND CrsCod='%ld'", Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod); // Get image associated to answer else - sprintf (Query,"SELECT ImageName,ImageTitle FROM tst_answers" + sprintf (Query,"SELECT ImageName,ImageTitle,ImageURL FROM tst_answers" " WHERE QstCod='%ld' AND AnsInd='%u'", Gbl.Test.QstCod,(unsigned) NumOpt); @@ -5034,8 +5058,8 @@ static void Tst_GetImageFromDB (int NumOpt,struct Image *Image) DB_QuerySELECT (Query,&mysql_res,"can not get image name"); row = mysql_fetch_row (mysql_res); - /***** Get the image name (row[0]) *****/ - Img_GetImageNameAndTitleFromRow (row[0],row[1],Image); + /***** Get the image name, title and URL (row[0], row[1], row[2]) *****/ + Img_GetImageNameTitleAndURLFromRow (row[0],row[1],row[2],Image); /***** Free structure that stores the query result *****/ DB_FreeMySQLResult (&mysql_res); @@ -5869,10 +5893,10 @@ static void Tst_InsertOrUpdateQstIntoDB (void) /***** Insert question in the table of questions *****/ sprintf (Query,"INSERT INTO tst_questions" " (CrsCod,EditTime,AnsType,Shuffle," - "Stem,Feedback,ImageName,ImageTitle," + "Stem,Feedback,ImageName,ImageTitle,ImageURL," "NumHits,Score)" " VALUES ('%ld',NOW(),'%s','%c'," - "'%s','%s','%s','%s'," + "'%s','%s','%s','%s','%s'," "'0','0')", Gbl.CurrentCrs.Crs.CrsCod, Tst_StrAnswerTypesDB[Gbl.Test.AnswerType], @@ -5881,7 +5905,8 @@ static void Tst_InsertOrUpdateQstIntoDB (void) Gbl.Test.Stem.Text, Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "", Gbl.Test.Image.Name, - Gbl.Test.Image.Title ? Gbl.Test.Image.Title : ""); + Gbl.Test.Image.Title ? Gbl.Test.Image.Title : "", + Gbl.Test.Image.URL ? Gbl.Test.Image.URL : ""); Gbl.Test.QstCod = DB_QueryINSERTandReturnCode (Query,"can not create question"); /* Update image status */ @@ -5894,7 +5919,8 @@ static void Tst_InsertOrUpdateQstIntoDB (void) /* Update question in database */ sprintf (Query,"UPDATE tst_questions" " SET EditTime=NOW(),AnsType='%s',Shuffle='%c'," - "Stem='%s',Feedback='%s',ImageName='%s',ImageTitle='%s'" + "Stem='%s',Feedback='%s'," + "ImageName='%s',ImageTitle='%s',ImageURL='%s'" " WHERE QstCod='%ld' AND CrsCod='%ld'", Tst_StrAnswerTypesDB[Gbl.Test.AnswerType], Gbl.Test.Shuffle ? 'Y' : @@ -5903,6 +5929,7 @@ static void Tst_InsertOrUpdateQstIntoDB (void) Gbl.Test.Feedback.Text ? Gbl.Test.Feedback.Text : "", Gbl.Test.Image.Name, Gbl.Test.Image.Title ? Gbl.Test.Image.Title : "", + Gbl.Test.Image.URL ? Gbl.Test.Image.URL : "", Gbl.Test.QstCod,Gbl.CurrentCrs.Crs.CrsCod); DB_QueryUPDATE (Query,"can not update question"); @@ -5970,8 +5997,9 @@ static void Tst_InsertAnswersIntoDB (void) { case Tst_ANS_INT: sprintf (Query,"INSERT INTO tst_answers" - " (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" - " VALUES (%ld,0,'%ld','','','','Y')", + " (QstCod,AnsInd,Answer,Feedback," + "ImageName,ImageTitle,ImageURL,Correct)" + " VALUES (%ld,0,'%ld','','','','','Y')", Gbl.Test.QstCod, Gbl.Test.Answer.Integer); DB_QueryINSERT (Query,"can not create answer"); @@ -5983,8 +6011,9 @@ static void Tst_InsertAnswersIntoDB (void) i++) { sprintf (Query,"INSERT INTO tst_answers" - " (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" - " VALUES (%ld,%u,'%lg','','','','Y')", + " (QstCod,AnsInd,Answer,Feedback," + "ImageName,ImageTitle,ImageURL,Correct)" + " VALUES (%ld,%u,'%lg','','','','','Y')", Gbl.Test.QstCod,i, Gbl.Test.Answer.FloatingPoint[i]); DB_QueryINSERT (Query,"can not create answer"); @@ -5993,8 +6022,9 @@ static void Tst_InsertAnswersIntoDB (void) break; case Tst_ANS_TRUE_FALSE: sprintf (Query,"INSERT INTO tst_answers" - " (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" - " VALUES (%ld,0,'%c','','','','Y')", + " (QstCod,AnsInd,Answer,Feedback," + "ImageName,ImageTitle,ImageURL,Correct)" + " VALUES (%ld,0,'%c','','','','','Y')", Gbl.Test.QstCod, Gbl.Test.Answer.TF); DB_QueryINSERT (Query,"can not create answer"); @@ -6008,13 +6038,16 @@ static void Tst_InsertAnswersIntoDB (void) if (Gbl.Test.Answer.Options[NumOpt].Text[0]) { sprintf (Query,"INSERT INTO tst_answers" - " (QstCod,AnsInd,Answer,Feedback,ImageName,ImageTitle,Correct)" - " VALUES ('%ld','%u','%s','%s','%s','%s','%c')", + " (QstCod,AnsInd,Answer,Feedback," + "ImageName,ImageTitle,ImageURL,Correct)" + " VALUES" + " ('%ld','%u','%s','%s','%s','%s','%s','%c')", Gbl.Test.QstCod,NumOpt, Gbl.Test.Answer.Options[NumOpt].Text, Gbl.Test.Answer.Options[NumOpt].Feedback ? Gbl.Test.Answer.Options[NumOpt].Feedback : "", Gbl.Test.Answer.Options[NumOpt].Image.Name, Gbl.Test.Answer.Options[NumOpt].Image.Title ? Gbl.Test.Answer.Options[NumOpt].Image.Title : "", + Gbl.Test.Answer.Options[NumOpt].Image.URL ? Gbl.Test.Answer.Options[NumOpt].Image.URL : "", Gbl.Test.Answer.Options[NumOpt].Correct ? 'Y' : 'N'); DB_QueryINSERT (Query,"can not create answer"); @@ -7516,9 +7549,10 @@ static void Tst_ShowExamTstResult (time_t TstTimeUTC) row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ /***** If this question has been edited later than test exam time ==> don't show question ****/ EditTimeUTC = Dat_GetUNIXTimeFromStr (row[1]); diff --git a/swad_test_import.c b/swad_test_import.c index 651d7f04b..cbf39c8b0 100644 --- a/swad_test_import.c +++ b/swad_test_import.c @@ -200,9 +200,10 @@ void TsI_CreateXML (unsigned long NumRows,MYSQL_RES *mysql_res) row[ 5] Feedback row[ 6] ImageName row[ 7] ImageTitle - row[ 8] NumHits - row[ 9] NumHitsNotBlank - row[10] Score + row[ 8] ImageURL + row[ 9] NumHits + row[10] NumHitsNotBlank + row[11] Score */ /* row[0] holds the code of the question */ if ((QstCod = Str_ConvertStrCodToLongCod (row[0])) < 0) @@ -312,7 +313,8 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod) row[ 2] Feedback row[ 3] ImageName row[ 4] ImageTitle - row[ 5] Correct + row[ 5] ImageURL + row[ 6] Correct */ /***** Write the answers *****/ switch (Gbl.Test.AnswerType) @@ -362,7 +364,7 @@ static void TsI_WriteAnswersOfAQstXML (long QstCod) fprintf (Gbl.Test.XML.FileXML,"%s" "%s%s",