[prev in list] [next in list] [prev in thread] [next in thread] 

List:       pecl-cvs
Subject:    [PECL-CVS] cvs: pecl /id3 TODO id3.c
From:       "Carsten Lucke" <luckec () php ! net>
Date:       2004-08-31 21:07:02
Message-ID: cvsluckec1093986422 () cvsserver
[Download RAW message or body]

luckec		Tue Aug 31 17:07:02 2004 EDT

  Modified files:              
    /pecl/id3	TODO id3.c 
  Log:
  implemented functions for frame-parsing,
  added function that enables text-frame-parsing
  
  
["luckec-20040831170702.txt" (text/plain)]

http://cvs.php.net/diff.php/pecl/id3/TODO?r1=1.1&r2=1.2&ty=u
Index: pecl/id3/TODO
diff -u pecl/id3/TODO:1.1 pecl/id3/TODO:1.2
--- pecl/id3/TODO:1.1	Mon Jun 21 03:57:43 2004
+++ pecl/id3/TODO	Tue Aug 31 17:07:01 2004
@@ -3,3 +3,6 @@
 check, whether supplied streams are able to seek and write
 implement id3v2
 check for 64bit problems (foo_len must be int)
+handle encoding in text-frames (id3v2)
+handle compressed and encrypted frames
+
http://cvs.php.net/diff.php/pecl/id3/id3.c?r1=1.20&r2=1.21&ty=u
Index: pecl/id3/id3.c
diff -u pecl/id3/id3.c:1.20 pecl/id3/id3.c:1.21
--- pecl/id3/id3.c:1.20	Tue Aug 31 04:46:39 2004
+++ pecl/id3/id3.c	Tue Aug 31 17:07:01 2004
@@ -17,7 +17,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: id3.c,v 1.20 2004/08/31 08:46:39 schst Exp $ */
+/* $Id: id3.c,v 1.21 2004/08/31 21:07:01 luckec Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -53,6 +53,8 @@
 short _php_id3v2_get_frameHeaderLength(short majorVersion TSRMLS_DC);
 int _php_deUnSynchronize(unsigned char* buf, int bufLen TSRMLS_DC);
 int _php_strnoffcpy(unsigned char *dest, unsigned char *src, int offset, int len \
TSRMLS_DC); +short _php_id3v2_parseFrame(zval *return_value, struct id3v2Header \
*sHeader, struct id3v2FrameHeader *sFrameHeader, unsigned char *frameContent \
TSRMLS_DC); +short _php_id3v2_parseTextFrame(zval *return_value, struct \
id3v2FrameHeader *sFrameHeader, unsigned char *frameContent TSRMLS_DC);  
 /* constants */
 const int ID3V2_BASEHEADER_LENGTH = 10;
@@ -398,13 +400,12 @@
 		currentReadPos = 0,
 		paddingStart,
 		paddingLength;
-		
-	int i;
 	
-	short	paddingValid = 0,
+	short	paddingValid = 1,
 			singleFrameLength;
 		
-	unsigned char *frameData, *frameContent;
+	unsigned char	*frameData, 
+					*frameContent;
 	
 	struct id3v2Header sHeader;
 	struct id3v2ExtHeader sExtHeader;
@@ -437,57 +438,146 @@
 	while (currentReadPos < frameDataLength) {
 		frameDataLeft	= frameDataLength - currentReadPos;
 	
-		
-		if (frameDataLeft <= singleFrameLength + 1) {
-		/* insufficient room left for data in the frame-header -> must be padding */
-			paddingStart	= frameDataOffset;
+		/* check if frame or padding */
+		if (frameData[currentReadPos] != 0x00) {
+		/* must be frame-data */
+			sFrameHeader		= _php_id3v2_get_frameHeader(frameData, currentReadPos, \
sHeader.version TSRMLS_CC); +			
+			/* set read-position forward after header was analyzed */
+			currentReadPos	+= singleFrameLength;
+			
+			/* allocate memory for actual frame-content */
+			frameContent					= emalloc(sFrameHeader.size + 1);
+			frameContent[sFrameHeader.size]	= 0; /* to make sure the buffer is \
zero-terminated */ +			_php_strnoffcpy(frameContent, frameData, currentReadPos, \
sFrameHeader.size TSRMLS_CC); +			
+			/* delegate parsing the frame-content to specialized methods */
+			if (_php_id3v2_parseFrame(return_value, &sHeader, &sFrameHeader, frameContent \
TSRMLS_CC) != 0) { +				/* TODO: should this throw a php-notice??? */
+				zend_printf("Parsing frame %s failed ...\n", sFrameHeader.id);
+			}
+			
+			/* set read-position forward after header was analyzed */
+			currentReadPos	+= sFrameHeader.size;
+			efree(frameContent);
+		} else {
+		/* padding found */
+			paddingStart	= currentReadPos;
 			paddingLength	= frameDataLeft;
-			paddingValid	= 1;
-		
-			for (i = 0; i < paddingLength; i++) {
-				if (frameData[i] != 0x00) {
-					paddingValid	= 0;
-					/* TODO: just temporarily commented */
-					//php_error_docref(NULL TSRMLS_CC, E_WARNING, "ID3v2 tag contains invalid \
                padding - tag considered invalid");
-					break;
+			
+			/* check whether padding is valid */
+			while (frameDataLeft) {
+				if (frameData[currentReadPos++] != 0x00) {
+					paddingValid = 0;
 				}
+				--frameDataLeft;
 			}
 			
-			/* skip rest of frame-data */
-			break;
+			if (! paddingValid) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "ID3v2 tag contains invalid padding \
- tag considered invalid"); +				break;
+			}
 		}
-		
-		/* read frame-header */
-		sFrameHeader		= _php_id3v2_get_frameHeader(frameData, currentReadPos, \
                sHeader.version TSRMLS_CC);
-		
-		/* TODO: Handle unsupported-flags case */
-		
-		/*
-		zend_printf("sFrameHeader.id: %s \n", sFrameHeader.id);
-		zend_printf("sFrameHeader.size: %d \n", sFrameHeader.size);
-		zend_printf("--------------------------\n");
-		*/
-		
-		/* set read-position forward after header was analyzed */
-		currentReadPos	+= singleFrameLength;
-		
-		/* allocate memory for actual frame-content */
-		frameContent					= emalloc(sFrameHeader.size + 1);
-		frameContent[sFrameHeader.size]	= 0; /* to make sure the buffer is zero-terminated \
                */
-		_php_strnoffcpy(frameContent, frameData, currentReadPos, sFrameHeader.size \
                TSRMLS_CC);
-		/*
-		zend_printf("Content:\n");
-		zend_printf("Byte1: %d\n", (int)frameContent[0]);
-		zend_printf("Byte2: %d\n", (int)frameContent[1]);
+	}
+	
+	efree(frameData);
+}
+/* }}} */
+
+/* {{{ 
+   Delegates parsing a frame to sepcialized functions after doing 
+   some general jobs like de-unsynchronization
+    
+	returns 0 if frame was successfully parsed, otherwise 1 */
+short _php_id3v2_parseFrame(zval *return_value, struct id3v2Header *sHeader, struct \
id3v2FrameHeader *sFrameHeader, unsigned char *frameContent TSRMLS_DC) +{
+	int deUnsynched;
+	
+	/* groupingIdentity is not yet supported by this extension */
+	if (sFrameHeader->flags.groupingIdentity == 1) {
+		return 1;	
+	}
+	
+	/* compression is not yet supported by this extension */
+	if (sFrameHeader->flags.compression == 1) {
+		return 1;	
+	}
+	
+	/* encryption is not yet supported by this extension */
+	if (sFrameHeader->flags.encryption == 1) {
+		return 1;	
+	}
+	
+	/* dataLengthIndicator-flag is not yet supported by this extension */
+	if (sFrameHeader->flags.dataLengthIndicator == 1) {
+		return 1;	
+	}
+	
+	/* if frame-content is unsynchronized it has to be de-unsynchronized now */
+	if (sFrameHeader->flags.unsynch == 1) {
+		/* if tag is <= v2.3 then it has been de-unsynchronized by _php_id3v2_get_tag() \
already  +			v2.4+ instead supports unsynchronization on frame-level
 		*/
+		if (sHeader->version > 3) {
+			deUnsynched = _php_deUnSynchronize(frameContent, sFrameHeader->size TSRMLS_CC);
+			if (deUnsynched != sFrameHeader->size) {
+				return 1;
+			}
+		}
+	}
+	
+	/* handle text-frames (T000 - TZZZ) */
+	if (sFrameHeader->id[0] == 0x54) {
+		_php_id3v2_parseTextFrame(return_value, sFrameHeader, frameContent TSRMLS_CC);
+	}
+
+	return 0;
+}
+/* }}} */
+
+/* {{{ 
+   Parses text-frames (T000 - TZZZ)
+    
+	returns 0 if frame-content was successfully added to the return_value, otherwise 1 \
*/ +short _php_id3v2_parseTextFrame(zval *return_value, struct id3v2FrameHeader \
*sFrameHeader, unsigned char *frameContent TSRMLS_DC) +{
+	/*
+		The text information frames are often the most important frames,
+		containing information like artist, album and more. There may only be
+		one text information frame of its kind in an tag. All text
+		information frames supports multiple strings, stored as a null
+		separated list, where null is reperesented by the termination code
+		for the charater encoding. All text frame identifiers begin with "T".
+		Only text frame identifiers begin with "T", with the exception of the
+		"TXXX" frame. All the text information frames have the following
+		format:
 		
-		/* set read-position forward after header was analyzed */
-		currentReadPos	+= sFrameHeader.size;
-		efree(frameContent);
-		//break; /* ONE RUN JUST FOR TESTING */
+			<Header for 'Text information frame', ID: "T000" - "TZZZ",
+			excluding "TXXX" described in 4.2.6.>
+			Text encoding                $xx
+			Information                  <text string(s) according to encoding>
+	*/
+
+	char	*information;
+	int		infoSize;
+	short	encoding;
+	
+	/* TODO: handle encoding */
+	
+	encoding	= frameContent[0];
+	infoSize	= sFrameHeader->size - 1;
+	information	= emalloc(infoSize);
+	_php_strnoffcpy(information, frameContent, 1, infoSize TSRMLS_CC);
+	
+	
+	if (strcmp(sFrameHeader->id, "TIT2") == 0) {
+		add_assoc_stringl(return_value, "title", information, infoSize, 1);
+		efree(information);
+		return 0;
 	}
 	
-	efree(frameData);
+	efree(information);
+	return 1;
 }
 /* }}} */
 
@@ -1095,7 +1185,7 @@
 	struct id3v2FrameHeader sFrameHeader;
 	struct id3v2FrameHeaderFlags sFlags;
 	
-	int	i, frameDataLength;
+	int frameDataLength;
 	
 	unsigned char 	*frameData,
 					*size;
@@ -1112,14 +1202,11 @@
 	sFlags.dataLengthIndicator		= -1;
 	sFlags.dataLength				= -1;
 
-	frameDataLength = _php_id3v2_get_frameHeaderLength(version TSRMLS_CC);
-	
-	frameData	= emalloc(frameDataLength);
+	frameDataLength	= _php_id3v2_get_frameHeaderLength(version TSRMLS_CC);
+	frameData		= emalloc(frameDataLength);
 	
 	/* copy relevant frame data */
-	for (i = 0; i < frameDataLength; i++) {
-		frameData[i]	= data[offset + i];
-	}
+	_php_strnoffcpy(frameData, data, offset, frameDataLength TSRMLS_CC);
 	
 	if (version == 2) {
 		/*



-- 
PECL CVS Mailing List 
To unsubscribe, visit: http://www.php.net/unsub.php

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic