diff options
| author | Thies C. Arntzen <thies@php.net> | 1999-07-05 07:42:07 +0000 |
|---|---|---|
| committer | Thies C. Arntzen <thies@php.net> | 1999-07-05 07:42:07 +0000 |
| commit | ad0076ee5318bba0c055c28271d6810c53db6f40 (patch) | |
| tree | a78e32db7af0b76cae871c20cdc8776531f39f21 | |
| parent | e9cb3539ad24d0a3c60b30fd7c21f315f76dc367 (diff) | |
| download | php-git-ad0076ee5318bba0c055c28271d6810c53db6f40.tar.gz | |
ported IPTC fro php3
| -rw-r--r-- | ext/standard/basic_functions.c | 1 | ||||
| -rw-r--r-- | ext/standard/iptc.c | 301 | ||||
| -rw-r--r-- | ext/standard/php3_iptc.h | 1 |
3 files changed, 286 insertions, 17 deletions
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 8ddde08a6e..d182714053 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -129,6 +129,7 @@ function_entry basic_functions[] = { {"md5", php3_md5, NULL}, {"iptcparse", php3_iptcparse, NULL}, + {"iptcembed", php3_iptcembed, NULL}, {"parse_url", php3_parse_url, NULL}, {"parse_str", php3_parsestr, NULL}, diff --git a/ext/standard/iptc.c b/ext/standard/iptc.c index 5fe1a3ffbe..7b017ebb7a 100644 --- a/ext/standard/iptc.c +++ b/ext/standard/iptc.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP HTML Embedded Scripting Language Version 3.0 | +----------------------------------------------------------------------+ - | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + | Copyright (c) 1997-1999 PHP Development Team (See Credits file) | +----------------------------------------------------------------------+ | This program is free software; you can redistribute it and/or modify | | it under the terms of one of the following licenses: | @@ -33,31 +33,292 @@ * Functions to parse & compse IPTC data. * PhotoShop >= 3.0 can read and write textual data to JPEG files. * ... more to come ..... + * + * i know, parts of this is now duplicated in image.c + * but in this case i think it's okay! */ /* * TODO: * - add IPTC translation table - * - implement a call to embed iptc into a JPEG file */ #include "php.h" #include "php3_iptc.h" +#include "ext/standard/head.h" +#include <sys/stat.h> + + +/* some defines for the different JPEG block types */ +#define M_SOF0 0xC0 /* Start Of Frame N */ +#define M_SOF1 0xC1 /* N indicates which compression process */ +#define M_SOF2 0xC2 /* Only SOF0-SOF2 are now in common use */ +#define M_SOF3 0xC3 +#define M_SOF5 0xC5 /* NB: codes C4 and CC are NOT SOF markers */ +#define M_SOF6 0xC6 +#define M_SOF7 0xC7 +#define M_SOF9 0xC9 +#define M_SOF10 0xCA +#define M_SOF11 0xCB +#define M_SOF13 0xCD +#define M_SOF14 0xCE +#define M_SOF15 0xCF +#define M_SOI 0xD8 +#define M_EOI 0xD9 /* End Of Image (end of datastream) */ +#define M_SOS 0xDA /* Start Of Scan (begins compressed data) */ +#define M_APP0 0xe0 +#define M_APP1 0xe1 +#define M_APP2 0xe2 +#define M_APP3 0xe3 +#define M_APP4 0xe4 +#define M_APP5 0xe5 +#define M_APP6 0xe6 +#define M_APP7 0xe7 +#define M_APP8 0xe8 +#define M_APP9 0xe9 +#define M_APP10 0xea +#define M_APP11 0xeb +#define M_APP12 0xec +#define M_APP13 0xed +#define M_APP14 0xee +#define M_APP15 0xef + +static int php3_iptc_put1(FILE *fp,int spool,unsigned char c,unsigned char **spoolbuf) +{ + if (spool > 0) + PUTC(c); + + if (spoolbuf) *(*spoolbuf)++ = c; + + return c; +} + +static int php3_iptc_get1(FILE *fp,int spool,unsigned char **spoolbuf) +{ + int c; + char cc; + + c = getc(fp); + + if (c == EOF) return EOF; + + if (spool > 0) { + cc = c; + PUTC(cc); + } + + if (spoolbuf) *(*spoolbuf)++ = c; + + return c; +} + +static int php3_iptc_read_remaining(FILE *fp,int spool,unsigned char **spoolbuf) +{ + int c; + + while ((c = php3_iptc_get1(fp,spool,spoolbuf)) != EOF) continue; + + return M_EOI; +} + +static int php3_iptc_skip_variable(FILE *fp,int spool,unsigned char **spoolbuf) +{ + unsigned int length; + int c1,c2; + + if ((c1 = php3_iptc_get1(fp,spool,spoolbuf)) == EOF) return M_EOI; + + if ((c2 = php3_iptc_get1(fp,spool,spoolbuf)) == EOF) return M_EOI; + + length = (((unsigned char) c1) << 8) + ((unsigned char) c2); + + length -= 2; + + while (length--) + if (php3_iptc_get1(fp,spool,spoolbuf) == EOF) return M_EOI; + + return 0; +} + +static int php3_iptc_nextmarker(FILE *fp,int spool,unsigned char **spoolbuf) +{ + int c; + + /* skip unimportant stuff */ + + c = php3_iptc_get1(fp,spool,spoolbuf); + + if (c == EOF) return M_EOI; + + while (c != 0xff) { + if ((c = php3_iptc_get1(fp,spool,spoolbuf)) == EOF) + return M_EOI; /* we hit EOF */ + } + + /* get marker byte, swallowing possible padding */ + do { + c = php3_iptc_get1(fp,0,0); + if (c == EOF) + return M_EOI; /* we hit EOF */ + else + if (c == 0xff) + php3_iptc_put1(fp,spool,(unsigned char)c,spoolbuf); + } while (c == 0xff); + + return (unsigned int) c; +} + +static char psheader[] = "\xFF\xED\0\0Photoshop 3.0\08BIM\x04\x04\0\0\0\0"; + +/* {{{ proto array iptcembed(string iptcdata, string jpeg_file_name [ , int spool ]) + Embed binary IPTC data into a JPEG image. */ +PHP_FUNCTION(iptcembed) +{ + pval *iptcdata, *jpeg_file, *spool_flag; + FILE *fp; + unsigned int marker; + unsigned int spool = 0, done = 0, inx, len; + unsigned char *spoolbuf=0,*poi=0; + struct stat sb; + + switch(ARG_COUNT(ht)){ + case 3: + if (getParameters(ht, 3, &iptcdata, &jpeg_file, &spool_flag) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(iptcdata); + convert_to_string(jpeg_file); + convert_to_long(spool_flag); + spool = spool_flag->value.lval; + break; + + case 2: + if (getParameters(ht, 2, &iptcdata, &jpeg_file) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string(iptcdata); + convert_to_string(jpeg_file); + break; + + default: + WRONG_PARAM_COUNT; + break; + } + + if (_php3_check_open_basedir(jpeg_file->value.str.val)) + RETURN_FALSE; + + if ((fp = fopen(jpeg_file->value.str.val,"rb")) == 0) { + php3_error(E_WARNING, "Unable to open %s", jpeg_file->value.str.val); + RETURN_FALSE; + } + + if (spool > 0) + if (!php3_header()){ /* we got a HEAD request. */ + if (spool == 2){ + RETURN_TRUE; /* we only wanted to spool - report success. */ + } else + if (spool == 1) { + spool = 0; /* we wanted the file to be spooled/returned, just return it */ + } + } + + len = iptcdata->value.str.len; + + if (spool < 2) { + fstat(fileno(fp),&sb); + + poi = spoolbuf = emalloc(len + 30 + sb.st_size); + + if (! spoolbuf) { + fclose(fp); + RETURN_FALSE; + } + } + + if (php3_iptc_get1(fp,spool,poi?&poi:0) != 0xFF) { + fclose(fp); + RETURN_FALSE; + } + + if (php3_iptc_get1(fp,spool,poi?&poi:0) != 0xD8) { + fclose(fp); + RETURN_FALSE; + } + + while (!done) { + marker = php3_iptc_nextmarker(fp,spool,poi?&poi:0); + + if (marker == M_EOI) { /* EOF */ + break; + } else if (marker != M_APP13) { + php3_iptc_put1(fp,spool,(unsigned char)marker,poi?&poi:0); + } + + switch (marker) { + case M_APP13: + /* we are going to write a new APP13 marker, so don't output the old one */ + php3_iptc_skip_variable(fp,0,0); + php3_iptc_read_remaining(fp,spool,poi?&poi:0); + done = 1; + break; + + case M_APP0: + /* APP0 is in each and every JPEG, so when we hit APP0 we insert our new APP13! */ + php3_iptc_skip_variable(fp,spool,poi?&poi:0); + + if (len & 1) len++; /* make the length even */ + + psheader[ 2 ] = (len+28)>>8; + psheader[ 3 ] = (len+28)&0xff; + + for (inx = 0; inx < 28; inx++) + php3_iptc_put1(fp,spool,psheader[inx],poi?&poi:0); + + php3_iptc_put1(fp,spool,(unsigned char)(len>>8),poi?&poi:0); + php3_iptc_put1(fp,spool,(unsigned char)(len&0xff),poi?&poi:0); + + for (inx = 0; inx < len; inx++) + php3_iptc_put1(fp,spool,iptcdata->value.str.val[inx],poi?&poi:0); + break; + + case M_SOS: + /* we hit data, no more marker-inserting can be done! */ + php3_iptc_read_remaining(fp,spool,poi?&poi:0); + done = 1; + break; + + default: + php3_iptc_skip_variable(fp,spool,poi?&poi:0); + break; + } + } + + fclose(fp); + + if (spool < 2) { + RETVAL_STRINGL(spoolbuf,poi - spoolbuf,0); + } else { + RETURN_TRUE; + } +} + +/* {{{ proto array iptcparse(string iptcdata) + Parse binary IPTC-data into associative array. */ PHP_FUNCTION(iptcparse) { unsigned int length, inx, len, inheader, tagsfound; unsigned char *buffer; unsigned char recnum, dataset; unsigned char key[ 16 ]; - pval values, *str, *element; + pval *values, *str, **element; if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &str) == FAILURE) { WRONG_PARAM_COUNT; } convert_to_string(str); - inx = 0; length = str->value.str.len; buffer = str->value.str.val; @@ -65,16 +326,18 @@ PHP_FUNCTION(iptcparse) inheader = 0; /* have we already found the IPTC-Header??? */ tagsfound = 0; /* number of tags already found */ - while (inx < length) { - if (buffer[ inx++ ] != 0x1c) { /* skip all junk */ - if (inheader) { - break; /* we ran against some data which does not conform to IPTC - stop parsing! */ - } else { - continue; - } + while (inx < length) { /* find 1st tag */ + if ((buffer[inx] == 0x1c) && (buffer[inx+1] == 0x02)){ + break; } else { - inheader = 1; + inx++; } + } + + while (inx < length) { + if (buffer[ inx++ ] != 0x1c) { + break; /* we ran against some data which does not conform to IPTC - stop parsing! */ + } if ((inx + 4) >= length) break; @@ -82,11 +345,11 @@ PHP_FUNCTION(iptcparse) dataset = buffer[ inx++ ]; recnum = buffer[ inx++ ]; - if (buffer[ inx ] & (unsigned char) 0x80) { + if (buffer[ inx ] & (unsigned char) 0x80) { /* long tag */ len = (((long) buffer[ inx + 2 ]) << 24) + (((long) buffer[ inx + 3 ]) << 16) + (((long) buffer[ inx + 4 ]) << 8) + (((long) buffer[ inx + 5 ])); inx += 6; - } else { + } else { /* short tag */ len = (((unsigned short) buffer[ inx ])<<8) | (unsigned short)buffer[ inx+1 ]; inx += 2; } @@ -104,15 +367,18 @@ PHP_FUNCTION(iptcparse) } if (_php3_hash_find(return_value->value.ht,key,strlen(key) + 1,(void **) &element) == FAILURE) { - if (array_init(&values) == FAILURE) { + values = emalloc(sizeof(pval)); + values->is_ref = 0; + values->refcount = 1; + if (array_init(values) == FAILURE) { php3_error(E_ERROR, "Unable to initialize array"); RETURN_FALSE; } - _php3_hash_update(return_value->value.ht, key, strlen(key)+1, (void *) &values, sizeof(pval), (void **) &element); + _php3_hash_update(return_value->value.ht, key, strlen(key)+1, (void *) &values, sizeof(pval*), (void **) &element); } - add_next_index_stringl(element,buffer+inx,len,1); + add_next_index_stringl(*element,buffer+inx,len,1); inx += len; @@ -123,6 +389,7 @@ PHP_FUNCTION(iptcparse) RETURN_FALSE; } } +/* }}} */ /* * Local variables: diff --git a/ext/standard/php3_iptc.h b/ext/standard/php3_iptc.h index 3a18915537..2abc43dae1 100644 --- a/ext/standard/php3_iptc.h +++ b/ext/standard/php3_iptc.h @@ -34,5 +34,6 @@ #define _PHPIPTC_H PHP_FUNCTION(iptcparse); +PHP_FUNCTION(iptcembed); #endif /* _PHPIPTC_H */ |
