File decomp.patch of Package xtandem

diff --git a/src/Makefile_ubuntu b/src/Makefile_ubuntu
index 27521b5..48c1d5b 100644
--- a/src/Makefile_ubuntu
+++ b/src/Makefile_ubuntu
@@ -17,7 +17,7 @@ CXXFLAGS = -w -O2 -DGCC4_3
 #ubuntu 64 bit version
 
 #LDFLAGS =  -lpthread -lm -L/usr/lib -static -lexpat
-LDFLAGS = -lpthread -L/usr/lib -lm -lexpat
+LDFLAGS = -lpthread -lm -lexpat -lz
 
 SRCS := $(wildcard *.cpp)
 OBJS := $(patsubst %.cpp,%.o,$(wildcard *.cpp))
diff --git a/src/base64.cpp b/src/base64.cpp
index aa75eba..069864a 100644
--- a/src/base64.cpp
+++ b/src/base64.cpp
@@ -2,6 +2,7 @@
 //#include <math.h>
 //#include <stdio.h>
 //#include <string.h>
+#include <zlib.h>
 #include "stdafx.h"
 
 #include "base64.h"
@@ -90,11 +91,12 @@ inline int getPosition( char buf )
 }
 
 
-// Returns the total number of bytes decoded
-int b64_decode_mio ( char *dest,  char *src, size_t size )
+// Returns the total number of bytes decoded, or -1 if destination buffer overflows or there is a decompression error
+int b64_decode_mio ( char *const dest, const size_t dest_size, char *src, const size_t src_size, bool decomp )
 {
 	char *temp = dest;
-	char *end = dest + size;
+	char *const dest_end = dest + dest_size;
+	char *const src_end = src + src_size;
 
 	for (;;)
 	{
@@ -102,11 +104,11 @@ int b64_decode_mio ( char *dest,  char *src, size_t size )
 		int register b;
 		int t1,t2,t3,t4;
 
-		if (!(t1 = *src++) || !(t2 = *src++) || !(t3 = *src++) || !(t4 = *src++))
-			return (int)(temp-dest);
-
-		if (t1 == 61 || temp >= end)		// if == '='
-			return(int)(temp-dest);
+		// Read first and second characters
+		if (src >= src_end || !(t1 = *src++) || t1 == 61)	// if == '='
+			break;
+		if (src >= src_end || !(t2 = *src++))
+			break;
 
 		if( t1 > 96 )		// [a-z]
 			a = (t1 - 71);
@@ -119,7 +121,6 @@ int b64_decode_mio ( char *dest,  char *src, size_t size )
 		else				// src[0] == '/'
 			a = 63;     
 
-
 		if( t2 > 96 )		// [a-z]
 			b = (t2 - 71);
 		else if( t2 > 64 )		// [A-Z]
@@ -131,10 +132,14 @@ int b64_decode_mio ( char *dest,  char *src, size_t size )
 		else				// src[0] == '/'
 			b = 63;     
 
+		// Write first byte
+		if (temp >= dest_end)	// destination overflow!
+			return -1;
 		*temp++ = ( a << 2) | ( b >> 4);
 
-		if (t3 == 61 || temp >= end)
-			return (int)(temp-dest);;
+		// Read third character (if any)
+		if (src >= src_end || !(t3 = *src++) || t3 == 61)
+			break;
 
 		if( t3 > 96 )		// [a-z]
 			a = (t3 - 71);
@@ -147,10 +152,14 @@ int b64_decode_mio ( char *dest,  char *src, size_t size )
 		else				// src[0] == '/'
 			a = 63;     
 
+		// Write second byte
+		if (temp >= dest_end)	// destination overflow!
+			return -1;
 		*temp++ = ( b << 4) | ( a >> 2);
 
-		if (t4 == 61 || temp >= end)
-			return (int)(temp-dest);;
+		// Read fourth character (if any)
+		if (src >= src_end || !(t4 = *src++) || t4 == 61)
+			break;
 
 		if( t4 > 96 )		// [a-z]
 			b = (t4 - 71);
@@ -163,6 +172,26 @@ int b64_decode_mio ( char *dest,  char *src, size_t size )
 		else				// src[0] == '/'
 			b = 63;    
 
+		// Write third byte
+		if (temp >= dest_end)	// destination overflow!
+			return -1;
 		*temp++ = ( a << 6) | ( b );
 	}
+
+	// Decompress if required
+	if (decomp) {
+		Bytef *decompBuf = (Bytef*)malloc(dest_size);
+		uLongf decompLen = dest_size;
+		int result = uncompress(decompBuf, &decompLen, (Bytef*)dest, (uLong)(temp - dest));
+		if (result == Z_OK) {
+			memcpy(dest, decompBuf, decompLen);
+			temp = dest + decompLen;
+		}
+		free(decompBuf);
+		if (result != Z_OK)	// decompression error
+			return -1;
+	}
+
+	// Done
+	return temp - dest;
 }
diff --git a/src/base64.h b/src/base64.h
index e7c1bc5..b529dfa 100644
--- a/src/base64.h
+++ b/src/base64.h
@@ -1,5 +1,5 @@
 #ifndef BASE64_H
 #define BASE64_H
 
-int b64_decode_mio (char *dest, char *src, size_t size);
+int b64_decode_mio (char *dest, size_t dest_size, char *src, size_t src_size, bool decomp);
 #endif /* BASE64_H */
diff --git a/src/saxhandler.cpp b/src/saxhandler.cpp
index 7afcebf..16a92e9 100644
--- a/src/saxhandler.cpp
+++ b/src/saxhandler.cpp
@@ -299,7 +299,7 @@ void SAXSpectraHandler::pushSpectrum()
 	}
 }
 
-void SAXSpectraHandler::pushPeaks(bool bM /*= true*/, bool bI /*= true*/)
+void SAXSpectraHandler::pushPeaks(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/)
 {
 	if(bM)
 		m_vfM.clear();
@@ -340,10 +340,10 @@ void SAXSpectraHandler::pushPeaks(bool bM /*= true*/, bool bI /*= true*/)
 	}
 	else{
 		if (m_bLowPrecision)	{
-			decode32(bM,bI);
+			decode32(bM,bI,decomp);
 		}
 		else	{
-			decode64(bM,bI);
+			decode64(bM,bI,decomp);
 		}
 	}
 }
@@ -393,7 +393,7 @@ void SAXSpectraHandler::numDepress(char* indata, size_t indataLength, bool bM /*
 }
 
 
-void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/)
+void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/)
 {
 	// This code block was revised so that it packs floats correctly
 	// on both 64 and 32 bit machines, by making use of the uint32_t
@@ -407,15 +407,15 @@ void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/)
 	if(bI == true) {
 		setCount++;
 	}
-	size_t size = stringSize * setCount * 3 / 4;
-	char* pDecoded = (char *) new char[size];
-
-	memset(pDecoded, 0, size);
+	size_t size = m_peaksCount * setCount * sizeof(uint32_t);
+	size_t dest_size = size + 32;
+	char* pDecoded = (char *) new char[dest_size];
+	memset(pDecoded, 0, dest_size);
 	if(m_peaksCount > 0) {
 		// Base64 decoding
 		// By comparing the size of the unpacked data and the expected size
 		// an additional check of the data file integrity can be performed
-		int length = b64_decode_mio( (char*) pDecoded , (char*) pData, stringSize );
+		int length = b64_decode_mio( (char*) pDecoded, dest_size, (char*) pData, stringSize, decomp );
 		if (!m_strNumpress.empty()){
 			numDepress((char*) pDecoded, length, bM, bI);
 		}
@@ -451,7 +451,7 @@ void SAXSpectraHandler::decode32(bool bM /*= true*/, bool bI /*= true*/)
 	delete[] pDecoded;
 }
 
-void SAXSpectraHandler::decode64(bool bM /*= true*/, bool bI /*= true*/)
+void SAXSpectraHandler::decode64(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/)
 {
 // This code block was revised so that it packs floats correctly
 // on both 64 and 32 bit machines, by making use of the uint32_t
@@ -465,14 +465,15 @@ void SAXSpectraHandler::decode64(bool bM /*= true*/, bool bI /*= true*/)
 	if(bI == true) {
 		setCount++;
 	}
-	size_t size = stringSize * setCount * 3 / 4;
-        char* pDecoded = (char *) new char[size];
-        memset(pDecoded, 0, size);
+	size_t size = m_peaksCount * setCount * sizeof(uint64_t);
+	size_t dest_size = size + 32;
+	char* pDecoded = (char *) new char[dest_size];
+	memset(pDecoded, 0, dest_size);
 	if(m_peaksCount > 0) {
 		// Base64 decoding
 		// By comparing the size of the unpacked data and the expected size
 		// an additional check of the data file integrity can be performed
-		int length = b64_decode_mio( (char*) pDecoded , (char*) pData, stringSize );
+		int length = b64_decode_mio( (char*) pDecoded, dest_size, (char*) pData, stringSize, decomp );
 
 		if (!m_strNumpress.empty()){
 			numDepress(pDecoded, length, bM, bI);
diff --git a/src/saxhandler.h b/src/saxhandler.h
index 8a076fd..fc66dcc 100644
--- a/src/saxhandler.h
+++ b/src/saxhandler.h
@@ -231,7 +231,7 @@ public:
 protected:
 	void pushSpectrum();	// Load current data into pvSpec, may have to guess charge
 	void pushSpectrum(int charge);	// Load current data into pvSpec with specific charge
-	void pushPeaks(bool bM = true, bool bI = true);	// Decode m_strData into a peak list
+	void pushPeaks(bool bM = true, bool bI = true, bool decomp = false);    // Decode m_strData into a peak list
 
 	inline void reset()
 	{
@@ -247,8 +247,8 @@ private:
 	int guessCharge();	// Guess the charge based on spectrum peaks
 	void setDescription();	// Set specCurrent description based on current data
     void numDepress(char* indata, size_t indataLength, bool bM /*= true*/, bool bI /*= true*/);
-	void decode32(bool bM /*= true*/, bool bI /*= true*/);
-	void decode64(bool bM /*= true*/, bool bI /*= true*/);
+	void decode32(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/);
+	void decode64(bool bM /*= true*/, bool bI /*= true*/, bool decomp /*= false*/);
 	unsigned long dtohl(uint32_t l, bool bNet);	// Convert from data to host long
 	uint64_t dtohl(uint64_t l, bool bNet);
 protected:
diff --git a/src/saxmzmlhandler.cpp b/src/saxmzmlhandler.cpp
index fe9cfd6..9348b62 100644
--- a/src/saxmzmlhandler.cpp
+++ b/src/saxmzmlhandler.cpp
@@ -44,6 +44,7 @@ SAXMzmlHandler::SAXMzmlHandler( vector<mspectrum>& _vS, mspectrumcondition& _sC,
 	m_bNetworkData = true;
 	m_bLowPrecision = false;
 	m_bGaml = false;
+	m_bDecomp = false;
 }
 
 SAXMzmlHandler::~SAXMzmlHandler()
@@ -130,6 +131,7 @@ void SAXMzmlHandler::startElement(const XML_Char *el, const XML_Char **attr)
 			m_peaksCount = atoi(getAttrValue("arrayLength", attr));
 		}
 		m_bInData = true;
+		m_bDecomp = false;              // reset flag
 	}
 }
 
@@ -215,8 +217,7 @@ void SAXMzmlHandler::processCVParam(const char* name, const char* accession, con
 		m_bInmzArrayBinary = false;
 	}
 	else if(!strcmp(name, "zlib compression") || !strcmp(accession,"MS:1000574"))	{
-		cout << "\nFatal error: unsupported CODEC used for mzML peak data (CODEC type=" << name << ").\n";
-		exit(-10);
+		m_bDecomp = true;
 	}
 	else if(!strcmp(accession, "MS:1002312") || !strcmp(accession, "MS:1002313") || !strcmp(accession, "MS:1002314"))	{
 		m_strNumpress = string(accession);
@@ -227,11 +228,11 @@ void SAXMzmlHandler::processData()
 {
 	if(m_bInmzArrayBinary && m_bInMsLevel2 && m_bInData)
 	{
-		pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary);
+		pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary, m_bDecomp);
 	}
 	else if(m_bInintenArrayBinary && m_bInMsLevel2 && m_bInData)
 	{
-		pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary);
+		pushPeaks(m_bInmzArrayBinary, m_bInintenArrayBinary, m_bDecomp);
 	}
 
 	m_strData.clear();
diff --git a/src/saxmzmlhandler.h b/src/saxmzmlhandler.h
index 3c4d121..c11eae9 100644
--- a/src/saxmzmlhandler.h
+++ b/src/saxmzmlhandler.h
@@ -72,6 +72,7 @@ private:
 	bool m_bInmzArrayBinary;
 	bool m_bInintenArrayBinary;
 	bool m_bInData;
+	bool m_bDecomp;
 	string m_ccurrentRefGroupName;
 	class cvParam
 	{
diff --git a/src/saxmzxmlhandler.cpp b/src/saxmzxmlhandler.cpp
index afccebb..fe34ce9 100644
--- a/src/saxmzxmlhandler.cpp
+++ b/src/saxmzxmlhandler.cpp
@@ -25,6 +25,7 @@ SAXMzxmlHandler::SAXMzxmlHandler( vector<mspectrum>& _vS, mspectrumcondition& _s
 	m_bInMsLevel2 = false;
 	m_bInPrecursorMz =  false;
 	m_bInPeaks = false;
+	m_bDecomp = false;
 	//added this (true by default)
 	m_bNetworkData = false;
 }
@@ -58,9 +59,16 @@ void SAXMzxmlHandler::startElement(const XML_Char *el, const XML_Char **attr)
 		m_bInPeaks = true;
 		m_bLowPrecision = (strcmp("64", getAttrValue("precision", attr)) != 0);
 		const char *pcompressionType = getAttrValue("compressionType", attr);
-		if(strlen(pcompressionType) != 0 && !strstr(pcompressionType,"none"))	{
-			cout << "\nFatal error: unsupported CODEC used for mzXML peak data (CODEC type=" << pcompressionType << ").\n";
-			exit(-10);
+		m_bDecomp = false;              // default to false in case required attribute is missing
+		if(strlen(pcompressionType) != 0) {
+			if (!strcmp(pcompressionType,"none")) {
+				m_bDecomp = false;
+			} else if (strstr(pcompressionType,"zlib")) {
+				m_bDecomp = true;
+			} else {
+				cout << "Non-standard CODEC used for mzXML peak data (CODEC type=" << pcompressionType << "): file cannot be interpreted.\n";
+				exit(-10);
+			}
 		}
 	}
 	else if(isElement("precursorMz", el))
@@ -106,7 +114,7 @@ void SAXMzxmlHandler::processData()
 {
 	if( m_bInPeaks && m_cidLevel == 2)
 	{
-		pushPeaks();
+		pushPeaks(true, true, m_bDecomp);
 	}
 	else if (m_bInPrecursorMz)
 	{
diff --git a/src/saxmzxmlhandler.h b/src/saxmzxmlhandler.h
index e92f441..fb8c857 100644
--- a/src/saxmzxmlhandler.h
+++ b/src/saxmzxmlhandler.h
@@ -56,6 +56,7 @@ private:
 	bool m_bInMsLevel2;
 	bool m_bInPrecursorMz;
 	bool m_bInPeaks;
+	bool m_bDecomp;
 };
 
 #endif				//SAXMzxmlHandler_H
openSUSE Build Service is sponsored by