• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 /**
19 * @file pv_id3_parcom_types.cpp
20 * @brief Type definitions for ID3 Parser-Composer
21 */
22 
23 #ifndef PV_ID3_PARCOM_H_INCLUDED
24 #include "pv_id3_parcom.h"
25 #endif
26 #ifndef PV_ID3_PARCOM_CONSTANTS_H_INCLUDED
27 #include "pv_id3_parcom_constants.h"
28 #endif
29 #ifndef OSCL_SNPRINTF_H_INCLUDED
30 #include "oscl_snprintf.h"
31 #endif
32 #ifndef PVLOGGER_H_INCLUDED
33 #include "pvlogger.h"
34 #endif
35 #ifndef PVMI_KVP_UTIL_H_INCLUDED
36 #include "pvmi_kvp_util.h"
37 #endif
38 #ifndef OSCL_MIME_STRING_UTILS_H
39 #include "pv_mime_string_utils.h"
40 #endif
41 #ifndef OSCL_DLL_H_INCLUDED
42 #include "oscl_dll.h"
43 #endif
44 #ifndef WCHAR_SIZE_UTILS_H_INCLUDED
45 #include "wchar_size_utils.h"
46 #endif
47 
48 #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m);
49 #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m);
50 #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
51 
52 #ifndef NULL_TERM_CHAR
53 #define NULL_TERM_CHAR '\0'
54 #endif
55 
56 // DLL entry point
57 OSCL_DLL_ENTRY_POINT_DEFAULT()
58 
59 ////////////////////////////////////////////////////////////////////////////
60 class PVID3ParComKvpCleanupDA : public OsclDestructDealloc
61 {
62     public:
PVID3ParComKvpCleanupDA(Oscl_DefAlloc * in_gen_alloc)63         PVID3ParComKvpCleanupDA(Oscl_DefAlloc* in_gen_alloc) :
64                 gen_alloc(in_gen_alloc) {};
~PVID3ParComKvpCleanupDA()65         virtual ~PVID3ParComKvpCleanupDA() {};
66 
destruct_and_dealloc(OsclAny * ptr)67         virtual void destruct_and_dealloc(OsclAny* ptr)
68         {
69             // no need to call destructors in this case just dealloc
70             gen_alloc->deallocate(ptr);
71         }
72 
73     private:
74         Oscl_DefAlloc* gen_alloc;
75 };
76 
77 ////////////////////////////////////////////////////////////////////////////
PVID3ParCom()78 OSCL_EXPORT_REF PVID3ParCom::PVID3ParCom()
79         : iInputFile(NULL),
80         iTitleFoundFlag(false),
81         iArtistFoundFlag(false),
82         iAlbumFoundFlag(false),
83         iYearFoundFlag(false),
84         iCommentFoundFlag(false),
85         iTrackNumberFoundFlag(false),
86         iGenereFoundFlag(false),
87         iFileSizeInBytes(0),
88         iByteOffsetToStartOfAudioFrames(0),
89         iID3V1Present(false),
90         iID3V2Present(false),
91         iVersion(PV_ID3_INVALID_VERSION),
92         iUseMaxTagSize(false),
93         iMaxTagSize(0),
94         iUsePadding(false),
95         iTagAtBof(false),
96         iSeekFrameFound(false)
97 {
98     iLogger = PVLogger::GetLoggerObject("PVID3ParCom");
99     iID3TagInfo.iID3V2ExtendedHeaderSize = 0;
100     iID3TagInfo.iID3V2FrameSize = 0;
101     iID3TagInfo.iID3V2TagFlagsV2 = 0;
102     iID3TagInfo.iID3V2TagSize = 0 ;
103     iID3TagInfo.iFooterPresent = false;
104 
105     oscl_memset(&iID3TagInfo.iID3V2FrameFlag, 0, sizeof(iID3TagInfo.iID3V2FrameFlag));
106 
107 }
108 
109 ////////////////////////////////////////////////////////////////////////////
~PVID3ParCom()110 OSCL_EXPORT_REF PVID3ParCom::~PVID3ParCom()
111 {
112     iFrames.clear();
113 }
114 
115 ////////////////////////////////////////////////////////////////////////////
GetID3TagSize(PVFile * aFile)116 OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize(PVFile* aFile)
117 {
118     if (!aFile)
119     {
120         return 0;
121     }
122 
123     iInputFile = aFile;
124 
125     if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
126     {
127         iFileSizeInBytes = 0;
128     }
129     else
130     {
131         iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes);
132         if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
133         {
134             return 0;
135         }
136     }
137 
138     uint32 buffsize = 100; //number of bytes to search , from the end of file, to look for footer
139     if (CheckForTagID3V2()
140             || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess))
141     {
142         if (iInputFile->Seek(2, Oscl_File::SEEKCUR) == -1)
143         {
144             return 0;
145         }
146 
147         // Read and convert tag flags
148         uint8 flags = 0;
149         if (read8(iInputFile, flags) == false)
150         {
151             return 0;
152         }
153 
154         // Read and convert tag size
155         uint32 synchIntTagSize;
156         if (read32(iInputFile, synchIntTagSize) == false)
157         {
158             return 0;
159         }
160 
161         // tagSize will store the file's Id3v2 tag size
162         uint32 tagSize = SafeSynchIntToInt32(synchIntTagSize) + ID3V2_TAG_NUM_BYTES_HEADER;
163 
164         //check if footer is present
165         if ((iVersion == PV_ID3_V2_4) && (flags & FTR_FLAGMASK))
166             tagSize += ID3V2_TAG_NUM_BYTES_HEADER; // add 10 bytes for footer
167 
168         return tagSize;
169     }
170     else
171     {
172         if (CheckForTagID3V1())
173         {
174             return ID3V1_MAX_NUM_BYTES_TOTAL;
175         }
176     }
177     return 0;
178 }
179 
180 ////////////////////////////////////////////////////////////////////////////
GetID3TagSize()181 OSCL_EXPORT_REF uint32 PVID3ParCom::GetID3TagSize()
182 {
183     uint32 composedTagSize = 0;
184     switch (iVersion)
185     {
186         case PV_ID3_V2_2:
187         case PV_ID3_V2_3:
188         case PV_ID3_V2_4:
189         {
190             composedTagSize = ID3V2_TAG_NUM_BYTES_HEADER + iID3TagInfo.iID3V2TagSize;
191 
192             if (iID3TagInfo.iFooterPresent)
193                 composedTagSize += ID3V2_TAG_NUM_BYTES_HEADER; //footer is replica of Tag Header
194         }
195         break;
196 
197         case PV_ID3_V1:
198         case PV_ID3_V1_1:
199             composedTagSize =  128; // ID3v1 tag has fix size
200             break;
201         default:
202             composedTagSize = 0;
203 
204     }
205 
206     return composedTagSize;
207 }
208 
209 ////////////////////////////////////////////////////////////////////////////
SetMaxID3TagSize(bool aUseMaxSize,uint32 aMaxSize,bool aUsePadding)210 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetMaxID3TagSize(bool aUseMaxSize, uint32 aMaxSize, bool aUsePadding)
211 {
212     switch (iVersion)
213     {
214         case PV_ID3_V1:
215         case PV_ID3_V1_1:
216         case PV_ID3_INVALID_VERSION:
217         {
218             LOG_ERR((0, "PVID3Parcom::SetMaxID3TagSize: Error - Fix size ID3 tag"));
219             return PVMFErrNotSupported;
220         }
221         case PV_ID3_V2_2:
222             // Minimum for an ID3v2_2 tag is tag header plus 1 frame.  The minimum data length of
223             // a frame is 1 byte
224         {
225             if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_2_FRAME_NUM_BYTES_HEADER + 1))
226             {
227                 LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 17 bytes"));
228                 return PVMFErrArgument;
229             }
230         }
231         break;
232         case PV_ID3_V2_3:
233         case PV_ID3_V2_4:
234             // Minimum for an ID3v2 tag is tag header plus 1 frame.  The minimum data length of
235             // a frame is 1 byte
236             if (aUseMaxSize && aMaxSize < (ID3V2_TAG_NUM_BYTES_HEADER + ID3V2_FRAME_NUM_BYTES_HEADER + 1))
237             {
238                 LOG_ERR((0, "PVID3ParCom::SetMaxID3TagSize: Error - Minimum tag size is 21 bytes"));
239                 return PVMFErrArgument;
240             }
241     }
242 
243     iUseMaxTagSize = aUseMaxSize;
244     if (iUseMaxTagSize)
245     {
246         iMaxTagSize = aMaxSize;
247         iUsePadding = aUsePadding;
248     }
249     else
250     {
251         iMaxTagSize = 0;
252         iUsePadding = false;
253     }
254 
255     return PVMFSuccess;
256 }
257 
258 ////////////////////////////////////////////////////////////////////////////
ParseID3Tag(PVFile * aFile,uint32 buffsize)259 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ParseID3Tag(PVFile* aFile, uint32 buffsize)
260 {
261     if (!aFile)
262     {
263         return PVMFFailure;
264     }
265 
266     iInputFile = aFile;
267 
268     int32 currentFilePosn = 0;
269 
270     // SEEK TO THE END OF THE FILE AND GET FILE SIZE
271     currentFilePosn = iInputFile->Tell();
272     if (currentFilePosn == -1)
273     {
274         return PVMFFailure;
275     }
276 
277     if (iInputFile->Seek(0, Oscl_File::SEEKSET) == -1)
278     {
279         iFileSizeInBytes = 0;
280     }
281     else
282     {
283         iInputFile->GetRemainingBytes((uint32&)iFileSizeInBytes);
284         if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
285         {
286             iInputFile = NULL;
287             return PVMFFailure;
288         }
289     }
290 
291     bool readTags = false;
292     //check for ID3 Version 2
293     if (CheckForTagID3V2() || (LookForV2_4Footer(buffsize, 0) == PVMFSuccess))
294     {
295         //Read the header
296         readTags = ReadHeaderID3V2();
297 
298         //check for ID3 Version 1
299         if (CheckForTagID3V1())
300         {
301             iVersion = PV_ID3_V1;
302             ReadID3V1Tag();
303         }
304         if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
305         {
306             iInputFile = NULL;
307             return PVMFFailure;
308         }
309     }
310     else if (!readTags && CheckForTagID3V1())
311     {
312         //check for ID3 Version 1
313         iVersion = PV_ID3_V1;
314         //Read the header
315         ReadID3V1Tag();
316 
317         iByteOffsetToStartOfAudioFrames = 0;
318         if (iInputFile->Seek(currentFilePosn, Oscl_File::SEEKSET) == -1)
319         {
320             iInputFile = NULL;
321             return PVMFFailure;
322         }
323     }
324     else
325     {
326         return PVMFFailure;
327     }
328 
329     iInputFile = NULL;
330     return PVMFSuccess;
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////
GetID3Version() const334 OSCL_EXPORT_REF PVID3Version PVID3ParCom::GetID3Version() const
335 {
336     return iVersion;
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////
IsID3V1Present() const340 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V1Present() const
341 {
342     return iID3V1Present;
343 }
344 
345 ////////////////////////////////////////////////////////////////////////////
IsID3V2Present() const346 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present() const
347 {
348     return iID3V2Present;
349 }
350 
351 ////////////////////////////////////////////////////////////////////////////
GetID3Frames(PvmiKvpSharedPtrVector & aFrames)352 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frames(PvmiKvpSharedPtrVector& aFrames)
353 {
354     aFrames = iFrames;
355     return PVMFSuccess;
356 }
357 
358 ////////////////////////////////////////////////////////////////////////////
GetID3Frame(const OSCL_String & aFrameType,PvmiKvpSharedPtrVector & aFrameVector)359 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::GetID3Frame(const OSCL_String& aFrameType, PvmiKvpSharedPtrVector& aFrameVector)
360 {
361     uint32 i;
362     for (i = 0; i < iFrames.size(); i++)
363     {
364         if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
365         {
366             return PushFrameToFrameVector(iFrames[i], aFrameVector);
367         }
368     }
369 
370     return PVMFSuccess;
371 }
372 
373 ////////////////////////////////////////////////////////////////////////////
IsID3FrameAvailable(const OSCL_String & aFrameType)374 OSCL_EXPORT_REF bool PVID3ParCom::IsID3FrameAvailable(const OSCL_String& aFrameType)
375 {
376     uint32 i;
377     for (i = 0; i < iFrames.size(); i++)
378     {
379         if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
380         {
381             return true;
382         }
383     }
384 
385     return false;
386 }
387 
388 ////////////////////////////////////////////////////////////////////////////
SetID3Version(PVID3Version aVersion)389 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Version(PVID3Version aVersion)
390 {
391     iVersion = aVersion;
392     return PVMFSuccess;
393 }
394 
395 ////////////////////////////////////////////////////////////////////////////
SetID3Frame(const PvmiKvp & aFrame)396 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::SetID3Frame(const PvmiKvp& aFrame)
397 {
398     uint32 i;
399     OSCL_StackString<4> frameID;
400     PVID3FrameType newFrameType;
401     PVID3FrameType existingFrameType;
402     PVMFStatus status = PVMFSuccess;
403 
404     // Find an existing entry in iFrames with matching frame type
405     status = GetFrameTypeFromKvp(aFrame, frameID, newFrameType);
406     for (i = 0; status == PVMFSuccess && i < iFrames.size(); i++)
407     {
408         status = GetFrameTypeFromKvp(iFrames[i], frameID, existingFrameType);
409         if (status != PVMFSuccess)
410         {
411             LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - GetFrameTypeFromKvp failed"));
412             break;
413         }
414         if (existingFrameType == newFrameType)
415         {
416             iFrames.erase(iFrames.begin() + i);
417             break;
418         }
419 
420     }
421 
422     if (status != PVMFSuccess)
423     {
424         return status;
425     }
426 
427     PvmiKvpValueType kvpValueType = GetValTypeFromKeyString(aFrame.key);
428     OSCL_StackString<128> key = _STRLIT_CHAR(aFrame.key);
429     uint32 valueSize = 0;
430     uint32 valueStrLen = 0;
431     switch (kvpValueType)
432     {
433         case PVMI_KVPVALTYPE_CHARPTR:
434             valueStrLen = oscl_strlen(aFrame.value.pChar_value);
435             valueSize = valueStrLen + 1;
436             break;
437         case PVMI_KVPVALTYPE_WCHARPTR:
438             valueStrLen = oscl_strlen(aFrame.value.pWChar_value);
439             valueSize = (valueStrLen + 2) * sizeof(oscl_wchar);
440             break;
441         case PVMI_KVPVALTYPE_KSV:
442             // Comment field
443             break;
444         case PVMI_KVPVALTYPE_UINT32:
445             valueSize = 0;
446             break;
447         default:
448             return PVMFErrNotSupported;
449     }
450 
451     status = PVMFSuccess;
452     PvmiKvpSharedPtr kvp;
453     bool truncate = false;
454     kvp = HandleErrorForKVPAllocation(key, kvpValueType, valueSize, truncate, status);
455 
456     if (truncate || (PVMFSuccess != status) || !kvp)
457     {
458         return PVMFErrNoMemory;
459     }
460 
461     switch (kvpValueType)
462     {
463         case PVMI_KVPVALTYPE_CHARPTR:
464             oscl_strncpy(kvp->value.pChar_value, aFrame.value.pChar_value, valueStrLen);
465             kvp->value.pChar_value[valueStrLen] = NULL_TERM_CHAR;
466             break;
467         case PVMI_KVPVALTYPE_WCHARPTR:
468             oscl_strncpy(kvp->value.pWChar_value, aFrame.value.pWChar_value, valueStrLen);
469             kvp->value.pWChar_value[valueStrLen] = NULL_TERM_CHAR;
470             break;
471         case PVMI_KVPVALTYPE_UINT32:
472             kvp->value.uint32_value = aFrame.value.uint32_value;
473             break;
474         case PVMI_KVPVALTYPE_KSV:
475             // comment field
476         default:
477             return PVMFErrNotSupported;
478     }
479 
480 
481     if (PVMFSuccess != PushFrameToFrameVector(kvp, iFrames))
482     {
483         return PVMFErrNoMemory;
484     }
485     return PVMFSuccess;
486 }
487 
488 ////////////////////////////////////////////////////////////////////////////
RemoveID3Frame(const OSCL_String & aFrameType)489 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::RemoveID3Frame(const OSCL_String& aFrameType)
490 {
491     uint32 i;
492     for (i = 0; i < iFrames.size(); i++)
493     {
494         if (pv_mime_strcmp(iFrames[i]->key, aFrameType.get_str()) == 0)
495         {
496             iFrames.erase(iFrames.begin() + i);
497             return PVMFSuccess;
498         }
499     }
500 
501     // Frame of specified type is not found
502     return PVMFErrArgument;
503 }
504 
505 ////////////////////////////////////////////////////////////////////////////
ComposeID3Tag(OsclRefCounterMemFrag & aTag)506 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::ComposeID3Tag(OsclRefCounterMemFrag& aTag)
507 {
508     switch (iVersion)
509     {
510         case PV_ID3_V2_2:
511         case PV_ID3_V2_3:
512         case PV_ID3_V2_4:
513             return ComposeID3v2Tag(aTag);
514         default:
515             return PVMFErrNotSupported;
516     }
517 }
518 
519 ////////////////////////////////////////////////////////////////////////////
Reset()520 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::Reset()
521 {
522     iFrames.clear();
523     return PVMFSuccess;
524 }
525 
526 ////////////////////////////////////////////////////////////////////////////
CheckForTagID3V1()527 bool PVID3ParCom::CheckForTagID3V1()
528 {
529     uint8 tagHeader[ID3V1_TAG_NUM_BYTES_HEADER+1] = {0};
530 
531     // Make sure file is big enough to contain a tag
532     if (iFileSizeInBytes >= ID3V1_MAX_NUM_BYTES_TOTAL)
533     {
534         uint32 nBytes = 0;
535         // Read the value at the tag position
536 
537         nBytes = iFileSizeInBytes - ID3V1_MAX_NUM_BYTES_TOTAL;
538         if (iInputFile->Seek(nBytes, Oscl_File::SEEKSET) == -1)
539         {
540             return false;
541         }
542 
543 
544         if (!readByteData(iInputFile, ID3V1_TAG_NUM_BYTES_HEADER, tagHeader))
545         {
546             return false;
547         }
548 
549         // Read in ID3 Tags at the front of the file.
550         if (oscl_memcmp(ID3_V1_IDENTIFIER, tagHeader, ID3V1_TAG_NUM_BYTES_HEADER) == 0)
551         {
552             iID3V1Present = true;
553             return true;
554         }
555     }
556     return false;
557 }
558 
559 ////////////////////////////////////////////////////////////////////////////
CheckForTagID3V2()560 bool PVID3ParCom::CheckForTagID3V2()
561 {
562     uint8 id3Header[ID3V2_TAG_NUM_BYTES_HEADER+1] = {0};
563 
564     if (!readByteData(iInputFile, ID3V2_TAG_NUM_BYTES_ID, id3Header))
565     {
566         return false;
567     }
568 
569     // Read in ID3 Tags at the front of the file.
570     if (oscl_memcmp(ID3_V2_IDENTIFIER, id3Header, ID3V2_TAG_NUM_BYTES_ID) == 0)
571     {
572         iTagAtBof = true;
573         iID3V2Present = true;
574         return true;
575     }
576     return false;
577 }
578 
IsID3V2Present(PVFile * aFile,uint32 & aTagSize)579 OSCL_EXPORT_REF bool PVID3ParCom::IsID3V2Present(PVFile* aFile, uint32& aTagSize)
580 {
581     iInputFile = aFile;
582     if (iID3V2Present)
583     {
584         // if id3 tag has already been discovered, just return the tag size
585         aTagSize = iByteOffsetToStartOfAudioFrames;
586         return true;
587     }
588 
589     if (CheckForTagID3V2())
590     {
591         // we dont want to parse the id3 frames, just read the id3 header
592 
593         ReadHeaderID3V2(false);
594         aTagSize = iByteOffsetToStartOfAudioFrames;
595         return true;
596     }
597     return false;
598 }
599 
LookForV2_4Footer(uint32 aBuffSz,uint32 aFileOffset)600 OSCL_EXPORT_REF PVMFStatus PVID3ParCom::LookForV2_4Footer(uint32 aBuffSz, uint32 aFileOffset)
601 {
602     if (iTagAtBof)  //already found tag. no need to search from the end.
603         return PVMFFailure;
604 
605     uint32 footer_location = SearchTagV2_4(aBuffSz, aFileOffset);
606 
607     if (footer_location == 0)
608         return PVMFFailure;
609 
610     if (iInputFile->Seek(footer_location  + ID3V2_TAG_NUM_BYTES_ID + ID3V2_TAG_NUM_BYTES_VERSION + ID3V2_TAG_NUM_BYTES_FLAG,
611                          Oscl_File::SEEKSET) == -1)
612     {
613         return PVMFFailure;
614     }
615 
616     uint32 tag_size = 0, size = 0;
617 
618     if (read32(iInputFile, size) == false)
619     {
620         return PVMFFailure;
621     }
622 
623     tag_size = SafeSynchIntToInt32(size);
624 
625     if (iInputFile->Seek(-(int32)(tag_size + ID3V2_TAG_NUM_BYTES_HEADER + (ID3V2_TAG_NUM_BYTES_HEADER - ID3V2_TAG_NUM_BYTES_ID)),
626                          Oscl_File::SEEKCUR) == -1)
627     {
628         return PVMFFailure;
629     }
630 
631     return PVMFSuccess;
632 }
633 ////////////////////////////////////////////////////////////////////////////
634 // (if an error is detected, this returns 0)
635 
SearchTagV2_4(uint32 aBuffSz,uint32 aFileOffset)636 uint32 PVID3ParCom::SearchTagV2_4(uint32 aBuffSz, uint32 aFileOffset)
637 {
638 
639     if (iFileSizeInBytes == 0)
640         return 0;
641 
642     uint8 *buff = (uint8 *)oscl_malloc(aBuffSz);
643     if (! buff)     // malloc might fail
644         return 0;
645 
646     int remaining_bytes = 0;
647 
648     int num_bytes_read = aBuffSz + aFileOffset;
649 
650     //in case we have almost reached to the begining of file,
651     //and remaining bytes are less than the buffer size,
652     //look for ID3 tag in the remaining bytes only.
653 
654     if (num_bytes_read > iFileSizeInBytes)
655         remaining_bytes = iFileSizeInBytes - (num_bytes_read - aBuffSz);
656 
657     if (remaining_bytes > 0)
658     {
659 
660         if (iInputFile->Seek(0 , Oscl_File::SEEKSET) == -1)
661         {
662             oscl_free(buff);
663             return 0;
664         }
665 
666         if (readByteData(iInputFile, remaining_bytes, buff) == false)
667         {
668             oscl_free(buff);
669             return 0;
670         }
671 
672         for (int i = 0; i < remaining_bytes; i++)
673         {
674             if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0)
675             {
676                 oscl_free(buff);
677                 return i;
678             }
679 
680         }
681 
682         oscl_free(buff);
683         return 0;
684     }
685     else
686     {
687 
688         if (iInputFile->Seek((iFileSizeInBytes - (aFileOffset + aBuffSz)), Oscl_File::SEEKSET) == -1)
689         {
690             oscl_free(buff);
691             return 0;
692         }
693 
694         if (readByteData(iInputFile, aBuffSz, buff) == false)
695         {
696             oscl_free(buff);
697             return 0;
698         }
699 
700         for (uint i = 0; i < aBuffSz; i++)
701         {
702             if (oscl_memcmp(buff + i, ID3_V2_4_TAG_FOOTER, ID3V2_TAG_NUM_BYTES_ID) == 0)
703             {
704                 oscl_free(buff);
705                 return ((iFileSizeInBytes - ((aFileOffset + aBuffSz) - i)));
706             }
707 
708         }
709 
710     }
711 
712     oscl_free(buff);
713     return 0;
714 }
715 
716 ////////////////////////////////////////////////////////////////////////////
ReadID3V1Tag(void)717 void PVID3ParCom::ReadID3V1Tag(void)
718 {
719 
720     PVMFStatus status = PVMFSuccess;
721     bool truncate = false;
722 
723     if (!iTitleFoundFlag)
724     {
725         //Title
726         status = ReadStringValueFrame(PV_ID3_FRAME_TITLE, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_TITLE);
727         if (status != PVMFSuccess)
728         {
729             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for title"));
730             OSCL_LEAVE(OsclErrGeneral);
731         }
732         iTitleFoundFlag = true;
733     }
734     else
735     {
736 
737         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_TITLE, Oscl_File::SEEKCUR) == -1)
738         {
739             return;
740         }
741 
742     }
743     if (!iArtistFoundFlag)
744     {
745         //Artist
746         status = ReadStringValueFrame(PV_ID3_FRAME_ARTIST, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ARTIST);
747         if (status != PVMFSuccess)
748         {
749             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for artist"));
750             OSCL_LEAVE(OsclErrGeneral);
751         }
752         iArtistFoundFlag = true;
753     }
754     else
755     {
756         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_ARTIST, Oscl_File::SEEKCUR) == -1)
757         {
758             return;
759         }
760     }
761 
762     if (!iAlbumFoundFlag)
763     {
764         // Album
765         status = ReadStringValueFrame(PV_ID3_FRAME_ALBUM, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_ALBUM);
766         if (status != PVMFSuccess)
767         {
768             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for album"));
769             OSCL_LEAVE(OsclErrGeneral);
770         }
771         iAlbumFoundFlag = true;
772     }
773     else
774     {
775         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_ALBUM, Oscl_File::SEEKCUR) == -1)
776         {
777             return;
778         }
779     }
780 
781     if (!iYearFoundFlag)
782     {
783         //Year
784         status = ReadStringValueFrame(PV_ID3_FRAME_YEAR, PV_ID3_CHARSET_ISO88591, ID3V1_MAX_NUM_BYTES_YEAR);
785         if (status != PVMFSuccess)
786         {
787             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error = ReadStringValueFrame failed for year"));
788             OSCL_LEAVE(OsclErrGeneral);
789         }
790         iYearFoundFlag = true;
791     }
792     else
793     {
794         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_YEAR, Oscl_File::SEEKCUR) == -1)
795         {
796             return;
797         }
798     }
799     OSCL_StackString<128> keyStr;
800     PvmiKvpSharedPtr kvpPtr;
801     uint8* frameData = NULL;
802 
803     if (!iCommentFoundFlag   || !iTrackNumberFoundFlag)
804     {
805         frameData = NULL;
806         //Comment or Track Number
807         // Read and convert comment & track number
808         uint32 frameDataSize = ID3V1_MAX_NUM_BYTES_FIELD_SIZE + 1;
809         int32 err = OsclErrNone;
810         frameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, frameDataSize, &iAlloc);
811         if (OsclErrNone != err || !frameData)
812         {
813             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - Out of memory"));
814             OSCL_LEAVE(OsclErrNoMemory);
815         }
816         oscl_memset(frameData, 0, frameDataSize);
817 
818         if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_COMMENT, frameData) == false)
819         {
820             iAlloc.deallocate(frameData);
821             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed"));
822             OSCL_LEAVE(OsclErrGeneral);
823         }
824 
825 
826         if (frameData[ID3V1_MAX_NUM_BYTES_COMMENT-2] == 0 &&
827                 frameData[ID3V1_MAX_NUM_BYTES_COMMENT-1] != 0)
828         {
829             if (!iTrackNumberFoundFlag)
830             {
831                 // This would mean its an ID3v1.1 tag and hence has the
832                 // the track number also, so extract it
833                 iVersion = PV_ID3_V1_1;
834 
835                 if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_NUMBER, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
836                 {
837                     iAlloc.deallocate(frameData);
838                     LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber"));
839                     OSCL_LEAVE(OsclErrNotSupported);
840                 }
841 
842                 // Allocate key-value pair
843                 OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate););
844                 if (OsclErrNone != err || !kvpPtr)
845                 {
846                     LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
847                     iAlloc.deallocate(frameData);
848                     OSCL_LEAVE(OsclErrNoMemory);
849                     return;
850                 }
851 
852                 if (!truncate)
853                 {
854                     kvpPtr->value.uint32_value = (uint32)frameData[ID3V1_MAX_NUM_BYTES_COMMENT - 1];
855                 }
856                 OSCL_TRY(err, iFrames.push_back(kvpPtr););
857                 OSCL_FIRST_CATCH_ANY(err,
858                                      LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
859                                      iAlloc.deallocate(frameData);
860                                      OSCL_LEAVE(OsclErrNoMemory);
861                                      return;
862                                     );
863                 iTrackNumberFoundFlag = true;
864             }
865         }
866         if (!iCommentFoundFlag)
867         {
868 
869             // Comment frame
870             frameData[ID3V1_MAX_NUM_BYTES_COMMENT] = 0;
871             if (ConstructKvpKey(keyStr, PV_ID3_FRAME_COMMENT, PV_ID3_CHARSET_ISO88591) != PVMFSuccess)
872             {
873                 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for tracknumber"));
874                 iAlloc.deallocate(frameData);
875                 OSCL_LEAVE(OsclErrNotSupported);
876             }
877 
878             uint32 dataSize = ID3V1_MAX_NUM_BYTES_COMMENT + 1;
879             // Allocate key-value pair
880             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataSize, truncate););
881             if (OsclErrNone != err || !kvpPtr)
882             {
883                 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
884                 iAlloc.deallocate(frameData);
885                 OSCL_LEAVE(OsclErrNoMemory);
886                 return;
887             }
888 
889             if (!truncate)
890             {
891                 uint32 comment_size = oscl_strlen((char*) frameData);
892                 oscl_strncpy(kvpPtr->value.pChar_value, (char *)frameData, dataSize);
893                 kvpPtr->value.pChar_value[comment_size] = 0;
894                 kvpPtr->length = comment_size + 1;
895             }
896 
897             if (PVMFSuccess != PushFrameToFrameVector(kvpPtr, iFrames))
898             {
899                 LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - iFrame.push_back failed"));
900                 iAlloc.deallocate(frameData);
901                 return ;
902             }
903             iCommentFoundFlag = true;
904 
905         }
906         iAlloc.deallocate(frameData);
907     }
908     else
909     {
910         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_FIELD_SIZE, Oscl_File::SEEKCUR) == -1)
911         {
912             return;
913         }
914     }
915     if (!iGenereFoundFlag)
916     {
917         // Genre frame
918         uint32 frameDataSize = ID3V1_MAX_NUM_BYTES_GENRE + 1;
919         int32 err = 0;
920         frameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, frameDataSize, &iAlloc);
921         if (OsclErrNone != err || !frameData)
922         {
923             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - Out of memory"));
924             OSCL_LEAVE(OsclErrNoMemory);
925         }
926         oscl_memset(frameData, 0, frameDataSize);
927 
928         if (readByteData(iInputFile, ID3V1_MAX_NUM_BYTES_GENRE, frameData) == false)
929         {
930             iAlloc.deallocate(frameData);
931             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - readByteData failed"));
932             OSCL_LEAVE(OsclErrGeneral);
933         }
934 
935         if (ConstructKvpKey(keyStr, PV_ID3_FRAME_GENRE, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
936         {
937             iAlloc.deallocate(frameData);
938             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - ConstructKvpKey failed for genre"));
939             OSCL_LEAVE(OsclErrNotSupported);
940         }
941 
942         OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate););
943         if (OsclErrNone != err || !kvpPtr)
944         {
945             iAlloc.deallocate(frameData);
946             LOG_ERR((0, "PVID3ParCom::ReadID3V1Tag: Error - AllocateKvp failed. err=%d", err));
947             OSCL_LEAVE(OsclErrNoMemory);
948             return;
949         }
950 
951         if (!truncate)
952         {
953             kvpPtr->value.uint32_value = (uint32)(frameData[ID3V1_MAX_NUM_BYTES_GENRE - 1]);
954         }
955         OSCL_TRY(err, iFrames.push_back(kvpPtr););
956         OSCL_FIRST_CATCH_ANY(err,
957                              iAlloc.deallocate(frameData);
958                              LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
959                              OSCL_LEAVE(OsclErrNoMemory);
960                              return;
961                             );
962         iAlloc.deallocate(frameData);
963         iGenereFoundFlag = true;
964     }
965     else
966     {
967         if (iInputFile->Seek(ID3V1_MAX_NUM_BYTES_GENRE, Oscl_File::SEEKCUR) == -1)
968         {
969             return;
970         }
971     }
972 }
973 
974 ////////////////////////////////////////////////////////////////////////////
ReadHeaderID3V2(bool aReadTags)975 bool PVID3ParCom::ReadHeaderID3V2(bool aReadTags)
976 {
977     bool result = false;
978 
979     // Read and convert tag versions, Major and Minor
980     uint8 ID3V2MajorVer, ID3V2MinorVer;
981     if (read8(iInputFile, ID3V2MajorVer) == false)
982     {
983         return false;
984     }
985     if (read8(iInputFile, ID3V2MinorVer) == false)
986     {
987         return false;
988     }
989 
990     switch (ID3V2MajorVer)
991     {
992         case PV_ID3_V2_2:
993             iVersion = PV_ID3_V2_2;
994             break;
995         case PV_ID3_V2_3:
996             iVersion = PV_ID3_V2_3;
997             break;
998         case PV_ID3_V2_4:
999             iVersion = PV_ID3_V2_4;
1000             break;
1001     }
1002 
1003 BEGIN_V2:
1004     // Read and convert tag flags
1005     if (read8(iInputFile, iID3TagInfo.iID3V2TagFlagsV2) == false)
1006     {
1007         return false;
1008     }
1009 
1010     uint32 tagsize = 0;
1011 
1012     // Read and convert tag size
1013     if (read32(iInputFile, tagsize) == false)
1014     {
1015         return false;
1016     }
1017 
1018     // Now check if an extended header exists
1019     bool extHeaderFlag = false;
1020     if (iID3TagInfo.iID3V2TagFlagsV2 & EXT_FLAGMASK)
1021     {
1022         if (iVersion == PV_ID3_V2_2)
1023         {
1024             // Since no compression scheme has been decided yet, just ignore the entire tag
1025             LOG_ERR((0, "PVID3ParCom::ReadHeaderID3V2(): Error - cannot process a compressed tag"));
1026             OSCL_LEAVE(OsclErrGeneral);
1027         }
1028 
1029         extHeaderFlag = true;
1030         //read extended header data
1031         if (!ReadExtendedHeader())
1032             return false;
1033     }
1034 
1035     //check if footer is present.
1036     if (iID3TagInfo.iID3V2TagFlagsV2 & FTR_FLAGMASK)
1037     {
1038         iID3TagInfo.iFooterPresent = true;
1039     }
1040 
1041     // tagSize will store the file's Id3v2 tag size
1042     iID3TagInfo.iID3V2TagSize = SafeSynchIntToInt32(tagsize);
1043 
1044     //calculate start of audio frame.
1045     if (iTagAtBof)
1046     {
1047         // set iByteOffsetToStartOfAudioFrames and it must account for the frame header
1048         iByteOffsetToStartOfAudioFrames =
1049             iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER;
1050 
1051         if (iID3TagInfo.iFooterPresent)
1052             iByteOffsetToStartOfAudioFrames += ID3V2_TAG_NUM_BYTES_HEADER; //header & footer are of same size.
1053     }
1054     else
1055     {
1056         iByteOffsetToStartOfAudioFrames = 0;
1057     }
1058 
1059     // Header read is completed, now check whether we need to read the tags or not
1060     if (!aReadTags)
1061     {
1062         return false;
1063     }
1064     else
1065     {
1066         int count = ReadTagID3V2(iVersion);
1067         if (count > 0)
1068         {
1069             // we found some tags
1070             result = true;
1071         }
1072 
1073         if (iSeekFrameFound)
1074         {
1075             //jump to the new tag location skipping 5 bytes of tag ID and version.
1076             uint32 seek_size = iID3TagInfo.iID3V2TagSize + ID3V2_TAG_NUM_BYTES_HEADER + (iID3TagInfo.iFooterPresent ? ID3V2_TAG_NUM_BYTES_HEADER : 0);
1077             if (iInputFile->Seek(seek_size, Oscl_File::SEEKSET) == -1)
1078             {
1079                 return false;
1080             }
1081 
1082             //skip 5 bytes of tag ID and version.
1083             if (iInputFile->Seek(iID3TagInfo.iID3V2SeekOffset, Oscl_File::SEEKCUR) == -1)
1084             {
1085                 return false;
1086             }
1087 
1088             if (!CheckForTagID3V2())
1089                 return false;
1090 
1091             if (read8(iInputFile, ID3V2MajorVer) == false)
1092             {
1093                 return false;
1094             }
1095 
1096             if (read8(iInputFile, ID3V2MinorVer) == false)
1097             {
1098                 return false;
1099             }
1100 
1101             if (ID3V2MajorVer != PV_ID3_V2_4)
1102                 return false;
1103 
1104             //parse new tag, located at the seek offset.
1105             iSeekFrameFound = false;
1106             goto BEGIN_V2;
1107         }
1108     }
1109     return result;
1110 }
1111 
1112 /////////////////////////////////////////////////////////////////////////////////
ReadExtendedHeader()1113 bool PVID3ParCom::ReadExtendedHeader()
1114 {
1115 
1116     uint32 extsize = 0;
1117     if (read32(iInputFile, extsize) == false)
1118     {
1119         return false;
1120     }
1121 
1122     // Calculate the length of the extended header.
1123     iID3TagInfo.iID3V2ExtendedHeaderSize = SafeSynchIntToInt32(extsize);
1124 
1125 
1126     if (iVersion == PV_ID3_V2_4)
1127     {
1128         //subtract "ext hdr size" field size from the header size.
1129         iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - ID3V2_TAG_EXTENDED_HEADER_SIZE;
1130 
1131         //check if this tag is an update of previous tag.
1132         uint8 flgsize = 0, exthdrflg = 0;
1133         // Read and ext hdr flg size tag flags
1134         if (read8(iInputFile, flgsize) == false)
1135         {
1136             return false;
1137         }
1138         if (flgsize > 0x01) //flg size should be 1 byte in V2.4
1139             return false ;
1140         // Read tag flags
1141         if (read8(iInputFile, exthdrflg) == false)
1142         {
1143             return false;
1144         }
1145         //if this tag is not an update flag, ignore any tag found before this one
1146         if (!(exthdrflg & EXTHDR_UPDMASK) && (iFrames.size() > 0))
1147         {
1148             while (iFrames.size() > 0)
1149                 iFrames.pop_back();
1150         }
1151 
1152         //subtract 2 bytes for flg size and flg from ext hdr size.
1153         iID3TagInfo.iID3V2ExtendedHeaderSize = iID3TagInfo.iID3V2ExtendedHeaderSize - 2;
1154     }
1155 
1156     if (iVersion == PV_ID3_V2_3)
1157     {
1158         //V2.3 extended hdr size field does not include 6 byte size of the header
1159         iID3TagInfo.iID3V2ExtendedHeaderSize += ID3V2_TAG_EXTENDED_HEADER_TOTAL_SIZE;
1160     }
1161 
1162     return true;
1163 }
1164 
1165 /////////////////////////////////////////////////////////////////////////////////
ReadTagID3V2(PVID3Version aVersion)1166 int PVID3ParCom::ReadTagID3V2(PVID3Version aVersion)
1167 {
1168     PVID3FrameType frameType = PV_ID3_FRAME_EEND;
1169     uint32 i = 0;
1170     uint32 currFrameLength = 0;
1171     uint32 current_file_pos = iInputFile->Tell();
1172     uint32 data_len_indicator_size = 0;
1173     uint32 count = 0;
1174 
1175     if (iID3TagInfo.iID3V2ExtendedHeaderSize > 0)
1176         i += iID3TagInfo.iID3V2ExtendedHeaderSize ;
1177 
1178     while (i <= (iID3TagInfo.iID3V2TagSize))
1179     {
1180         // Read the frame header
1181         if (iInputFile->Seek(current_file_pos + i, Oscl_File::SEEKSET) == -1)
1182         {
1183             return count;
1184         }
1185 
1186         ReadFrameHeaderID3V2(aVersion);
1187 
1188         currFrameLength = iID3TagInfo.iID3V2FrameSize;
1189         frameType = FrameSupportedID3V2(aVersion);
1190 
1191         if ((frameType != PV_ID3_FRAME_SEEK) && (currFrameLength > iID3TagInfo.iID3V2TagSize))
1192         {
1193             break;
1194         }
1195         // handle the frame header
1196 
1197         uint32 frame_header_size = 0;
1198         if (aVersion == PV_ID3_V2_2)
1199             frame_header_size = ID3V2_2_FRAME_NUM_BYTES_HEADER;
1200         else
1201             frame_header_size = ID3V2_FRAME_NUM_BYTES_HEADER;
1202 
1203 
1204         if ((currFrameLength == 0) && (frameType != PV_ID3_FRAME_EEND))
1205         {
1206             i += frame_header_size;
1207             continue;
1208         }
1209         if (aVersion == PV_ID3_V2_3)
1210         {
1211             if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_3_FLAGMASK)
1212                 frameType = PV_ID3_FRAME_UNRECOGNIZED;
1213         }
1214         else if (aVersion == PV_ID3_V2_4)
1215         {
1216             if (iID3TagInfo.iID3V2FrameFlag[1] & ENCR_COMP_4_FLAGMASK)
1217                 frameType = PV_ID3_FRAME_UNRECOGNIZED;
1218         }
1219 
1220         if (frameType == PV_ID3_FRAME_SEEK)
1221         {
1222             iSeekFrameFound = true;
1223             iID3TagInfo.iID3V2SeekOffset = iID3TagInfo.iID3V2FrameSize;
1224             return count;
1225         }
1226 
1227         // Check if data length indicator is present
1228         if (aVersion == PV_ID3_V2_4 && (iID3TagInfo.iID3V2FrameFlag[1] & FRAME_LENGTH_INDICATOR_FLAGMASK))
1229         {
1230             uint32 temp = 0;
1231             // Read data length indicator
1232             if (read32(iInputFile, temp) == false)
1233             {
1234                 return count;
1235             }
1236             // stored as syncsafe integer
1237             currFrameLength = SafeSynchIntToInt32(temp);
1238 
1239             data_len_indicator_size = ID3V2_4_DATA_LENGTH_INDICATOR_SIZE;
1240         }
1241 
1242         if (((currFrameLength > 1) && (frameType != PV_ID3_FRAME_UNRECOGNIZED
1243                                        && frameType != PV_ID3_FRAME_INVALID
1244                                        && frameType != PV_ID3_FRAME_EEND
1245                                        && frameType != PV_ID3_FRAME_CANDIDATE)))
1246         {
1247             uint8 unicodeCheck;
1248 
1249             if (read8(iInputFile, unicodeCheck) == false)
1250             {
1251                 return count;
1252             }
1253 
1254             if ((frameType == PV_ID3_FRAME_LYRICS) || (frameType == PV_ID3_FRAME_COMMENT))
1255             {
1256                 ReadLyricsCommFrame(unicodeCheck, currFrameLength - 1, frameType);
1257 
1258             }
1259             else if ((frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC))
1260             {
1261                 if (currFrameLength > 3000000)
1262                 {
1263                     // TODO: scale down album art to something manageable right here
1264                     LOG_DEBUG((0, "PVID3ParCom::ReadTagID3V2: skipping > 3MB album art"));
1265                 }
1266                 else
1267                 {
1268                     if (ReadAlbumArtFrame(frameType, unicodeCheck, currFrameLength)  != PVMFSuccess)
1269                     {
1270                         LOG_ERR((0, "PVID3ParCom::ReadTagID3V2: Error - ReadAPICFrame failed"));
1271                         return count;
1272                     }
1273                 }
1274             }
1275             else if (unicodeCheck < PV_ID3_CHARSET_END)
1276             {
1277 
1278                 if (!ReadFrameData(unicodeCheck, frameType,
1279                                    current_file_pos + i + frame_header_size + data_len_indicator_size + 1,
1280                                    currFrameLength))
1281                 {
1282                     return count;
1283                 }
1284             }
1285             else
1286             {
1287                 // This case is when no text type is defined in the frame.
1288                 HandleID3V2FrameDataASCII(frameType, i + frame_header_size + data_len_indicator_size, currFrameLength);
1289             }
1290             count++;
1291         }
1292         else
1293         {
1294             if (frameType == PV_ID3_FRAME_EEND ||
1295                     frameType == PV_ID3_FRAME_INVALID)
1296             {
1297                 i = iID3TagInfo.iID3V2TagSize + 1;
1298             }
1299             else if (frameType == PV_ID3_FRAME_UNRECOGNIZED ||
1300                      frameType == PV_ID3_FRAME_CANDIDATE) // handle candidate frames as we do unsupported
1301             {
1302                 if (i < iID3TagInfo.iID3V2TagSize)
1303                 {
1304                     HandleID3V2FrameUnsupported(frameType,
1305                                                 current_file_pos + i,
1306                                                 currFrameLength + frame_header_size + data_len_indicator_size);
1307                 }
1308             }
1309         }
1310 
1311         i += iID3TagInfo.iID3V2FrameSize + frame_header_size;
1312     }
1313     return count;
1314 }
1315 
ValidateFrameV2_4(PVID3FrameType & frameType,bool bUseSyncSafeFrameSize)1316 bool PVID3ParCom::ValidateFrameV2_4(PVID3FrameType& frameType, bool bUseSyncSafeFrameSize)
1317 {
1318     // Initialize OUT param
1319     frameType = PV_ID3_FRAME_INVALID;
1320 
1321     uint8 frameid[ID3V2_FRAME_NUM_BYTES_ID + 1] = {0};
1322     // read frame id for next frame
1323     if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_ID, frameid) == false)
1324     {
1325         return false;
1326     }
1327     frameid[ID3V2_FRAME_NUM_BYTES_ID] = 0;
1328 
1329     // Get frame type from frame ID
1330     frameType = FrameSupportedID3V2(PV_ID3_V2_4, frameid);
1331     if (PV_ID3_FRAME_INVALID == frameType ||
1332             PV_ID3_FRAME_EEND == frameType)
1333     {
1334         return false;
1335     }
1336     else
1337     {
1338         uint32 frameSize = 0;
1339         uint8 frameflags[ID3V2_FRAME_NUM_BYTES_FLAG] = {0};
1340 
1341         // Validate frame size and flags
1342 
1343         if (read32(iInputFile, frameSize) == false)
1344         {
1345             return false;
1346         }
1347         if (bUseSyncSafeFrameSize)
1348         {
1349             frameSize = SafeSynchIntToInt32(frameSize);
1350         }
1351 
1352         if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_FLAG, frameflags) == false)
1353         {
1354             return false;
1355         }
1356 
1357         if ((0 == frameSize ||
1358                 (frameSize + ID3V2_FRAME_NUM_BYTES_HEADER) > iID3TagInfo.iID3V2TagSize) ||
1359                 ((frameflags[0] & ID3V2_4_MASK_FRAME_FLAG_VERIFICATION) ||
1360                  (frameflags[1] & ID3V2_4_MASK_FRAME_FLAG_VERIFICATION)))
1361         {
1362             // validation for frame size or flags failed
1363             return false;
1364         }
1365         else
1366         {
1367             return true;
1368         }
1369     }
1370 }
1371 
ValidateFrameLengthV2_4(uint32 aFrameSize)1372 uint32 PVID3ParCom::ValidateFrameLengthV2_4(uint32 aFrameSize)
1373 {
1374     int32 currFilePos = iInputFile->Tell();
1375     int32 errCode = -1;
1376     int32 actualFrameLen = 0;
1377 
1378     // we have already read the complete current frame header
1379 
1380     do
1381     {
1382         // Assuming syncsafe frame size
1383         actualFrameLen = SafeSynchIntToInt32(aFrameSize);
1384 
1385         //
1386         /* validate frame using syncsafe size */
1387         //
1388 
1389         // Seek to next frame boundary with syncsafe size
1390         errCode = iInputFile->Seek(actualFrameLen, Oscl_File::SEEKCUR);
1391         if (-1 == errCode)
1392         {
1393             // proceed with default syncsafe handling
1394             break;
1395         }
1396 
1397         bool bIsSyncSafeFrameValid = false;
1398         PVID3FrameType frameTypeUsingSyncSafeSize = PV_ID3_FRAME_INVALID;
1399         // Get the validation status and frame type
1400         bIsSyncSafeFrameValid = ValidateFrameV2_4(frameTypeUsingSyncSafeSize);
1401 
1402         //
1403         /* validate frame using non-syncsafe size */
1404         //
1405 
1406         // FrameSize is not even stored as non-syncsafe
1407         if ((aFrameSize + ID3V2_FRAME_NUM_BYTES_HEADER) > iID3TagInfo.iID3V2TagSize)
1408         {
1409             // proceed with syncsafe, as non-syncsafe length not valid
1410             break;
1411         }
1412 
1413         // Seek back
1414         errCode = iInputFile->Seek(currFilePos, Oscl_File::SEEKSET);
1415         if (-1 == errCode)
1416         {
1417             LOG_ERR((0, "PVID3ParCom::ValidateFrameLengthV2_4: Error - iInputFile->Seek failed"));
1418             OSCL_LEAVE(OsclErrGeneral);
1419         }
1420         // Seek to next frame boundary with non-syncsafe size
1421         errCode = iInputFile->Seek(aFrameSize, Oscl_File::SEEKCUR);
1422         if (-1 == errCode)
1423         {
1424             // proceed with default syncsafe handling
1425             break;
1426         }
1427 
1428         bool bIsNonSyncSafeFrameValid = false;
1429         PVID3FrameType frameTypeUsingNonSyncSafeSize = PV_ID3_FRAME_INVALID;
1430         // Get the validation status and frame type
1431         bIsNonSyncSafeFrameValid = ValidateFrameV2_4(frameTypeUsingNonSyncSafeSize, false);
1432 
1433         // - Give more priority to non-syncsafe VALID frame ID,
1434         //      than syncsafe candidate frame ID (frame validation is true for both)
1435         // - In case, we have frame validation true for both syncsafe and non-syncsafe size,
1436         //      we will use default syncsafe representation
1437         // - In case, we have frame validation false for both syncsafe and non-syncsafe size,
1438         //      we will use default syncsafe representation
1439         if (bIsSyncSafeFrameValid && frameTypeUsingSyncSafeSize != PV_ID3_FRAME_CANDIDATE)
1440         {
1441             // syncsafe representation
1442         }
1443         else if (bIsNonSyncSafeFrameValid && frameTypeUsingNonSyncSafeSize != PV_ID3_FRAME_CANDIDATE)
1444         {
1445             // non-syncsafe representation
1446             actualFrameLen = aFrameSize;
1447         }
1448         else if (!bIsSyncSafeFrameValid && bIsNonSyncSafeFrameValid)
1449         {
1450             // non-syncsafe representation
1451             actualFrameLen = aFrameSize;
1452         }
1453         else
1454         {
1455             // consider rest all syncsafe representation
1456         }
1457 
1458     }
1459     while (false);
1460 
1461     // Seek back
1462     errCode = iInputFile->Seek(currFilePos, Oscl_File::SEEKSET);
1463     if (-1 == errCode)
1464     {
1465         LOG_ERR((0, "PVID3ParCom::ValidateFrameLengthV2_4: Error - iInputFile->Seek failed"));
1466         OSCL_LEAVE(OsclErrGeneral);
1467     }
1468 
1469     return actualFrameLen;
1470 }
1471 
1472 //////////////////////////////////////////////////////////////////////////
ReadFrameData(uint8 unicodeCheck,PVID3FrameType frameType,uint32 pos,uint32 currFrameLength)1473 bool  PVID3ParCom::ReadFrameData(uint8 unicodeCheck, PVID3FrameType frameType, uint32 pos, uint32 currFrameLength)
1474 {
1475     if (unicodeCheck == PV_ID3_CHARSET_ISO88591)
1476     {
1477         // This frame contains normal ASCII text strings. (ISO-8859-1)
1478         iID3TagInfo.iTextType = PV_ID3_CHARSET_ISO88591;
1479         HandleID3V2FrameDataASCII(frameType, pos, currFrameLength - 1);
1480     }
1481     else if (unicodeCheck == PV_ID3_CHARSET_UTF16)
1482     {
1483         uint16 endianCheck;
1484 
1485         if (read16(iInputFile, endianCheck) == false)
1486         {
1487             return false;
1488         }
1489 
1490         // This frame's text strings are Unicode and the frame
1491         // does include a BOM value. (UTF-16)
1492         iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
1493         uint32 endianType;
1494         if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
1495         {
1496             endianType = UNICODE_LITTLE_ENDIAN;
1497         }
1498         else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
1499         {
1500             endianType = UNICODE_BIG_ENDIAN;
1501         }
1502         else
1503         {
1504             return false;
1505         }
1506 
1507         // value of 2 is for BOM Character
1508         HandleID3V2FrameDataUnicode16(frameType, pos + 2, currFrameLength - 3, endianType);
1509     }
1510     else if (unicodeCheck == PV_ID3_CHARSET_UTF16BE)
1511     {
1512         // This frame's text strings are Unicode but the frame
1513         // does not contain a BOM(byte order mark) (UTF-16BE)
1514         iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16BE;
1515         // Default ID3V2 endian type to Big Endian
1516         uint32 endianType = UNICODE_BIG_ENDIAN;
1517         // Big Endian is assumed since the frame did not specify the endian type.
1518         HandleID3V2FrameDataUnicode16(frameType, pos, currFrameLength - 1, endianType);
1519     }
1520     else if (unicodeCheck == PV_ID3_CHARSET_UTF8)
1521     {
1522         // This frame's text strings are Unicode (UTF-8)
1523         iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF8;
1524         HandleID3V2FrameDataUTF8(frameType, pos, currFrameLength - 1);
1525     }
1526     return true;
1527 }
1528 
1529 ////////////////////////////////////////////////////////////////////////////
ReadFrameHeaderID3V2(PVID3Version aVersion)1530 void PVID3ParCom::ReadFrameHeaderID3V2(PVID3Version aVersion)
1531 {
1532     if (aVersion == PV_ID3_V2_2)
1533     {
1534         ReadFrameHeaderID3V2_2();
1535     }
1536     else
1537     {
1538         // Read frame ID
1539         if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false)
1540         {
1541             return;
1542         }
1543         iID3TagInfo.iID3V2FrameID[ID3V2_FRAME_NUM_BYTES_ID] = 0;
1544         // Read frame size
1545         if (read32(iInputFile, iID3TagInfo.iID3V2FrameSize) == false)
1546         {
1547             return;
1548         }
1549         // Read frame flag
1550         if (readByteData(iInputFile, ID3V2_FRAME_NUM_BYTES_FLAG, iID3TagInfo.iID3V2FrameFlag) == false)
1551         {
1552             return;
1553         }
1554 
1555         if (PV_ID3_V2_4 == aVersion)
1556         {
1557             if (iID3TagInfo.iID3V2FrameSize > MAX_SYNCSAFE_LEN)
1558             {
1559                 // Verify whether frame length is SyncSafe or Non-SyncSafe
1560                 iID3TagInfo.iID3V2FrameSize = ValidateFrameLengthV2_4(iID3TagInfo.iID3V2FrameSize);
1561             }
1562         }
1563     }
1564     return;
1565 }
1566 
1567 ////////////////////////////////////////////////////////////////////////////
ReadFrameHeaderID3V2_2()1568 void PVID3ParCom::ReadFrameHeaderID3V2_2()
1569 {
1570     if (readByteData(iInputFile, ID3V2_2_FRAME_NUM_BYTES_ID, iID3TagInfo.iID3V2FrameID) == false)
1571     {
1572         return;
1573     }
1574     iID3TagInfo.iID3V2FrameID[ID3V2_2_FRAME_NUM_BYTES_ID] = 0;
1575     if (read24(iInputFile, iID3TagInfo.iID3V2FrameSize) == false)
1576     {
1577         return;
1578     }
1579 
1580     return;
1581 }
1582 
1583 //////////////////////////////////////////////////////////////////////////////
HandleID3V2FrameDataASCII(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize)1584 void PVID3ParCom::HandleID3V2FrameDataASCII(PVID3FrameType aFrameType,
1585         uint32         aPos,
1586         uint32         aSize)
1587 {
1588     OSCL_StackString<128> keyStr;
1589     PvmiKvpSharedPtr kvpPtr;
1590     PVMFStatus status = PVMFSuccess;
1591     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1592     {
1593         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed"));
1594         OSCL_LEAVE(OsclErrGeneral);
1595     }
1596 
1597     switch (aFrameType)
1598     {
1599         case PV_ID3_FRAME_TRACK_LENGTH:
1600             status = ReadTrackLengthFrame(aSize, PV_ID3_CHARSET_ISO88591);
1601             if (status != PVMFSuccess)
1602             {
1603                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadTrackLengthFrame failed. status=%d", status));
1604                 OSCL_LEAVE(OsclErrGeneral);
1605             }
1606             break;
1607         case PV_ID3_FRAME_TITLE:
1608         case PV_ID3_FRAME_ARTIST:
1609         case PV_ID3_FRAME_ALBUM:
1610         case PV_ID3_FRAME_YEAR:
1611         case PV_ID3_FRAME_TRACK_NUMBER:
1612         case PV_ID3_FRAME_GENRE:
1613         case PV_ID3_FRAME_COPYRIGHT:
1614         case PV_ID3_FRAME_DATE:
1615         case PV_ID3_FRAME_RECORDING_TIME:
1616 //new frames support
1617         case PV_ID3_FRAME_AUTHOR:
1618         case PV_ID3_FRAME_COMPOSER:
1619         case PV_ID3_FRAME_DESCRIPTION:
1620         case PV_ID3_FRAME_VERSION:
1621         case PV_ID3_FRAME_PART_OF_SET:
1622 
1623             status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_ISO88591, aSize);
1624             if (status != PVMFSuccess)
1625             {
1626                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status));
1627                 OSCL_LEAVE(OsclErrGeneral);
1628             }
1629             if (aFrameType == PV_ID3_FRAME_TITLE)
1630                 iTitleFoundFlag = true;
1631             if (aFrameType == PV_ID3_FRAME_ARTIST)
1632                 iArtistFoundFlag = true;
1633             if (aFrameType == PV_ID3_FRAME_ALBUM)
1634                 iAlbumFoundFlag = true;
1635             if (aFrameType == PV_ID3_FRAME_YEAR)
1636                 iYearFoundFlag = true;
1637             if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
1638                 iTrackNumberFoundFlag = true;
1639             if (aFrameType == PV_ID3_FRAME_GENRE)
1640                 iGenereFoundFlag = true;
1641 
1642             break;
1643 
1644         default:
1645             break;
1646     }
1647 }
1648 
HandleID3V2FrameUnsupported(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize)1649 void PVID3ParCom::HandleID3V2FrameUnsupported(PVID3FrameType aFrameType,
1650         uint32         aPos,
1651         uint32         aSize)
1652 {
1653 // In Android, don't try to read unsupported metadata, because a) we don't
1654 // know what to do with it anyway, and b) we end up here for corrupted files
1655 // too, in which case the size is likely bogus and will result in running
1656 // out of RAM.
1657 #ifndef ANDROID
1658     OSCL_StackString<128> keyStr;
1659     PvmiKvpSharedPtr kvpPtr;
1660     PVMFStatus status = PVMFSuccess;
1661     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1662     {
1663         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - iInputFile->Seek failed"));
1664         OSCL_LEAVE(OsclErrGeneral);
1665     }
1666 
1667     status = ReadFrame(aFrameType, aSize);
1668     if (status != PVMFSuccess)
1669     {
1670         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataASCII: Error - ReadStringValueFrame failed. status=%d", status));
1671         OSCL_LEAVE(OsclErrGeneral);
1672     }
1673 #endif
1674 }
1675 
1676 ////////////////////////////////////////////////////////////////////////////
HandleID3V2FrameDataUnicode16(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize,uint32 aEndianType)1677 void PVID3ParCom::HandleID3V2FrameDataUnicode16(PVID3FrameType aFrameType,
1678         uint32 aPos,
1679         uint32 aSize,
1680         uint32 aEndianType)
1681 {
1682     // seek to the beginning of the current frame data
1683     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1684     {
1685         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - iInputFile->Seek failed"));
1686         OSCL_LEAVE(OsclErrGeneral);
1687         return;
1688     }
1689 
1690     PVMFStatus status = PVMFSuccess;
1691     PVID3CharacterSet charSet;
1692     if (aEndianType == UNICODE_BIG_ENDIAN)
1693         charSet = PV_ID3_CHARSET_UTF16BE;
1694     else
1695         charSet = PV_ID3_CHARSET_UTF16;
1696 
1697     switch (aFrameType)
1698     {
1699 
1700         case PV_ID3_FRAME_TRACK_LENGTH:
1701             //is a numeric string and does not depend on text encoding.
1702             status = ReadTrackLengthFrame(aSize, charSet);
1703             if (status != PVMFSuccess)
1704             {
1705                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadTrackLengthFrame failed. status=%d", status));
1706                 OSCL_LEAVE(OsclErrGeneral);
1707                 return;
1708             }
1709             break;
1710         case PV_ID3_FRAME_TITLE:
1711         case PV_ID3_FRAME_ARTIST:
1712         case PV_ID3_FRAME_ALBUM:
1713         case PV_ID3_FRAME_YEAR:
1714         case PV_ID3_FRAME_TRACK_NUMBER:
1715         case PV_ID3_FRAME_GENRE:
1716         case PV_ID3_FRAME_COPYRIGHT:
1717         case PV_ID3_FRAME_DATE:
1718         case PV_ID3_FRAME_RECORDING_TIME:
1719 //new frames support
1720         case PV_ID3_FRAME_AUTHOR:
1721         case PV_ID3_FRAME_COMPOSER:
1722         case PV_ID3_FRAME_DESCRIPTION:
1723         case PV_ID3_FRAME_VERSION:
1724         case PV_ID3_FRAME_PART_OF_SET:
1725 
1726             status = ReadStringValueFrame(aFrameType, charSet, aSize);
1727             if (status != PVMFSuccess)
1728             {
1729                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUnicode16: Error - ReadStringValueFrame failed. status=%d", status));
1730                 OSCL_LEAVE(OsclErrGeneral);
1731                 return;
1732             }
1733             if (aFrameType == PV_ID3_FRAME_TITLE)
1734                 iTitleFoundFlag = true;
1735             if (aFrameType == PV_ID3_FRAME_ARTIST)
1736                 iArtistFoundFlag = true;
1737             if (aFrameType == PV_ID3_FRAME_ALBUM)
1738                 iAlbumFoundFlag = true;
1739             if (aFrameType == PV_ID3_FRAME_YEAR)
1740                 iYearFoundFlag = true;
1741             if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
1742                 iTrackNumberFoundFlag = true;
1743             if (aFrameType == PV_ID3_FRAME_GENRE)
1744                 iGenereFoundFlag = true;
1745 
1746             break;
1747 
1748         default:
1749             break;
1750     }
1751 }
1752 
1753 ////////////////////////////////////////////////////////////////////////////
HandleID3V2FrameDataUTF8(PVID3FrameType aFrameType,uint32 aPos,uint32 aSize)1754 void PVID3ParCom::HandleID3V2FrameDataUTF8(PVID3FrameType aFrameType,
1755         uint32         aPos,
1756         uint32         aSize)
1757 {
1758     if (iInputFile->Seek(aPos, Oscl_File::SEEKSET) == -1)
1759     {
1760         LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - iInputFile->Seek failed"));
1761         OSCL_LEAVE(OsclErrGeneral);
1762     }
1763 
1764     PVMFStatus status = PVMFSuccess;
1765     switch (aFrameType)
1766     {
1767 
1768         case PV_ID3_FRAME_TRACK_LENGTH:
1769             status = ReadTrackLengthFrame(aSize, PV_ID3_CHARSET_UTF8);
1770             if (status != PVMFSuccess)
1771             {
1772                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadTrackLengthFrame failed. status=%d", status));
1773                 OSCL_LEAVE(OsclErrGeneral);
1774             }
1775             break;
1776 
1777         case PV_ID3_FRAME_TITLE:
1778         case PV_ID3_FRAME_ARTIST:
1779         case PV_ID3_FRAME_ALBUM:
1780         case PV_ID3_FRAME_YEAR:
1781         case PV_ID3_FRAME_TRACK_NUMBER:
1782         case PV_ID3_FRAME_GENRE:
1783         case PV_ID3_FRAME_COPYRIGHT:
1784         case PV_ID3_FRAME_DATE:
1785         case PV_ID3_FRAME_RECORDING_TIME:
1786 //new frames support
1787         case PV_ID3_FRAME_AUTHOR:
1788         case PV_ID3_FRAME_COMPOSER:
1789         case PV_ID3_FRAME_DESCRIPTION:
1790         case PV_ID3_FRAME_VERSION:
1791         case PV_ID3_FRAME_PART_OF_SET:
1792 
1793             status = ReadStringValueFrame(aFrameType, PV_ID3_CHARSET_UTF8, aSize);
1794             if (status != PVMFSuccess)
1795             {
1796                 LOG_ERR((0, "PVID3ParCom::HandleID3V2FrameDataUTF8: Error - ReadStringValueFrame failed. status=%d", status));
1797                 OSCL_LEAVE(OsclErrGeneral);
1798             }
1799             if (aFrameType == PV_ID3_FRAME_TITLE)
1800                 iTitleFoundFlag = true;
1801             if (aFrameType == PV_ID3_FRAME_ARTIST)
1802                 iArtistFoundFlag = true;
1803             if (aFrameType == PV_ID3_FRAME_ALBUM)
1804                 iAlbumFoundFlag = true;
1805             if (aFrameType == PV_ID3_FRAME_YEAR)
1806                 iYearFoundFlag = true;
1807             if (aFrameType == PV_ID3_FRAME_TRACK_NUMBER)
1808                 iTrackNumberFoundFlag = true;
1809             if (aFrameType == PV_ID3_FRAME_GENRE)
1810                 iGenereFoundFlag = true;
1811 
1812             break;
1813 
1814         default:
1815             break;
1816     }
1817 }
1818 
1819 //----------------------------------------------------------------------------
1820 // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2(PVID3Version)
1821 //----------------------------------------------------------------------------
1822 // INPUT AND OUTPUT DEFINITIONS
1823 //
1824 //  Inputs: None
1825 //
1826 //  Outputs: None
1827 //
1828 //  Returns:
1829 //    ID3V2FrameTypeReturnValue - The value that describes the current frame.
1830 //                                of type enum TID3V2FrameType
1831 //
1832 //  Global Variables Used:
1833 //    TID3V2FrameType - The enum table containing the supported frame types
1834 //
1835 //----------------------------------------------------------------------------
1836 // FUNCTION DESCRIPTION
1837 //
1838 //  This function detects the ID3V2FrameType and returns the enum value that
1839 //  corresponds to the current frame.
1840 //
1841 //------------------------------------------------------------------------------
1842 
FrameSupportedID3V2(PVID3Version aVersion,uint8 * aframeid)1843 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2(PVID3Version aVersion, uint8* aframeid)
1844 {
1845     PVID3FrameType ID3V2FrameTypeReturnValue;
1846     uint8* pFrameID = (aframeid) ? aframeid : iID3TagInfo.iID3V2FrameID;
1847 
1848     if (0xff == pFrameID[0])
1849     {
1850         //possibly start of mp3 frame. Stop further parsing.
1851         return PV_ID3_FRAME_EEND;
1852     }
1853 
1854     if (aVersion == PV_ID3_V2_2)
1855     {
1856         ID3V2FrameTypeReturnValue = FrameSupportedID3V2_2();
1857     }
1858     else    //for v2.3 & v2.4
1859     {
1860         uint8 endTestBuf[ID3V2_FRAME_NUM_BYTES_ID] = {0};
1861 
1862         if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TITLE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1863         {
1864             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TITLE;
1865             iTitleFoundFlag = true;
1866         }
1867         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ARTIST, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1868         {
1869             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST;
1870             iArtistFoundFlag = true;
1871         }
1872         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_PART_OF_SET, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1873         {
1874             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET;
1875         }
1876         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ALBUM, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1877         {
1878             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM;
1879             iAlbumFoundFlag = true;
1880         }
1881         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COPYRIGHT, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1882         {
1883             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT;
1884         }
1885         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_GENRE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1886         {
1887             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_GENRE;
1888             iGenereFoundFlag = true;
1889         }
1890         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TRACK_NUMBER, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1891         {
1892             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER;
1893             iTrackNumberFoundFlag = true;
1894         }
1895         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_TRACK_LENGTH, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1896         {
1897             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH;
1898         }
1899         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COMMENT, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1900         {
1901             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT;
1902             iCommentFoundFlag = true;
1903         }
1904         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_YEAR, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1905         {
1906             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_YEAR;
1907             iYearFoundFlag = true;
1908         }
1909         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_RECORDING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1910         {
1911             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_RECORDING_TIME;
1912             iYearFoundFlag = true;
1913         }
1914         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_DATE, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1915         {
1916             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DATE;
1917         }
1918 
1919         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_ALBUMART, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1920         {
1921             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_APIC;
1922         }
1923         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_LYRICIST, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1924         {
1925             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS;
1926         }
1927 
1928         // For the seek frame.
1929         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_SEEK, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1930         {
1931             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_SEEK;
1932         }
1933         //new frames support
1934         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_AUTHOR, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1935         {
1936             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR;
1937         }
1938         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_COMPOSER, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1939         {
1940             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER;
1941         }
1942         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_DESCRIPTION, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1943         {
1944             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION;
1945         }
1946         else if (oscl_memcmp(pFrameID, ID3_FRAME_ID_VERSION, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1947         {
1948             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_VERSION;
1949         }
1950         else if (oscl_memcmp(pFrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1951         {
1952             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
1953         }
1954         else if (oscl_memcmp(pFrameID, endTestBuf, ID3V2_FRAME_NUM_BYTES_ID) == 0)
1955         {
1956             ID3V2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
1957         }
1958         else
1959         {
1960             // Find whether frame is invalid or unsupported
1961             ID3V2FrameTypeReturnValue = FrameValidatedID3V2_4(pFrameID);
1962         }
1963     }
1964     return ID3V2FrameTypeReturnValue;
1965 }
1966 
1967 //----------------------------------------------------------------------------
1968 // FUNCTION NAME: PVID3ParCom::FrameSupportedID3V2_2(void)
1969 //----------------------------------------------------------------------------
1970 // INPUT AND OUTPUT DEFINITIONS
1971 //
1972 //  Inputs: None
1973 //
1974 //  Outputs: None
1975 //
1976 //  Returns:
1977 //    ID3V2_2FrameTypeReturnValue - The value that describes the current frame.
1978 //                                of type enum TID3V2FrameType
1979 //
1980 //  Global Variables Used:
1981 //    TID3V2_2FrameType - The enum table containing the supported frame types
1982 //
1983 //----------------------------------------------------------------------------
1984 // FUNCTION DESCRIPTION
1985 //
1986 //  This function detects the ID3V2_2FrameType and returns the enum value that
1987 //  corresponds to the current frame.
1988 //
1989 //------------------------------------------------------------------------------
1990 
FrameSupportedID3V2_2(void)1991 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameSupportedID3V2_2(void)
1992 {
1993     uint8 endTestBuf[ID3V2_2_FRAME_NUM_BYTES_ID] = {0};
1994     PVID3FrameType ID3V2_2FrameTypeReturnValue;
1995 
1996     if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TITLE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
1997     {
1998         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TITLE;
1999         iTitleFoundFlag = true;
2000     }
2001     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ARTIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2002     {
2003         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ARTIST;
2004         iArtistFoundFlag = true;
2005     }
2006     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_PART_OF_SET, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2007     {
2008         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PART_OF_SET;
2009     }
2010     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUM, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2011     {
2012         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_ALBUM;
2013         iAlbumFoundFlag = true;
2014     }
2015     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COPYRIGHT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2016     {
2017         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COPYRIGHT;
2018     }
2019     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_GENRE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2020     {
2021         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_GENRE;
2022         iGenereFoundFlag = true;
2023     }
2024     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_NUMBER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2025     {
2026         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_NUMBER;
2027         iTrackNumberFoundFlag = true;
2028     }
2029     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_TRACK_LENGTH, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2030     {
2031         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_TRACK_LENGTH;
2032     }
2033     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMMENT, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2034     {
2035         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMMENT;
2036         iCommentFoundFlag = true;
2037     }
2038     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_YEAR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2039     {
2040         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_YEAR;
2041         iYearFoundFlag = true;
2042     }
2043     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DATE, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2044     {
2045         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DATE;
2046     }
2047     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_ALBUMART, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2048     {
2049         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_PIC;
2050     }
2051     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_LYRICIST, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2052     {
2053         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_LYRICS;
2054     }
2055 //new frames support
2056     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_AUTHOR, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2057     {
2058         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_AUTHOR;
2059     }
2060     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_COMPOSER, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2061     {
2062         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_COMPOSER;
2063     }
2064     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_DESCRIPTION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2065     {
2066         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_DESCRIPTION;
2067     }
2068     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, ID3V2_2_FRAME_ID_VERSION, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2069     {
2070         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_VERSION;
2071     }
2072 
2073     else if (oscl_memcmp(iID3TagInfo.iID3V2FrameID, endTestBuf, ID3V2_2_FRAME_NUM_BYTES_ID) == 0)
2074     {
2075         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_EEND;
2076     }
2077 
2078     else
2079     {
2080         ID3V2_2FrameTypeReturnValue = PV_ID3_FRAME_UNRECOGNIZED;
2081     }
2082 
2083     return ID3V2_2FrameTypeReturnValue;
2084 }
2085 
2086 //----------------------------------------------------------------------------
2087 // FUNCTION NAME: PVID3ParCom::EightBitToWideCharBufferTransfer(
2088 //                                               const TPtr8& aPtrFrameData8,
2089 //                                               uint32         aSize,
2090 //                                               uint32         aEndianType,
2091 //                                               TPtr16&      aPtrFrameData16)
2092 //----------------------------------------------------------------------------
2093 // INPUT AND OUTPUT DEFINITIONS
2094 //
2095 //  Inputs:
2096 //    aPtrFrameData8  - pointer to intput string format of either big
2097 //                      or little endian.
2098 //    aSize           - number of character elements in aPtrFrameData8
2099 //    aEndianType     - This describes if the encoded Unicode text in the
2100 //                      aPtrFrameData8 buffer is in big or little endian.
2101 //  Outputs:
2102 //    aPtrFrameDataWCBase - pointer to the output string in unicode format.
2103 //
2104 //  Returns: size of data in aPtrFrameDataWCBase
2105 //
2106 //  Global Variables Used: None
2107 //
2108 //----------------------------------------------------------------------------
2109 // FUNCTION DESCRIPTION
2110 //
2111 //  This function moves unicode data sotred in uint8 buffer to wchar buffer.
2112 //  The endian is taken care of by this function as well.
2113 //
2114 //------------------------------------------------------------------------------
EightBitToWideCharBufferTransfer(const uint8 * aPtrFrameData8,uint32 aSize,uint32 aEndianType,oscl_wchar * aPtrFrameDataWCBase)2115 uint32 PVID3ParCom::EightBitToWideCharBufferTransfer(const uint8 * aPtrFrameData8,
2116         uint32        aSize,
2117         uint32        aEndianType,
2118         oscl_wchar  * aPtrFrameDataWCBase)
2119 {
2120     if (aPtrFrameData8 == NULL || aPtrFrameDataWCBase == NULL)
2121     {
2122         return 0;
2123     }
2124 
2125     oscl_wchar * aPtrFrameDataWC = aPtrFrameDataWCBase;
2126     uint16 tempFrameData16;
2127     oscl_wchar tempFrameDataWC = 0;
2128     uint32 index = 0;
2129     uint32 z = 0, x = 0;
2130     uint8 tempByteOne, tempByteTwo;
2131     if (aEndianType != UNICODE_BIG_ENDIAN)
2132         // Indication check of big-endian vs. little endian
2133     {
2134         z = 0;
2135         for (x = 0; x < (aSize >> 1); x++)
2136         {
2137             z = x << 1;
2138             tempByteOne = aPtrFrameData8[z];
2139             tempByteTwo = aPtrFrameData8[z + 1];
2140             if ((tempByteOne == 0) && (tempByteTwo == 0))
2141             {
2142                 x++;
2143                 // End of string here and skip to start of next string.
2144                 aPtrFrameDataWC[index++] = ((oscl_wchar)'\0');
2145             }
2146             else
2147             {
2148                 tempFrameData16 = (uint16)((((uint16)(tempByteTwo << 8)) | tempByteOne));
2149                 tempFrameDataWC = tempFrameData16;
2150                 aPtrFrameDataWC[index++] = tempFrameDataWC;
2151             }
2152         }
2153     }
2154     else
2155     {
2156         z = 0;
2157         for (x = 0; x < (aSize >> 1); x++)
2158         {
2159             z = x << 1;
2160             tempByteOne = aPtrFrameData8[z];
2161             tempByteTwo = aPtrFrameData8[z + 1];
2162             if ((tempByteTwo == 0) && (tempByteOne == 0))
2163             {
2164                 x++;
2165                 // End of string here and skip to start of next string.
2166                 aPtrFrameDataWC[index++] = ((oscl_wchar)'\0');
2167             }
2168             else
2169             {
2170                 tempFrameData16 = (uint16)((((uint16)(tempByteOne << 8)) | tempByteTwo));
2171                 int32 l = sizeof(oscl_wchar);
2172                 if (l == 4)
2173                     tempFrameDataWC = (tempFrameData16 << 16) && 0xff00;
2174                 else if (l == 2)
2175                     tempFrameDataWC = tempFrameData16;
2176                 else
2177                     return 0;
2178                 aPtrFrameDataWC[index++] = tempFrameDataWC;
2179             }
2180         }
2181     }
2182     return (index);
2183 }
2184 
ConvertToSyncSafeInt(uint32 src)2185 uint32 PVID3ParCom::ConvertToSyncSafeInt(uint32 src)
2186 {
2187     uint32  dest = (src & 0x0FE00000) << 3;
2188     dest |= (src & 0x001FC000) << 2;
2189     dest |= (src & 0x00003f80) << 1;
2190     dest |= (src & 0x0000007f);
2191 
2192     return dest;
2193 }
2194 
2195 ////////////////////////////////////////////////////////////////////////////
SafeSynchIntToInt32(uint32 aSafeSynchInteger)2196 uint32 PVID3ParCom::SafeSynchIntToInt32(uint32 aSafeSynchInteger)
2197 {
2198     uint8 * pBuf = (uint8 *) & (aSafeSynchInteger);
2199     uint8 tmpByte = 0;
2200     int32 i = 0;
2201     uint32 integer = 0;
2202 
2203     // This loop will calculate the correct size from the bytes designated for size
2204     // It is stored as a SynchSafe Integer. This means the 8th bit is reserved in
2205     // each byte and not used for integer precision.. The number is effectively 28
2206     // bits in length/precision.
2207     // Assumes: sizeof(uint32) = 4 Bytes
2208     for (i = 0; i < 4; i++)
2209     {
2210 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
2211         tmpByte = (uint8)(pBuf[i] & MASK127);
2212 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
2213         tmpByte = pBuf[4-i-1] & MASK127;
2214 #else
2215 #error "Must Specify ENDIANNESS"
2216 #endif
2217         // now shift the data to it's correct place
2218         integer += tmpByte << VALID_BITS_IN_SYNC_SAFE_BYTE * i;
2219     }
2220 
2221     return integer;
2222 }
2223 
2224 ////////////////////////////////////////////////////////////////////////////
readByteData(PVFile * aInputFile,uint32 length,uint8 * aData)2225 bool PVID3ParCom::readByteData(PVFile* aInputFile, uint32 length, uint8 *aData)
2226 {
2227     if (length > 0)
2228     {
2229         uint32 bytesRead;
2230         bytesRead = aInputFile->Read(aData, 1, length);
2231 
2232         if (bytesRead < (uint32)length) // read byte data failed
2233         {
2234             return false;
2235         }
2236     }
2237     return true;
2238 }
2239 
2240 ////////////////////////////////////////////////////////////////////////////
read32(PVFile * aInputFile,uint32 & aData)2241 bool PVID3ParCom::read32(PVFile* aInputFile, uint32 &aData)
2242 {
2243     const int32 N = 4;
2244     uint8 bytes[N];
2245     aData = 0;
2246 
2247     int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
2248 
2249     if (retVal < N)
2250         return false;
2251 
2252     for (int32 i = 0; i < N; i++)
2253         aData = (aData << 8) | bytes[i];
2254 
2255     return true;
2256 }
2257 ////////////////////////////////////////////////////////////////////////////
read16(PVFile * aInputFile,uint16 & aData)2258 bool PVID3ParCom::read16(PVFile* aInputFile, uint16 &aData)
2259 {
2260     const int32 N = 2;
2261     uint8 bytes[N];
2262     aData = 0;
2263 
2264     int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
2265 
2266     if (retVal < N)
2267         return false;
2268 
2269     for (int32 i = 0; i < N; i++)
2270         aData = (uint16)((aData << 8) | bytes[i]);
2271 
2272     return true;
2273 }
2274 
2275 ////////////////////////////////////////////////////////////////////////////
read24(PVFile * aInputFile,uint32 & aData)2276 bool PVID3ParCom::read24(PVFile* aInputFile, uint32 &aData)
2277 {
2278     const int32 N = 3;
2279     uint8 bytes[N];
2280     aData = 0;
2281 
2282     int32 retVal = (int32)(aInputFile->Read((void*)bytes, 1, N));
2283 
2284     if (retVal < N)
2285         return false;
2286 
2287     for (int32 i = 0; i < N; i++)
2288         aData = (aData << 8) | bytes[i];
2289 
2290     return true;
2291 }
2292 
2293 ////////////////////////////////////////////////////////////////////////////
read8(PVFile * aInputFile,uint8 & aData)2294 bool PVID3ParCom::read8(PVFile* aInputFile, uint8 &aData)
2295 {
2296     aData = 0;
2297 
2298     int32 retVal = (int32)(aInputFile->Read((void*) & aData, 1, 1));
2299 
2300     if (retVal < 1)
2301         return false;
2302 
2303     return true;
2304 }
2305 
2306 ////////////////////////////////////////////////////////////////////////////
2307 
AllocateKvp(OSCL_String & aKey,PvmiKvpValueType aValueType,uint32 aValueSize,bool & truncate)2308 PvmiKvpSharedPtr PVID3ParCom::AllocateKvp(OSCL_String& aKey, PvmiKvpValueType aValueType, uint32 aValueSize, bool &truncate)
2309 {
2310     uint8* myPtr = NULL;
2311     OsclRefCounter* refCounter;
2312 
2313     uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterDA));
2314     uint aligned_cleanup_size = oscl_mem_aligned_size(sizeof(PVID3ParComKvpCleanupDA));
2315     uint aligned_kvp_size = oscl_mem_aligned_size(sizeof(PvmiKvp));
2316     uint32 key_size = oscl_mem_aligned_size(aKey.get_size() + 1);
2317     uint32 total_size = aligned_refcnt_size + aligned_cleanup_size +
2318                         aligned_kvp_size + key_size + aValueSize;
2319 
2320     int32 error = 0;
2321     myPtr = (uint8*) AllocateValueArray(error, PVMI_KVPVALTYPE_UINT8PTR, total_size, &iAlloc);
2322     if ((error != OsclErrNone) || (!myPtr) || (total_size < aValueSize))
2323     {
2324         if (myPtr)
2325         {
2326             iAlloc.deallocate(myPtr);
2327         }
2328 
2329         char str_data_len[MAX_RANGE_INT_SIZE + 1] = {0};
2330         oscl_snprintf(str_data_len, MAX_RANGE_INT_SIZE + 1, "%d", aValueSize);
2331         aKey += SEMI_COLON;
2332         aKey += KVP_VALTYPE_REQSIZE;
2333         aKey += _STRLIT_CHAR((char *)str_data_len);
2334         uint32 new_key_size = oscl_mem_aligned_size(aKey.get_size() + 1);
2335         error = OsclErrNone;
2336         total_size = aligned_refcnt_size + aligned_cleanup_size + aligned_kvp_size + new_key_size;
2337         myPtr = (uint8*) AllocateValueArray(error, PVMI_KVPVALTYPE_UINT8PTR, total_size, &iAlloc);
2338         truncate = true;
2339         if (OsclErrNone != error)
2340         {
2341             OSCL_LEAVE(OsclErrNoMemory);
2342         }
2343     }
2344     oscl_memset(myPtr, 0, total_size);
2345 
2346     PVID3ParComKvpCleanupDA* kvpCleanup = OSCL_PLACEMENT_NEW(myPtr + aligned_refcnt_size, PVID3ParComKvpCleanupDA(&iAlloc));
2347     refCounter = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterDA(myPtr, kvpCleanup));
2348     myPtr += aligned_refcnt_size + aligned_cleanup_size;
2349 
2350     PvmiKvp* kvp = OSCL_STATIC_CAST(PvmiKvp *, myPtr) ;
2351     myPtr += aligned_kvp_size;
2352 
2353     kvp->key = OSCL_STATIC_CAST(char* , myPtr);
2354     myPtr += key_size;
2355     oscl_strncpy(kvp->key, aKey.get_cstr(), key_size);
2356     if (!truncate)
2357     {
2358         switch (aValueType)
2359         {
2360             case PVMI_KVPVALTYPE_WCHARPTR:
2361                 kvp->value.pWChar_value = OSCL_STATIC_CAST(oscl_wchar*, myPtr);
2362                 break;
2363             case PVMI_KVPVALTYPE_CHARPTR:
2364                 kvp->value.pChar_value = OSCL_STATIC_CAST(char* , myPtr);
2365                 break;
2366             case PVMI_KVPVALTYPE_UINT8PTR:
2367                 kvp->value.pUint8_value = OSCL_STATIC_CAST(uint8*, myPtr);
2368                 break;
2369             case PVMI_KVPVALTYPE_INT32PTR:
2370                 kvp->value.pInt32_value = OSCL_STATIC_CAST(int32*, myPtr);
2371                 break;
2372             case PVMI_KVPVALTYPE_UINT32PTR:
2373                 kvp->value.pUint32_value = OSCL_STATIC_CAST(uint32*, myPtr);
2374                 break;
2375             case PVMI_KVPVALTYPE_INT64PTR:
2376                 kvp->value.pInt64_value = OSCL_STATIC_CAST(int64* , myPtr);
2377                 break;
2378             case PVMI_KVPVALTYPE_UINT64PTR:
2379                 kvp->value.pUint64_value = OSCL_STATIC_CAST(uint64* , myPtr);
2380                 break;
2381             case PVMI_KVPVALTYPE_FLOATPTR:
2382                 kvp->value.pFloat_value = OSCL_STATIC_CAST(float* , myPtr);
2383                 break;
2384             case PVMI_KVPVALTYPE_DOUBLEPTR:
2385                 kvp->value.pDouble_value = OSCL_STATIC_CAST(double*, myPtr);
2386                 break;
2387             case PVMI_KVPVALTYPE_KSV:
2388                 kvp->value.key_specific_value = OSCL_STATIC_CAST(OsclAny*, myPtr);
2389             default:
2390                 break;
2391         }
2392         kvp->length = aValueSize;
2393         kvp->capacity = aValueSize;
2394     }
2395     else
2396     {
2397         kvp->length = 0;
2398         kvp->capacity = 0;
2399 
2400     }
2401     PvmiKvpSharedPtr sharedPtr(kvp, refCounter);
2402     return sharedPtr;
2403 }
2404 
2405 ////////////////////////////////////////////////////////////////////////////
ConstructKvpKey(OSCL_String & aKey,PVID3FrameType aType,PVID3CharacterSet aCharSet)2406 PVMFStatus PVID3ParCom::ConstructKvpKey(OSCL_String& aKey, PVID3FrameType aType, PVID3CharacterSet aCharSet)
2407 {
2408     aKey = _STRLIT_CHAR("");
2409 
2410     switch (aType)
2411     {
2412         case PV_ID3_FRAME_TITLE:
2413             aKey += _STRLIT_CHAR(KVP_KEY_TITLE);
2414             break;
2415         case PV_ID3_FRAME_ARTIST:
2416             aKey += _STRLIT_CHAR(KVP_KEY_ARTIST);
2417             break;
2418         case PV_ID3_FRAME_PART_OF_SET:
2419             aKey += _STRLIT_CHAR(KVP_KEY_PART_OF_SET);
2420             break;
2421         case PV_ID3_FRAME_ALBUM:
2422             aKey += _STRLIT_CHAR(KVP_KEY_ALBUM);
2423             break;
2424         case PV_ID3_FRAME_COPYRIGHT:
2425             aKey += _STRLIT_CHAR(KVP_KEY_COPYRIGHT);
2426             break;
2427         case PV_ID3_FRAME_GENRE:
2428             aKey += _STRLIT_CHAR(KVP_KEY_GENRE);
2429             if (aCharSet == PV_ID3_CHARSET_INVALID)
2430             {
2431                 // ID3 V1 genre is a uint32 value
2432                 aKey += SEMI_COLON;
2433                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING);
2434                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING);
2435                 aKey += SEMI_COLON;
2436                 aKey += _STRLIT_CHAR(KVP_FORMAT_ID3V1);
2437                 return PVMFSuccess;
2438             }
2439             break;
2440         case PV_ID3_FRAME_TRACK_NUMBER:
2441             aKey += _STRLIT_CHAR(KVP_KEY_TRACK_NUMBER);
2442             if (aCharSet == PV_ID3_CHARSET_INVALID)
2443             {
2444                 // ID3 V1 track number is a uint32 value
2445                 aKey += SEMI_COLON;
2446                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_STRING);
2447                 aKey += _STRLIT_CHAR(PVMI_KVPVALTYPE_UINT32_STRING);
2448                 return PVMFSuccess;
2449             }
2450             break;
2451         case PV_ID3_FRAME_YEAR:
2452             aKey += _STRLIT_CHAR(KVP_KEY_YEAR);
2453             break;
2454         case PV_ID3_FRAME_DATE:
2455             aKey += _STRLIT_CHAR(KVP_KEY_DATE);
2456             break;
2457         case PV_ID3_FRAME_RECORDING_TIME:
2458             aKey += _STRLIT_CHAR(KVP_KEY_RECORDING_TIME);
2459             break;
2460 //new frames support
2461         case PV_ID3_FRAME_AUTHOR:
2462             aKey += _STRLIT_CHAR(KVP_KEY_AUTHOR);
2463             break;
2464         case PV_ID3_FRAME_COMPOSER:
2465             aKey += _STRLIT_CHAR(KVP_KEY_COMPOSER);
2466             break;
2467         case PV_ID3_FRAME_DESCRIPTION:
2468             aKey += _STRLIT_CHAR(KVP_KEY_DESCRIPTION);
2469             break;
2470         case PV_ID3_FRAME_VERSION:
2471             aKey += _STRLIT_CHAR(KVP_KEY_VERSION);
2472             break;
2473         case PV_ID3_FRAME_COMMENT:
2474             aKey += _STRLIT_CHAR(KVP_KEY_COMMENT);
2475             if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1))
2476             {
2477                 aKey += SEMI_COLON;
2478                 aKey += KVP_VALTYPE_LYRICS;
2479             }
2480             break;
2481         case PV_ID3_FRAME_TRACK_LENGTH:
2482             aKey += _STRLIT_CHAR(KVP_KEY_ID3DURATION);
2483             aKey += SEMI_COLON;
2484             aKey += _STRLIT_CHAR(KVP_VALTYPE_DURATION);
2485             return PVMFSuccess; // No character set for track length
2486         case PV_ID3_FRAME_PIC:
2487         case PV_ID3_FRAME_APIC:
2488             aKey += _STRLIT_CHAR(KVP_KEY_ALBUMART);
2489             aKey += SEMI_COLON;
2490             return PVMFSuccess;
2491         case PV_ID3_FRAME_LYRICS:
2492             aKey += _STRLIT_CHAR(KVP_KEY_LYRICS);
2493             aKey += SEMI_COLON;
2494             aKey += KVP_VALTYPE_LYRICS;
2495             break;
2496         case PV_ID3_FRAME_UNRECOGNIZED:
2497         case PV_ID3_FRAME_CANDIDATE:
2498             aKey += _STRLIT_CHAR(KVP_ID3V2_VALUE);
2499             aKey += FORWARD_SLASH;
2500             aKey += _STRLIT_CHAR((char *)iID3TagInfo.iID3V2FrameID);
2501             aKey += SEMI_COLON;
2502             aKey += _STRLIT_CHAR(KVP_VALTYPE_UINT8PTR_STRING);
2503             return PVMFSuccess;
2504             break;
2505         default:
2506             return PVMFErrNotSupported;
2507     }
2508 
2509 
2510     //add language code to lyrics key
2511     if ((aType == PV_ID3_FRAME_LYRICS) || (aType == PV_ID3_FRAME_COMMENT))
2512     {
2513         //not valid for id3 v1
2514         if ((iVersion != PV_ID3_V1_1) && (iVersion != PV_ID3_V1))
2515         {
2516             aKey += SEMI_COLON;
2517             aKey += _STRLIT_CHAR(KVP_PARAM_LANGUAGE_CODE);
2518             aKey += _STRLIT_CHAR((char*)iID3TagInfo.iID3V2LanguageID);
2519             return PVMFSuccess;
2520         }
2521     }
2522     aKey += SEMI_COLON;
2523     switch (aCharSet)
2524     {
2525         case PV_ID3_CHARSET_ISO88591:
2526             aKey += _STRLIT_CHAR(KVP_VALTYPE_ISO88591_CHAR);
2527             break;
2528         case PV_ID3_CHARSET_UTF16:
2529             aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16_WCHAR);
2530             break;
2531         case PV_ID3_CHARSET_UTF16BE:
2532             aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF16BE_WCHAR);
2533             break;
2534         case PV_ID3_CHARSET_UTF8:
2535             aKey += _STRLIT_CHAR(KVP_VALTYPE_UTF8_CHAR);
2536             break;
2537         default:
2538             return PVMFErrNotSupported;
2539     }
2540 
2541     aKey += NULL_CHARACTER;
2542 
2543     return PVMFSuccess;
2544 }
2545 
2546 ////////////////////////////////////////////////////////////////////////////
ReadStringValueFrame(PVID3FrameType aFrameType,PVID3CharacterSet aCharSet,uint32 aValueSize)2547 PVMFStatus PVID3ParCom::ReadStringValueFrame(PVID3FrameType aFrameType, PVID3CharacterSet aCharSet, uint32 aValueSize)
2548 {
2549     // Construct key string
2550     OSCL_StackString<128> keyStr;
2551     if (ConstructKvpKey(keyStr, aFrameType, aCharSet) != PVMFSuccess)
2552     {
2553         LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed"));
2554         return PVMFErrNotSupported;
2555     }
2556 
2557     // Allocate key-value pair
2558     int32 err = OsclErrNone;
2559     PvmiKvpSharedPtr kvpPtr;
2560     bool truncate = false;
2561     switch (aCharSet)
2562     {
2563         case PV_ID3_CHARSET_ISO88591:
2564         case PV_ID3_CHARSET_UTF8:
2565             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1, truncate););
2566             if (OsclErrNone != err || !kvpPtr)
2567             {
2568                 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err));
2569                 return PVMFErrNoMemory;
2570             }
2571 
2572             if (truncate)
2573             {
2574                 iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
2575                 kvpPtr->length = 0;
2576             }
2577             else
2578             {
2579                 if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pChar_value) == false)
2580                 {
2581                     LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed"));
2582                     return PVMFFailure;
2583                 }
2584 
2585                 int32 valueLen = aValueSize;
2586                 valueLen = oscl_strlen((char*)kvpPtr->value.pChar_value);
2587 
2588                 kvpPtr->value.pChar_value[valueLen] = NULL_TERM_CHAR;
2589                 kvpPtr->length = valueLen + 1;
2590             }
2591             // Add to frame vector
2592             OSCL_TRY(err, iFrames.push_back(kvpPtr););
2593             OSCL_FIRST_CATCH_ANY(err,
2594                                  LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrames.push_back failed. err=%d", err));
2595                                  return PVMFErrNoMemory;
2596                                 );
2597             break;
2598 
2599         case PV_ID3_CHARSET_UTF16:
2600         case PV_ID3_CHARSET_UTF16BE:
2601         {
2602             // create buffers to store frame data
2603             uint8* ptrFrameData = NULL;
2604             ptrFrameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, aValueSize + 2, &iAlloc);
2605             if (OsclErrNone != err || !ptrFrameData)
2606             {
2607                 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - frameData allocation failed"));
2608                 return PVMFErrNoMemory;
2609             }
2610             oscl_memset(ptrFrameData, 0, aValueSize + 2);
2611             uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes.
2612             // Allocate key-value pair
2613             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_WCHARPTR, (wchar_size / 2) * (aValueSize + 2), truncate););
2614             if (OsclErrNone != err || !kvpPtr)
2615             {
2616                 LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - AllocateKvp failed. err=%d", err));
2617                 return PVMFErrNoMemory;
2618             }
2619 
2620             if (truncate)
2621             {
2622                 iAlloc.deallocate(ptrFrameData);
2623                 iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
2624                 kvpPtr->length = 0;
2625             }
2626             else
2627             {
2628                 if (readByteData(iInputFile, aValueSize, ptrFrameData) == false)
2629                 {
2630                     iAlloc.deallocate(ptrFrameData);
2631                     LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - readByteData failed"));
2632                     return PVMFFailure;
2633                 }
2634                 ptrFrameData[aValueSize] = 0;
2635                 ptrFrameData[aValueSize+1] = 0;
2636 
2637                 uint32 endianType = UNICODE_LITTLE_ENDIAN;
2638                 if (aCharSet == PV_ID3_CHARSET_UTF16BE)
2639                 {
2640                     endianType = UNICODE_BIG_ENDIAN;
2641                 }
2642 
2643                 uint32 wcSize = EightBitToWideCharBufferTransfer(ptrFrameData, aValueSize, endianType, kvpPtr->value.pWChar_value);
2644                 kvpPtr->value.pWChar_value[wcSize] = NULL_TERM_CHAR;
2645                 iAlloc.deallocate(ptrFrameData);
2646                 kvpPtr->length = wcSize;
2647             }
2648             OSCL_TRY(err, iFrames.push_back(kvpPtr););
2649             OSCL_FIRST_CATCH_ANY(err,
2650                                  LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - iFrame.push_back failed"));
2651                                  iAlloc.deallocate((OsclAny*)ptrFrameData);
2652                                  return PVMFErrNoMemory;
2653                                 );
2654         }
2655         break;
2656         default:
2657             return PVMFFailure;
2658     }
2659 
2660     return PVMFSuccess;
2661 }
2662 
2663 
2664 ////////////////////////////////////////////////////////////////////////////
ReadFrame(PVID3FrameType aFrameType,uint32 aValueSize)2665 PVMFStatus PVID3ParCom::ReadFrame(PVID3FrameType aFrameType, uint32 aValueSize)
2666 {
2667 
2668     // Construct key string
2669     OSCL_StackString<128> keyStr;
2670     if (ConstructKvpKey(keyStr, aFrameType, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
2671     {
2672         LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - ConstructKvpKey failed"));
2673         return PVMFErrNotSupported;
2674     }
2675 
2676     // Allocate key-value pair
2677     int32 err = OsclErrNone;
2678     PvmiKvpSharedPtr kvpPtr;
2679     bool truncate = false;
2680     OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, aValueSize + 1 + VERSION_SIZE, truncate););
2681     if (OsclErrNone != err || !kvpPtr)
2682     {
2683         LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - AllocateKvp failed. err=%d", err));
2684         return PVMFErrNoMemory;
2685     }
2686 
2687     if (truncate)
2688     {
2689         iInputFile->Seek(aValueSize, Oscl_File::SEEKCUR);
2690         kvpPtr->length = 0;
2691     }
2692     else
2693     {
2694         kvpPtr->value.pUint8_value[0] = (uint8)iVersion;
2695         kvpPtr->value.pUint8_value[1] = 0;
2696 
2697         if (readByteData(iInputFile, aValueSize, (uint8*)kvpPtr->value.pUint8_value + VERSION_SIZE) == false)
2698         {
2699             LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - readByteData failed"));
2700             return PVMFFailure;
2701         }
2702         kvpPtr->value.pUint8_value[aValueSize+VERSION_SIZE] = 0;
2703         kvpPtr->length = aValueSize + VERSION_SIZE;
2704     }
2705     // Add to frame vector
2706     OSCL_TRY(err, iFrames.push_back(kvpPtr););
2707     OSCL_FIRST_CATCH_ANY(err,
2708                          LOG_ERR((0, "PVID3ParCom::ReadFrame: Error - iFrames.push_back failed. err=%d", err));
2709                          return PVMFErrNoMemory;
2710                         );
2711 
2712 
2713     return PVMFSuccess;
2714 }
2715 
2716 
2717 ////////////////////////////////////////////////////////////////////////////
2718 
2719 // Read in a NULL terminated UNICODE string byte by byte and take most significant byte first
2720 PVMFStatus
readNullTerminatedUnicodeString(PVFile * aInputFile,OSCL_wHeapString<OsclMemAllocator> & aData,uint32 & bomSz)2721 PVID3ParCom::readNullTerminatedUnicodeString(PVFile* aInputFile, OSCL_wHeapString<OsclMemAllocator> &aData, uint32 &bomSz)
2722 {
2723     uint8 buff[ID3_MAX_STRING_FRAME_LEN];
2724     uint32 index = 0;
2725     uint16 endianCheck;
2726     if (read16(aInputFile, endianCheck) == false)
2727     {
2728         return PVMFFailure;
2729     }
2730 
2731     iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
2732     uint32 endianType = 0;
2733 
2734     //some id3 tools does not add BOM with null strings.
2735     if (endianCheck != 0)
2736     {
2737         bomSz = UNICODE_BOM_SIZE;
2738         // This frame's text strings are Unicode and the frame
2739         // does include a BOM value. (UTF-16)
2740         if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
2741         {
2742             endianType = UNICODE_LITTLE_ENDIAN;
2743         }
2744         else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
2745         {
2746             endianType = UNICODE_BIG_ENDIAN;
2747         }
2748         //read frame data from file
2749         bool more = true;
2750         while (more && (index < ID3_MAX_STRING_FRAME_LEN))
2751         {
2752             if (read8(iInputFile, buff[index]) == false)
2753                 return PVMFFailure;
2754 
2755             if ((index > 0) && (buff[index] == 0) && (buff[index -1] == 0))
2756                 more = false;
2757             index++;
2758         }
2759 
2760         //read remaining characters if any.
2761         if (more)
2762         {
2763             uint16 temp = 1;
2764             while (temp != 0)
2765                 if (read16(iInputFile, temp) == false)
2766                     return PVMFFailure;
2767         }
2768 
2769     }
2770     else
2771     {
2772         buff[0] = 0;
2773         buff[1] = 0;
2774         bomSz = 0;
2775         index = 2;
2776     }
2777 
2778     int32 err = OsclErrNone;
2779     oscl_wchar *tmpData = NULL;
2780     tmpData = (oscl_wchar*) AllocateValueArray(err, PVMI_KVPVALTYPE_WCHARPTR, index);
2781     if (OsclErrNone != err || !tmpData)
2782     {
2783         LOG_ERR((0, "PVID3ParCom::readNullTerminatedUnicodeString: Error - allocation failed"));
2784         return PVMFErrNoMemory;
2785     }
2786 
2787     uint32 wcSize = EightBitToWideCharBufferTransfer(buff, index, endianType, tmpData);
2788     tmpData[wcSize] = 0;
2789     aData = tmpData;
2790     OSCL_ARRAY_DELETE(tmpData);
2791     return PVMFSuccess;
2792 }
2793 
2794 bool
readNullTerminatedAsciiString(PVFile * aInputFile,OSCL_HeapString<OsclMemAllocator> & aData)2795 PVID3ParCom::readNullTerminatedAsciiString(PVFile* aInputFile, OSCL_HeapString<OsclMemAllocator> &aData)
2796 {
2797     uint8 buf[256];
2798     int32 index = 0;
2799 
2800     if (!read8(aInputFile, buf[index]))
2801         return PVMFFailure;
2802 
2803     bool nextChar = (buf[index] == 0) ? false : true;
2804 
2805     while (nextChar && (index < 256))
2806     {
2807         index++;
2808 
2809         if (!read8(aInputFile, buf[index]))
2810             return PVMFFailure;
2811 
2812         nextChar = (buf[index] == 0) ? false : true;
2813     }
2814 
2815     OSCL_HeapString<OsclMemAllocator> temp((const char *)buf);
2816     aData = temp;
2817     return true;
2818 }
2819 
ReadAlbumArtFrame(PVID3FrameType aFrameType,uint8 unicode,uint32 aFrameSize)2820 PVMFStatus PVID3ParCom::ReadAlbumArtFrame(PVID3FrameType aFrameType, uint8 unicode, uint32 aFrameSize)
2821 {
2822     PvmfApicStruct* aApicStruct = NULL;
2823     uint8   picType;
2824     uint32  dataLen;
2825     OSCL_HeapString<OsclMemAllocator> ImageFormat;
2826     bool pic_as_url = false;
2827     bool truncate = false;
2828     int32 err = OsclErrNone;
2829     PvmiKvpSharedPtr kvpPtr;
2830     OSCL_StackString<128> keyStr;
2831 
2832     if (ConstructKvpKey(keyStr, PV_ID3_FRAME_APIC, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
2833     {
2834         LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - ConstructKvpKey failed"));
2835         return PVMFErrNotSupported;
2836     }
2837 
2838     switch (unicode)
2839     {
2840         case PV_ID3_CHARSET_ISO88591:
2841         case PV_ID3_CHARSET_UTF8:
2842         {
2843             OSCL_HeapString<OsclMemAllocator> description;
2844 
2845             if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess)
2846                 return PVMFFailure;
2847 
2848             if (!oscl_strcmp(ImageFormat.get_cstr(), "-->"))
2849             {
2850                 pic_as_url = true;
2851                 break;
2852             }
2853 
2854             keyStr += KVP_FORMAT_ALBUMART;
2855             keyStr += SEMI_COLON;
2856             keyStr += KVP_VALTYPE_ALBUMART;
2857 
2858             //description and image format are stored as wchar.
2859             uint32 rfs = aFrameSize - (ImageFormat.get_size() + description.get_size());
2860             uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes.
2861             uint32 total_size = sizeof(PvmfApicStruct) + rfs + ((wchar_size) * (ImageFormat.get_size() + description.get_size())) + 2 * sizeof(oscl_wchar) ;
2862 
2863             // Allocate key-value pair
2864             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate););
2865             if (OsclErrNone != err || !kvpPtr)
2866             {
2867                 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
2868                 return PVMFFailure;
2869             }
2870 
2871             if (truncate)
2872             {
2873                 iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
2874                 kvpPtr->capacity = 0;
2875                 kvpPtr->length = 0;
2876 
2877                 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2878                 OSCL_FIRST_CATCH_ANY(err,
2879                                      LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
2880                                      return PVMFErrNoMemory;);
2881 
2882                 return PVMFSuccess;
2883 
2884             }
2885 
2886             kvpPtr->capacity = total_size;
2887             kvpPtr->length = total_size;
2888 
2889             //convert raw data to struct
2890             PVMFStatus status;
2891             status = ConvertAsciiDataToApic(ImageFormat.get_str(), description.get_str(), picType,
2892                                             dataLen, kvpPtr->value.key_specific_value, total_size);
2893         }
2894         break;
2895 
2896 
2897         case PV_ID3_CHARSET_UTF16:
2898         case PV_ID3_CHARSET_UTF16BE:
2899         {
2900             OSCL_wHeapString<OsclMemAllocator> description;
2901             if (GetAlbumArtInfo(aFrameType, aFrameSize, ImageFormat, picType, description, dataLen) != PVMFSuccess)
2902                 return PVMFFailure;
2903 
2904             if (!oscl_strcmp(ImageFormat.get_cstr(), "-->"))
2905             {
2906                 pic_as_url = true;
2907                 break;
2908             }
2909 
2910             keyStr += KVP_FORMAT_ALBUMART;
2911             keyStr += SEMI_COLON;
2912             keyStr += KVP_VALTYPE_ALBUMART;
2913 
2914             //image format is stored as wchar.
2915             uint32 rfs = aFrameSize - (ImageFormat.get_size() + (2 * oscl_strlen(description.get_str())));
2916             uint32 wchar_size = sizeof(oscl_wchar); //for platforms that store wchar as 4 bytes.
2917             uint32 total_size = sizeof(PvmfApicStruct) + rfs + (wchar_size * (ImageFormat.get_size() + description.get_size())) + (2 * wchar_size);
2918 
2919             // Allocate key-value pair
2920             OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size, truncate););
2921             if (OsclErrNone != err || !kvpPtr)
2922             {
2923                 LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
2924                 return PVMFFailure;
2925             }
2926 
2927             if (truncate)
2928             {
2929                 iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
2930                 kvpPtr->capacity = 0;
2931                 kvpPtr->length = 0;
2932 
2933                 OSCL_TRY(err, iFrames.push_back(kvpPtr););
2934                 OSCL_FIRST_CATCH_ANY(err,
2935                                      LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
2936                                      return PVMFErrNoMemory;);
2937 
2938                 return PVMFSuccess;
2939 
2940             }
2941 
2942             kvpPtr->capacity = total_size;
2943             kvpPtr->length = total_size;
2944 
2945             //convert raw data to struct
2946             PVMFStatus status;
2947             status = ConvertUnicodeDataToApic(ImageFormat.get_str(), description.get_str(), picType,
2948                                               dataLen , kvpPtr->value.key_specific_value, total_size);
2949         }
2950         break;
2951         default:
2952             return PVMFFailure;
2953 
2954     }
2955 
2956     if (pic_as_url)
2957     {
2958 
2959         keyStr += KVP_VALTYPE_ISO88591_CHAR;
2960         bool truncate = false;
2961         // Allocate key-value pair
2962         OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_CHARPTR, dataLen, truncate););
2963         if (OsclErrNone != err || !kvpPtr)
2964         {
2965             LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - AllocateKvp failed. err=%d", err));
2966             return PVMFFailure;
2967         }
2968 
2969         if (truncate)
2970         {
2971             iInputFile->Seek(dataLen, Oscl_File::SEEKCUR);
2972             kvpPtr->length = 0;
2973 
2974             OSCL_TRY(err, iFrames.push_back(kvpPtr););
2975             OSCL_FIRST_CATCH_ANY(err,
2976                                  LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
2977                                  return PVMFErrNoMemory;);
2978 
2979             return PVMFSuccess;
2980 
2981         }
2982         else
2983         {
2984             if (readByteData(iInputFile, dataLen, (uint8 *)kvpPtr->value.pChar_value) == false)
2985                 return PVMFFailure;
2986             kvpPtr->value.pChar_value[dataLen] = NULL_TERM_CHAR;
2987             kvpPtr->length = dataLen;
2988         }
2989     }
2990     else
2991     {
2992         aApicStruct = OSCL_STATIC_CAST(PvmfApicStruct *, kvpPtr->value.key_specific_value);
2993         if (readByteData(iInputFile, dataLen, aApicStruct->iGraphicData) == false)
2994             return PVMFFailure;
2995     }
2996 
2997 
2998     OSCL_TRY(err, iFrames.push_back(kvpPtr););
2999     OSCL_FIRST_CATCH_ANY(err,
3000                          LOG_ERR((0, "PVID3ParCom::ReadAlbumArtFrame: Error - iFrame.push_back failed"));
3001                          return PVMFErrNoMemory;
3002                         );
3003 
3004     return PVMFSuccess;
3005 }
3006 
ReadLyricsCommFrame(uint8 unicodeCheck,uint32 aFramesize,PVID3FrameType aFrameType)3007 PVMFStatus PVID3ParCom::ReadLyricsCommFrame(uint8 unicodeCheck, uint32 aFramesize, PVID3FrameType aFrameType)
3008 {
3009 
3010     uint32 framesize = aFramesize;
3011     bool truncate = false;
3012     if (readByteData(iInputFile, ID3V2_LANGUAGE_SIZE, iID3TagInfo.iID3V2LanguageID) == false)
3013     {
3014         return PVMFFailure;
3015     }
3016 
3017     iID3TagInfo.iID3V2LanguageID[ID3V2_LANGUAGE_SIZE] = 0;
3018 
3019     //subtract 3 bytes of language from the frame size.
3020     framesize = aFramesize - ID3V2_LANGUAGE_SIZE ;
3021     if ((framesize == 0) || (framesize > aFramesize))
3022     {
3023         return PVMFFailure;
3024     }
3025     //construct kvp for lyrics frame
3026     OSCL_StackString<128> keyStr;
3027     if (ConstructKvpKey(keyStr, aFrameType, (PVID3ParCom::PVID3CharacterSet)unicodeCheck) != PVMFSuccess)
3028     {
3029         LOG_ERR((0, "PVID3ParCom::ReadStringValueFrame: Error - ConstructKvpKey failed"));
3030         return PVMFErrNotSupported;
3031     }
3032 
3033     int32 err = OsclErrNone;
3034     PvmiKvpSharedPtr kvpPtr;
3035     uint32 wchar_size = sizeof(oscl_wchar); //for platforms where wchar is 4 bytes.
3036     uint32 total_size = (wchar_size * framesize) + sizeof(PvmfLyricsCommStruct) + (2 * wchar_size) ;
3037     uint32 used_size = 0;
3038     // Allocate key-value pair
3039     OSCL_TRY(err, kvpPtr = AllocateKvp(keyStr, PVMI_KVPVALTYPE_KSV, total_size , truncate););
3040     if (OsclErrNone != err || !kvpPtr)
3041     {
3042         LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - AllocateKvp failed. err=%d", err));
3043         return PVMFFailure;
3044     }
3045 
3046     if (truncate)
3047     {
3048         iInputFile->Seek(framesize, Oscl_File::SEEKCUR);
3049         kvpPtr->capacity = 0;
3050         kvpPtr->length = 0;
3051 
3052         OSCL_TRY(err, iFrames.push_back(kvpPtr););
3053         OSCL_FIRST_CATCH_ANY(err,
3054                              LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
3055                              return PVMFErrNoMemory;);
3056 
3057         return PVMFSuccess;
3058 
3059     }
3060 
3061     PvmfLyricsCommStruct *lcStruct = NULL;
3062     uint8 *ptr = NULL;
3063     lcStruct = OSCL_STATIC_CAST(PvmfLyricsCommStruct *, kvpPtr->value.key_specific_value);
3064     ptr = (uint8 *)kvpPtr->value.key_specific_value;
3065     if (!ptr)
3066     {
3067         return PVMFFailure;
3068     }
3069 
3070     ptr += sizeof(PvmfLyricsCommStruct);
3071     used_size += sizeof(PvmfLyricsCommStruct);
3072 
3073     switch (unicodeCheck)
3074     {
3075         case PV_ID3_CHARSET_ISO88591:
3076         case PV_ID3_CHARSET_UTF8:
3077         {
3078             OSCL_HeapString<OsclMemAllocator> descriptor;
3079 
3080             if (readNullTerminatedAsciiString(iInputFile, descriptor) == false)
3081             {
3082                 iAlloc.deallocate(lcStruct);
3083                 return PVMFFailure;
3084             }
3085 
3086             uint32 desc_sz = descriptor.get_size();
3087             framesize = framesize - desc_sz - 1 ; //subtract 1 for null character
3088 
3089             if ((framesize > aFramesize) || (framesize == 0))
3090             {
3091                 lcStruct->iDescription = NULL;
3092                 lcStruct->iData = NULL;
3093                 break;
3094             }
3095 
3096             lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3097             ptr += wchar_size * (desc_sz + 1); //1 for null char
3098 
3099             used_size += wchar_size * (desc_sz + 1);
3100             if (used_size > total_size)
3101                 return PVMFErrOverflow;
3102             if (desc_sz > 0)
3103             {
3104                 uint32 sz = desc_sz + 1;
3105                 oscl_UTF8ToUnicode((const char *)descriptor.get_cstr(), descriptor.get_size(), lcStruct->iDescription,  sz);
3106                 lcStruct->iDescription[sz] = 0;
3107             }
3108             else
3109             {
3110                 lcStruct->iDescription[desc_sz] = 0;
3111             }
3112 
3113             uint8 *data = NULL;
3114             uint32 datasz = framesize + 1;
3115             OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz););
3116 
3117             if (OsclErrNone != err || !(data))
3118             {
3119                 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed"));
3120                 iInputFile->Seek(framesize, Oscl_File::SEEKCUR);
3121 
3122             }
3123 
3124             else
3125             {
3126 
3127                 if ((readByteData(iInputFile, framesize, data) == false))
3128                 {
3129                     iAlloc.deallocate(data);
3130                     return PVMFFailure;
3131                 }
3132 
3133                 lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3134                 used_size += datasz;
3135 
3136                 if (used_size > total_size)
3137                     return PVMFErrOverflow;
3138                 oscl_UTF8ToUnicode((const char *)data, framesize, lcStruct->iData,  datasz);
3139                 lcStruct->iData[datasz] = 0;
3140 
3141                 iAlloc.deallocate(data);
3142             }
3143         }
3144 
3145         break;
3146 
3147         case PV_ID3_CHARSET_UTF16:
3148         case PV_ID3_CHARSET_UTF16BE:
3149         {
3150 
3151             uint32 bomSize = 0;
3152             OSCL_wHeapString<OsclMemAllocator> description ;
3153 
3154             if (readNullTerminatedUnicodeString(iInputFile, description, bomSize) == false)
3155             {
3156                 return PVMFFailure;
3157             }
3158 
3159             uint32 desc_len = oscl_strlen(description.get_str()) ;
3160             framesize = framesize - (2 * desc_len) - 2 - bomSize; // description(2 byte unicode in id3 tag), null char, bom
3161             if ((framesize > aFramesize) || (framesize == 0))
3162             {
3163                 lcStruct->iDescription = NULL;
3164                 lcStruct->iData = NULL;
3165                 break;
3166             }
3167 
3168             lcStruct->iDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3169             ptr += wchar_size * (desc_len + 1); //1 for null char
3170 
3171             used_size += wchar_size * (desc_len + 1);
3172             if (used_size > total_size)
3173                 return PVMFErrOverflow;
3174 
3175             if (desc_len > 0)
3176             {
3177                 oscl_strncpy(lcStruct->iDescription, description.get_str(), desc_len);
3178                 lcStruct->iDescription[desc_len + 1] = 0;
3179             }
3180             else
3181             {
3182                 lcStruct->iDescription[desc_len] = 0;
3183             }
3184 
3185 
3186             uint16 endianCheck = 0;
3187             //check endian type
3188             if (read16(iInputFile, endianCheck) == false)
3189             {
3190 
3191                 return PVMFFailure;
3192             }
3193 
3194             // This frame's text strings are Unicode and the frame
3195             // does include a BOM value. (UTF-16)
3196             iID3TagInfo.iTextType = PV_ID3_CHARSET_UTF16;
3197             uint32 endianType = 0;
3198 
3199             if (endianCheck == UNICODE_LITTLE_ENDIAN_INDICATOR_FULL)
3200             {
3201                 endianType = UNICODE_LITTLE_ENDIAN;
3202             }
3203             else if (endianCheck == UNICODE_BIG_ENDIAN_INDICATOR_FULL)
3204             {
3205                 endianType = UNICODE_BIG_ENDIAN;
3206             }
3207 
3208             framesize -= UNICODE_BOM_SIZE;
3209             if ((framesize > aFramesize) || (framesize == 0))
3210             {
3211                 lcStruct->iDescription = NULL;
3212                 lcStruct->iData = NULL;
3213                 break;
3214             }
3215 
3216             uint8 *data = NULL;
3217             uint32 datasz = framesize + 2;
3218             int32 err = OsclErrNone;
3219             OSCL_TRY(err, data = (uint8*)iAlloc.allocate(datasz););
3220             if (OsclErrNone != err || !(data))
3221             {
3222                 LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - allocation failed"));
3223                 truncate = true;
3224             }
3225             else
3226             {
3227 
3228                 oscl_memset(data, 0, datasz);
3229                 if ((readByteData(iInputFile, framesize, data) == false))
3230                 {
3231                     iAlloc.deallocate(data);
3232                     return PVMFFailure;
3233                 }
3234                 lcStruct->iData = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3235 
3236                 used_size += wchar_size * (framesize / 2);  //UCS-2 unicode
3237                 if (used_size > total_size)
3238                     return PVMFErrOverflow;
3239 
3240                 uint32 sz = EightBitToWideCharBufferTransfer(data, framesize, endianType , lcStruct->iData);
3241                 lcStruct->iData[sz] = 0;
3242 
3243                 iAlloc.deallocate(data);
3244             }
3245         }
3246         break;
3247 
3248         default:
3249             return PVMFFailure;
3250 
3251     }
3252 
3253     kvpPtr->capacity = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ;
3254     kvpPtr->length = (aFramesize - ID3V2_LANGUAGE_SIZE) + sizeof(PvmfLyricsCommStruct) ;
3255 
3256     OSCL_TRY(err, iFrames.push_back(kvpPtr););
3257     OSCL_FIRST_CATCH_ANY(err,
3258                          LOG_ERR((0, "PVID3ParCom::ReadLyricsCommFrame: Error - iFrame.push_back failed"));
3259                          return PVMFErrNoMemory;
3260                         );
3261 
3262 
3263     return PVMFSuccess;
3264 }
3265 
ConvertAsciiDataToApic(char * aMimeTypeID3,char * aDescriptionID3,uint8 aGraphicType,uint32 aGraphicDataLen,void * key_specific_value,uint32 total_size)3266 PVMFStatus PVID3ParCom::ConvertAsciiDataToApic(char* aMimeTypeID3, char* aDescriptionID3,
3267         uint8 aGraphicType, uint32 aGraphicDataLen,
3268         void *key_specific_value, uint32 total_size)
3269 {
3270     uint32 used_size = 0;
3271     uint8 *ptr = (uint8 *)key_specific_value;
3272     PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value);
3273     uint32 mime_string_size;
3274     uint32 description_size;
3275     mime_string_size = oscl_strlen(aMimeTypeID3) + 1;
3276     description_size = oscl_strlen(aDescriptionID3) + 1;
3277     ptr += sizeof(PvmfApicStruct);
3278     used_size += sizeof(PvmfApicStruct);
3279     if (used_size > total_size)
3280         return PVMFErrOverflow;
3281     aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3282     ptr += sizeof(oscl_wchar) * (mime_string_size);
3283     used_size += sizeof(oscl_wchar) * (mime_string_size);
3284     if (used_size > total_size)
3285         return PVMFErrOverflow;
3286     aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3287     ptr += sizeof(oscl_wchar) * (description_size);
3288     used_size += sizeof(oscl_wchar) * (description_size);
3289     if (used_size > total_size)
3290         return PVMFErrOverflow;
3291 
3292     oscl_memset(aAPICStruct->iGraphicDescription, 0 , description_size);
3293     oscl_memset(aAPICStruct->iGraphicMimeType , 0 ,  mime_string_size);
3294     oscl_UTF8ToUnicode((const char *)aDescriptionID3, description_size , aAPICStruct->iGraphicDescription,  description_size);
3295     oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size, aAPICStruct->iGraphicMimeType, mime_string_size);
3296 
3297     //push the data to PvmfApicStruct
3298     aAPICStruct->iGraphicType = aGraphicType;
3299 
3300     aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr);
3301 
3302     aAPICStruct->iGraphicDataLen = aGraphicDataLen;
3303 
3304     used_size += aGraphicDataLen;
3305     if (used_size > total_size)
3306         return PVMFErrOverflow;
3307     return PVMFSuccess;
3308 }
3309 
ConvertUnicodeDataToApic(char * aMimeTypeID3,oscl_wchar * aDescriptionID3,uint8 aGraphicType,uint32 aGraphicDataLen,void * key_specific_value,uint32 total_size)3310 PVMFStatus PVID3ParCom::ConvertUnicodeDataToApic(char* aMimeTypeID3, oscl_wchar* aDescriptionID3,
3311         uint8 aGraphicType, uint32 aGraphicDataLen,
3312         void *key_specific_value, uint32 total_size)
3313 {
3314     uint32 used_size = 0;
3315     uint8 *ptr = (uint8 *)key_specific_value;
3316     PvmfApicStruct* aAPICStruct = OSCL_STATIC_CAST(PvmfApicStruct*, key_specific_value);
3317     uint32 mime_string_size;
3318     uint32 description_size;
3319 
3320     mime_string_size = oscl_strlen(aMimeTypeID3) + 1;
3321     description_size = oscl_strlen(aDescriptionID3) + 1;
3322 
3323     ptr += sizeof(PvmfApicStruct);
3324     used_size += sizeof(PvmfApicStruct);
3325     if (used_size > total_size)
3326         return PVMFErrOverflow;
3327 
3328     aAPICStruct->iGraphicMimeType = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3329     ptr += sizeof(oscl_wchar) * mime_string_size;
3330     used_size += sizeof(oscl_wchar) * mime_string_size;
3331     if (used_size > total_size)
3332         return PVMFErrOverflow;
3333     aAPICStruct->iGraphicDescription = OSCL_STATIC_CAST(oscl_wchar *, ptr);
3334     ptr += sizeof(oscl_wchar) * description_size;
3335     used_size += sizeof(oscl_wchar) * description_size;
3336     if (used_size > total_size)
3337         return PVMFErrOverflow;
3338     //push the data to PvmfApicStruct
3339     oscl_memset(aAPICStruct->iGraphicDescription, '\0', sizeof(oscl_wchar)*description_size);
3340     oscl_memset(aAPICStruct->iGraphicMimeType , '\0', sizeof(oscl_wchar)*mime_string_size);
3341     oscl_UTF8ToUnicode((const char *)aMimeTypeID3, mime_string_size - 1, aAPICStruct->iGraphicMimeType, mime_string_size);
3342     aAPICStruct->iGraphicMimeType[mime_string_size] = 0;
3343 
3344     oscl_strncpy(aAPICStruct->iGraphicDescription, aDescriptionID3, description_size);
3345     aAPICStruct->iGraphicDescription[description_size] = 0;
3346     aAPICStruct->iGraphicType = aGraphicType;
3347     aAPICStruct->iGraphicDataLen = aGraphicDataLen;
3348     aAPICStruct->iGraphicData = OSCL_STATIC_CAST(uint8 *, ptr);
3349     used_size += aGraphicDataLen;
3350     if (used_size > total_size)
3351         return PVMFErrOverflow;
3352 
3353     return PVMFSuccess;
3354 }
3355 
GetAlbumArtInfo(PVID3FrameType aFrameType,uint32 aFrameSize,OSCL_HeapString<OsclMemAllocator> & aImageFormat,uint8 & aPicType,OSCL_HeapString<OsclMemAllocator> & aDescription,uint32 & aDataLen)3356 PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat,
3357                                         uint8 &aPicType, OSCL_HeapString<OsclMemAllocator> &aDescription,   uint32 &aDataLen)
3358 {
3359     uint8 image_format[4] = {0};
3360     PVMFStatus status = 0;
3361     uint32 size = 0;
3362     uint32 currentfilepos = 0 ;
3363     if (aFrameType == PV_ID3_FRAME_PIC)
3364     {
3365         if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false)
3366         {
3367             return PVMFFailure;
3368         }
3369         else
3370         {
3371             aImageFormat = (char *)image_format;
3372         }
3373         if (read8(iInputFile, aPicType) == false)
3374         {
3375             return PVMFFailure;
3376         }
3377 
3378         currentfilepos = iInputFile->Tell();
3379         //read description from file
3380         status = readNullTerminatedAsciiString(iInputFile, aDescription);
3381         if (status != PVMFSuccess)
3382         {
3383             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3384             return PVMFFailure;
3385         }
3386         //get the graphic data len
3387         size = aDescription.get_size() + 1 ; // 1 byte for null char
3388         aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size);
3389         if (aDataLen > aFrameSize)
3390         {
3391             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3392             aDataLen = 0;
3393             return PVMFFailure;
3394         }
3395 
3396 
3397 
3398     }
3399     else if (aFrameType == PV_ID3_FRAME_APIC)
3400     {
3401         uint32 mimeSize;
3402         uint32 desSize;
3403 
3404         currentfilepos = iInputFile->Tell();
3405         status = readNullTerminatedAsciiString(iInputFile, aImageFormat);
3406         if (status != PVMFSuccess)
3407         {
3408             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3409             return PVMFFailure;
3410         }
3411         if (read8(iInputFile, aPicType) == false)
3412         {
3413             return PVMFFailure;
3414         }
3415         currentfilepos = iInputFile->Tell();
3416         status = readNullTerminatedAsciiString(iInputFile, aDescription);
3417         if (status != PVMFSuccess)
3418         {
3419             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3420             return status;
3421         }
3422 
3423         //get the graphic data len
3424         mimeSize = aImageFormat.get_size() + 1; //for null string
3425         desSize = aDescription.get_size() + 1; //for null string
3426 
3427         aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize);
3428 
3429         if (aDataLen > aFrameSize)
3430         {
3431             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3432             aDataLen = 0;
3433             return PVMFFailure;
3434         }
3435 
3436 
3437     }
3438     return PVMFSuccess;
3439 }
3440 
GetAlbumArtInfo(PVID3FrameType aFrameType,uint32 aFrameSize,OSCL_HeapString<OsclMemAllocator> & aImageFormat,uint8 & aPicType,OSCL_wHeapString<OsclMemAllocator> & aDescription,uint32 & aDataLen)3441 PVMFStatus PVID3ParCom::GetAlbumArtInfo(PVID3FrameType aFrameType, uint32 aFrameSize, OSCL_HeapString<OsclMemAllocator> &aImageFormat,
3442                                         uint8 &aPicType, OSCL_wHeapString<OsclMemAllocator> &aDescription, uint32 &aDataLen)
3443 {
3444     uint8 image_format[4] = {0};
3445     uint32 currentfilepos = 0;
3446     uint32 size = 0;
3447     if (aFrameType == PV_ID3_FRAME_PIC)
3448     {
3449         if (readByteData(iInputFile, ID3V2_IMAGE_FORMAT_SIZE, image_format) == false)
3450         {
3451             return PVMFFailure;
3452         }
3453         else
3454         {
3455             aImageFormat = (char *)image_format;
3456         }
3457         if (read8(iInputFile, aPicType) == false)
3458         {
3459             return PVMFFailure;
3460         }
3461 
3462         uint32 bomSz = 0;
3463         currentfilepos = iInputFile->Tell();
3464         //read description from file
3465         if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false)
3466         {
3467             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3468             return PVMFFailure;
3469         }
3470 
3471         //get the graphic data len
3472         size = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 byte null character
3473         aDataLen = aFrameSize - (ID3V2_PIC_CONST_SIZE + size);
3474         if (aDataLen > aFrameSize)
3475         {
3476             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3477             aDataLen = 0;
3478             return PVMFFailure;
3479         }
3480 
3481 
3482     }
3483     else if (aFrameType == PV_ID3_FRAME_APIC)
3484     {
3485         uint32 mimeSize;
3486         uint32 desSize;
3487         currentfilepos = iInputFile->Tell();
3488         //read the mime type information
3489         if (readNullTerminatedAsciiString(iInputFile, aImageFormat) == false)
3490         {
3491             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3492             return PVMFFailure;
3493         }
3494         //read the picture type information
3495         if (read8(iInputFile, aPicType) == false)
3496         {
3497             return PVMFFailure;
3498         }
3499         uint32 bomSz = 0;
3500         currentfilepos = iInputFile->Tell();
3501         //read the null terminated description information
3502         if (readNullTerminatedUnicodeString(iInputFile, aDescription, bomSz) == false)
3503         {
3504             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3505             return PVMFFailure;
3506         }
3507         //get the graphic data len
3508         mimeSize = aImageFormat.get_size() + 1;
3509         desSize = (2 * oscl_strlen(aDescription.get_str())) + bomSz + sizeof(oscl_wchar) * 1; //2 bytes for null character
3510         aDataLen = aFrameSize - (ID3V2_APIC_CONST_SIZE + mimeSize + desSize);
3511         if (aDataLen > aFrameSize)
3512         {
3513             iInputFile->Seek(currentfilepos, Oscl_File::SEEKSET);
3514             aDataLen = 0;
3515             return PVMFFailure;
3516         }
3517 
3518 
3519 
3520     }
3521     return PVMFSuccess;
3522 }
3523 
3524 
3525 ////////////////////////////////////////////////////////////////////////////
ReadTrackLengthFrame(uint32 aValueSize,PVID3CharacterSet aCharSet)3526 PVMFStatus PVID3ParCom::ReadTrackLengthFrame(uint32 aValueSize, PVID3CharacterSet aCharSet)
3527 {
3528     OSCL_StackString<128> keyStr;
3529     if (ConstructKvpKey(keyStr, PV_ID3_FRAME_TRACK_LENGTH, PV_ID3_CHARSET_INVALID) != PVMFSuccess)
3530     {
3531         LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ConstructKvpKey failed"));
3532         return PVMFErrNotSupported;
3533     }
3534 
3535     int32 err = OsclErrNone;
3536     uint8* ptrFrameData = NULL;
3537     ptrFrameData = (uint8*) AllocateValueArray(err, PVMI_KVPVALTYPE_UINT8PTR, aValueSize + 2, &iAlloc);
3538     if (OsclErrNone != err || !ptrFrameData)
3539     {
3540         LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - ptrFrameData allocation failed"));
3541         return PVMFErrNoMemory;
3542     }
3543 
3544     if (readByteData(iInputFile, aValueSize, ptrFrameData) == false)
3545     {
3546         iAlloc.deallocate((OsclAny*)ptrFrameData);
3547         LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - readByteData failed"));
3548         return PVMFFailure;
3549     }
3550     ptrFrameData[aValueSize] = 0;
3551     ptrFrameData[aValueSize+1] = 0;
3552 
3553     switch (aCharSet)
3554     {
3555         case PV_ID3_CHARSET_UTF16:
3556         case PV_ID3_CHARSET_UTF16BE:
3557         {
3558             //it uses 16-bit unicode 2.0 (ISO/IEC 10646-1:1993, UCS-2)
3559 
3560             char* tmpData = NULL;
3561             int len = aValueSize / UNICODE_CHAR_SIZE + 1;
3562             tmpData = (char*) AllocateValueArray(err, PVMI_KVPVALTYPE_CHARPTR, len, &iAlloc);
3563 
3564             if (sizeof(oscl_wchar) == UNICODE_CHAR_SIZE)
3565             {
3566                 oscl_UnicodeToUTF8((oscl_wchar*)ptrFrameData, aValueSize / sizeof(oscl_wchar), tmpData, len);
3567             }
3568             else
3569             {
3570                 oscl_wchar* tmpData2 = NULL;
3571 
3572                 tmpData2 = (oscl_wchar*) AllocateValueArray(err, PVMI_KVPVALTYPE_WCHARPTR, len);
3573                 // convert 2 byte unicode data  to 4 byte wchar data
3574                 ExpandWChar2BytesTo4Bytes(tmpData2, (uint16*)ptrFrameData, len);
3575 
3576                 oscl_UnicodeToUTF8(tmpData2, aValueSize / UNICODE_CHAR_SIZE, tmpData, len);
3577 
3578                 OSCL_ARRAY_DELETE(tmpData2);
3579             }
3580 
3581             // copy the UTF8 string back to ptrFrameData
3582             oscl_strncpy((char*)ptrFrameData, tmpData, len);
3583 
3584             iAlloc.deallocate((OsclAny*)tmpData);
3585         }
3586         break;
3587         case PV_ID3_CHARSET_ISO88591:
3588         case PV_ID3_CHARSET_UTF8:
3589             break;
3590         default:
3591             return PVMFFailure;
3592     }
3593 
3594     // The ID3 Track Length is a numeric string in milliseconds.
3595     uint32 duration = 0;
3596     int32 numericStringLen = oscl_strlen((const char*)ptrFrameData);
3597 
3598     if (!PV_atoi((const char *)ptrFrameData, 'd', numericStringLen, duration))
3599     {
3600         uint8* ptr = ptrFrameData;
3601         bool invalid_frame = false;
3602         while (ptr - ptrFrameData < numericStringLen)
3603         {
3604             // if the charater read is a digit or decimal point
3605             // then truncate it to integer value
3606             if (!(((*ptr >= ZERO_CHARACTER_ASCII_VALUE) &&
3607                     (*ptr <= NINE_CHARACTER_ASCII_VALUE)) ||
3608                     (*ptr == PERIOD_CHARACTER_ASCII_VALUE) ||
3609                     (*ptr == COMMA_CHARACTER_ASCII_VALUE)))
3610             {
3611                 invalid_frame = true;
3612                 break;
3613             }
3614             else if (*ptr == PERIOD_CHARACTER_ASCII_VALUE ||
3615                      *ptr == COMMA_CHARACTER_ASCII_VALUE)
3616             {
3617                 numericStringLen = ptr - ptrFrameData;
3618                 break;
3619             }
3620             ptr++;
3621         }
3622 
3623         if (!invalid_frame)
3624         {
3625             numericStringLen = ptr - ptrFrameData;
3626         }
3627         else
3628         {
3629             iAlloc.deallocate((OsclAny*)ptrFrameData);
3630             numericStringLen = 0;
3631             return PVMFSuccess;
3632         }
3633     }
3634 
3635     // Allocate key-value pair
3636     bool truncate = false;
3637     PvmiKvpSharedPtr kvpPtr;
3638     PVMFStatus status = PVMFSuccess;
3639     kvpPtr = HandleErrorForKVPAllocation(keyStr, PVMI_KVPVALTYPE_UINT32, 1, truncate, status);
3640     if (PVMFSuccess != status || !kvpPtr)
3641     {
3642         iAlloc.deallocate((OsclAny*)ptrFrameData);
3643         return PVMFErrNoMemory;
3644     }
3645 
3646     kvpPtr->value.uint32_value = duration; // Track length in milliseconds
3647     kvpPtr->length = numericStringLen;
3648 
3649     iAlloc.deallocate((OsclAny*)ptrFrameData);
3650 
3651     OSCL_TRY(err, iFrames.push_back(kvpPtr););
3652     OSCL_FIRST_CATCH_ANY(err,
3653                          LOG_ERR((0, "PVID3ParCom::ReadTrackLengthFrame: Error - iFrame.push_back failed"));
3654                          return PVMFErrNoMemory;
3655                         );
3656 
3657     return PVMFSuccess;
3658 }
3659 
3660 
3661 ////////////////////////////////////////////////////////////////////////////
GetKvpValueType(PvmiKvpSharedPtr aKvp,PvmiKvpValueType & aValueType,PVID3CharacterSet & aCharSet)3662 PVMFStatus PVID3ParCom::GetKvpValueType(PvmiKvpSharedPtr aKvp,
3663                                         PvmiKvpValueType& aValueType,
3664                                         PVID3CharacterSet& aCharSet)
3665 {
3666     aValueType = GetValTypeFromKeyString(aKvp->key);
3667     aCharSet = PV_ID3_CHARSET_INVALID;
3668     char* param = NULL;
3669     switch (aValueType)
3670     {
3671         case PVMI_KVPVALTYPE_CHARPTR:
3672             aCharSet = PV_ID3_CHARSET_ISO88591;
3673             if (pv_mime_string_parse_param(aKvp->key, (char*) KVP_PARAM_CHAR_ENCODING_UTF8, param) > 0)
3674                 aCharSet = PV_ID3_CHARSET_UTF8;
3675             break;
3676         case PVMI_KVPVALTYPE_WCHARPTR:
3677             aCharSet = PV_ID3_CHARSET_UTF16;
3678             if (pv_mime_string_parse_param(aKvp->key, (char*) KVP_PARAM_CHAR_ENCODING_UTF16BE, param) > 0)
3679                 aCharSet = PV_ID3_CHARSET_UTF16BE;
3680             break;
3681         case PVMI_KVPVALTYPE_KSV:
3682             // Comment field
3683             break;
3684         case PVMI_KVPVALTYPE_UNKNOWN:
3685             return PVMFFailure;
3686         default:
3687             break;
3688     }
3689 
3690     return PVMFSuccess;
3691 }
3692 
3693 ////////////////////////////////////////////////////////////////////////////
GetFrameTypeFromKvp(PvmiKvpSharedPtr aKvp,OSCL_String & aFrameID,PVID3FrameType & aFrameType)3694 PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(PvmiKvpSharedPtr aKvp,
3695         OSCL_String& aFrameID,
3696         PVID3FrameType& aFrameType)
3697 {
3698     return GetFrameTypeFromKvp(*aKvp, aFrameID, aFrameType);
3699 }
3700 
3701 ////////////////////////////////////////////////////////////////////////////
GetFrameTypeFromKvp(const PvmiKvp & aKvp,OSCL_String & aFrameID,PVID3FrameType & aFrameType)3702 PVMFStatus PVID3ParCom::GetFrameTypeFromKvp(const PvmiKvp& aKvp,
3703         OSCL_String& aFrameID,
3704         PVID3FrameType& aFrameType)
3705 {
3706     if (iVersion == PV_ID3_V2_2)
3707     {
3708         if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0)
3709         {
3710             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TITLE);
3711             aFrameType = PV_ID3_FRAME_TITLE;
3712         }
3713         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0)
3714         {
3715             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ARTIST);
3716             aFrameType = PV_ID3_FRAME_ARTIST;
3717         }
3718         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0)
3719         {
3720             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_PART_OF_SET);
3721             aFrameType = PV_ID3_FRAME_PART_OF_SET;
3722         }
3723         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0)
3724         {
3725             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUM);
3726             aFrameType = PV_ID3_FRAME_ALBUM;
3727         }
3728         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACK_NUMBER) == 0)
3729         {
3730             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_NUMBER);
3731             aFrameType = PV_ID3_FRAME_TRACK_NUMBER;
3732         }
3733         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0)
3734         {
3735             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_GENRE);
3736             aFrameType = PV_ID3_FRAME_GENRE;
3737         }
3738         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0)
3739         {
3740             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_YEAR);
3741             aFrameType = PV_ID3_FRAME_YEAR;
3742         }
3743         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0)
3744         {
3745             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COPYRIGHT);
3746             aFrameType = PV_ID3_FRAME_COPYRIGHT;
3747         }
3748         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0)
3749         {
3750             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMMENT);
3751             aFrameType = PV_ID3_FRAME_COMMENT;
3752         }
3753         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0)
3754         {
3755             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_TRACK_LENGTH);
3756             aFrameType = PV_ID3_FRAME_TRACK_LENGTH;
3757         }
3758         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0)
3759         {
3760             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DATE);
3761             aFrameType = PV_ID3_FRAME_DATE;
3762         }
3763         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0)
3764         {
3765             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_ALBUMART);
3766             aFrameType = PV_ID3_FRAME_PIC;
3767         }
3768         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0)
3769         {
3770             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_LYRICIST);
3771             aFrameType = PV_ID3_FRAME_LYRICS;
3772         }
3773         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0)
3774         {
3775             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_AUTHOR);
3776             aFrameType = PV_ID3_FRAME_AUTHOR;
3777         }
3778         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0)
3779         {
3780             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_COMPOSER);
3781             aFrameType = PV_ID3_FRAME_COMPOSER;
3782         }
3783         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) >= 0)
3784         {
3785             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_DESCRIPTION);
3786             aFrameType = PV_ID3_FRAME_DESCRIPTION;
3787         }
3788         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0)
3789         {
3790             aFrameID = _STRLIT_CHAR(ID3V2_2_FRAME_ID_VERSION);
3791             aFrameType = PV_ID3_FRAME_VERSION;
3792         }
3793         else
3794         {
3795             LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing"));
3796             return PVMFErrNotSupported;
3797         }
3798     }
3799     else
3800     {
3801         if (pv_mime_strcmp(aKvp.key, KVP_KEY_TITLE) == 0)
3802         {
3803             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TITLE);
3804             aFrameType = PV_ID3_FRAME_TITLE;
3805         }
3806         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ARTIST) == 0)
3807         {
3808             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ARTIST);
3809             aFrameType = PV_ID3_FRAME_ARTIST;
3810         }
3811         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_PART_OF_SET) == 0)
3812         {
3813             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_PART_OF_SET);
3814             aFrameType = PV_ID3_FRAME_PART_OF_SET;
3815         }
3816         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUM) == 0)
3817         {
3818             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUM);
3819             aFrameType = PV_ID3_FRAME_ALBUM;
3820         }
3821         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_TRACK_NUMBER) == 0)
3822         {
3823             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_NUMBER);
3824             aFrameType = PV_ID3_FRAME_TRACK_NUMBER;
3825         }
3826         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_GENRE) == 0)
3827         {
3828             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_GENRE);
3829             aFrameType = PV_ID3_FRAME_GENRE;
3830         }
3831         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_YEAR) == 0)
3832         {
3833             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_YEAR);
3834             aFrameType = PV_ID3_FRAME_YEAR;
3835         }
3836         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COPYRIGHT) == 0)
3837         {
3838             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COPYRIGHT);
3839             aFrameType = PV_ID3_FRAME_COPYRIGHT;
3840         }
3841         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMMENT) == 0)
3842         {
3843             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMMENT);
3844             aFrameType = PV_ID3_FRAME_COMMENT;
3845         }
3846         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ID3DURATION) == 0)
3847         {
3848             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_TRACK_LENGTH);
3849             aFrameType = PV_ID3_FRAME_TRACK_LENGTH;
3850         }
3851         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_RECORDING_TIME) == 0)
3852         {
3853             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_RECORDING_TIME);
3854             aFrameType = PV_ID3_FRAME_RECORDING_TIME;
3855         }
3856         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_AUTHOR) == 0)
3857         {
3858             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_AUTHOR);
3859             aFrameType = PV_ID3_FRAME_AUTHOR;
3860         }
3861         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_COMPOSER) == 0)
3862         {
3863             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_COMPOSER);
3864             aFrameType = PV_ID3_FRAME_COMPOSER;
3865         }
3866         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DESCRIPTION) == 0)
3867         {
3868             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DESCRIPTION);
3869             aFrameType = PV_ID3_FRAME_DESCRIPTION;
3870         }
3871         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_VERSION) == 0)
3872         {
3873             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_VERSION);
3874             aFrameType = PV_ID3_FRAME_VERSION;
3875         }
3876         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_DATE) == 0)
3877         {
3878             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_DATE);
3879             aFrameType = PV_ID3_FRAME_DATE;
3880         }
3881         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_LYRICS) == 0)
3882         {
3883             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_LYRICIST);
3884             aFrameType = PV_ID3_FRAME_LYRICS;
3885         }
3886         else if (pv_mime_strcmp(aKvp.key, KVP_KEY_ALBUMART) == 0)
3887         {
3888             aFrameID = _STRLIT_CHAR(ID3_FRAME_ID_ALBUMART);
3889             aFrameType = PV_ID3_FRAME_APIC;
3890         }
3891         else
3892         {
3893             LOG_ERR((0, "PVID3ParCom::GetFrameTypeFromKvp: Error : Frame type not supported for composing"));
3894             return PVMFErrNotSupported;
3895         }
3896     }
3897 
3898     return PVMFSuccess;
3899 }
3900 
3901 ////////////////////////////////////////////////////////////////////////////
GetID3v2FrameDataSize(PvmiKvpSharedPtr aKvp,PvmiKvpValueType aValueType,PVID3CharacterSet aCharSet,uint32 & aSize)3902 PVMFStatus PVID3ParCom::GetID3v2FrameDataSize(PvmiKvpSharedPtr aKvp,
3903         PvmiKvpValueType aValueType,
3904         PVID3CharacterSet aCharSet,
3905         uint32& aSize)
3906 {
3907     aSize = 0;
3908     switch (aValueType)
3909     {
3910         case PVMI_KVPVALTYPE_CHARPTR:
3911             aSize += (BYTE_FOR_CHARACTERSET_FORMAT + oscl_strlen(aKvp->value.pChar_value) + 1);
3912             break;
3913         case PVMI_KVPVALTYPE_WCHARPTR:
3914             aSize += (BYTE_FOR_CHARACTERSET_FORMAT +
3915                       (oscl_strlen(aKvp->value.pWChar_value) + 1) * sizeof(oscl_wchar));
3916             break;
3917         case PVMI_KVPVALTYPE_KSV:
3918             // Comment field
3919             break;
3920         case PVMI_KVPVALTYPE_UINT32:
3921             uint32 value;
3922             value = aKvp->value.uint32_value;
3923             if (value == 0)
3924                 return PVMFSuccess;
3925             while (value > 0)
3926             {
3927                 value = value / 10;
3928                 ++aSize;
3929             }
3930             break;
3931         default:
3932             return PVMFErrNotSupported;
3933     }
3934 
3935     // Add 1 byte for BOM value to indicate byte order
3936     if (aCharSet == PV_ID3_CHARSET_UTF16)
3937         ++aSize;
3938 
3939     return PVMFSuccess;
3940 }
3941 
3942 ////////////////////////////////////////////////////////////////////////////
ComposeID3v2Tag(OsclRefCounterMemFrag & aTag)3943 PVMFStatus PVID3ParCom::ComposeID3v2Tag(OsclRefCounterMemFrag& aTag)
3944 {
3945     uint8* memFragPtr;
3946     uint32 index = 0;
3947     uint32 composedTagSize = 0;
3948     uint32 frameDataSize = 0;
3949     uint32 i = 0;
3950     char bufTrackLength[16];
3951     oscl_wchar wbufTrackLength[16];
3952     oscl_memset(bufTrackLength, 0, 16);
3953     oscl_memset(wbufTrackLength, 0, 16);
3954     PvmiKvpValueType kvpValueType;
3955     PVID3CharacterSet charSet;
3956     PVMFStatus status = PVMFSuccess;
3957 
3958     // At least one frame should be present for a valid ID3 tag to be composed
3959     if (iFrames.empty())
3960     {
3961         LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - No Frames are available to add"));
3962         return PVMFFailure;
3963     }
3964 
3965     // Calculate the size of composed ID3tag
3966     composedTagSize = GetID3TagSize();
3967     if (composedTagSize == 0)
3968     {
3969         LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3TagSize failed"));
3970         return PVMFFailure;
3971     }
3972 
3973     //iUseMaxTagSize on but the max tag size set is smaller than the total tag size.
3974     if (iUseMaxTagSize && (iMaxTagSize < composedTagSize))
3975     {
3976         LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Max tag size is smaller than size of composed tag"));
3977         return PVMFFailure;
3978     }
3979 
3980     //if maxsize is greater than tagsize and padding is ON, allocate memory equal to iMaxTagSize
3981     if (iUseMaxTagSize && iUsePadding)
3982         composedTagSize = iMaxTagSize;
3983 
3984     //if the fragment buffer size is not sufficient, allocate memory
3985     OsclMemoryFragment& my_memfrag = aTag.getMemFrag();
3986     if (composedTagSize > aTag.getMemFragSize())
3987     {
3988         OsclRefCounter* my_refcnt;
3989 
3990         // Create mem frag for ID3 tag
3991         OsclMemAllocDestructDealloc<uint8> my_alloc;
3992         uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
3993         uint8* myPtr = (uint8*) my_alloc.allocate(aligned_refcnt_size + composedTagSize);
3994         my_refcnt = OSCL_PLACEMENT_NEW(myPtr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(myPtr));
3995         myPtr += aligned_refcnt_size;
3996 
3997         my_memfrag.ptr = myPtr;
3998         my_memfrag.len = 0;
3999 
4000         OsclRefCounterMemFrag mynewRefCntMemFrag(my_memfrag, my_refcnt, composedTagSize);
4001 
4002         //frees the old memeory and make the RefCounterMemFrag point to newly allocated memory
4003         aTag = mynewRefCntMemFrag;
4004     }
4005 
4006     memFragPtr = (uint8*)aTag.getMemFragPtr();
4007     oscl_memset(memFragPtr, 0, composedTagSize);
4008 
4009     // Form the tag header and place it into the tag buffer
4010     oscl_memcpy(memFragPtr, ID3_V2_IDENTIFIER, ID3V2_TAG_NUM_BYTES_ID);
4011     index += ID3V2_TAG_NUM_BYTES_ID;
4012 
4013     // Store ID3 tag version
4014     memFragPtr[index++] = (uint8)iVersion;
4015     memFragPtr[index++] = 0;
4016 
4017     // ID3v2 flags
4018     memFragPtr[index++] = ID3V2_FLAGS;
4019 
4020     // Tag size (4 bytes)
4021     uint32 syncSafeInt = ConvertToSyncSafeInt(composedTagSize - 10); // Total Size of ID3 tag - 10 bytes for header
4022 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4023     memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24);
4024     memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
4025     memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
4026     memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
4027 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4028     uint32* sizePtr = (uint32*)(memFragPtr + index);
4029     *sizePtr = syncSafeInt;
4030     index += 4;
4031 #else
4032 #error "Byte order is not specified in OSCL"
4033 #endif
4034 
4035     //iterate the frames and write into the tag buffer
4036     OSCL_StackString<4> frameID;
4037     PVID3FrameType frameType;
4038     for (i = 0; i < iFrames.size(); i++)
4039     {
4040         // 4 character Frame ID
4041         status = GetFrameTypeFromKvp(iFrames[i], frameID, frameType);
4042 
4043         //ignore unsupported frames.
4044         if ((status == PVMFErrNotSupported) || (frameType == PV_ID3_FRAME_LYRICS) ||
4045                 (frameType == PV_ID3_FRAME_APIC) || (frameType == PV_ID3_FRAME_PIC) ||
4046                 (frameType == PV_ID3_FRAME_COMMENT))
4047         {
4048             continue;
4049         }
4050 
4051         if ((status != PVMFSuccess))
4052         {
4053             LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetFrameTypeFromKvp failed. status=%d", status));
4054             return status;
4055         }
4056         if (iVersion == PV_ID3_V2_2)
4057         {
4058             oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_2_FRAME_NUM_BYTES_ID);
4059             index += ID3V2_2_FRAME_NUM_BYTES_ID;
4060         }
4061         else
4062         {
4063             oscl_memcpy(memFragPtr + index, frameID.get_cstr(), ID3V2_FRAME_NUM_BYTES_ID);
4064             index += ID3V2_FRAME_NUM_BYTES_ID;
4065         }
4066         status = GetKvpValueType(iFrames[i], kvpValueType, charSet);
4067         if (status != PVMFSuccess)
4068         {
4069             LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetKvpValueType failed. status=%d", status));
4070             return status;
4071         }
4072 
4073         // Size of Frame (4 byte sync safe integer)
4074         status = GetID3v2FrameDataSize(iFrames[i], kvpValueType, charSet, frameDataSize);
4075         if (status != PVMFSuccess)
4076         {
4077             LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - GetID3v2FrameDataSize failed. status=%d", status));
4078             return status;
4079         }
4080 //      syncSafeInt = ConvertToSyncSafeInt(frameDataSize);
4081         syncSafeInt = frameDataSize;
4082 
4083         if (iVersion == PV_ID3_V2_2)
4084         {
4085 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4086             memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
4087             memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
4088             memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
4089 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4090             sizePtr = (uint32*)(memFragPtr + index);
4091             *sizePtr = syncSafeInt;
4092             index += 3;
4093 #else
4094 #error "Byte order not specified in OSCL"
4095 #endif
4096 
4097         }
4098         else
4099         {
4100 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4101             memFragPtr[index++] = (uint8)((syncSafeInt & 0xFF000000) >> 24);
4102             memFragPtr[index++] = (uint8)((syncSafeInt & 0x00FF0000) >> 16);
4103             memFragPtr[index++] = (uint8)((syncSafeInt & 0x0000FF00) >> 8);
4104             memFragPtr[index++] = (uint8)(syncSafeInt & 0x000000FF);
4105 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4106             sizePtr = (uint32*)(memFragPtr + index);
4107             *sizePtr = syncSafeInt;
4108             index += 4;
4109 #else
4110 #error "Byte order not specified in OSCL"
4111 #endif
4112 
4113             //frame Flag for status messages
4114             memFragPtr[index++] = ID3V2_FLAGS;
4115 
4116             //frame flag for format description
4117             memFragPtr[index++] = ID3V2_FLAGS;
4118         }
4119 
4120         switch (kvpValueType)
4121         {
4122             case PVMI_KVPVALTYPE_CHARPTR:
4123                 memFragPtr[index++] = (uint8) charSet;
4124                 frameDataSize -= 2; // Minus 1 byte for the character set and 1 byte for NULL character
4125                 oscl_memcpy(memFragPtr + index, iFrames[i]->value.pChar_value, frameDataSize);
4126                 index += frameDataSize;
4127                 memFragPtr[index++] = 0; // NULL terminate the string
4128                 break;
4129             case PVMI_KVPVALTYPE_WCHARPTR:
4130                 memFragPtr[index++] = (uint8)charSet;
4131                 frameDataSize -= 3; // Minus 1 byte for the character set and 2 bytes for NULL character
4132                 if (charSet == PV_ID3_CHARSET_UTF16)
4133                 {
4134 #if (OSCL_BYTE_ORDER_LITTLE_ENDIAN)
4135                     memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR;
4136                     memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR;
4137 #elif (OSCL_BYTE_ORDER_BIG_ENDIAN)
4138                     memFragPtr[index++] = UNICODE_BIG_ENDIAN_INDICATOR;
4139                     memFragPtr[index++] = UNICODE_LITTLE_ENDIAN_INDICATOR;
4140 
4141 #else
4142 #error "Byte order not specified"
4143 #endif
4144                     frameDataSize -= 2; // Minus 1 byte for byte order
4145                 }
4146                 oscl_memcpy(memFragPtr + index, iFrames[i]->value.pWChar_value, frameDataSize);
4147                 index += frameDataSize;
4148                 memFragPtr[index++] = 0; // NULL terminate the string
4149                 memFragPtr[index++] = 0; // NULL terminate the string
4150                 break;
4151             case PVMI_KVPVALTYPE_UINT32:
4152                 // Track length frame
4153                 oscl_snprintf((char*)(memFragPtr + index), frameDataSize, "%d\0", iFrames[i]->value.uint32_value);
4154                 break;
4155             case PVMI_KVPVALTYPE_KSV:
4156                 // Comment frame
4157                 memFragPtr[index++] = (uint8)charSet;
4158                 frameDataSize -= 1; // Minus 1 byte for the character set
4159                 break;
4160             default:
4161                 LOG_ERR((0, "PVID3ParCom::ComposeID3v2Tag: Error - Unsupported key-value pair value type"));
4162                 return PVMFErrNotSupported;
4163         }
4164 
4165     }
4166 
4167     //if padding is on and the tag size is less than the maximum tag specified, do the padding
4168     if (iUseMaxTagSize && iUsePadding && (index < iMaxTagSize))
4169     {
4170         oscl_memset((OsclAny*)(memFragPtr + index), 0, (iMaxTagSize - index));
4171         my_memfrag.len = iMaxTagSize;
4172     }
4173     else
4174     {
4175         //save the filesize into the memory fragment
4176         my_memfrag.len = index;
4177     }
4178 
4179     return PVMFSuccess;
4180 }
4181 
4182 ////////////////////////////////////////////////////////////////////////////
FrameValidatedID3V2_4(uint8 * aFrameID)4183 PVID3ParCom::PVID3FrameType PVID3ParCom::FrameValidatedID3V2_4(uint8* aFrameID)
4184 {
4185     PVID3FrameType ID3V2FrameTypeReturnValue;
4186 
4187     if ((oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCRYPTION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4188             (oscl_memcmp(aFrameID, ID3_FRAME_ID_AUDIO_SEEK_POINT_INDEX, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4189             (oscl_memcmp(aFrameID, ID3_FRAME_ID_COMMERCIAL_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4190             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCRYPTION_REGISTRATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4191             (oscl_memcmp(aFrameID, ID3_FRAME_ID_EQUALIZATION2, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4192             (oscl_memcmp(aFrameID, ID3_FRAME_ID_EVENT_TIMING_CODES, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4193             (oscl_memcmp(aFrameID, ID3_FRAME_ID_GENERAL_ENCAPSULATED_OBJECT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4194             (oscl_memcmp(aFrameID, ID3_FRAME_ID_GROUP_IDENTITY_REGISTRATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4195             (oscl_memcmp(aFrameID, ID3_FRAME_ID_LINKED_INFORMATION, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4196             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MUSIC_CD_IDENTIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4197             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MPEG_LOCATION_LOOKUP_TABLE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4198             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OWNERSHIP_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4199             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PRIVATE_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4200             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PLAY_COUNTER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4201             (oscl_memcmp(aFrameID, ID3_FRAME_ID_POPULARIMETER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4202             (oscl_memcmp(aFrameID, ID3_FRAME_ID_POSITION_SYNCH_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4203             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RECOMMENDED_BUFFER_SIZE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4204             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RELATIVE_VOLUME_ADJUSTMENT2, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4205             (oscl_memcmp(aFrameID, ID3_FRAME_ID_REVERB, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4206             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SYNCHRONIZED_LYRICS_TEXT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4207             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SYNCHRONIZED_TEMPO_CODES, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4208             (oscl_memcmp(aFrameID, ID3_FRAME_ID_BPM, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4209             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PLAYLIST_DELAY, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4210             (oscl_memcmp(aFrameID, ID3_FRAME_ID_FILE_TYPE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4211             (oscl_memcmp(aFrameID, ID3_FRAME_ID_CONTENT_GROUP_DESC, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4212             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INITIAL_KEY, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4213             (oscl_memcmp(aFrameID, ID3_FRAME_ID_LANGUAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4214             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MEDIA_TYPE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4215             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_ALBUM, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4216             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_FILENAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4217             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_LYRICIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4218             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_ARTIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4219             (oscl_memcmp(aFrameID, ID3_FRAME_ID_FILE_LICENSEE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4220             (oscl_memcmp(aFrameID, ID3_FRAME_ID_BAND, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4221             (oscl_memcmp(aFrameID, ID3_FRAME_ID_CONDUCTOR, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4222             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MODIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4223             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PART_OF_SET, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4224             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PUBLISHER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4225             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INTERNET_RADIO_STATION_NAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4226             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INTERNET_RADIO_STATION_OWNER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4227             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RECORDING_CODE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4228             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SOFTWARE_SETTING_ENCODE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4229             (oscl_memcmp(aFrameID, ID3_FRAME_ID_UNIQUE_FILE_IDENTIFIER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4230             (oscl_memcmp(aFrameID, ID3_FRAME_ID_TERMS_OF_USE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4231             (oscl_memcmp(aFrameID, ID3_FRAME_ID_COMMERCIAL_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4232             (oscl_memcmp(aFrameID, ID3_FRAME_ID_LEGAL_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4233             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_AUDIO_FILE_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4234             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_ARTIST_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4235             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_AUDIO__SOURCE_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4236             (oscl_memcmp(aFrameID, ID3_FRAME_ID_OFFICIAL_RADIO_STATION_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4237             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PAYMENT, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4238             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PUBLISHER_OFFICIAL_WEBPAGE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4239             (oscl_memcmp(aFrameID, ID3_FRAME_ID_USER_DEFINED_URL_LINK_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4240             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SIGNATURE_FRAME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4241             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ENCODING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4242             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ORIGINAL_RELEASE_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4243             (oscl_memcmp(aFrameID, ID3_FRAME_ID_RELEASE_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4244             (oscl_memcmp(aFrameID, ID3_FRAME_ID_TAGGING_TIME, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4245             (oscl_memcmp(aFrameID, ID3_FRAME_ID_INVOLVED_PEOPLE_LIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4246             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MUSICIAN_CREDITS_LIST, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4247             (oscl_memcmp(aFrameID, ID3_FRAME_ID_MOOD, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4248             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PRODUCED_NOTICE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4249             (oscl_memcmp(aFrameID, ID3_FRAME_ID_ALBUM_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4250             (oscl_memcmp(aFrameID, ID3_FRAME_ID_PERFORMER_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4251             (oscl_memcmp(aFrameID, ID3_FRAME_ID_TITLE_SORT_ORDER, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4252             (oscl_memcmp(aFrameID, ID3_FRAME_ID_SET_SUBTITLE, ID3V2_FRAME_NUM_BYTES_ID) == 0) ||
4253             (oscl_memcmp(aFrameID, ID3_FRAME_ID_USER_DEFINED_TEXT_INFO, ID3V2_FRAME_NUM_BYTES_ID) == 0)
4254        )
4255     {
4256         ID3V2FrameTypeReturnValue = PV_ID3_FRAME_UNRECOGNIZED;
4257     }
4258     // The frame ID made out of the characters capital A-Z and 0-9.
4259     else if (IS_POTENTIAL_FRAME_ID(aFrameID))
4260     {
4261         ID3V2FrameTypeReturnValue = PV_ID3_FRAME_CANDIDATE;
4262     }
4263     else
4264     {
4265         // Frame ID doesn't match with defined/possible frame Ids
4266         ID3V2FrameTypeReturnValue = PV_ID3_FRAME_INVALID;
4267     }
4268     return ID3V2FrameTypeReturnValue;
4269 }
4270 
PushFrameToFrameVector(PvmiKvpSharedPtr & aFrame,PvmiKvpSharedPtrVector & aFrameVector)4271 PVMFStatus PVID3ParCom::PushFrameToFrameVector(PvmiKvpSharedPtr& aFrame, PvmiKvpSharedPtrVector& aFrameVector)
4272 {
4273     int32 err = OsclErrNone;
4274     OSCL_TRY(err, aFrameVector.push_back(aFrame););
4275     OSCL_FIRST_CATCH_ANY(err,
4276                          LOG_ERR((0, "PVID3ParCom::GetID3Frame: Error - aFrame.push_back failed"));
4277                          return PVMFErrNoMemory;);
4278     return PVMFSuccess;
4279 }
4280 
AllocateValueArray(int32 & aLeaveCode,PvmiKvpValueType aValueType,int32 aNumElements,OsclMemAllocator * aMemAllocator)4281 OsclAny* PVID3ParCom::AllocateValueArray(int32& aLeaveCode, PvmiKvpValueType aValueType, int32 aNumElements, OsclMemAllocator* aMemAllocator)
4282 {
4283     int32 leaveCode = OsclErrNone;
4284     OsclAny* buffer = NULL;
4285     switch (aValueType)
4286     {
4287         case PVMI_KVPVALTYPE_WCHARPTR:
4288             if (aMemAllocator)
4289             {
4290                 OSCL_TRY(leaveCode,
4291                          buffer = (oscl_wchar*) aMemAllocator->ALLOCATE(aNumElements););
4292             }
4293             else
4294             {
4295                 OSCL_TRY(leaveCode,
4296                          buffer = (oscl_wchar*) OSCL_ARRAY_NEW(oscl_wchar, aNumElements););
4297             }
4298             break;
4299 
4300         case PVMI_KVPVALTYPE_CHARPTR:
4301             if (aMemAllocator)
4302             {
4303                 OSCL_TRY(leaveCode,
4304                          buffer = (char*) aMemAllocator->ALLOCATE(aNumElements););
4305             }
4306             else
4307             {
4308                 OSCL_TRY(leaveCode,
4309                          buffer = (char*) OSCL_ARRAY_NEW(char, aNumElements););
4310             }
4311             break;
4312         case PVMI_KVPVALTYPE_UINT8PTR:
4313             if (aMemAllocator)
4314             {
4315                 OSCL_TRY(leaveCode,
4316                          buffer = (uint8*) aMemAllocator->ALLOCATE(aNumElements););
4317             }
4318             else
4319             {
4320                 OSCL_TRY(leaveCode,
4321                          buffer = (uint8*) OSCL_ARRAY_NEW(char, aNumElements););
4322             }
4323             break;
4324         default:
4325             break;
4326     }
4327     aLeaveCode = leaveCode;
4328     return buffer;
4329 }
4330 
HandleErrorForKVPAllocation(OSCL_String & aKey,PvmiKvpValueType aValueType,uint32 aValueSize,bool & truncate,PVMFStatus & aStatus)4331 PvmiKvpSharedPtr PVID3ParCom::HandleErrorForKVPAllocation(OSCL_String& aKey, PvmiKvpValueType aValueType, uint32 aValueSize, bool &truncate, PVMFStatus &aStatus)
4332 {
4333     PvmiKvpSharedPtr kvp;
4334     int32 err = OsclErrNone;
4335     aStatus = PVMFSuccess;
4336     OSCL_TRY(err, kvp = AllocateKvp(aKey, aValueType, aValueSize, truncate););
4337     if (OsclErrNone != err)
4338     {
4339         LOG_ERR((0, "PVID3ParCom::SetID3Frame: Error - AllocateKvp failed"));
4340         aStatus = PVMFErrNoMemory;
4341     }
4342     return kvp;
4343 }
4344