1 /* Read and write a vips file.
2  *
3  * 22/5/08
4  * 	- from im_open.c, im_openin.c, im_desc_hd.c, im_readhist.c,
5  * 	  im_openout.c
6  * 19/3/09
7  *	- block mmaps of nodata images
8  * 12/5/09
9  *	- fix signed/unsigned warnings
10  * 12/10/09
11  *	- heh argh reading history always stopped after the first line
12  * 9/12/09
13  * 	- only wholly map input files on im_incheck() ... this reduces VM use,
14  * 	  especially with large numbers of small files
15  * 14/2/11
16  * 	- renamed to vips.c from im_open_vips.c, some stuff chopped out for
17  * 	  image.c ... this file now just does read / write to disc
18  * 28/3/11
19  * 	- moved to vips_ namespace
20  * 25/2/17
21  * 	- use expat for xml read, printf for xml write
22  * 16/8/17
23  * 	- validate strs as being utf-8 before we write
24  * 9/4/18 Alexander--
25  * 	- use O_TMPFILE, if available
26  * 23/7/18
27  * 	- escape ASCII control characters in XML
28  * 29/8/19
29  * 	- verify bands/format for coded images
30  */
31 
32 /*
33 
34     This file is part of VIPS.
35 
36     VIPS is free software; you can redistribute it and/or modify
37     it under the terms of the GNU Lesser General Public License as published by
38     the Free Software Foundation; either version 2 of the License, or
39     (at your option) any later version.
40 
41     This program is distributed in the hope that it will be useful,
42     but WITHOUT ANY WARRANTY; without even the implied warranty of
43     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
44     GNU Lesser General Public License for more details.
45 
46     You should have received a copy of the GNU Lesser General Public License
47     along with this program; if not, write to the Free Software
48     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
49     02110-1301  USA
50 
51  */
52 
53 /*
54 
55     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
56 
57  */
58 
59 /*
60 #define SHOW_HEADER
61 #define DEBUG
62  */
63 
64 /* Enable linux extensions like O_TMPFILE, if available.
65  */
66 #define _GNU_SOURCE
67 
68 #ifdef HAVE_CONFIG_H
69 #include <config.h>
70 #endif /*HAVE_CONFIG_H*/
71 #include <vips/intl.h>
72 
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <ctype.h>
77 
78 #include <stdio.h>
79 #include <assert.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <sys/types.h>
83 #include <sys/stat.h>
84 #include <fcntl.h>
85 #ifdef HAVE_SYS_FILE_H
86 #include <sys/file.h>
87 #endif /*HAVE_SYS_FILE_H*/
88 #ifdef HAVE_UNISTD_H
89 #include <unistd.h>
90 #endif /*HAVE_UNISTD_H*/
91 #ifdef HAVE_IO_H
92 #include <io.h>
93 #endif /*HAVE_IO_H*/
94 #include <expat.h>
95 #include <errno.h>
96 
97 #include <vips/vips.h>
98 
99 #ifdef G_OS_WIN32
100 #include <windows.h>
101 #endif /*G_OS_WIN32*/
102 
103 #include <vips/debug.h>
104 #include <vips/internal.h>
105 
106 /**
107  * SECTION: vips
108  * @short_description: startup, shutdown, version
109  * @stability: Stable
110  * @see_also: <link linkend="VipsOperation">VipsOperation</link>
111  * @include: vips/vips.h
112  *
113  * Start VIPS up, shut VIPS down, get version information, relocation.
114  *
115  * VIPS is a relocatable package, meaning you can move the directory tree you
116  * compiled it to at runtime and it will still be able to find all data files.
117  * This is required for OS X and Windows, but slightly unusual in the Unix
118  * world. See vips_init() and vips_guess_prefix().
119  */
120 
121 /* Open mode for image write.
122  *
123  * We use O_RDWR not O_WRONLY since after writing we may want to rewind the
124  * image and read from it.
125  */
126 #define MODE_WRITE CLOEXEC (BINARYIZE (O_RDWR | O_CREAT | O_TRUNC))
127 
128 /* Mode for read/write. This is if we might later want to mmaprw () the file.
129  */
130 #define MODE_READWRITE CLOEXEC (BINARYIZE (O_RDWR))
131 
132 /* Mode for read only. This is the fallback if READWRITE fails.
133  */
134 #define MODE_READONLY CLOEXEC (BINARYIZE (O_RDONLY))
135 
136 /* Our XML namespace.
137  */
138 #define NAMESPACE_URI "http://www.vips.ecs.soton.ac.uk/"
139 
140 /* Open for read for image files.
141  */
142 int
vips__open_image_read(const char * filename)143 vips__open_image_read( const char *filename )
144 {
145 	int fd;
146 
147 	/* Try to open read-write, so that calls to vips_image_inplace() will
148 	 * work. When we later mmap this file, we set read-only, so there
149 	 * is little danger of scrubbing over files we own.
150 	 */
151 	fd = vips_tracked_open( filename, MODE_READWRITE, 0 );
152 	if( fd == -1 )
153 		/* Open read-write failed. Fall back to open read-only.
154 		 */
155 		fd = vips_tracked_open( filename, MODE_READONLY, 0 );
156 
157 	if( fd == -1 ) {
158 		vips_error_system( errno, "VipsImage",
159 			_( "unable to open \"%s\"" ), filename );
160 		return( -1 );
161 	}
162 
163 	return( fd );
164 }
165 
166 /* Open for write for image files.
167  */
168 int
vips__open_image_write(const char * filename,gboolean temp)169 vips__open_image_write( const char *filename, gboolean temp )
170 {
171 	int flags;
172 	int fd;
173 
174 	fd = -1;
175 
176 #ifndef O_TMPFILE
177 	if( temp )
178 		g_info( "vips__open_image_write: O_TMPFILE not available" );
179 #endif /*!O_TMPFILE*/
180 
181 #ifdef O_TMPFILE
182 	/* Linux-only extension creates an unlinked file. CREAT and TRUNC must
183 	 * be clear. The filename arg to open() must name a directory.
184 	 *
185 	 * This can fail since not all filesystems support it. In this case,
186 	 * we open as a regular file and rely on the delete-on-close
187 	 * mechanism, see vips_image_delete().
188 	 */
189 	if( temp ) {
190 		char *dirname;
191 
192 		g_info( "vips__open_image_write: opening with O_TMPFILE" );
193 		dirname = g_path_get_dirname( filename );
194 		fd = vips_tracked_open( dirname, O_TMPFILE | O_RDWR , 0644 );
195 		g_free( dirname );
196 
197 		if( fd < 0 )
198 			g_info( "vips__open_image_write: O_TMPFILE failed!" );
199 	}
200 #endif /*O_TMPFILE*/
201 
202 	flags = MODE_WRITE;
203 
204 #ifdef _O_TEMPORARY
205 	/* On Windows, setting _O_TEMPORARY will delete the file automatically
206 	 * on process exit, even if the processes crashes.
207 	 */
208 	if( temp ) {
209 		g_info( "vips__open_image_write: setting _O_TEMPORARY" );
210 		flags |= _O_TEMPORARY;
211 	}
212 #endif /*_O_TEMPORARY*/
213 
214 	if( fd < 0 ) {
215 		g_info( "vips__open_image_write: simple open" );
216 		fd = vips_tracked_open( filename, flags, 0644 );
217 	}
218 
219 	if( fd < 0 ) {
220 		g_info( "vips__open_image_write: failed!" );
221 		vips_error_system( errno, "VipsImage",
222 			_( "unable to write to \"%s\"" ), filename );
223 		return( -1 );
224 	}
225 
226 	return( fd );
227 }
228 
229 /* Predict the size of the header plus pixel data. Don't use off_t,
230  * it's sometimes only 32 bits (eg. on many windows build environments) and we
231  * want to always be 64 bit.
232  */
233 static gint64
image_pixel_length(VipsImage * image)234 image_pixel_length( VipsImage *image )
235 {
236 	gint64 psize;
237 
238 	switch( image->Coding ) {
239 	case VIPS_CODING_LABQ:
240 	case VIPS_CODING_RAD:
241 	case VIPS_CODING_NONE:
242 		psize = VIPS_IMAGE_SIZEOF_IMAGE( image );
243 		break;
244 
245 	default:
246 		psize = image->Length;
247 		break;
248 	}
249 
250 	return( psize + image->sizeof_header );
251 }
252 
253 /* Copy 2 and 4 bytes, optionally swapping byte order.
254  */
255 void
vips__copy_4byte(int swap,unsigned char * to,unsigned char * from)256 vips__copy_4byte( int swap, unsigned char *to, unsigned char *from )
257 {
258 	guint32 *in = (guint32 *) from;
259 	guint32 *out = (guint32 *) to;
260 
261 	if( swap )
262 		*out = GUINT32_SWAP_LE_BE( *in );
263 	else
264 		*out = *in;
265 }
266 
267 void
vips__copy_2byte(gboolean swap,unsigned char * to,unsigned char * from)268 vips__copy_2byte( gboolean swap, unsigned char *to, unsigned char *from )
269 {
270 	guint16 *in = (guint16 *) from;
271 	guint16 *out = (guint16 *) to;
272 
273 	if( swap )
274 		*out = GUINT16_SWAP_LE_BE( *in );
275 	else
276 		*out = *in;
277 }
278 
279 guint32
vips__file_magic(const char * filename)280 vips__file_magic( const char *filename )
281 {
282 	guint32 magic;
283 
284 	if( vips__get_bytes( filename, (unsigned char *) &magic, 4 ) == 4 &&
285 		(magic == VIPS_MAGIC_INTEL ||
286 		 magic == VIPS_MAGIC_SPARC) )
287 		return( magic );
288 
289 	return( 0 );
290 }
291 
292 /* offset, read, write functions.
293  */
294 typedef struct _FieldIO {
295 	glong offset;
296 	int size;
297 	void (*copy)( gboolean swap, unsigned char *to, unsigned char *from );
298 } FieldIO;
299 
300 static FieldIO fields[] = {
301 	{ G_STRUCT_OFFSET( VipsImage, Xsize ), 4, vips__copy_4byte },
302 	{ G_STRUCT_OFFSET( VipsImage, Ysize ), 4, vips__copy_4byte },
303 	{ G_STRUCT_OFFSET( VipsImage, Bands ), 4, vips__copy_4byte },
304 	{ G_STRUCT_OFFSET( VipsImage, Bbits ), 4, vips__copy_4byte },
305 	{ G_STRUCT_OFFSET( VipsImage, BandFmt ), 4, vips__copy_4byte },
306 	{ G_STRUCT_OFFSET( VipsImage, Coding ), 4, vips__copy_4byte },
307 	{ G_STRUCT_OFFSET( VipsImage, Type ), 4, vips__copy_4byte },
308 	{ G_STRUCT_OFFSET( VipsImage, Xres_float ), 4, vips__copy_4byte },
309 	{ G_STRUCT_OFFSET( VipsImage, Yres_float ), 4, vips__copy_4byte },
310 	{ G_STRUCT_OFFSET( VipsImage, Length ), 4, vips__copy_4byte },
311 	{ G_STRUCT_OFFSET( VipsImage, Compression ), 2, vips__copy_2byte },
312 	{ G_STRUCT_OFFSET( VipsImage, Level ), 2, vips__copy_2byte },
313 	{ G_STRUCT_OFFSET( VipsImage, Xoffset ), 4, vips__copy_4byte },
314 	{ G_STRUCT_OFFSET( VipsImage, Yoffset ), 4, vips__copy_4byte }
315 };
316 
317 int
vips__read_header_bytes(VipsImage * im,unsigned char * from)318 vips__read_header_bytes( VipsImage *im, unsigned char *from )
319 {
320 	gboolean swap;
321 	int i;
322 	GEnumValue *value;
323 
324 #ifdef SHOW_HEADER
325 	printf( "vips__read_header_bytes: file bytes:\n" );
326 	for( i = 0; i < im->sizeof_header; i++ )
327 		printf( "%2d - 0x%02x\n", i, from[i] );
328 #endif /*SHOW_HEADER*/
329 
330 	/* The magic number is always written MSB first, we may need to swap.
331 	 */
332 	vips__copy_4byte( !vips_amiMSBfirst(),
333 		(unsigned char *) &im->magic, from );
334 	from += 4;
335 	if( im->magic != VIPS_MAGIC_INTEL &&
336 		im->magic != VIPS_MAGIC_SPARC ) {
337 		vips_error( "VipsImage",
338 			_( "\"%s\" is not a VIPS image" ), im->filename );
339 		return( -1 );
340 	}
341 
342 	/* We need to swap for other fields if the file byte order is
343 	 * different from ours.
344 	 */
345 	swap = vips_amiMSBfirst() != vips_image_isMSBfirst( im );
346 
347 	for( i = 0; i < VIPS_NUMBER( fields ); i++ ) {
348 		fields[i].copy( swap,
349 			&G_STRUCT_MEMBER( unsigned char, im, fields[i].offset ),
350 			from );
351 		from += fields[i].size;
352 	}
353 
354 	/* Set this ourselves ... bbits is deprecated in the file format.
355 	 */
356 	im->Bbits = vips_format_sizeof( im->BandFmt ) << 3;
357 
358 	/* We read xres/yres as floats to a staging area, then copy to double
359 	 * in the main fields.
360 	 */
361 	im->Xres = im->Xres_float;
362 	im->Yres = im->Yres_float;
363 
364 	/* Some protection against malicious files. We also check predicted
365 	 * (based on these values) against real file length, see below.
366 	 */
367 	im->Xsize = VIPS_CLIP( 1, im->Xsize, VIPS_MAX_COORD );
368 	im->Ysize = VIPS_CLIP( 1, im->Ysize, VIPS_MAX_COORD );
369 	im->Bands = VIPS_CLIP( 1, im->Bands, VIPS_MAX_COORD );
370 	im->BandFmt = VIPS_CLIP( 0, im->BandFmt, VIPS_FORMAT_LAST - 1 );
371 
372 	/* Coding and Type have missing values, so we look up in the enum.
373 	 */
374 	value = g_enum_get_value( g_type_class_ref( VIPS_TYPE_INTERPRETATION ),
375 		im->Type );
376 	if( !value ||
377 		strcmp( value->value_nick, "last" ) == 0 )
378 		im->Type = VIPS_INTERPRETATION_ERROR;
379 	value = g_enum_get_value( g_type_class_ref( VIPS_TYPE_CODING ),
380 		im->Coding );
381 	if( !value ||
382 		strcmp( value->value_nick, "last" ) == 0 )
383 		im->Coding = VIPS_CODING_ERROR;
384 
385 	/* Offset, Res, etc. don't affect vips file layout, just
386 	 * pixel interpretation, don't clip them.
387 	 */
388 
389 	/* Coding values imply Bands and BandFmt settings --- make sure they
390 	 * are sane.
391 	 */
392 	switch( im->Coding ) {
393 	case VIPS_CODING_ERROR:
394 		vips_error( "VipsImage",
395 			"%s", _( "unknown coding" ) );
396 		return( -1 );
397 
398 	case VIPS_CODING_NONE:
399 		break;
400 
401 	case VIPS_CODING_LABQ:
402 		if( im->Bands != 4 ||
403 			im->BandFmt != VIPS_FORMAT_UCHAR ) {
404 			vips_error( "VipsImage",
405 				"%s", _( "malformed LABQ image" ) );
406 			return( -1 );
407 		}
408 		break;
409 
410 	case VIPS_CODING_RAD:
411 		if( im->Bands != 4 ||
412 			im->BandFmt != VIPS_FORMAT_UCHAR ) {
413 			vips_error( "VipsImage",
414 				"%s", _( "malformed RAD image" ) );
415 			return( -1 );
416 		}
417 		break;
418 
419 	default:
420 		g_assert_not_reached();
421 		break;
422 	}
423 
424 	return( 0 );
425 }
426 
427 int
vips__write_header_bytes(VipsImage * im,unsigned char * to)428 vips__write_header_bytes( VipsImage *im, unsigned char *to )
429 {
430 	/* Swap if the byte order we are asked to write the header in is
431 	 * different from ours.
432 	 */
433 	gboolean swap = vips_amiMSBfirst() != vips_image_isMSBfirst( im );
434 
435 	int i;
436 	unsigned char *q;
437 
438 	/* We set xres/yres as floats in a staging area, then copy those
439 	 * smaller values to the file.
440 	 */
441 	im->Xres_float = im->Xres;
442 	im->Yres_float = im->Yres;
443 
444 	/* Always write the magic number MSB first.
445 	 */
446 	vips__copy_4byte( !vips_amiMSBfirst(),
447 		to, (unsigned char *) &im->magic );
448 	q = to + 4;
449 
450 	for( i = 0; i < VIPS_NUMBER( fields ); i++ ) {
451 		fields[i].copy( swap,
452 			q,
453 			&G_STRUCT_MEMBER( unsigned char, im,
454 				fields[i].offset ) );
455 		q += fields[i].size;
456 	}
457 
458 	/* Pad spares with zeros.
459 	 */
460 	while( q - to < im->sizeof_header )
461 		*q++ = 0;
462 
463 #ifdef SHOW_HEADER
464 	printf( "vips__write_header_bytes: file bytes:\n" );
465 	for( i = 0; i < im->sizeof_header; i++ )
466 		printf( "%2d - 0x%02x\n", i, to[i] );
467 #endif /*SHOW_HEADER*/
468 
469 	return( 0 );
470 }
471 
472 /* Read a chunk of an fd into memory. Add a '\0' at the end.
473  */
474 static char *
read_chunk(int fd,gint64 offset,size_t length)475 read_chunk( int fd, gint64 offset, size_t length )
476 {
477 	char *buf;
478 
479 	if( vips__seek( fd, offset, SEEK_SET ) == -1 )
480 		return( NULL );
481 	if( !(buf = vips_malloc( NULL, length + 1 )) )
482 		return( NULL );
483 	if( read( fd, buf, length ) != (ssize_t) length ) {
484 		g_free( buf );
485 		vips_error( "VipsImage", "%s", _( "unable to read history" ) );
486 		return( NULL );
487 	}
488 	buf[length] = '\0';
489 
490 	return( buf );
491 }
492 
493 /* Does it look like an image has an extension block?
494  */
495 int
vips__has_extension_block(VipsImage * im)496 vips__has_extension_block( VipsImage *im )
497 {
498 	gint64 psize;
499 
500 	psize = image_pixel_length( im );
501 	g_assert( im->file_length > 0 );
502 
503 	return( im->file_length - psize > 0 );
504 }
505 
506 /* Read everything after the pixels into memory.
507  */
508 void *
vips__read_extension_block(VipsImage * im,int * size)509 vips__read_extension_block( VipsImage *im, int *size )
510 {
511 	gint64 psize;
512 	void *buf;
513 
514 	psize = image_pixel_length( im );
515 	g_assert( im->file_length > 0 );
516 	if( im->file_length - psize > 100 * 1024 * 1024 ) {
517 		vips_error( "VipsImage",
518 			"%s", _( "more than 100 megabytes of XML? "
519 			"sufferin' succotash!" ) );
520 		return( NULL );
521 	}
522 	if( im->file_length - psize == 0 )
523 		return( NULL );
524 	if( !(buf = read_chunk( im->fd, psize, im->file_length - psize )) )
525 		return( NULL );
526 	if( size )
527 		*size = im->file_length - psize;
528 
529 #ifdef DEBUG
530 	printf( "vips__read_extension_block: read %d bytes from %s\n",
531 		(int) (im->file_length - psize), im->filename );
532 	printf( "data: \"%s\"\n", (char *) buf );
533 #endif /*DEBUG*/
534 
535 	return( buf );
536 }
537 
538 static int
parser_read_fd(XML_Parser parser,int fd)539 parser_read_fd( XML_Parser parser, int fd )
540 {
541 	const int chunk_size = 1024;
542 
543 	gint64 bytes_read;
544 	gint64 len;
545 
546 	bytes_read = 0;
547 
548 	do {
549 		void *buf;
550 
551 		if( !(buf = XML_GetBuffer( parser, chunk_size )) ) {
552 			vips_error( "VipsImage",
553 				"%s", _( "unable to allocate read buffer" ) );
554 			return( -1 );
555 		}
556 		len = read( fd, buf, chunk_size );
557 		if( len == -1 ) {
558 			vips_error( "VipsImage",
559 				"%s", _( "read error while fetching XML" ) );
560 			return( -1 );
561 		}
562 
563 		/* Allow missing XML block.
564 		 */
565 		if( bytes_read == 0 &&
566 			len == 0 )
567 			break;
568 		bytes_read += len;
569 
570 		if( !XML_ParseBuffer( parser, len, len == 0 ) ) {
571 			vips_error( "VipsImage", "%s", _( "XML parse error" ) );
572 			return( -1 );
573 		}
574 	} while( len > 0 );
575 
576 	return( 0 );
577 }
578 
579 #define MAX_PARSE_ATTR (256)
580 
581 /* What we track during expat parse.
582  */
583 typedef struct _VipsExpatParse {
584 	VipsImage *image;
585 
586 	/* Set on error.
587 	 */
588 	gboolean error;
589 
590 	/* TRUE for in header section.
591 	 */
592 	gboolean header;
593 
594 	/* For the current node, the type and name.
595 	 */
596 	XML_Char type[MAX_PARSE_ATTR];
597 	XML_Char name[MAX_PARSE_ATTR];
598 
599 	/* Accumulate data here.
600 	 */
601 	VipsDbuf dbuf;
602 } VipsExpatParse;
603 
604 static void
parser_element_start_handler(void * user_data,const XML_Char * name,const XML_Char ** atts)605 parser_element_start_handler( void *user_data,
606 	const XML_Char *name, const XML_Char **atts )
607 {
608 	VipsExpatParse *vep = (VipsExpatParse *) user_data;
609 	const XML_Char **p;
610 
611 #ifdef DEBUG
612 	printf( "parser_element_start: %s\n", name );
613 	for( p = atts; *p; p += 2 )
614 		printf( "%s = %s\n", p[0], p[1] );
615 #endif /*DEBUG*/
616 
617 	if( strcmp( name, "field" ) == 0 ) {
618 		for( p = atts; *p; p += 2 ) {
619 			if( strcmp( p[0], "name" ) == 0 )
620 				vips_strncpy( vep->name, p[1], MAX_PARSE_ATTR );
621 			if( strcmp( p[0], "type" ) == 0 )
622 				vips_strncpy( vep->type, p[1], MAX_PARSE_ATTR );
623 		}
624 
625 		vips_dbuf_reset( &vep->dbuf );
626 	}
627 	else if( strcmp( name, "header" ) == 0 )
628 		vep->header = TRUE;
629 	else if( strcmp( name, "meta" ) == 0 )
630 		vep->header = FALSE;
631 	else if( strcmp( name, "root" ) == 0 ) {
632 		for( p = atts; *p; p += 2 )
633 			if( strcmp( p[0], "xmlns" ) == 0 &&
634 				!vips_isprefix( NAMESPACE_URI "vips", p[1] ) ) {
635 				vips_error( "VipsImage", "%s",
636 					_( "incorrect namespace in XML" ) );
637 				vep->error = TRUE;
638 			}
639 	}
640 }
641 
642 /* Chop history into lines, add each one as a refstring.
643  */
644 static void
set_history(VipsImage * im,char * history)645 set_history( VipsImage *im, char *history )
646 {
647 	GSList *history_list;
648 	char *p, *q;
649 
650 	/* There can be history there already if we're rewinding.
651 	 */
652 	VIPS_FREEF( vips__gslist_gvalue_free, im->history_list );
653 
654 	history_list = NULL;
655 
656 	for( p = history; *p; p = q ) {
657 		if( (q = strchr( p, '\n' )) ) {
658 			*q = '\0';
659 			q += 1;
660 		}
661 		else
662 			q = p + strlen( p );
663 
664 		history_list = g_slist_prepend( history_list,
665 			vips__gvalue_ref_string_new( p ) );
666 	}
667 
668 	im->history_list = g_slist_reverse( history_list );
669 }
670 
671 static int
set_meta(VipsImage * image,GType gtype,const char * name,const char * data)672 set_meta( VipsImage *image, GType gtype, const char *name, const char *data )
673 {
674 	GValue save_value = { 0 };
675 	GValue value = { 0 };
676 
677 	g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
678 	vips_value_set_save_string( &save_value, data );
679 
680 	g_value_init( &value, gtype );
681 	if( !g_value_transform( &save_value, &value ) ) {
682 		g_value_unset( &save_value );
683 		vips_error( "VipsImage", "%s",
684 			_( "error transforming from save format" ) );
685 		return( -1 );
686 	}
687 
688 	vips_image_set( image, name, &value );
689 	g_value_unset( &save_value );
690 	g_value_unset( &value );
691 
692 	return( 0 );
693 }
694 
695 static void
parser_element_end_handler(void * user_data,const XML_Char * name)696 parser_element_end_handler( void *user_data, const XML_Char *name )
697 {
698 	VipsExpatParse *vep = (VipsExpatParse *) user_data;
699 
700 #ifdef DEBUG
701 	printf( "parser_element_end_handler: %s\n", name );
702 #endif /*DEBUG*/
703 
704 	if( strcmp( name, "field" ) == 0 ) {
705 		if( vep->header ) {
706 			if( strcmp( name, "Hist" ) == 0 )
707 				set_history( vep->image,
708 					(char *) vips_dbuf_string( &vep->dbuf,
709 						NULL ) );
710 		}
711 		else {
712 			GType gtype = g_type_from_name( vep->type );
713 
714 			/* Can we convert from VIPS_SAVE_STRING to type?
715 			 */
716 			if( gtype &&
717 				g_value_type_transformable(
718 					VIPS_TYPE_SAVE_STRING, gtype ) &&
719 				set_meta( vep->image,
720 					gtype, vep->name,
721 					(char *) vips_dbuf_string( &vep->dbuf,
722 						NULL ) ) )
723 				vep->error = TRUE;
724 		}
725 	}
726 }
727 
728 static void
parser_data_handler(void * user_data,const XML_Char * data,int len)729 parser_data_handler( void *user_data, const XML_Char *data, int len )
730 {
731 	VipsExpatParse *vep = (VipsExpatParse *) user_data;
732 
733 #ifdef DEBUG
734 	printf( "parser_data_handler: %d bytes\n", len );
735 #endif /*DEBUG*/
736 
737 	vips_dbuf_write( &vep->dbuf, (unsigned char *) data, len );
738 }
739 
740 /* Called at the end of vips open ... get any XML after the pixel data
741  * and read it in.
742  */
743 static int
readhist(VipsImage * im)744 readhist( VipsImage *im )
745 {
746 	XML_Parser parser;
747 	VipsExpatParse vep;
748 
749 	if( vips__seek( im->fd, image_pixel_length( im ), SEEK_SET ) == -1 )
750 		return( -1 );
751 
752 	parser = XML_ParserCreate( "UTF-8" );
753 
754 	vep.image = im;
755 	vips_dbuf_init( &vep.dbuf );
756 	vep.error = FALSE;
757 	XML_SetUserData( parser, &vep );
758 
759 	XML_SetElementHandler( parser,
760 		parser_element_start_handler, parser_element_end_handler );
761 	XML_SetCharacterDataHandler( parser, parser_data_handler );
762 
763 	if( parser_read_fd( parser, im->fd ) ||
764 		vep.error ) {
765 		vips_dbuf_destroy( &vep.dbuf );
766 		XML_ParserFree( parser );
767 		return( -1 );
768 	}
769 
770 	vips_dbuf_destroy( &vep.dbuf );
771 	XML_ParserFree( parser );
772 
773 	return( 0 );
774 }
775 
776 int
vips__write_extension_block(VipsImage * im,void * buf,int size)777 vips__write_extension_block( VipsImage *im, void *buf, int size )
778 {
779 	gint64 length;
780 	gint64 psize;
781 
782 	psize = image_pixel_length( im );
783 	if( (length = vips_file_length( im->fd )) == -1 )
784 		return( -1 );
785 	if( length < psize ) {
786 		vips_error( "VipsImage", "%s", _( "file has been truncated" ) );
787 		return( -1 );
788 	}
789 
790 	if( vips__ftruncate( im->fd, psize ) ||
791 		vips__seek( im->fd, psize, SEEK_SET ) == -1 )
792 		return( -1 );
793 	if( vips__write( im->fd, buf, size ) )
794                 return( -1 );
795 
796 #ifdef DEBUG
797 	printf( "vips__write_extension_block: written %d bytes of XML to %s\n",
798 		size, im->filename );
799 #endif /*DEBUG*/
800 
801 	return( 0 );
802 }
803 
804 /* Append a string to a buffer, but escape " as \".
805  */
806 static void
target_write_quotes(VipsTarget * target,const char * str)807 target_write_quotes( VipsTarget *target, const char *str )
808 {
809 	const char *p;
810 	size_t len;
811 
812 	for( p = str; *p; p += len ) {
813 		len = strcspn( p, "\"" );
814 
815 		vips_target_write( target, (unsigned char *) p, len );
816 		if( p[len] == '"' )
817 			vips_target_writes( target, "\\" );
818 	}
819 }
820 
821 static void *
build_xml_meta(VipsMeta * meta,VipsTarget * target,void * b)822 build_xml_meta( VipsMeta *meta, VipsTarget *target, void *b )
823 {
824 	GType type = G_VALUE_TYPE( &meta->value );
825 
826 	const char *str;
827 
828 	/* If we can transform to VIPS_TYPE_SAVE_STRING and back, we can save
829 	 * and restore.
830 	 */
831 	if( g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) &&
832 		g_value_type_transformable( VIPS_TYPE_SAVE_STRING, type ) ) {
833 		GValue save_value = { 0 };
834 
835 		g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
836 		if( !g_value_transform( &meta->value, &save_value ) ) {
837 			vips_error( "VipsImage", "%s",
838 				_( "error transforming to save format" ) );
839 			return( meta );
840 		}
841 
842 		/* We need to validate the str to make sure we'll be able to
843 		 * read it back.
844 		 */
845 		str = vips_value_get_save_string( &save_value );
846 		if( g_utf8_validate( str, -1, NULL ) ) {
847 			vips_target_writef( target,
848 				"    <field type=\"%s\" name=\"",
849 				g_type_name( type ) );
850 			target_write_quotes( target, meta->name );
851 			vips_target_writes( target, "\">" );
852 			vips_target_write_amp( target, str );
853 			vips_target_writes( target, "</field>\n" );
854 		}
855 
856 		g_value_unset( &save_value );
857 	}
858 
859 	return( NULL );
860 }
861 
862 /* Make the xml we append to vips images after the pixel data.
863  */
864 static char *
build_xml(VipsImage * image)865 build_xml( VipsImage *image )
866 {
867 	VipsTarget *target;
868 	const char *str;
869 	char *result;
870 
871 	target = vips_target_new_to_memory();
872 
873 	vips_target_writef( target, "<?xml version=\"1.0\"?>\n" );
874 	vips_target_writef( target, "<root xmlns=\"%svips/%d.%d.%d\">\n",
875 		NAMESPACE_URI,
876 		VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
877 	vips_target_writef( target, "  <header>\n" );
878 
879 	str = vips_image_get_history( image );
880 	if( g_utf8_validate( str, -1, NULL ) ) {
881 		vips_target_writef( target,
882 			"    <field type=\"%s\" name=\"Hist\">",
883 			g_type_name( VIPS_TYPE_REF_STRING ) );
884 		vips_target_write_amp( target, str );
885 		vips_target_writef( target, "</field>\n" );
886 	}
887 
888 	vips_target_writef( target, "  </header>\n" );
889 	vips_target_writef( target, "  <meta>\n" );
890 
891 	if( vips_slist_map2( image->meta_traverse,
892 		(VipsSListMap2Fn) build_xml_meta, target, NULL ) ) {
893 		VIPS_UNREF( target );
894 		return( NULL );
895 	}
896 
897 	vips_target_writef( target, "  </meta>\n" );
898 	vips_target_writef( target, "</root>\n" );
899 
900 	result = vips_target_steal_text( target );
901 
902 	VIPS_UNREF( target );
903 
904 	return( result );
905 }
906 
907 static void *
vips__xml_properties_meta(VipsImage * image,const char * field,GValue * value,void * a)908 vips__xml_properties_meta( VipsImage *image,
909 	const char *field, GValue *value, void *a )
910 {
911 	VipsTarget *target = (VipsTarget *) a;
912 	GType type = G_VALUE_TYPE( value );
913 
914 	const char *str;
915 
916 	/* If we can transform to VIPS_TYPE_SAVE_STRING and back, we can save
917 	 * and restore.
918 	 */
919 	if( g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) &&
920 		g_value_type_transformable( VIPS_TYPE_SAVE_STRING, type ) ) {
921 		GValue save_value = { 0 };
922 
923 		g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
924 		if( !g_value_transform( value, &save_value ) ) {
925 			vips_error( "VipsImage", "%s",
926 				_( "error transforming to save format" ) );
927 			return( target );
928 		}
929 		str = vips_value_get_save_string( &save_value );
930 
931 		vips_target_writef( target, "    <property>\n" );
932 		vips_target_writef( target, "      <name>" );
933 		vips_target_write_amp( target, field );
934 		vips_target_writef( target, "</name>\n" );
935 		vips_target_writef( target, "      <value type=\"%s\">",
936 			g_type_name( type ) );
937 		vips_target_write_amp( target, str );
938 		vips_target_writef( target, "</value>\n" );
939 		vips_target_writef( target, "    </property>\n" );
940 
941 		g_value_unset( &save_value );
942 	}
943 
944 	return( NULL );
945 }
946 
947 /* Make the xml we write to vips-properties in dzsave, or to TIFF. A simple
948  * dump of all vips metadata. Free with g_free().
949  */
950 char *
vips__xml_properties(VipsImage * image)951 vips__xml_properties( VipsImage *image )
952 {
953 	VipsTarget *target;
954 	char *date;
955 	char *result;
956 
957 	date = vips__get_iso8601();
958 
959 	target = vips_target_new_to_memory();
960 	vips_target_writef( target, "<?xml version=\"1.0\"?>\n" );
961 	vips_target_writef( target, "<image xmlns=\"%s/dzsave\" "
962 		"date=\"%s\" version=\"%d.%d.%d\">\n",
963 		NAMESPACE_URI,
964 		date,
965 		VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
966 	vips_target_writef( target, "  <properties>\n" );
967 
968 	g_free( date );
969 
970 	if( vips_image_map( image, vips__xml_properties_meta, target ) ) {
971 		VIPS_UNREF( target );
972 		return( NULL );
973 	}
974 
975 	vips_target_writef( target, "  </properties>\n" );
976 	vips_target_writef( target, "</image>\n" );
977 
978 	result = vips_target_steal_text( target );
979 
980 	VIPS_UNREF( target );
981 
982 	return( result );
983 }
984 
985 /* Append XML to output fd.
986  */
987 int
vips__writehist(VipsImage * image)988 vips__writehist( VipsImage *image )
989 {
990 	char *xml;
991 
992 	assert( image->dtype == VIPS_IMAGE_OPENOUT );
993 	assert( image->fd != -1 );
994 
995 	if( !(xml = build_xml( image )) )
996 		return( -1 );
997 
998 	if( vips__write_extension_block( image, xml, strlen( xml ) ) ) {
999 		g_free( xml );
1000                 return( -1 );
1001         }
1002 
1003 #ifdef DEBUG
1004 	printf( "vips__writehist: saved XML is: \"%s\"\n", xml );
1005 #endif /*DEBUG*/
1006 
1007 	g_free( xml );
1008 
1009 	return( 0 );
1010 }
1011 
1012 /* Open the filename, read the header, some sanity checking.
1013  */
1014 int
vips_image_open_input(VipsImage * image)1015 vips_image_open_input( VipsImage *image )
1016 {
1017 	/* We don't use im->sizeof_header here, but we know we're reading a
1018 	 * VIPS image anyway.
1019 	 */
1020 	unsigned char header[VIPS_SIZEOF_HEADER];
1021 
1022 	gint64 psize;
1023 	gint64 rsize;
1024 
1025 	image->dtype = VIPS_IMAGE_OPENIN;
1026 
1027 	/* We may have an fd already, see vips_image_rewind_output().
1028 	 */
1029 	if( image->fd == -1 ) {
1030 		image->fd = vips__open_image_read( image->filename );
1031 		if( image->fd == -1 )
1032 			return( -1 );
1033 	}
1034 
1035 	vips__seek( image->fd, 0, SEEK_SET );
1036 	if( read( image->fd, header, VIPS_SIZEOF_HEADER ) !=
1037 		VIPS_SIZEOF_HEADER ||
1038 		vips__read_header_bytes( image, header ) ) {
1039 		vips_error_system( errno, "VipsImage",
1040 			_( "unable to read header for \"%s\"" ),
1041 			image->filename );
1042 		return( -1 );
1043 	}
1044 
1045 	/* Predict and check the file size. Only issue a warning, we want to be
1046 	 * able to read all the header fields we can, even if the actual data
1047 	 * isn't there.
1048 	 */
1049 	psize = image_pixel_length( image );
1050 	if( (rsize = vips_file_length( image->fd )) == -1 )
1051 		return( -1 );
1052 	image->file_length = rsize;
1053 	if( psize > rsize )
1054 		g_warning( _( "unable to read data for \"%s\", %s" ),
1055 			image->filename, _( "file has been truncated" ) );
1056 
1057 	/* Set demand style. This suits a disc file we read sequentially.
1058 	 */
1059 	image->dhint = VIPS_DEMAND_STYLE_THINSTRIP;
1060 
1061 	/* Set the history part of im descriptor. Don't return an error if this
1062 	 * fails (due to eg. corrupted XML) because it's probably mostly
1063 	 * harmless.
1064 	 */
1065 	if( readhist( image ) ) {
1066 		g_warning( _( "error reading vips image metadata: %s" ),
1067 			vips_error_buffer() );
1068 		vips_error_clear();
1069 	}
1070 
1071 	return( 0 );
1072 }
1073 
1074 int
vips_image_open_output(VipsImage * image)1075 vips_image_open_output( VipsImage *image )
1076 {
1077 	if( image->fd == -1 ) {
1078 		/* Don't use im->sizeof_header here, but we know we're
1079 		 * writing a VIPS image anyway.
1080 		 */
1081 		unsigned char header[VIPS_SIZEOF_HEADER];
1082 
1083 		if( (image->fd = vips__open_image_write( image->filename,
1084 			image->delete_on_close )) < 0 )
1085 			return( -1 );
1086 
1087 		/* We always write in native mode, so we must overwrite the
1088 		 * magic we read from the file originally.
1089 		 */
1090 		image->magic = vips_amiMSBfirst() ?
1091 			VIPS_MAGIC_SPARC : VIPS_MAGIC_INTEL;
1092 
1093 		if( vips__write_header_bytes( image, header ) ||
1094 			vips__write( image->fd, header, VIPS_SIZEOF_HEADER ) )
1095 			return( -1 );
1096 	}
1097 
1098 	return( 0 );
1099 }
1100