2016-04-03 01:24:57 +02:00
|
|
|
|
// swad_image.c: processing of image uploaded in a form
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
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.
|
2018-04-24 13:21:53 +02:00
|
|
|
|
Copyright (C) 1999-2018 Antonio Ca<EFBFBD>as Vargas
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
|
it under the terms of the GNU Affero General 3 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 *********************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include <linux/limits.h> // For PATH_MAX
|
|
|
|
|
#include <stdbool.h> // For boolean type
|
|
|
|
|
#include <stdlib.h> // For exit, system, malloc, free, etc
|
|
|
|
|
#include <string.h> // For string functions
|
2016-04-11 22:46:08 +02:00
|
|
|
|
#include <sys/wait.h> // For the macro WEXITSTATUS
|
2016-04-03 01:24:57 +02:00
|
|
|
|
#include <unistd.h> // For unlink
|
|
|
|
|
|
|
|
|
|
#include "swad_config.h"
|
|
|
|
|
#include "swad_global.h"
|
|
|
|
|
#include "swad_file.h"
|
|
|
|
|
#include "swad_file_browser.h"
|
2018-11-09 20:47:39 +01:00
|
|
|
|
#include "swad_form.h"
|
2016-04-03 01:24:57 +02:00
|
|
|
|
#include "swad_image.h"
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****************************** Public constants *****************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Internal constants ****************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/****************************** Internal types *******************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************** External global variables from others modules ****************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
extern struct Globals Gbl;
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************************* Internal global variables *************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Internal prototypes ***************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-14 19:19:55 +02:00
|
|
|
|
static void Img_ProcessImage (struct Image *Image,
|
|
|
|
|
const char *FileNameImgOriginal,
|
|
|
|
|
const char *FileNameImgProcessed);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
2016-04-08 23:30:43 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/*************************** Reset image fields ******************************/
|
|
|
|
|
/*****************************************************************************/
|
2016-04-09 02:04:45 +02:00
|
|
|
|
// Every struct Image must be initialized with this function Img_ImageConstructor after it is declared
|
|
|
|
|
// Every call to Img_ImageConstructor must have a call to Img_ImageDestructor
|
2016-04-08 23:30:43 +02:00
|
|
|
|
|
|
|
|
|
void Img_ImageConstructor (struct Image *Image)
|
2016-04-09 02:04:45 +02:00
|
|
|
|
{
|
2016-04-15 02:33:16 +02:00
|
|
|
|
Img_ResetImageExceptTitleAndURL (Image);
|
2016-04-09 02:04:45 +02:00
|
|
|
|
Image->Title = NULL;
|
2016-04-15 02:33:16 +02:00
|
|
|
|
Image->URL = NULL;
|
2016-04-09 02:04:45 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2016-04-15 02:33:16 +02:00
|
|
|
|
/***************** Reset image fields except title and URL *******************/
|
2016-04-09 02:04:45 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-15 02:33:16 +02:00
|
|
|
|
void Img_ResetImageExceptTitleAndURL (struct Image *Image)
|
2016-04-08 23:30:43 +02:00
|
|
|
|
{
|
|
|
|
|
Image->Action = Img_ACTION_NO_IMAGE;
|
|
|
|
|
Image->Status = Img_FILE_NONE;
|
|
|
|
|
Image->Name[0] = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************************** Free image *********************************/
|
|
|
|
|
/*****************************************************************************/
|
2016-04-09 02:04:45 +02:00
|
|
|
|
// Every call to Img_ImageConstructor must have a call to Img_ImageDestructor
|
2016-04-08 23:30:43 +02:00
|
|
|
|
|
|
|
|
|
void Img_ImageDestructor (struct Image *Image)
|
|
|
|
|
{
|
2016-04-15 10:58:35 +02:00
|
|
|
|
Img_FreeImageTitle (Image);
|
|
|
|
|
Img_FreeImageURL (Image);
|
2016-04-08 23:30:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 01:10:04 +02:00
|
|
|
|
/*****************************************************************************/
|
2016-04-15 10:58:35 +02:00
|
|
|
|
/****************************** Free image title *****************************/
|
2016-04-06 01:10:04 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-15 10:58:35 +02:00
|
|
|
|
void Img_FreeImageTitle (struct Image *Image)
|
2016-04-06 01:10:04 +02:00
|
|
|
|
{
|
2016-04-08 23:30:43 +02:00
|
|
|
|
// Image->Title must be initialized to NULL after declaration
|
2016-04-06 01:10:04 +02:00
|
|
|
|
if (Image->Title)
|
2016-04-06 19:26:09 +02:00
|
|
|
|
{
|
2016-04-06 01:10:04 +02:00
|
|
|
|
free ((void *) Image->Title);
|
2016-04-06 19:26:09 +02:00
|
|
|
|
Image->Title = NULL;
|
|
|
|
|
}
|
2016-04-15 10:58:35 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************************* Free image URL ******************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void Img_FreeImageURL (struct Image *Image)
|
|
|
|
|
{
|
2016-04-15 02:33:16 +02:00
|
|
|
|
// Image->URL must be initialized to NULL after declaration
|
|
|
|
|
if (Image->URL)
|
|
|
|
|
{
|
|
|
|
|
free ((void *) Image->URL);
|
|
|
|
|
Image->URL = NULL;
|
|
|
|
|
}
|
2016-04-06 01:10:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
2016-04-15 02:33:16 +02:00
|
|
|
|
/**** Get image name, title and URL from a query result and copy to struct ***/
|
2016-04-06 01:10:04 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-15 02:33:16 +02:00
|
|
|
|
void Img_GetImageNameTitleAndURLFromRow (const char *Name,
|
|
|
|
|
const char *Title,
|
|
|
|
|
const char *URL,
|
|
|
|
|
struct Image *Image)
|
2016-04-06 01:10:04 +02:00
|
|
|
|
{
|
|
|
|
|
size_t Length;
|
|
|
|
|
|
2016-04-06 19:26:09 +02:00
|
|
|
|
/***** Copy image name to struct *****/
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (Image->Name,Name,
|
2017-03-13 14:22:36 +01:00
|
|
|
|
Img_BYTES_NAME);
|
2016-04-06 19:26:09 +02:00
|
|
|
|
|
|
|
|
|
/***** Set status of image file *****/
|
|
|
|
|
Image->Status = Image->Name[0] ? Img_NAME_STORED_IN_DB :
|
|
|
|
|
Img_FILE_NONE;
|
2016-04-06 01:10:04 +02:00
|
|
|
|
|
2016-04-15 02:33:16 +02:00
|
|
|
|
|
2016-04-15 10:58:35 +02:00
|
|
|
|
/***** Copy image title to struct *****/
|
|
|
|
|
// Image->Title can be empty or filled with previous value
|
2016-04-08 23:30:43 +02:00
|
|
|
|
// If filled ==> free it
|
2016-04-15 10:58:35 +02:00
|
|
|
|
Img_FreeImageTitle (Image);
|
2016-04-06 19:26:09 +02:00
|
|
|
|
if (Title[0])
|
2016-04-06 01:10:04 +02:00
|
|
|
|
{
|
2016-04-06 19:26:09 +02:00
|
|
|
|
/* Get and limit length of the title */
|
|
|
|
|
Length = strlen (Title);
|
|
|
|
|
if (Length > Img_MAX_BYTES_TITLE)
|
2016-04-15 02:33:16 +02:00
|
|
|
|
Length = Img_MAX_BYTES_TITLE;
|
2016-04-06 01:10:04 +02:00
|
|
|
|
|
2017-01-17 03:10:43 +01:00
|
|
|
|
if ((Image->Title = (char *) malloc (Length + 1)) == NULL)
|
2016-04-06 19:26:09 +02:00
|
|
|
|
Lay_ShowErrorAndExit ("Error allocating memory for image title.");
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (Image->Title,Title,
|
|
|
|
|
Length);
|
2016-04-06 01:10:04 +02:00
|
|
|
|
}
|
2016-04-15 02:33:16 +02:00
|
|
|
|
|
2016-04-15 10:58:35 +02:00
|
|
|
|
/***** Copy image URL to struct *****/
|
|
|
|
|
// Image->URL can be empty or filled with previous value
|
|
|
|
|
// If filled ==> free it
|
|
|
|
|
Img_FreeImageURL (Image);
|
2016-04-15 02:33:16 +02:00
|
|
|
|
if (URL[0])
|
|
|
|
|
{
|
|
|
|
|
/* Get and limit length of the URL */
|
|
|
|
|
Length = strlen (URL);
|
|
|
|
|
if (Length > Img_MAX_BYTES_TITLE)
|
|
|
|
|
Length = Img_MAX_BYTES_TITLE;
|
|
|
|
|
|
2017-01-17 03:10:43 +01:00
|
|
|
|
if ((Image->URL = (char *) malloc (Length + 1)) == NULL)
|
2016-04-15 02:33:16 +02:00
|
|
|
|
Lay_ShowErrorAndExit ("Error allocating memory for image URL.");
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (Image->URL,URL,
|
|
|
|
|
Length);
|
2016-04-15 02:33:16 +02:00
|
|
|
|
}
|
2016-04-06 01:10:04 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-14 14:21:38 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************ Draw input fields to upload an image inside a form *************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-15 10:58:35 +02:00
|
|
|
|
void Img_PutImageUploader (int NumImgInForm,const char *ClassImgTitURL)
|
2016-04-14 14:21:38 +02:00
|
|
|
|
{
|
|
|
|
|
extern const char *Txt_Image;
|
|
|
|
|
extern const char *Txt_optional;
|
|
|
|
|
extern const char *Txt_Image_title_attribution;
|
2016-04-15 10:58:35 +02:00
|
|
|
|
extern const char *Txt_Link;
|
2016-04-14 21:33:24 +02:00
|
|
|
|
struct ParamUploadImg ParamUploadImg;
|
2018-11-09 20:47:39 +01:00
|
|
|
|
char Id[Frm_MAX_BYTES_ID + 1];
|
2016-04-14 14:21:38 +02:00
|
|
|
|
|
2016-04-14 21:33:24 +02:00
|
|
|
|
/***** Set names of parameters depending on number of image in form *****/
|
|
|
|
|
Img_SetParamNames (&ParamUploadImg,NumImgInForm);
|
|
|
|
|
|
2016-04-14 14:21:38 +02:00
|
|
|
|
/***** Create unique id for this image uploader *****/
|
2018-11-09 20:47:39 +01:00
|
|
|
|
Frm_SetUniqueId (Id);
|
2016-04-14 14:21:38 +02:00
|
|
|
|
|
|
|
|
|
/***** Start container *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"IMG_UPLOAD_CONTAINER\">");
|
|
|
|
|
|
|
|
|
|
/***** Action to perform on image *****/
|
2016-04-14 21:33:24 +02:00
|
|
|
|
Par_PutHiddenParamUnsigned (ParamUploadImg.Action,(unsigned) Img_ACTION_NEW_IMAGE);
|
2016-04-14 14:21:38 +02:00
|
|
|
|
|
|
|
|
|
/***** Image file *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<label class=\"IMG_UPLOAD_BUTTON\">"
|
|
|
|
|
"<img src=\"%s/photo64x64.gif\""
|
|
|
|
|
" alt=\"%s\" title=\"%s (%s)\""
|
2016-11-14 10:05:41 +01:00
|
|
|
|
" class=\"IMG_UPLOAD_ICO\" />"
|
2016-04-14 18:59:18 +02:00
|
|
|
|
"<input type=\"file\" name=\"%s\" accept=\"image/*\""
|
2016-04-14 14:21:38 +02:00
|
|
|
|
" class=\"IMG_UPLOAD_FILE\""
|
|
|
|
|
" onchange=\"imageUploadOnSelectFile (this,'%s');\" />"
|
|
|
|
|
"<span id=\"%s_fil\" class=\"IMG_UPLOAD_FILENAME\" />"
|
|
|
|
|
"</span>"
|
2016-04-15 10:58:35 +02:00
|
|
|
|
"</label>",
|
2016-04-14 14:21:38 +02:00
|
|
|
|
Gbl.Prefs.IconsURL,
|
|
|
|
|
Txt_Image,Txt_Image,Txt_optional,
|
2016-04-14 21:33:24 +02:00
|
|
|
|
ParamUploadImg.File,
|
2016-04-14 14:21:38 +02:00
|
|
|
|
Id,Id);
|
|
|
|
|
|
2016-04-15 10:58:35 +02:00
|
|
|
|
/***** Image title/attribution and URL *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"<div id=\"%s_tit_url\" style=\"display:none;\">",
|
|
|
|
|
Id);
|
|
|
|
|
fprintf (Gbl.F.Out,"<input type=\"text\" name=\"%s\""
|
|
|
|
|
" placeholder=\"%s (%s)\""
|
|
|
|
|
" class=\"%s\" maxlength=\"%u\" value=\"\" />",
|
|
|
|
|
ParamUploadImg.Title,
|
2016-04-14 14:21:38 +02:00
|
|
|
|
Txt_Image_title_attribution,Txt_optional,
|
2017-03-08 14:12:33 +01:00
|
|
|
|
ClassImgTitURL,Img_MAX_CHARS_TITLE);
|
2016-04-15 10:58:35 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"<br />"
|
2016-11-20 14:32:15 +01:00
|
|
|
|
"<input type=\"url\" name=\"%s\""
|
2016-04-15 10:58:35 +02:00
|
|
|
|
" placeholder=\"%s (%s)\""
|
|
|
|
|
" class=\"%s\" maxlength=\"%u\" value=\"\" />",
|
|
|
|
|
ParamUploadImg.URL,
|
|
|
|
|
Txt_Link,Txt_optional,
|
2017-03-08 14:12:33 +01:00
|
|
|
|
ClassImgTitURL,Cns_MAX_CHARS_WWW);
|
2016-04-15 10:58:35 +02:00
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
2016-04-14 14:21:38 +02:00
|
|
|
|
|
|
|
|
|
/***** End container *****/
|
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-04 12:13:37 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/***************************** Get image from form ***************************/
|
|
|
|
|
/*****************************************************************************/
|
2016-04-18 11:45:07 +02:00
|
|
|
|
// If NumImgInForm < 0, params have no suffix
|
|
|
|
|
// If NumImgInForm >= 0, the number is a suffix of the params
|
2016-04-04 12:13:37 +02:00
|
|
|
|
|
2016-04-14 21:33:24 +02:00
|
|
|
|
void Img_GetImageFromForm (int NumImgInForm,struct Image *Image,
|
|
|
|
|
void (*GetImageFromDB) (int NumImgInForm,struct Image *Image))
|
2016-04-04 12:13:37 +02:00
|
|
|
|
{
|
2016-04-14 21:33:24 +02:00
|
|
|
|
struct ParamUploadImg ParamUploadImg;
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char Title[Img_MAX_BYTES_TITLE + 1];
|
2017-03-08 14:12:33 +01:00
|
|
|
|
char URL[Cns_MAX_BYTES_WWW + 1];
|
2016-04-06 19:26:09 +02:00
|
|
|
|
size_t Length;
|
|
|
|
|
|
2016-04-14 21:33:24 +02:00
|
|
|
|
/***** Set names of parameters depending on number of image in form *****/
|
|
|
|
|
Img_SetParamNames (&ParamUploadImg,NumImgInForm);
|
|
|
|
|
|
2016-04-08 23:30:43 +02:00
|
|
|
|
/***** First, get action and initialize image
|
|
|
|
|
(except title, that will be get after the image file) *****/
|
2016-04-14 21:33:24 +02:00
|
|
|
|
Image->Action = Img_GetImageActionFromForm (ParamUploadImg.Action);
|
2016-04-04 14:48:12 +02:00
|
|
|
|
Image->Status = Img_FILE_NONE;
|
2016-04-08 16:37:59 +02:00
|
|
|
|
Image->Name[0] = '\0';
|
2016-04-06 19:26:09 +02:00
|
|
|
|
|
2016-04-08 23:30:43 +02:00
|
|
|
|
/***** Secondly, get the image name and the file *****/
|
2016-04-04 14:48:12 +02:00
|
|
|
|
switch (Image->Action)
|
2016-04-04 12:13:37 +02:00
|
|
|
|
{
|
|
|
|
|
case Img_ACTION_NEW_IMAGE: // Upload new image
|
|
|
|
|
/***** Get new image (if present ==> process and create temporary file) *****/
|
2016-04-14 21:33:24 +02:00
|
|
|
|
Img_GetAndProcessImageFileFromForm (Image,ParamUploadImg.File);
|
2016-04-18 11:45:07 +02:00
|
|
|
|
switch (Image->Status)
|
2016-04-04 12:13:37 +02:00
|
|
|
|
{
|
2016-04-18 11:45:07 +02:00
|
|
|
|
case Img_FILE_NONE: // No new image received
|
|
|
|
|
Image->Action = Img_ACTION_NO_IMAGE;
|
|
|
|
|
Image->Name[0] = '\0';
|
|
|
|
|
break;
|
|
|
|
|
case Img_FILE_RECEIVED: // New image received, but not processed
|
|
|
|
|
Image->Status = Img_FILE_NONE;
|
|
|
|
|
Image->Name[0] = '\0';
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
2016-04-04 12:13:37 +02:00
|
|
|
|
}
|
|
|
|
|
break;
|
2016-04-11 15:32:59 +02:00
|
|
|
|
case Img_ACTION_KEEP_IMAGE: // Keep current image unchanged
|
|
|
|
|
/***** Get image name *****/
|
|
|
|
|
if (GetImageFromDB != NULL)
|
2016-04-14 21:33:24 +02:00
|
|
|
|
GetImageFromDB (NumImgInForm,Image);
|
2016-04-11 15:32:59 +02:00
|
|
|
|
break;
|
2016-04-04 12:13:37 +02:00
|
|
|
|
case Img_ACTION_CHANGE_IMAGE: // Replace old image by new image
|
|
|
|
|
/***** Get new image (if present ==> process and create temporary file) *****/
|
2016-04-14 21:33:24 +02:00
|
|
|
|
Img_GetAndProcessImageFileFromForm (Image,ParamUploadImg.File);
|
2016-04-08 16:37:59 +02:00
|
|
|
|
if (Image->Status != Img_FILE_PROCESSED && // No new image received-processed successfully
|
2016-04-11 15:32:59 +02:00
|
|
|
|
GetImageFromDB != NULL)
|
2016-04-04 12:13:37 +02:00
|
|
|
|
/* Get image name */
|
2016-04-14 21:33:24 +02:00
|
|
|
|
GetImageFromDB (NumImgInForm,Image);
|
2016-04-04 12:13:37 +02:00
|
|
|
|
break;
|
2016-04-11 15:32:59 +02:00
|
|
|
|
case Img_ACTION_NO_IMAGE: // Do not use image (remove current image if exists)
|
|
|
|
|
break;
|
2016-04-04 12:13:37 +02:00
|
|
|
|
}
|
2016-04-06 19:26:09 +02:00
|
|
|
|
|
2016-04-15 10:58:35 +02:00
|
|
|
|
/***** Third, get image title from form *****/
|
2016-04-14 21:33:24 +02:00
|
|
|
|
Par_GetParToText (ParamUploadImg.Title,Title,Img_MAX_BYTES_TITLE);
|
2016-04-08 23:30:43 +02:00
|
|
|
|
/* If the title coming from the form is empty, keep current image title unchanged
|
|
|
|
|
If not empty, copy it to current image title */
|
|
|
|
|
if ((Length = strlen (Title)) > 0)
|
2016-04-06 19:26:09 +02:00
|
|
|
|
{
|
|
|
|
|
/* Overwrite current title (empty or coming from database)
|
|
|
|
|
with the title coming from the form */
|
2016-04-15 10:58:35 +02:00
|
|
|
|
Img_FreeImageTitle (Image);
|
2016-04-06 19:26:09 +02:00
|
|
|
|
if ((Image->Title = (char *) malloc (Length + 1)) == NULL)
|
|
|
|
|
Lay_ShowErrorAndExit ("Error allocating memory for image title.");
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (Image->Title,Title,
|
|
|
|
|
Length);
|
2016-04-06 19:26:09 +02:00
|
|
|
|
}
|
2016-04-15 10:58:35 +02:00
|
|
|
|
|
|
|
|
|
/***** By last, get image URL from form *****/
|
2017-03-08 14:12:33 +01:00
|
|
|
|
Par_GetParToText (ParamUploadImg.URL,URL,Cns_MAX_BYTES_WWW);
|
2016-04-15 10:58:35 +02:00
|
|
|
|
/* If the URL coming from the form is empty, keep current image URL unchanged
|
|
|
|
|
If not empty, copy it to current image URL */
|
|
|
|
|
if ((Length = strlen (URL)) > 0)
|
|
|
|
|
{
|
|
|
|
|
/* Overwrite current URL (empty or coming from database)
|
|
|
|
|
with the URL coming from the form */
|
|
|
|
|
Img_FreeImageURL (Image);
|
|
|
|
|
if ((Image->URL = (char *) malloc (Length + 1)) == NULL)
|
|
|
|
|
Lay_ShowErrorAndExit ("Error allocating memory for image URL.");
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (Image->URL,URL,
|
|
|
|
|
Length);
|
2016-04-15 10:58:35 +02:00
|
|
|
|
}
|
2016-04-04 12:13:37 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-14 21:33:24 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/********* Set parameters names depending on number of image in form *********/
|
|
|
|
|
/*****************************************************************************/
|
2017-01-13 10:49:56 +01:00
|
|
|
|
// If NumImgInForm < 0, params have no suffix
|
2016-04-18 11:45:07 +02:00
|
|
|
|
// If NumImgInForm >= 0, the number is a suffix of the params
|
2016-04-14 21:33:24 +02:00
|
|
|
|
|
|
|
|
|
void Img_SetParamNames (struct ParamUploadImg *ParamUploadImg,int NumImgInForm)
|
|
|
|
|
{
|
|
|
|
|
if (NumImgInForm < 0) // One unique image in form ==> no suffix needed
|
|
|
|
|
{
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (ParamUploadImg->Action,"ImgAct",
|
2017-03-07 19:55:29 +01:00
|
|
|
|
Img_MAX_BYTES_PARAM_UPLOAD_IMG);
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (ParamUploadImg->File ,"ImgFil",
|
2017-03-07 19:55:29 +01:00
|
|
|
|
Img_MAX_BYTES_PARAM_UPLOAD_IMG);
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (ParamUploadImg->Title ,"ImgTit",
|
2017-03-07 19:55:29 +01:00
|
|
|
|
Img_MAX_BYTES_PARAM_UPLOAD_IMG);
|
2017-01-17 03:10:43 +01:00
|
|
|
|
Str_Copy (ParamUploadImg->URL ,"ImgURL",
|
2017-03-07 19:55:29 +01:00
|
|
|
|
Img_MAX_BYTES_PARAM_UPLOAD_IMG);
|
2016-04-14 21:33:24 +02:00
|
|
|
|
}
|
|
|
|
|
else // Several images in form ==> add suffix
|
|
|
|
|
{
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (ParamUploadImg->Action,sizeof (ParamUploadImg->Action),
|
|
|
|
|
"ImgAct%u",
|
|
|
|
|
NumImgInForm);
|
|
|
|
|
snprintf (ParamUploadImg->File ,sizeof (ParamUploadImg->File),
|
|
|
|
|
"ImgFil%u",
|
|
|
|
|
NumImgInForm);
|
|
|
|
|
snprintf (ParamUploadImg->Title ,sizeof (ParamUploadImg->Title),
|
|
|
|
|
"ImgTit%u",
|
|
|
|
|
NumImgInForm);
|
|
|
|
|
snprintf (ParamUploadImg->URL ,sizeof (ParamUploadImg->URL),
|
|
|
|
|
"ImgURL%u",
|
|
|
|
|
NumImgInForm);
|
2016-04-14 21:33:24 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-03 01:24:57 +02:00
|
|
|
|
/*****************************************************************************/
|
2016-04-03 17:49:09 +02:00
|
|
|
|
/************************* Get image action from form ************************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-04 14:48:12 +02:00
|
|
|
|
Img_Action_t Img_GetImageActionFromForm (const char *ParamAction)
|
2016-04-03 17:49:09 +02:00
|
|
|
|
{
|
2016-04-08 16:37:59 +02:00
|
|
|
|
/***** Get parameter with the action to perform on image *****/
|
2017-01-29 21:41:08 +01:00
|
|
|
|
return (Img_Action_t)
|
|
|
|
|
Par_GetParToUnsignedLong (ParamAction,
|
|
|
|
|
0,
|
|
|
|
|
Img_NUM_ACTIONS - 1,
|
|
|
|
|
(unsigned long) Img_ACTION_DEFAULT);
|
2016-04-03 17:49:09 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**************************** Get image from form ****************************/
|
2016-04-03 01:24:57 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-14 19:19:55 +02:00
|
|
|
|
void Img_GetAndProcessImageFileFromForm (struct Image *Image,const char *ParamFile)
|
2016-04-03 01:24:57 +02:00
|
|
|
|
{
|
|
|
|
|
struct Param *Param;
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char FileNameImgSrc[PATH_MAX + 1];
|
2016-04-03 01:24:57 +02:00
|
|
|
|
char *PtrExtension;
|
|
|
|
|
size_t LengthExtension;
|
2017-01-15 18:02:52 +01:00
|
|
|
|
char MIMEType[Brw_MAX_BYTES_MIME_TYPE + 1];
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char PathImgPriv[PATH_MAX + 1];
|
|
|
|
|
char FileNameImgOrig[PATH_MAX + 1]; // Full name of original uploaded file
|
|
|
|
|
char FileNameImgTmp[PATH_MAX + 1]; // Full name of temporary processed file
|
2016-04-03 01:24:57 +02:00
|
|
|
|
bool WrongType = false;
|
|
|
|
|
|
2016-04-04 14:48:12 +02:00
|
|
|
|
/***** Rest image file status *****/
|
|
|
|
|
Image->Status = Img_FILE_NONE;
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
|
|
|
|
/***** Get filename and MIME type *****/
|
2016-04-04 12:13:37 +02:00
|
|
|
|
Param = Fil_StartReceptionOfFile (ParamFile,FileNameImgSrc,MIMEType);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
if (!FileNameImgSrc[0]) // No file present
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/* Get filename extension */
|
|
|
|
|
if ((PtrExtension = strrchr (FileNameImgSrc,(int) '.')) == NULL)
|
|
|
|
|
return;
|
2016-04-04 03:00:12 +02:00
|
|
|
|
|
|
|
|
|
LengthExtension = strlen (PtrExtension);
|
2017-03-07 11:03:05 +01:00
|
|
|
|
if (LengthExtension < Fil_MIN_BYTES_FILE_EXTENSION ||
|
|
|
|
|
LengthExtension > Fil_MAX_BYTES_FILE_EXTENSION)
|
2016-04-03 01:24:57 +02:00
|
|
|
|
return;
|
2016-04-04 03:00:12 +02:00
|
|
|
|
|
2016-04-03 01:24:57 +02:00
|
|
|
|
/* Check if the file type is image/ or application/octet-stream */
|
|
|
|
|
if (strncmp (MIMEType,"image/",strlen ("image/")))
|
|
|
|
|
if (strcmp (MIMEType,"application/octet-stream"))
|
|
|
|
|
if (strcmp (MIMEType,"application/octetstream"))
|
|
|
|
|
if (strcmp (MIMEType,"application/octet"))
|
|
|
|
|
WrongType = true;
|
|
|
|
|
if (WrongType)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
/***** Assign a unique name for the image *****/
|
2016-04-04 14:48:12 +02:00
|
|
|
|
Cry_CreateUniqueNameEncrypted (Image->Name);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
|
|
|
|
/***** Create private directories if not exist *****/
|
|
|
|
|
/* Create private directory for images if it does not exist */
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (PathImgPriv,sizeof (PathImgPriv),
|
|
|
|
|
"%s/%s",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
Fil_CreateDirIfNotExists (PathImgPriv);
|
|
|
|
|
|
|
|
|
|
/* Create temporary private directory for images if it does not exist */
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (PathImgPriv,sizeof (PathImgPriv),
|
|
|
|
|
"%s/%s/%s",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,Cfg_FOLDER_IMG_TMP);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
Fil_CreateDirIfNotExists (PathImgPriv);
|
|
|
|
|
|
2016-04-05 14:04:23 +02:00
|
|
|
|
/***** Remove old temporary private files *****/
|
|
|
|
|
Fil_RemoveOldTmpFiles (PathImgPriv,Cfg_TIME_TO_DELETE_IMAGES_TMP_FILES,false);
|
|
|
|
|
|
2016-04-03 01:24:57 +02:00
|
|
|
|
/***** End the reception of original not processed image
|
|
|
|
|
(it can be very big) into a temporary file *****/
|
2016-04-04 14:48:12 +02:00
|
|
|
|
Image->Status = Img_FILE_NONE;
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (FileNameImgOrig,sizeof (FileNameImgOrig),
|
|
|
|
|
"%s/%s/%s/%s_original.%s",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,Cfg_FOLDER_IMG_TMP,
|
|
|
|
|
Image->Name,PtrExtension);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
if (Fil_EndReceptionOfFile (FileNameImgOrig,Param)) // Success
|
|
|
|
|
{
|
2016-04-04 14:48:12 +02:00
|
|
|
|
Image->Status = Img_FILE_RECEIVED;
|
2016-04-04 03:00:12 +02:00
|
|
|
|
|
2016-04-04 14:48:12 +02:00
|
|
|
|
/***** Convert original image to temporary JPEG processed file
|
|
|
|
|
by calling to program that makes the conversion *****/
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (FileNameImgTmp,sizeof (FileNameImgTmp),
|
|
|
|
|
"%s/%s/%s/%s.jpg",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,Cfg_FOLDER_IMG_TMP,
|
|
|
|
|
Image->Name);
|
2016-04-14 19:19:55 +02:00
|
|
|
|
Img_ProcessImage (Image,FileNameImgOrig,FileNameImgTmp);
|
2016-04-04 14:48:12 +02:00
|
|
|
|
Image->Status = Img_FILE_PROCESSED;
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
2016-04-04 14:48:12 +02:00
|
|
|
|
/***** Remove temporary original file *****/
|
2016-04-03 01:24:57 +02:00
|
|
|
|
unlink (FileNameImgOrig);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/************ Process original image generating processed image **************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-14 19:19:55 +02:00
|
|
|
|
static void Img_ProcessImage (struct Image *Image,
|
|
|
|
|
const char *FileNameImgOriginal,
|
|
|
|
|
const char *FileNameImgProcessed)
|
2016-04-03 01:24:57 +02:00
|
|
|
|
{
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char Command[1024 + PATH_MAX * 2];
|
2016-04-03 01:24:57 +02:00
|
|
|
|
int ReturnCode;
|
|
|
|
|
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (Command,sizeof (Command),
|
|
|
|
|
"convert %s -resize '%ux%u>' -quality %u %s",
|
|
|
|
|
FileNameImgOriginal,
|
|
|
|
|
Image->Width,
|
|
|
|
|
Image->Height,
|
|
|
|
|
Image->Quality,
|
|
|
|
|
FileNameImgProcessed);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
ReturnCode = system (Command);
|
|
|
|
|
if (ReturnCode == -1)
|
|
|
|
|
Lay_ShowErrorAndExit ("Error when running command to process image.");
|
|
|
|
|
|
|
|
|
|
/***** Write message depending on return code *****/
|
|
|
|
|
ReturnCode = WEXITSTATUS(ReturnCode);
|
|
|
|
|
if (ReturnCode != 0)
|
|
|
|
|
{
|
2018-10-16 23:08:04 +02:00
|
|
|
|
snprintf (Gbl.Alert.Txt,sizeof (Gbl.Alert.Txt),
|
2018-10-16 21:56:01 +02:00
|
|
|
|
"Image could not be processed successfully.<br />"
|
|
|
|
|
"Error code returned by the program of processing: %d",
|
|
|
|
|
ReturnCode);
|
2017-05-10 10:25:01 +02:00
|
|
|
|
Lay_ShowErrorAndExit (Gbl.Alert.Txt);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/**** Move temporary processed image file to definitive private directory ****/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-04 14:48:12 +02:00
|
|
|
|
void Img_MoveImageToDefinitiveDirectory (struct Image *Image)
|
2016-04-03 01:24:57 +02:00
|
|
|
|
{
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char PathImgPriv[PATH_MAX + 1];
|
|
|
|
|
char FileNameImgTmp[PATH_MAX + 1]; // Full name of temporary processed file
|
|
|
|
|
char FileNameImg[PATH_MAX + 1]; // Full name of definitive processed file
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
|
|
|
|
/***** Create subdirectory if it does not exist *****/
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (PathImgPriv,sizeof (PathImgPriv),
|
|
|
|
|
"%s/%s/%c%c",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,
|
|
|
|
|
Image->Name[0],
|
|
|
|
|
Image->Name[1]);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
Fil_CreateDirIfNotExists (PathImgPriv);
|
|
|
|
|
|
|
|
|
|
/***** Temporary processed file *****/
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (FileNameImgTmp,sizeof (FileNameImgTmp),
|
|
|
|
|
"%s/%s/%s/%s.jpg",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,Cfg_FOLDER_IMG_TMP,
|
|
|
|
|
Image->Name);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
|
|
|
|
/***** Definitive processed file *****/
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (FileNameImg,sizeof (FileNameImg),
|
|
|
|
|
"%s/%s/%c%c/%s.jpg",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,
|
|
|
|
|
Image->Name[0],
|
|
|
|
|
Image->Name[1],
|
|
|
|
|
Image->Name);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
|
|
|
|
/***** Move file *****/
|
|
|
|
|
if (rename (FileNameImgTmp,FileNameImg)) // Fail
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_ERROR,"Can not move file.");
|
2016-04-03 01:24:57 +02:00
|
|
|
|
else // Success
|
2016-04-04 14:48:12 +02:00
|
|
|
|
Image->Status = Img_FILE_MOVED;
|
2016-04-03 01:24:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/******************** Write the image of a test question *********************/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
2016-04-15 14:30:28 +02:00
|
|
|
|
void Img_ShowImage (struct Image *Image,
|
|
|
|
|
const char *ClassContainer,const char *ClassImg)
|
2016-04-03 01:24:57 +02:00
|
|
|
|
{
|
2016-04-05 14:04:23 +02:00
|
|
|
|
extern const char *Txt_Image_not_found;
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char FileNameImgPriv[PATH_MAX + 1];
|
|
|
|
|
char FullPathImgPriv[PATH_MAX + 1];
|
|
|
|
|
char URL[PATH_MAX + 1];
|
2016-04-15 14:30:28 +02:00
|
|
|
|
bool PutLink;
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
|
|
|
|
/***** If no image to show ==> nothing to do *****/
|
2016-04-04 14:48:12 +02:00
|
|
|
|
if (!Image->Name)
|
2016-04-03 01:24:57 +02:00
|
|
|
|
return;
|
2016-04-04 14:48:12 +02:00
|
|
|
|
if (!Image->Name[0])
|
2016-04-03 01:24:57 +02:00
|
|
|
|
return;
|
2016-04-04 14:48:12 +02:00
|
|
|
|
if (Image->Status != Img_NAME_STORED_IN_DB)
|
2016-04-03 01:24:57 +02:00
|
|
|
|
return;
|
|
|
|
|
|
2016-04-05 14:04:23 +02:00
|
|
|
|
/***** Create a temporary public directory used to show the image *****/
|
2016-04-03 01:24:57 +02:00
|
|
|
|
Brw_CreateDirDownloadTmp ();
|
|
|
|
|
|
|
|
|
|
/***** Build private path to image *****/
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (FileNameImgPriv,sizeof (FileNameImgPriv),
|
|
|
|
|
"%s.jpg",
|
|
|
|
|
Image->Name);
|
|
|
|
|
snprintf (FullPathImgPriv,sizeof (FullPathImgPriv),
|
|
|
|
|
"%s/%s/%c%c/%s",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,
|
|
|
|
|
Image->Name[0],
|
|
|
|
|
Image->Name[1],
|
|
|
|
|
FileNameImgPriv);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
|
2016-04-05 14:04:23 +02:00
|
|
|
|
/***** Check if private image file exists *****/
|
|
|
|
|
if (Fil_CheckIfPathExists (FullPathImgPriv))
|
|
|
|
|
{
|
|
|
|
|
/***** Create symbolic link from temporary public directory to private file
|
|
|
|
|
in order to gain access to it for showing/downloading *****/
|
|
|
|
|
Brw_CreateTmpPublicLinkToPrivateFile (FullPathImgPriv,FileNameImgPriv);
|
|
|
|
|
|
|
|
|
|
/***** Create URL pointing to symbolic link *****/
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (URL,sizeof (URL),
|
|
|
|
|
"%s/%s/%s/%s",
|
|
|
|
|
Cfg_URL_SWAD_PUBLIC,Cfg_FOLDER_FILE_BROWSER_TMP,
|
|
|
|
|
Gbl.FileBrowser.TmpPubDir,
|
|
|
|
|
FileNameImgPriv);
|
2016-04-05 14:04:23 +02:00
|
|
|
|
|
|
|
|
|
/***** Show image *****/
|
2016-04-15 14:30:28 +02:00
|
|
|
|
/* Check if optional link is present */
|
|
|
|
|
PutLink = false;
|
|
|
|
|
if (Image->URL)
|
|
|
|
|
if (Image->URL[0])
|
|
|
|
|
PutLink = true;
|
|
|
|
|
|
|
|
|
|
/* Start image container */
|
|
|
|
|
fprintf (Gbl.F.Out,"<div class=\"%s\">",ClassContainer);
|
|
|
|
|
|
|
|
|
|
/* Start optional link to external URL */
|
|
|
|
|
if (PutLink)
|
|
|
|
|
fprintf (Gbl.F.Out,"<a href=\"%s\" target=\"_blank\">",Image->URL);
|
|
|
|
|
|
|
|
|
|
/* Image */
|
|
|
|
|
fprintf (Gbl.F.Out,"<img src=\"%s\" class=\"%s\" alt=\"\"",URL,ClassImg);
|
2016-04-06 14:41:47 +02:00
|
|
|
|
if (Image->Title)
|
|
|
|
|
if (Image->Title[0])
|
|
|
|
|
fprintf (Gbl.F.Out," title=\"%s\"",Image->Title);
|
2016-04-15 14:30:28 +02:00
|
|
|
|
fprintf (Gbl.F.Out," />");
|
|
|
|
|
|
|
|
|
|
/* End optional link to external URL */
|
|
|
|
|
if (PutLink)
|
|
|
|
|
fprintf (Gbl.F.Out,"</a>");
|
|
|
|
|
|
|
|
|
|
/* End image container */
|
|
|
|
|
fprintf (Gbl.F.Out,"</div>");
|
2016-04-05 14:04:23 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
2017-05-11 23:45:46 +02:00
|
|
|
|
Ale_ShowAlert (Ale_WARNING,Txt_Image_not_found);
|
2016-04-03 01:24:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-03 14:18:43 +02:00
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
/** Remove private file with an image, given the image name (without .jpg) ***/
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
void Img_RemoveImageFile (const char *ImageName)
|
|
|
|
|
{
|
2017-01-28 15:58:46 +01:00
|
|
|
|
char FullPathImgPriv[PATH_MAX + 1];
|
2016-04-03 14:18:43 +02:00
|
|
|
|
|
2016-04-11 01:33:20 +02:00
|
|
|
|
if (ImageName[0])
|
|
|
|
|
{
|
|
|
|
|
/***** Build path to private file *****/
|
2018-10-18 02:02:32 +02:00
|
|
|
|
snprintf (FullPathImgPriv,sizeof (FullPathImgPriv),
|
|
|
|
|
"%s/%s/%c%c/%s.jpg",
|
|
|
|
|
Cfg_PATH_SWAD_PRIVATE,Cfg_FOLDER_IMG,
|
|
|
|
|
ImageName[0],
|
|
|
|
|
ImageName[1],
|
|
|
|
|
ImageName);
|
2016-04-03 14:18:43 +02:00
|
|
|
|
|
2016-04-11 01:33:20 +02:00
|
|
|
|
/***** Remove private file *****/
|
|
|
|
|
unlink (FullPathImgPriv);
|
2016-04-03 14:18:43 +02:00
|
|
|
|
|
2016-04-11 01:33:20 +02:00
|
|
|
|
// Public links are removed automatically after a period
|
|
|
|
|
}
|
2016-04-03 14:18:43 +02:00
|
|
|
|
}
|