1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
/*
netrik -- The ANTRIK Internet Viewer
Copyright (C) Olaf D. Buddenhagen AKA antrik, et al (see AUTHORS)
Published under the GNU GPL; see LICENSE for details.
*/
/*
* form-file.c -- file handling for "textarea" and "file" form controls
*
* (C) 2003 antrik
*/
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "form-file.h"
enum File_err {
ERR_NO=0,
ERR_OPEN,
ERR_SIZE,
ERR_READ
};
static enum File_err read_file(const char *file_name, struct Data_string *value);
/*
* Read file into memory.
*
* The file file_named "file_name" is opened and its content read into a newly
* malloced buffer; this buffer is stored in the "value" data string.
*
* If some error occured while reading the file, an appropriate error code is
* returned.
*/
static enum File_err read_file(file_name, value)
const char *file_name;
struct Data_string *value;
{
int fildes;
struct stat stat_buf;
int size;
char *data;
fildes=open(file_name, O_RDONLY);
if(fildes==-1) {
unlink(file_name);
return ERR_OPEN;
}
if(fstat(fildes, &stat_buf)==-1) {
close(fildes);
unlink(file_name);
return ERR_SIZE;
}
size=stat_buf.st_size;
data=malloc(size);
if(read(fildes, data, size)!=size) {
close(fildes);
unlink(file_name);
free(data);
return ERR_READ;
}
close(fildes);
/* store new data */
free(value->data);
value->data=data;
value->size=size;
return ERR_NO;
} /* read file */
/*
* Use external editor to edit the value of a "textarea" form input field.
*
* Creates a temporary file with the old contents of the input field, launches
* editor on that file, and reads new contents back.
*
* If some error occured in the system calls, a string describing the error is
* returned; NULL means no error.
*/
char *edit_textarea(value, name)
struct Data_string *value;
char *name;
{
/* external editor to use */
char *editor;
editor=getenv("EDITOR");
if(editor==NULL)
editor="vi";
if(!name)
name="";
/* write file/edit/read file */
{
/* get temp file name */
static const char format[]="netrik-textarea-%s-XXXXXX";
const int size=sizeof(format)+strlen(name);
char temp_name[size];
snprintf(temp_name, size, format, name);
/* make sure we get a proper filename */
{
char *chr;
for(chr=temp_name; *chr; ++chr)
if(!isalnum(*chr)) /* not safe filename char -> replace */
*chr='_';
}
/* write temporary file */
{
int fildes;
fildes=mkstemp(temp_name);
if(fildes==-1) {
return "failed to create temporary file";
}
if(write(fildes, value->data, value->size)!=value->size) {
close(fildes);
unlink(temp_name);
return "failed to write to temporary file";
}
if(close(fildes)==-1) {
unlink(temp_name);
return "failed to close temporary file after writing";
}
}
/* edit/read file */
{
/* get edit command */
static const char format[]="%s %s";
const int size=sizeof(format)+strlen(temp_name)+strlen(editor);
char edit_cmd[size];
snprintf(edit_cmd, size, format, editor, temp_name);
/* edit */
if(system(edit_cmd)!=0) {
unlink(temp_name);
return "invoking editor failed";
}
/* read temporary file */
{
enum File_err error;
error=read_file(temp_name, value);
switch(error) {
case ERR_NO: break;
case ERR_OPEN: return "failed to reopen temporary file";
case ERR_SIZE: return "failed to get file size";
case ERR_READ: return "failed to read from temporary file";
}
} /* read file */
} /* edit/read file */
unlink(temp_name);
} /* write file/edit/read file */
return NULL; /* no error */
}
/*
* Read a file into memory.
*
* The file contents is stored in a data string which is returned to the
* caller.
*
* If some error occured while reading the file, the "size" attribute of the
* data string is set to -1 to indicate no valid data.
*/
struct Data_string form_read_file(file_name)
const char *file_name;
{
struct Data_string value={NULL, 0};
enum File_err error;
error=read_file(file_name, &value);
if(error!=ERR_NO) {
static const char *err_str[]={
"", /* ERR_NO */
"open",
"get size of",
"read from"
};
fprintf(stderr, "\n\nfailed to %s file \"%s\" (to be submitted with form)\n", err_str[error], file_name);
value.size=-1;
}
return value;
}
|